diff --git a/.editorconfig b/.editorconfig
index 6219a927b2698e3718655e625a8c2c7e522c7462..23d04f8dd4e5b27c092351e7b524fe2d54a149f5 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -8,7 +8,7 @@ charset = utf-8
 trim_trailing_whitespace = true
 insert_final_newline = true
 
-[*.{js,coffee,html}]
+[*.{js,coffee,html,less,json}]
 indent_style = tab
 
 [*.md]
diff --git a/.eslintignore b/.eslintignore
index d4b84b0e78ca44bd8a088ba89bb1c670749352a6..000185fe150693094f8b62fd8dca842311d9ffb3 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -14,6 +14,7 @@ packages/rocketchat-ui/lib/Modernizr.js
 packages/rocketchat-ui/lib/recorderjs/recorder.js
 packages/rocketchat-ui/lib/textarea-autogrow.js
 packages/rocketchat-videobridge/client/public/external_api.js
+packages/rocketchat-theme/client/vendor/
 private/moment-locales/
 public/livechat/
 public/recorderWorker.js
diff --git a/.gitignore b/.gitignore
index f9ab2485e51781866c54d71cc68466c97c759bd0..ce142f9c01dd8ff109b970dd3277de4900791695 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,12 +39,15 @@
 .metadata
 .meteor/local*
 .meteor/meteorite
+.meteor/dev_bundle
+packages/rocketchat-livechat/app/.meteor/dev_bundle
 .mule
 .pmd
 .project
 .sass-cache
 .settings
 .Spotlight-V100
+tatus
 .Trashes
 .wtpmodules
 \#*\#
diff --git a/.meteor/packages b/.meteor/packages
index 00c4512aeab89348bdf5e09d57d33e443a17056f..d0fabc22b516026883557bcad465a00c2d140512 100644
--- a/.meteor/packages
+++ b/.meteor/packages
@@ -64,6 +64,7 @@ rocketchat:iframe-login
 rocketchat:importer
 rocketchat:importer-csv
 rocketchat:importer-hipchat
+rocketchat:importer-hipchat-enterprise
 rocketchat:importer-slack
 rocketchat:integrations
 rocketchat:internal-hubot
@@ -149,7 +150,6 @@ nimble:restivus
 nooitaf:colors
 ostrio:cookies
 pauli:accounts-linkedin
-perak:codemirror
 percolate:synced-cron
 raix:handlebar-helpers
 raix:push
diff --git a/.meteor/versions b/.meteor/versions
index cca9fdb3b4389b0d7756156b187515863722ab3d..f27bdcd655ba6b701e9cab52f476925892192f8b 100644
--- a/.meteor/versions
+++ b/.meteor/versions
@@ -13,7 +13,7 @@ babel-compiler@6.13.0
 babel-runtime@1.0.1
 base64@1.0.10
 binary-heap@1.0.10
-blaze@2.2.0
+blaze@2.2.1
 blaze-html-templates@1.0.5
 blaze-tools@1.0.10
 boilerplate-generator@1.0.11
@@ -62,7 +62,7 @@ kadira:flow-router@2.12.1
 kenton:accounts-sandstorm@0.5.1
 konecty:change-case@2.3.0
 konecty:delayed-task@1.0.0
-konecty:mongo-counter@0.0.5_2
+konecty:mongo-counter@0.0.5_3
 konecty:multiple-instances-status@1.0.6_1
 konecty:nrr@2.0.2
 konecty:user-presence@1.2.9
@@ -86,7 +86,7 @@ mizzao:timesync@0.3.4
 mobile-experience@1.0.4
 mobile-status-bar@1.0.13
 modules@0.7.7
-modules-runtime@0.7.7
+modules-runtime@0.7.8
 mongo@1.1.14
 mongo-id@1.0.6
 mongo-livedata@1.0.12
@@ -95,7 +95,7 @@ mystor:device-detection@0.2.0
 nimble:restivus@0.8.11
 nooitaf:colors@1.1.2_1
 npm-bcrypt@0.9.2
-npm-mongo@2.2.11_2
+npm-mongo@2.2.16_1
 oauth@1.1.12
 oauth1@1.1.11
 oauth2@1.1.11
@@ -106,9 +106,7 @@ pauli:accounts-linkedin@1.3.1
 pauli:linkedin@1.3.1
 peerlibrary:aws-sdk@2.4.9_1
 peerlibrary:blocking@0.5.2
-perak:codemirror@1.3.1
 percolate:synced-cron@1.3.2
-pntbr:js-yaml-client@0.0.1
 promise@0.8.8
 raix:eventemitter@0.1.3
 raix:eventstate@0.0.4
@@ -149,6 +147,7 @@ rocketchat:iframe-login@1.0.0
 rocketchat:importer@0.0.1
 rocketchat:importer-csv@1.0.0
 rocketchat:importer-hipchat@0.0.1
+rocketchat:importer-hipchat-enterprise@1.0.0
 rocketchat:importer-slack@0.0.1
 rocketchat:integrations@0.0.1
 rocketchat:internal-hubot@0.0.1
@@ -170,7 +169,7 @@ rocketchat:message-pin@0.0.1
 rocketchat:message-snippet@0.0.1
 rocketchat:message-star@0.0.1
 rocketchat:migrations@0.0.1
-rocketchat:oauth2-server@1.4.0
+rocketchat:oauth2-server@2.0.0
 rocketchat:oauth2-server-config@1.0.0
 rocketchat:oembed@0.0.1
 rocketchat:otr@0.0.1
diff --git a/.sandstorm/sandstorm-pkgdef.capnp b/.sandstorm/sandstorm-pkgdef.capnp
index bebb8d08f6e75224cbea6beec5ce9845329cc567..f27a0ea3eeeb5b9be9333d8789b6ed091cfbb72e 100644
--- a/.sandstorm/sandstorm-pkgdef.capnp
+++ b/.sandstorm/sandstorm-pkgdef.capnp
@@ -19,9 +19,9 @@ const pkgdef :Spk.PackageDefinition = (
 
 		appTitle = (defaultText = "Rocket.Chat"),
 
-		appVersion = 47,  # Increment this for every release.
+		appVersion = 50,  # Increment this for every release.
 
-		appMarketingVersion = (defaultText = "0.47.0-develop"),
+		appMarketingVersion = (defaultText = "0.50.0-develop"),
 		# Human-readable representation of appVersion. Should match the way you
 		# identify versions of your app in documentation and marketing.
 
diff --git a/.scripts/start-xvfb.sh b/.scripts/start-xvfb.sh
new file mode 100755
index 0000000000000000000000000000000000000000..70be0b2e6bd76a35f87862a934504c8023372a20
--- /dev/null
+++ b/.scripts/start-xvfb.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
+  sh -e /etc/init.d/xvfb start
+  sleep 3
+fi
diff --git a/.scripts/start.js b/.scripts/start.js
new file mode 100644
index 0000000000000000000000000000000000000000..fee3f78b90e85ea29a37abd8ebb57edacea993a9
--- /dev/null
+++ b/.scripts/start.js
@@ -0,0 +1,88 @@
+#!/usr/bin/env node
+var path = require('path'),
+	fs = require('fs'),
+	extend = require('util')._extend,
+	exec = require('child_process').exec,
+	processes = [];
+
+var baseDir = path.resolve(__dirname, '..'),
+	srcDir = path.resolve(baseDir);
+
+var appOptions = {
+	env: {
+		PORT: 3000,
+		ROOT_URL: 'http://localhost:3000'
+	}
+};
+
+function startProcess(opts, callback) {
+	var proc = exec(
+		opts.command,
+		opts.options
+	);
+
+	if (opts.waitForMessage) {
+		proc.stdout.on('data', function waitForMessage(data) {
+			if (data.toString().match(opts.waitForMessage)) {
+				if (callback) {
+					callback();
+				}
+			}
+		});
+	}
+
+	if (!opts.silent) {
+		proc.stdout.pipe(process.stdout);
+		proc.stderr.pipe(process.stderr);
+	}
+
+	if (opts.logFile) {
+		var logStream = fs.createWriteStream(opts.logFile, {flags: 'a'});
+		proc.stdout.pipe(logStream);
+		proc.stderr.pipe(logStream);
+	}
+
+	proc.on('close', function(code) {
+		console.log(opts.name, 'exited with code ' + code);
+		for (var i = 0; i < processes.length; i += 1) {
+			processes[i].kill();
+		}
+		process.exit(code);
+	});
+	processes.push(proc);
+}
+
+function startApp(callback) {
+	startProcess({
+		name: 'Meteor App',
+		command: 'node /tmp/build-test/bundle/main.js',
+		waitForMessage: appOptions.waitForMessage,
+		options: {
+			cwd: srcDir,
+			env: extend(appOptions.env, process.env)
+		}
+	}, callback);
+}
+
+function startChimp() {
+	startProcess({
+		name: 'Chimp',
+		command: 'meteor npm run chimp-test',
+		options: {
+			env: Object.assign({}, process.env, {
+				NODE_PATH: process.env.NODE_PATH +
+					path.delimiter + srcDir +
+					path.delimiter + srcDir + '/node_modules'
+			})
+		}
+	});
+}
+
+function chimpNoMirror() {
+	appOptions.waitForMessage = 'SERVER RUNNING';
+	startApp(function() {
+		startChimp();
+	});
+}
+
+chimpNoMirror();
diff --git a/.snapcraft/edge/snapcraft.yaml b/.snapcraft/edge/snapcraft.yaml
index 2b5db0e6cf4f8f0edf4d23f8ee954ad15c852ceb..cacb0f1d21af952f3ab90db3f369221c3339cf8f 100644
--- a/.snapcraft/edge/snapcraft.yaml
+++ b/.snapcraft/edge/snapcraft.yaml
@@ -7,13 +7,13 @@
 # 5.  `snapcraft snap`
 
 name: rocketchat-server
-version: 0.47.0-develop
+version: 0.50.0-develop
 summary: Rocket.Chat server
 description: Have your own Slack like online chat, built with Meteor. https://rocket.chat/
 confinement: strict
 apps:
     rocketchat-server:
-        command: env BABEL_CACHE_DIR=/tmp ROOT_URL=http://localhost PORT=3000 MONGO_URL=mongodb://localhost:27017/parties Accounts_AvatarStorePath=$SNAP_COMMON/uploads node $SNAP/main.js >$SNAP_DATA/server.log 2>&1
+        command: env BABEL_CACHE_DIR=/tmp ROOT_URL=http://localhost PORT=3000 MONGO_URL=mongodb://localhost:27017/parties Accounts_AvatarStorePath=$SNAP_COMMON/uploads node $SNAP/main.js
         daemon: simple
         plugs: [network, network-bind]
     rocketchat-mongo:
@@ -23,7 +23,7 @@ apps:
 parts:
     node:
         plugin: nodejs
-        node-engine: 4.6.2
+        node-engine: 4.7.1
         node-packages:
             - promise
             - fibers
diff --git a/.snapcraft/stable/snapcraft.yaml b/.snapcraft/stable/snapcraft.yaml
index dd5d765e04c1b20afad9f5085a77408be41200de..35c3312b8b0414279fa3fcca1ea5dbe759bc3198 100644
--- a/.snapcraft/stable/snapcraft.yaml
+++ b/.snapcraft/stable/snapcraft.yaml
@@ -7,13 +7,13 @@
 # 5.  `snapcraft snap`
 
 name: rocketchat-server
-version: 0.47.0-develop
+version: 0.50.0-develop
 summary: Rocket.Chat server
 description: Have your own Slack like online chat, built with Meteor. https://rocket.chat/
 confinement: strict
 apps:
     rocketchat-server:
-        command: env BABEL_CACHE_DIR=/tmp ROOT_URL=http://localhost PORT=3000 MONGO_URL=mongodb://localhost:27017/parties Accounts_AvatarStorePath=$SNAP_COMMON/uploads node $SNAP/main.js >$SNAP_DATA/server.log 2>&1
+        command: env BABEL_CACHE_DIR=/tmp ROOT_URL=http://localhost PORT=3000 MONGO_URL=mongodb://localhost:27017/parties Accounts_AvatarStorePath=$SNAP_COMMON/uploads node $SNAP/main.js
         daemon: simple
         plugs: [network, network-bind]
     rocketchat-mongo:
@@ -23,7 +23,7 @@ apps:
 parts:
     node:
         plugin: nodejs
-        node-engine: 4.6.2
+        node-engine: 4.7.1
         node-packages:
             - promise
             - fibers
diff --git a/.stylelintignore b/.stylelintignore
new file mode 100644
index 0000000000000000000000000000000000000000..5baac3a35e97342e3d785fa8427808fc61974cde
--- /dev/null
+++ b/.stylelintignore
@@ -0,0 +1,2 @@
+**/lesshat.less
+**/_lesshat.import.less
\ No newline at end of file
diff --git a/.stylelintrc b/.stylelintrc
new file mode 100644
index 0000000000000000000000000000000000000000..376a8b29f50ff72e178e1a534815a6b70236720d
--- /dev/null
+++ b/.stylelintrc
@@ -0,0 +1,115 @@
+{
+	"rules": {
+		"at-rule-empty-line-before": [ "always", {
+			except: [
+				"blockless-after-same-name-blockless",
+				"first-nested",
+			],
+			ignore: ["after-comment"],
+		} ],
+		"at-rule-name-case": "lower",
+		"at-rule-name-space-after": "always",
+		"at-rule-semicolon-newline-after": "always",
+		"block-closing-brace-empty-line-before": "never",
+		"block-closing-brace-newline-after": "always",
+		"block-closing-brace-newline-before": "always",
+		"block-closing-brace-space-before": "never-single-line",
+		"block-no-empty": true,
+		"block-opening-brace-newline-after": "always",
+		"block-opening-brace-space-after": "never-single-line",
+		"block-opening-brace-space-before": "always",
+		"color-hex-case": "lower",
+		"color-hex-length": "long",
+		"color-no-invalid-hex": true,
+		"comment-empty-line-before": [ "always", {
+			except: ["first-nested"],
+			ignore: ["stylelint-commands"],
+		} ],
+		"comment-no-empty": true,
+		"comment-whitespace-inside": "always",
+		"custom-property-empty-line-before": "never",
+		"declaration-bang-space-after": "never",
+		"declaration-bang-space-before": "always",
+		"declaration-block-no-duplicate-properties": [ true, {
+			ignore: ["consecutive-duplicates-with-different-values"],
+		} ],
+		"declaration-block-no-redundant-longhand-properties": true,
+		"declaration-block-no-shorthand-property-overrides": true,
+		"declaration-block-semicolon-newline-after": "always",
+		"declaration-block-semicolon-space-after": "always-single-line",
+		"declaration-block-semicolon-space-before": "never",
+		"declaration-block-single-line-max-declarations": 1,
+		"declaration-block-trailing-semicolon": "always",
+		"declaration-colon-newline-after": "always-multi-line",
+		"declaration-colon-space-after": "always-single-line",
+		"declaration-colon-space-before": "never",
+		"declaration-empty-line-before": "never",
+		"font-family-no-duplicate-names": true,
+		"function-calc-no-unspaced-operator": true,
+		"function-comma-newline-after": "always-multi-line",
+		"function-comma-space-after": "always-single-line",
+		"function-comma-space-before": "never",
+		"function-linear-gradient-no-nonstandard-direction": true,
+		"function-max-empty-lines": 0,
+		"function-name-case": "lower",
+		"function-parentheses-newline-inside": "always-multi-line",
+		"function-parentheses-space-inside": "never-single-line",
+		"function-whitespace-after": "always",
+		"indentation": "tab",
+		"keyframe-declaration-no-important": true,
+		"length-zero-no-unit": true,
+		"max-empty-lines": 1,
+		"media-feature-colon-space-after": "always",
+		"media-feature-colon-space-before": "never",
+		"media-feature-name-case": "lower",
+		"media-feature-name-no-unknown": true,
+		"media-feature-parentheses-space-inside": "never",
+		"media-feature-range-operator-space-after": "always",
+		"media-feature-range-operator-space-before": "always",
+		"media-query-list-comma-newline-after": "always-multi-line",
+		"media-query-list-comma-space-after": "always-single-line",
+		"media-query-list-comma-space-before": "never",
+		"no-duplicate-selectors": true,
+		"no-empty-source": true,
+		"no-eol-whitespace": true,
+		"no-extra-semicolons": true,
+		"no-missing-end-of-source-newline": true,
+		"number-leading-zero": "always",
+		"number-no-trailing-zeros": true,
+		"property-case": "lower",
+		"property-no-unknown": true,
+		"rule-nested-empty-line-before": [ "always", {
+			except: ["first-nested"],
+			ignore: ["after-comment"],
+		} ],
+		"rule-non-nested-empty-line-before": [ "always", {
+			ignore: ["after-comment"],
+		} ],
+		"selector-attribute-brackets-space-inside": "never",
+		"selector-attribute-operator-space-after": "never",
+		"selector-attribute-operator-space-before": "never",
+		"selector-combinator-space-after": "always",
+		"selector-combinator-space-before": "always",
+		"selector-descendant-combinator-no-non-space": true,
+		"selector-list-comma-newline-after": "always",
+		"selector-list-comma-space-before": "never",
+		"selector-max-empty-lines": 0,
+		"selector-pseudo-class-case": "lower",
+		"selector-pseudo-class-no-unknown": true,
+		"selector-pseudo-class-parentheses-space-inside": "never",
+		"selector-pseudo-element-case": "lower",
+		"selector-pseudo-element-colon-notation": "double",
+		"selector-pseudo-element-no-unknown": true,
+		"selector-type-case": "lower",
+		"selector-type-no-unknown": true,
+		"shorthand-property-no-redundant-values": true,
+		"string-no-newline": true,
+		"unit-case": "lower",
+		"unit-no-unknown": true,
+		"value-list-comma-newline-after": "always-multi-line",
+		"value-list-comma-space-after": "always-single-line",
+		"value-list-comma-space-before": "never",
+		"value-list-max-empty-lines": 0,
+	},
+	"ignoreFiles": "packages/rocketchat-livechat/app/client/stylesheets/utils/_lesshat.import.less"
+}
diff --git a/.travis.yml b/.travis.yml
index f59ebf8fb82c1c835f40b293d403f76d0991dba0..ee5356efffca7b2c81885a8b3ca0a58d02cc8793 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,7 @@
 language: node_js
 services:
 - docker
+- mongodb
 branches:
   only:
   - develop
@@ -13,9 +14,12 @@ node_js:
 addons:
   apt:
     sources:
+    - google-chrome
     - ubuntu-toolchain-r-test
     packages:
+    - google-chrome-stable
     - g++-4.8
+  firefox: "latest"
 before_cache:
 - rm -rf $HOME/build/RocketChat/Rocket.Chat/.meteor/local/log
 - rm -rf $HOME/build/RocketChat/Rocket.Chat/.meteor/local/run
@@ -33,14 +37,35 @@ cache:
   - "$HOME/build/RocketChat/Rocket.Chat/packages/rocketchat-livechat/app/.meteor/local"
 before_install:
 - if [ ! -e "$HOME/.meteor/meteor" ]; then curl https://install.meteor.com | sed s/--progress-bar/-sL/g | /bin/sh; fi
+# Start X Virtual Frame Buffer for headless testing with real browsers
+- .scripts/start-xvfb.sh
 install:
 - export PATH="$HOME/.meteor:$PATH"
 before_script:
+- echo "replication:" | sudo tee -a /etc/mongod.conf
+- |-
+  echo "  replSetName: \"rs0\"" | sudo tee -a /etc/mongod.conf
+- sudo service mongod restart
 - mkdir /tmp/build
 - travis_retry npm install
+- |-
+  mongo --eval 'rs.initiate({_id:"rs0", members: [{"_id":1, "host":"localhost:27017"}]})'
 - npm run lint
-script:
+- npm run stylelint
 - travis_retry meteor build --headless /tmp/build
+- mkdir /tmp/build-test
+- tar -xf /tmp/build/Rocket.Chat.tar.gz -C /tmp/build-test/
+- cd /tmp/build-test/bundle/programs/server
+- npm install -g node-gyp node-pre-gyp
+- npm install
+- cd -
+- mongo --eval 'rs.status()'
+- mongo meteor --eval 'db.getCollectionNames()'
+script:
+- npm test
+- mongo meteor --eval 'db.dropDatabase()'
+- unset MONGO_OPLOG_URL
+- npm test
 before_deploy:
 - source ".travis/setartname.sh"
 - source ".travis/setdeploydir.sh"
@@ -64,7 +89,11 @@ after_deploy:
 - ".travis/snap.sh"
 env:
   global:
+  - DISPLAY=:99.0
   - CXX=g++-4.8
   - secure: HrPOM5sBibYkMcf9aeQThYPCDiXeLkg0Xgv0HvH88/ku/gphDpNEjHNReHZM3cyfm9y3RhHpVdD+Zzy38S2goKyewRzpXJsuyerOYkjND0v3tivhs9CAX8PAUxj1U5zllTyH4bgW2ZwRtNnwnmtIM/JJlnySMpKVDqIZBpbhn3ph9bJ2J+BW3D3Jw8meQ1vCX8szIibyJK/5QX6HG2RBFXJGYoQ8DmR8jQv0aJQvT1Az5DO4yImk8tX4NP95qOc19Jywr1DsbaSBZeJ8lFJAmBpIGx7KAmUVCcxSxfbXGRhs2K4iEYb3rJ/dU6KiyPsKGUG4aYNGgbvcX0ZxX/BZ6ZU9ff0E4IIf43IxoN3ElrOqOFk5msJAXbrJEreINSzDqKOy8NFYtCQ49E2gwzfage4ZXkhFyx3wMPa5bzpr3ncsTceMjMVz03uL781X6NLuCkUmXv+n8K2MNhJU9Xinpdx1GRJm+0lXJspNNJ1ruHeJtls4epj4bmCwKmmZbFKPXqa5e8xVcMIkwt1LMiHduhE+WgKNHdOMhXrCcTxF62ybLlsHXmyLLJeNjTeKS8QG2XSoonClDAz/1R41I1DsMPblcgz9uvYCf7UtyftbhJ83bnJeEmOYQiwijLG0+QMq+B2+mmZan3Z7Hl7O53dnwuLxz7EO7EhQhY+CqHVgc6s=
   - secure: w55v/9dmQ9wKbc+fhkZdWfaXIGi+5Qo365J0/IEZRCle2jFWUMBSzEghUuubw9Pys56uAcivOzKozT7+qozVaQW9kSgTLK4bSUSWKeSuynF7Too0CNdzt8CWgjcxGvYVWP0vlp+2eTI0x9+HJlFZn1hP+3v9C+ASH6+sqXvi24kNOPANsUvlbwIC7+T3kOdOOFzrA/tNLkXp2NGs9OaHVnvOVrZlHIn0TL8kGV1HyW4k4KLPgAcwgDq8DRWQBWk+E59HyTGXMyt/GxAJkjEebcJ/TnrbCiExbrTY+OmHjwk8Yfp9CbWsEtEYWSdLoNaFMhUrJRGGKjtansqQWktfkrN/Ro6Scl+lorQQ3eBu+ZVdmx3BXj8TRyqkhh6sqbola5XGhffp61fKxLcbYFE6Ph7g9twvFArCt2/zifmKYxH/NniCKGir5eZZnfFwTE6y2b+m37gjd7jd4t8SEcbFKH7tvOVRNm79VDqBQo0rNieCM5fPKsZkYD7sjB9G7cuZaZLAKUJf1K/FYqCeGeNV0Wcxi95nBh5usenm88xdajShxxKJedi1n77qqj03KxW7ictDnt/sEzz6vHjyf1O2pFUuPZ2eVwenpa0utDOvBTYd10OSlqlWaG/ldNJ8ofl/fawm0of4xp0rY3UNaTYdCZsPm6qfq7NIocefb/qeAJ4=
   - secure: iihMgVr2PaP9d0GXuEe3JU/eK5agWWHWDH0WFOTHQ42L1x6wT6oom3zJfwGmFL28BDVp5qQQ3V5isc0p1Vca7PCsRWUht/37EzzLbfrutLDvCpvzGqzqTkvKeW9WINYcIwEQoDE0M2I12WZN9NhGCaT5Z3WanwYX1x6AzjHX4GK/gBzX0WWOqKp7UQijLpuWpdlMUhoWKatGKi9ft+PCBgOonhoqy6Pk9QYNG+jrq86RydOP428DE2Mo5aFxPwhSoMFukOlTIPQylJ3q3q9NDHI9XhV6AJwty/CE9UXr4wAI5RAR/9q0cHkoXj7P/y7cj+SI9pZMt5EaS4DPs4MVb8vvVP+7K0VfbVc5kcoXZoUsORtxiaPk5yPeqaqpB89xp7BjQizr5fOXeTp3Xe8UiZeWvpnbvzWEUAW7XXbMLJjyKT6OLRyVmZ240aMY7zdgC/e3nNePaam1LHYJRejJGM0aFIuwDqryGN9KJMjMFOL6LHm+OBQcjfDokBLc1wjfomNXcIrWWjdNTckpDEIhAFzwgxy9OlJQBJqtpPajPrcU1bxfrnbLks0KeQj9YTSTR0D7FknhVF8OpOnDZDPWdUBJL/dGd4eIf0UIr5xW7ZdFJ0xxhGXpJuH5ITG/C8CMOFsFvUMR1EG+cY4UN8YlVcUyp/S6eJgEzJM9fyWwDgs=
+  - MONGO_OPLOG_URL: "mongodb://localhost:27017/local"
+  - MONGO_URL: "mongodb://localhost:27017/meteor"
+  - TEST_MODE: "true"
diff --git a/FEATURES.md b/FEATURES.md
index 3a05264d2413459a96f8c03a319b2bdff7e4b4dc..381c09a0baf021677dcf49ee01cc0c7eb7ce01ba 100644
--- a/FEATURES.md
+++ b/FEATURES.md
@@ -1,3 +1,5 @@
+# Features
+
 - Self Host
   - Docker  
   - Multiple Deployment Options (Heroku, Digital Ocean, Sandstorm, etc.)  
diff --git a/HISTORY.md b/HISTORY.md
index 83fb60c8b1f42c3b9da2a9f13b86fa6f36cf0d05..8e436690ac762e4763ffea533dccbfd56b059115 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -1,6 +1,164 @@
 # History
 
-## 0.46.0, 2016-Nov-21
+## 0.49.0 - 2017-Jan-11
+
+### Now uses NodeJS 4.7.1
+
+- Add basic support for RFC 7233
+- Add Button to block direct message
+- Add caching layer using LokiDB
+- Add custom fields to user's profile
+- Add discard and reset button to admin panels
+- Add email address validation to livechat offline messages
+- Add file name and description on file upload
+- Add Livechat domains validations
+- Add many API endpoints, see https://rocket.chat/docs/developer-guides/rest-api/
+- Add methods from rest api 0.5 to v1
+- Add stylelint to CSS and LESS files
+- Add the migration for bots to be able to create rooms
+- Allow alias, avatar, and emoji in the sendFileMessage.
+- Allow query, sort, and fields on the queryParams of the rest api
+- Allow to merge users with LDAP on bulk sync
+- Bi-directional Sladk message edit, delete and reactions
+- Disable animations when TEST_MODE=true
+- Do not require .jpg for avatar url and return correct content type
+- Enable CDN_PREFIX for avatars
+- Fix crash at startup if Slack bridge enabled and slack.com is not reachable #5426
+- Fix importer relying on os file type, use file signature. Closes #3050
+- Fix issue creating users with username from OAuth
+- Fix screen sharing bug when receiving audio call. issue #5286
+- Migrate livechat visitors' emails field to visitorEmails
+- New livechat layout
+- Normalize favicons, tiles and touchicons
+- Refactored API endpoints to more closely conform to Slack API conventions and naming conventions
+- Remove alpha colors and add disabled buttons style
+- Sets default avatar after setting username for the first time by default
+- Several performance improvements
+- Styles cleanup (#5354) (#5364)
+- Support SAML IDP-initiated login mode
+- Update docker-compose to version 2
+- Use CodeMirror from Npm
+
+## 0.48.2 - 2016-Dec-20
+
+- Add button to refresh aouth services
+- Fix download on electron
+- Fix issue creating users with username from OAuth
+- Fix message when username field not exists in OAuth data
+- Fix OAuth global variable
+
+## 0.48.1 - 2016-Dec-13
+
+### Now uses NodeJS 4.7.0
+
+- Fix integration payload JSON.parse 
+
+## 0.48.0 - 2016-Dec-12
+
+- Add CustomOAuth logger
+- Add env var to disable animations
+- Add new options (username-field and merge-users) to CustomOAuth
+- Add search field in admin
+- Add support to set own avatar from URL on REST API
+- Add validateNewUser check to compare against whitelist
+- Allow setting other users avatars if you have permissions
+- Change all 'Has more' with loading animation
+- Change CustomOAuth setting format
+- Change field name to roles and type to Array.
+- Change from loading cert from a file to storing the cert
+- Don't allow changing the room type if you only have permission to create one and not the other
+- Fix accountFlex highlight on hover issue
+- Fix crash if a webhook payload had a field named "payload"
+- Fix email being unverified when calling user.update
+- Fix Geolocation button
+- Fix handle saml urls with query strings.
+- Fix katex
+- Fix SAML logout
+- Fix the chat.postMessage not returning any data about the sent message
+- Fix the nameFilter being required on groupsList, since it isn't a requirement
+- Fix to do saml http-redirect binding with signing.
+- Fix typo in result ordering regex.
+- Fix unread messages bar overlapping
+- Hide Sandstorm offer button on Cordova
+- Init API tests
+- Made the logged user check more modular
+- Make the server information of the api consistant with others
+- Move joinDefaultChannels to internal APIs
+- Move the channels to their own file and add several rest api methods
+- Move the groups v1 api calls out of the huge routes.coffee file
+- Move the rest of the current rest api to individual files
+- Move the v1 settings into the v1 folder
+- Only unwrapping webhook payloads if necessary
+- Pick only departments that would shown on registration if none set
+- Prevent register broadcastAuth more than one time
+- Remove reactions when messages are removed, fixes #5164
+- Set username automaticaly
+- Support username template in CustomOAuth
+- Update momentjs to 2.17.1
+- Update slack-client to 2.0.6
+
+## 0.47.1 - 2016-Dec-09
+
+- Fix color migrations
+- Fix to prevent register broadcastAuth more than one time
+
+## 0.47.0 - 2016-Dec-06
+
+- Add 'clear OEmbed cache now' button
+- Add a method and rest api to clean up a channel's history
+- Add ability to choose a department from the API to livechat
+- Add channel history rest api
+- Add channel history rest api which is slack compatiable.
+- Add ecmascript to all packages with coffeescript
+- Add feature to clear OEmbed cache after user-defined amount of time
+- Add heirarchy and refactor colour variables
+- Add method do check if process is running inside docker
+- Add migrations, label, toggle for minor colors
+- Add option to disable file uploads in direct messages
+- Add the feature to hide the file sharing btn and some fixes
+- Allow load css from subdir
+- Allow setting border colours in imports
+- Allow simpler pinning and unpinning via the methods, only require _id and rid.
+- Allow use expressions/variables as colors
+- Change custom account box items to button
+- Convert the channels.history from post to get
+- Fix 'user is typing' break line
+- Fix bug with Disable Embed for Users
+- Fix button/bg colors and contrast
+- Fix code that check for empty object
+- Fix file list in cordova
+- Fix improper use of head tag (replace with header)
+- Fix improve unread mark
+- Fix issue #4387, crash when using StartTLS and LDAP
+- Fix issue #4813
+- Fix jitsi lib load in sub dir
+- Fix login logo in subdir
+- Fix missed styles and cull transparent variables
+- Fix oauth client when client had previously authorized
+- Fix redirectUrl after custom oauth successful login initiated by iframe command, fixes #5042 (#5043)
+- Fix sandstorm call setPath on navigation
+- Fix set user's email from REST API
+- Fix to stop changing the instance IP if running in docker
+- Fix windows issues on startup
+- Improved performance of sidebar rendering. Fixed RTL sidebar opening.
+- Inject meta tag via Inject.rawHead
+- Load permissions styles through theme methods
+- Migrating from GoogleSiteVerification_id to Meta_google-site-verification
+- Move less mixins into separate import
+- No longer allow invisible agents get livechats
+- Recommend using meteor npm start
+- Remove c from function param
+- Remove the default value for the latest on the getChannelHistory
+- Rename action-buttons-color primary-action-color
+- Restore migrations post merge upstream versions
+- Serve theme.css through WebApp.rawConnectHandlers
+- Show 'connecting to agent..' message option on LIveChat client
+- Simplify button classes, remove color names
+- Update action link and permissions colors to use theme variables
+- Updated to autolinker 1.4.0
+- Use toastr from npm
+
+## 0.46.0 - 2016-Nov-21
 
 ### Upgraded to meteor 1.4.2.3 - Now uses NodeJS 4.6.2
 
@@ -68,7 +226,7 @@
 - Using border-with on CSS to control borders
 - Validate user access on file upload
 
-## 0.45.0, 2016-Oct-31
+## 0.45.0 - 2016-Oct-31
 
 - Add global keydown event handler
 - Add hubot packages as default
@@ -108,7 +266,7 @@
 - Update ip-range-check to version 0.0.2 to get rid of debugger call Day8/ip-range-check#1
 - Update all npm-shrinkwrap.json with npm 3.10.9
 
-## 0.44.0, 2016-Oct-25
+## 0.44.0 - 2016-Oct-25
 
 - Add archive and unarchive api endpoints
 - Add check package dependency to the iframe-login package. (#4664)
@@ -129,7 +287,7 @@
 - Replace mrt:moment-timezone by aldeed:moment-timezone as it depend on the official moment package
 - Set tap:i18n version in i18n package to install the expected version when the package is used in other projects
 
-## 0.43.0, 2016-Oct-17
+## 0.43.0 - 2016-Oct-17
 
 - Add @here support for only notifying users that are active
 - Add base support for config via webservices
@@ -155,7 +313,7 @@
 - Set babel cache directory for integrations
 - Switch snap from imagemagick to graphicsmagick
 
-## 0.42.0, 2016-Oct-04
+## 0.42.0 - 2016-Oct-04
 
 - Add dependency to package with avatar template
 - Add ids for irc.server callbacks
@@ -187,7 +345,7 @@
 - Standardize settings endpoint return
 - Update Autolinker to 1.2.0
 
-## 0.41.0, 2016-Sep-27
+## 0.41.0 - 2016-Sep-27
 
 - Add ability to close open livechats if an agent goes offline
 - Add basic channels tests
@@ -218,7 +376,7 @@
 - Replace autocomplte popups subscriptions with methods
 - Trigger global event to embedded images
 
-## 0.40.1, 2016-Sep-21
+## 0.40.1 - 2016-Sep-21
 
 - Allow Iframe login with default tokens
 - Fix embedded layout message box auto-resize
@@ -230,7 +388,7 @@
 - Show file type on file upload error (#3217)
 - Use the npm package of UAParser on LiveChat
 
-## 0.40.0, 2016-Sep-20
+## 0.40.0 - 2016-Sep-20
 
 ### Upgraded to meteor 1.4.1.1 - Now uses NodeJS 4.5
 
@@ -310,7 +468,7 @@
 - Using faster npm bcrypt module
 - Verify permissions on spotlight list
 
-## 0.39.0, 2016-Sep-05
+## 0.39.0 - 2016-Sep-05
 
 - Accept username from SAML response
 - Add image attachment support when a bot (ex using giffy) posts just an image
@@ -339,7 +497,7 @@
 - UI improvements to login screen
 - Update the opened livechat room by token
 
-## 0.38.0, 2016-Aug-30
+## 0.38.0 - 2016-Aug-30
 
 - Action links improvements
 - Add global event unread-changed-by-subscription
@@ -374,7 +532,7 @@
 - Update to depend only on the gMaps API key, add i18n strings for geolocaiotn sharing
 - Updated loginform a11y and UX - labels instead of placeholders (#4075)
 
-## 0.37.1, 2016-Aug-17
+## 0.37.1 - 2016-Aug-17
 
 - Allow deletion of records with same id on settings
 - Created inital Iframe integration
@@ -385,7 +543,7 @@
 - Changed SlackBridge to import from begin to end
 - Suppress message-pinned notification from import
 
-## 0.37.0, 2016-Aug-15
+## 0.37.0 - 2016-Aug-15
 
 - Added an option to SlackBridge to exclude some bots messages from propagating. (#3813)
 - Added bot-helpers package (#3799)
@@ -439,7 +597,7 @@
 - Update default setting for file upload types to include video
 - Update side-nav with room counts (#3967)
 
-## 0.36.0, 2016-Aug-02
+## 0.36.0 - 2016-Aug-02
 
 ### Core updates
 
@@ -515,7 +673,7 @@
 - Update emojione to 2.2.5 (#3736)
 - Update hubot version to v.0.1.4
 
-## 0.35.0, 2016-Jun-28
+## 0.35.0 - 2016-Jun-28
 
 - Add a list of reserved usernames
 - Add admin setting to disable merged groups and channels
@@ -534,12 +692,12 @@
 - Preventing message update on multiple sendMessage calls
 - Update for Dataporten closing #3580 (#3608)
 
-## 0.34.0, 2016-Jun-14
+## 0.34.0 - 2016-Jun-14
 
 - BETA JITSI INTEGRATION (#3476)
 - Add more config options to livechat (#3497)
 
-## 0.33.0, 2016-Jun-07
+## 0.33.0 - 2016-Jun-07
 
 - Add a method and api way to get a user's private groups, for external usage
 - Add ASCII art commands /tableflip /unflip /lennyface /gimme
@@ -562,7 +720,7 @@
 - Send livechat webhooks
 - Use <button/> rather than <i/> for tab buttons.
 
-## 0.32.0, 2016-May-30
+## 0.32.0 - 2016-May-30
 
 - Add autocomplete for adding users to roles
 - Add bad word filter to settings UI
@@ -594,7 +752,7 @@
 - Remove resize animation preventing scroll stay at bottom
 - Update user-presence package
 
-## 0.31.0, 2016-May-16
+## 0.31.0 - 2016-May-16
 
 - Add header and footer to e-mails
 - Add new livechat settings to livechat manager
@@ -625,7 +783,7 @@
 - Save room's name as the livechat visitor name
 - Use HTML emails instead of Text- 
 
-## 0.30.0, 2016-May-09
+## 0.30.0 - 2016-May-09
 
 - Ability to run imports several times without duplicate messages (#3123)
 - Add /shrug command
@@ -674,7 +832,7 @@
 - Use native code to set file upload cookies
 - Wait until user is logged-in to add message listener
 
-## 0.29.0, 2016-May-02
+## 0.29.0 - 2016-May-02
 
 - Add a i18nDefaultQuery option to settings
 - Add a sequential code for livechat rooms
@@ -725,7 +883,7 @@
 - Use new placholders.js for sending mail through Mailer
 - Verify if user's emails and phone are arrays before showing them
 
-## 0.28.0, 2016-Apr-25
+## 0.28.0 - 2016-Apr-25
 
  - Add "by" and "at" to language files
  - Add API method to list online users in a room
@@ -767,7 +925,7 @@
  - Show all - RTL fix (#2957)
  - Use the logo from uploaded assets for the menu footer
 
-## 0.27.0, 2016-Apr-18
+## 0.27.0 - 2016-Apr-18
 
 - Add admin to default list of allowed roles on 'pin-message' (#2846)
 - Add date/time format settings (#2852)
@@ -801,7 +959,7 @@
 - Use different color for mentions "all" (#2865)
 - User info tab bar improvements (#2893)
 
-## 0.26.0, 2016-Apr-11
+## 0.26.0 - 2016-Apr-11
 
 - Add a download icon to file list (#2817)
 - Add ability to hide embedded media
@@ -840,7 +998,7 @@
 - Use RocketChat Logger as SyncedCron logger
 - When creating a room, set user only as owner, not moderator
 
-## 0.25.0, 2016-Apr-04
+## 0.25.0 - 2016-Apr-04
 
 - Add black list email list options
 - Add more indexes to users collection
@@ -887,7 +1045,7 @@
 - Use page-loading animation when waiting subs
 - Use ReadOnly globals
 
-## 0.24.0, 2016-Mar-28
+## 0.24.0 - 2016-Mar-28
 
 - Add a title with emoji's shortname on picker
 - Add Assets and Blaze to jshint global variables
@@ -944,7 +1102,7 @@
 - Use the login layout for the reset password screen
 - Using PNG emoji sprites for better performance
 
-## 0.23.0, 2016-Mar-21
+## 0.23.0 - 2016-Mar-21
 
 - Accept * for all media types
 - Add emoji picker
@@ -988,7 +1146,7 @@
 - Use login logo as asset
 - Use URL compatible token and do not sabe in user record
 
-## 0.22.0, 2016-Mar-14
+## 0.22.0 - 2016-Mar-14
 
 - Add AES encryption routines
 - Add CDN config option for file upload
@@ -1032,7 +1190,7 @@
 - Trim slashes from Site_Url - closes #2462
 - Upload files to file system support
 
-## 0.21.0, 2016-Mar-07
+## 0.21.0 - 2016-Mar-07
 
 - Add ability for users to delete their own accounts
 - Add infinite scrolling to channels list
@@ -1066,7 +1224,7 @@
 - Shows OAuth Callback URLs
 - Support 'user_id' in addition to 'id' and 'ID' for service identifier
 
-## 0.20.0, 2016-Feb-29
+## 0.20.0 - 2016-Feb-29
 
 - Ability to disable sending nickname and message via push notification
 - Add back 'delete room' button - closes #2351
@@ -1104,7 +1262,7 @@
 - Updated sweetalert
 - Uses the setting for validating rooms renaming - closes #2297
 
-## 0.19.0, 2016-Feb-22
+## 0.19.0 - 2016-Feb-22
 
 - Add alerts for highlight words
 - Add button to show offline users in a room
@@ -1143,7 +1301,7 @@
 - Split CA cert into array of strings.
 - Switched CAS configuration from Meteor.settings to RocketChat.settings.
 
-## 0.18.0, 2016-Feb-15
+## 0.18.0 - 2016-Feb-15
 
 - Add .jshintrc to project
 - Add button to test desktop notifications
@@ -1168,7 +1326,7 @@
 - Terminal output should be displayed in LTR always
 - Using REST to send pushes through gateway
 
-## 0.17.0, 2016-Feb-09
+## 0.17.0 - 2016-Feb-09
 
 - Add a button to allow deleting an uploaded file
 - Add an example of how to send logs from server to client
@@ -1203,7 +1361,7 @@
 - Show that server is running on logs
 - Use the RocketChat.Info.version on headers
 
-## 0.16.0, 2016-Feb-01
+## 0.16.0 - 2016-Feb-01
 
 - Add option for admin to require user to change password
 - Add option for admins to manually add new users
@@ -1218,7 +1376,7 @@
 - Show "Room not Found" correctly
 - Update konecty:multiple-instances-status to 1.0.5
 
-## 0.15.0, 2016-Jan-25
+## 0.15.0 - 2016-Jan-25
 
 - Ability to change email on account
 - Add "Default Domain" to LDAP config
@@ -1239,7 +1397,7 @@
 - Outgoing: Get the room from posted message to reply
 - Temporary fix for AM/PM timestamp breaking cog
 
-## 0.14.0, 2016-Jan-18
+## 0.14.0 - 2016-Jan-18
 
 - Add admin setting to Force SSL
 - Add connections status bar to login page
@@ -1288,7 +1446,7 @@
 - Using default values instead of integration data
 - Using processWebhookMessage on V1 APIs
 
-## 0.13.0, 2016-Jan-11
+## 0.13.0 - 2016-Jan-11
 
 - Add api `chat.messageExample`
 - Add apis 'integrations.create' and 'integrations.remove'
@@ -1330,11 +1488,11 @@
 - Update log.coffee
 - Use different ids for members info and user info tabbars
 
-## 0.12.1, 2016-Jan-05
+## 0.12.1 - 2016-Jan-05
 
 - Fix problem with middleware that tries to parse json body
 
-## 0.12.0, 2016-Jan-04
+## 0.12.0 - 2016-Jan-04
 
 - Add a setting to disable form-based login
 - Add request debug messages
@@ -1352,7 +1510,7 @@
 - Try to parse all request bodies as JSON
 - Upload build artifacts to GitHub and sign tgz for docker images
 
-## 0.11.0, 2015-Dec-28
+## 0.11.0 - 2015-Dec-28
 
 - Add "Jump to" and infinite scroll to message search results
 - Add infinite scroll to files list
@@ -1395,15 +1553,15 @@
 - Turn channel and triggerWords optional in triggers
 - Using branding image from main APP
 
-## 0.10.2, 2015-Dec-22
+## 0.10.2 - 2015-Dec-22
 
 - Fixes image preview bugs with filenames containing spaces
 
-## 0.10.1, 2015-Dec-21
+## 0.10.1 - 2015-Dec-21
 
 - Fix upload permissions introduced in raik:ufs 0.3.4
 
-## 0.10.0, 2015-Dec-21
+## 0.10.0 - 2015-Dec-21
 
 - Accept property *msg* as text in attachments
 - Add "Room has been deleted" entry
@@ -1503,7 +1661,7 @@
 - Use attachments to render preview of uploads and use relative paths
 - Using flow-router group routes
 
-## 0.9.0, 2015-Dec-14
+## 0.9.0 - 2015-Dec-14
 
 - Add a new setting type "action" to call server methods
 - Add lib clipboard.js
@@ -1545,7 +1703,7 @@
 - Prompt users to install extentions to enable screen sharing
 - Shos if message is from bot and never render compact message version
 
-## 0.8.0, 2015-Dec-8
+## 0.8.0 - 2015-Dec-8
 
 - Add "Meiryo UI" to font-family
 - Add option to disable "Forgot Password" link on login page
@@ -1576,6 +1734,6 @@
 - Translate section of settings
 - Update the flex-nav hidden element for RTL
 
-## 0.1.0, 2015-May-19
+## 0.1.0 - 2015-May-19
 
 - Initial public launch
diff --git a/README.md b/README.md
index 2301f956ac32983d4abb080310525786779b8e81..7d974a5e5b97a248cff83b528d7e6b7e0d575e94 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,7 @@
 
 [![Rocket.Chat](https://demo.rocket.chat/images/join-chat.svg)](https://demo.rocket.chat/)
 [![Build Status](https://img.shields.io/travis/RocketChat/Rocket.Chat/master.svg)](https://travis-ci.org/RocketChat/Rocket.Chat)
+[![Project Dependencies](https://david-dm.org/RocketChat/Rocket.Chat.svg)](https://david-dm.org/RocketChat/Rocket.Chat)
 [![Codacy Badge](https://api.codacy.com/project/badge/grade/8580571ba024426d9649e9ab389bd5dd)](https://www.codacy.com/app/RocketChat/Rocket-Chat)
 [![Coverage Status](https://coveralls.io/repos/RocketChat/Rocket.Chat/badge.svg)](https://coveralls.io/r/RocketChat/Rocket.Chat)
 [![Code Climate](https://codeclimate.com/github/RocketChat/Rocket.Chat/badges/gpa.svg)](https://codeclimate.com/github/RocketChat/Rocket.Chat)
diff --git a/README.nitrous.md b/README.nitrous.md
deleted file mode 100644
index 99ffe29084aa1918b55a297a280509829751ba4f..0000000000000000000000000000000000000000
--- a/README.nitrous.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# Setup
-
-Welcome to your Rocket.Chat project on Nitrous.
-
-## Running the development server:
-
-In the [Nitrous IDE](https://community.nitrous.io/docs/ide-overview), enter the following commands in the terminal window:
-
-1. `cd ~/code/Rocket.Chat`
-2. `meteor --port 0.0.0.0:3000`
-
-Now you've got a development server running and can see the output in the Nitrous terminal window. You can open up a new shell or utilize [tmux](https://community.nitrous.io/docs/tmux) to open new shells to run other commands.
-
-## Preview the app
-
-In the Nitrous IDE, open the "Preview" menu and click "Port 3000".
diff --git a/app.json b/app.json
index 2b703091f2a23a3326fc4d6f68a8c871164413d7..e4d3a3c577c562eaec88687bb9ff1417bc3589ba 100644
--- a/app.json
+++ b/app.json
@@ -6,7 +6,7 @@
   "keywords": ["meteor", "social", "community", "chat"],
   "website": "https://rocket.chat",
   "env": {
-    "BUILDPACK_URL": "https://github.com/RocketChat/heroku-buildpack-meteor.git",
+    "BUILDPACK_URL": "https://github.com/RocketChat/meteor-buildpack-horse.git",
     "HEROKU_APP_NAME": {
       "description": "Please re-enter your App Name from the top.",
       "required": true
diff --git a/client/helpers/log.coffee b/client/helpers/log.coffee
deleted file mode 100644
index bc6666749306cd453967c769bdcc405499b14105..0000000000000000000000000000000000000000
--- a/client/helpers/log.coffee
+++ /dev/null
@@ -1,2 +0,0 @@
-Template.registerHelper 'log', ->
-	console.log.apply console, arguments
diff --git a/client/helpers/log.js b/client/helpers/log.js
new file mode 100644
index 0000000000000000000000000000000000000000..0c6ee1e3c000063941a032fa515b305f78e21ba5
--- /dev/null
+++ b/client/helpers/log.js
@@ -0,0 +1,3 @@
+Template.registerHelper('log', () => {
+	console.log.apply(console, arguments);
+});
diff --git a/client/helpers/not.js b/client/helpers/not.js
new file mode 100644
index 0000000000000000000000000000000000000000..91b4e19a3c86403181d72f49b23a6c73d904782d
--- /dev/null
+++ b/client/helpers/not.js
@@ -0,0 +1,3 @@
+Template.registerHelper('not', (value) => {
+	return !value;
+});
diff --git a/client/methods/deleteMessage.coffee b/client/methods/deleteMessage.coffee
deleted file mode 100644
index fc2dc6f57747feb051ec215462ae4ee5b7881d3f..0000000000000000000000000000000000000000
--- a/client/methods/deleteMessage.coffee
+++ /dev/null
@@ -1,27 +0,0 @@
-import moment from 'moment'
-import toastr from 'toastr'
-
-Meteor.methods
-	deleteMessage: (message) ->
-		if not Meteor.userId()
-			return false
-
-		hasPermission = RocketChat.authz.hasAtLeastOnePermission('delete-message', message.rid)
-		deleteAllowed = RocketChat.settings.get 'Message_AllowDeleting'
-		deleteOwn = message?.u?._id is Meteor.userId()
-
-		unless hasPermission or (deleteAllowed and deleteOwn)
-			return false
-
-		blockDeleteInMinutes = RocketChat.settings.get 'Message_AllowDeleting_BlockDeleteInMinutes'
-		if blockDeleteInMinutes? and blockDeleteInMinutes isnt 0
-			msgTs = moment(message.ts) if message.ts?
-			currentTsDiff = moment().diff(msgTs, 'minutes') if msgTs?
-			if currentTsDiff > blockDeleteInMinutes
-				toastr.error t('error-message-deleting-blocked')
-				return false
-
-		Tracker.nonreactive ->
-			ChatMessage.remove
-				_id: message._id
-				'u._id': Meteor.userId()
diff --git a/client/methods/deleteMessage.js b/client/methods/deleteMessage.js
new file mode 100644
index 0000000000000000000000000000000000000000..2f77e1d825cf82e9fed9153f29b6278e06020b0a
--- /dev/null
+++ b/client/methods/deleteMessage.js
@@ -0,0 +1,42 @@
+import moment from 'moment';
+import toastr from 'toastr';
+
+Meteor.methods({
+	deleteMessage(message) {
+		if (!Meteor.userId()) {
+			return false;
+		}
+
+		const hasPermission = RocketChat.authz.hasAtLeastOnePermission('delete-message', message.rid);
+		const deleteAllowed = RocketChat.settings.get('Message_AllowDeleting');
+		let deleteOwn = false;
+		if (message && message.u && message.u._id) {
+			deleteOwn = message.u._id === Meteor.userId();
+		}
+
+		if (!(hasPermission || (deleteAllowed && deleteOwn))) {
+			return false;
+		}
+
+		const blockDeleteInMinutes = RocketChat.settings.get('Message_AllowDeleting_BlockDeleteInMinutes');
+		if (_.isNumber(blockDeleteInMinutes) && blockDeleteInMinutes !== 0) {
+			if (message.ts) {
+				const msgTs = moment(message.ts);
+				if (msgTs) {
+					const currentTsDiff = moment().diff(msgTs, 'minutes');
+					if (currentTsDiff > blockDeleteInMinutes) {
+						toastr.error(t('error-message-deleting-blocked'));
+						return false;
+					}
+				}
+			}
+		}
+
+		Tracker.nonreactive(function() {
+			ChatMessage.remove({
+				_id: message._id,
+				'u._id': Meteor.userId()
+			});
+		});
+	}
+});
diff --git a/client/methods/hideRoom.coffee b/client/methods/hideRoom.coffee
deleted file mode 100644
index 09ea75739572981a49b4a58b1cc2b34b66296741..0000000000000000000000000000000000000000
--- a/client/methods/hideRoom.coffee
+++ /dev/null
@@ -1,12 +0,0 @@
-Meteor.methods
-	hideRoom: (rid) ->
-		if not Meteor.userId()
-			return false
-
-		ChatSubscription.update
-			rid: rid
-			'u._id': Meteor.userId()
-		,
-			$set:
-				alert: false
-				open: false
diff --git a/client/methods/hideRoom.js b/client/methods/hideRoom.js
new file mode 100644
index 0000000000000000000000000000000000000000..801f464e420b7d21950b53f3bd18eca15a26997d
--- /dev/null
+++ b/client/methods/hideRoom.js
@@ -0,0 +1,17 @@
+Meteor.methods({
+	hideRoom(rid) {
+		if (!Meteor.userId()) {
+			return false;
+		}
+
+		ChatSubscription.update({
+			rid: rid,
+			'u._id': Meteor.userId()
+		}, {
+			$set: {
+				alert: false,
+				open: false
+			}
+		});
+	}
+});
diff --git a/client/methods/leaveRoom.coffee b/client/methods/leaveRoom.coffee
deleted file mode 100644
index b9877543838f572f4b4311416c6898e7f0e407b4..0000000000000000000000000000000000000000
--- a/client/methods/leaveRoom.coffee
+++ /dev/null
@@ -1,13 +0,0 @@
-Meteor.methods
-	leaveRoom: (rid) ->
-		if not Meteor.userId()
-			return false
-
-		ChatSubscription.remove
-			rid: rid
-			'u._id': Meteor.userId()
-
-		ChatRoom.update rid,
-			$pull:
-				usernames: Meteor.user().username
-
diff --git a/client/methods/leaveRoom.js b/client/methods/leaveRoom.js
new file mode 100644
index 0000000000000000000000000000000000000000..8de1d369484975ed291f2c68f8751a310180aa19
--- /dev/null
+++ b/client/methods/leaveRoom.js
@@ -0,0 +1,18 @@
+Meteor.methods({
+	leaveRoom(rid) {
+		if (!Meteor.userId()) {
+			return false;
+		}
+
+		ChatSubscription.remove({
+			rid: rid,
+			'u._id': Meteor.userId()
+		});
+
+		ChatRoom.update(rid, {
+			$pull: {
+				usernames: Meteor.user().username
+			}
+		});
+	}
+});
diff --git a/client/methods/openRoom.coffee b/client/methods/openRoom.coffee
deleted file mode 100644
index bb40b2bdbf3a0ef0e322f84532254202e5b9ca48..0000000000000000000000000000000000000000
--- a/client/methods/openRoom.coffee
+++ /dev/null
@@ -1,11 +0,0 @@
-Meteor.methods
-  openRoom: (rid) ->
-    if not Meteor.userId()
-      return false
-
-    ChatSubscription.update
-      rid: rid
-      'u._id': Meteor.userId()
-    ,
-      $set:
-        open: true
diff --git a/client/methods/openRoom.js b/client/methods/openRoom.js
new file mode 100644
index 0000000000000000000000000000000000000000..9aa659e937b87b8c6c4a336a96e63f87599f8558
--- /dev/null
+++ b/client/methods/openRoom.js
@@ -0,0 +1,16 @@
+Meteor.methods({
+	openRoom(rid) {
+		if (!Meteor.userId()) {
+			return false;
+		}
+
+		ChatSubscription.update({
+			rid: rid,
+			'u._id': Meteor.userId()
+		}, {
+			$set: {
+				open: true
+			}
+		});
+	}
+});
diff --git a/client/methods/setUserActiveStatus.coffee b/client/methods/setUserActiveStatus.coffee
deleted file mode 100644
index ac4c9614e43a6ccc9f20126642070e238c3d6ab3..0000000000000000000000000000000000000000
--- a/client/methods/setUserActiveStatus.coffee
+++ /dev/null
@@ -1,4 +0,0 @@
-Meteor.methods
-	setUserActiveStatus: (userId, active) ->
-		Meteor.users.update userId, { $set: { active: active } }
-		return true
\ No newline at end of file
diff --git a/client/methods/setUserActiveStatus.js b/client/methods/setUserActiveStatus.js
new file mode 100644
index 0000000000000000000000000000000000000000..d61598877df422076d017fe2326bd3cb9990497b
--- /dev/null
+++ b/client/methods/setUserActiveStatus.js
@@ -0,0 +1,6 @@
+Meteor.methods({
+	setUserActiveStatus(userId, active) {
+		Meteor.users.update(userId, { $set: { active: active } });
+		return true;
+	}
+});
diff --git a/client/methods/toggleFavorite.coffee b/client/methods/toggleFavorite.coffee
deleted file mode 100644
index 6348bc9cd536d7600211a043f7dce92b39971c8d..0000000000000000000000000000000000000000
--- a/client/methods/toggleFavorite.coffee
+++ /dev/null
@@ -1,11 +0,0 @@
-Meteor.methods
-	toggleFavorite: (rid, f) ->
-		if not Meteor.userId()
-			return false
-
-		ChatSubscription.update
-			rid: rid
-			'u._id': Meteor.userId()
-		,
-			$set:
-				f: f
diff --git a/client/methods/toggleFavorite.js b/client/methods/toggleFavorite.js
new file mode 100644
index 0000000000000000000000000000000000000000..e58b8eb71c0a084d9ceb2b5cdd06f509e6363baa
--- /dev/null
+++ b/client/methods/toggleFavorite.js
@@ -0,0 +1,16 @@
+Meteor.methods({
+	toggleFavorite(rid, f) {
+		if (!Meteor.userId()) {
+			return false;
+		}
+
+		ChatSubscription.update({
+			rid: rid,
+			'u._id': Meteor.userId()
+		}, {
+			$set: {
+				f: f
+			}
+		});
+	}
+});
diff --git a/client/methods/updateMessage.coffee b/client/methods/updateMessage.coffee
deleted file mode 100644
index f9a8cb9139a6ade3f42d2b853f900fd528939238..0000000000000000000000000000000000000000
--- a/client/methods/updateMessage.coffee
+++ /dev/null
@@ -1,49 +0,0 @@
-import moment from 'moment'
-import toastr from 'toastr'
-
-Meteor.methods
-	updateMessage: (message) ->
-		if not Meteor.userId()
-			return false
-
-		originalMessage = ChatMessage.findOne message._id
-
-		hasPermission = RocketChat.authz.hasAtLeastOnePermission('edit-message', message.rid)
-		editAllowed = RocketChat.settings.get 'Message_AllowEditing'
-		editOwn = originalMessage?.u?._id is Meteor.userId()
-
-		me = Meteor.users.findOne Meteor.userId()
-
-		unless hasPermission or (editAllowed and editOwn)
-			toastr.error t('error-action-not-allowed', { action: t('Message_editing') })
-			return false
-
-		blockEditInMinutes = RocketChat.settings.get 'Message_AllowEditing_BlockEditInMinutes'
-		if blockEditInMinutes? and blockEditInMinutes isnt 0
-			msgTs = moment(originalMessage.ts) if originalMessage.ts?
-			currentTsDiff = moment().diff(msgTs, 'minutes') if msgTs?
-			if currentTsDiff > blockEditInMinutes
-				toastr.error t('error-message-editing-blocked')
-				return false
-
-		Tracker.nonreactive ->
-
-			if isNaN(TimeSync.serverOffset())
-				message.editedAt = new Date()
-			else
-				message.editedAt = new Date(Date.now() + TimeSync.serverOffset())
-
-			message.editedBy =
-				_id: Meteor.userId()
-				username: me.username
-
-			message = RocketChat.callbacks.run 'beforeSaveMessage', message
-
-			ChatMessage.update
-				_id: message._id
-				'u._id': Meteor.userId()
-			,
-				$set:
-					"editedAt": message.editedAt
-					"editedBy": message.editedBy
-					msg: message.msg
diff --git a/client/methods/updateMessage.js b/client/methods/updateMessage.js
new file mode 100644
index 0000000000000000000000000000000000000000..2f5a5d87c05529bb2d774aacb283051db2344f74
--- /dev/null
+++ b/client/methods/updateMessage.js
@@ -0,0 +1,67 @@
+import moment from 'moment';
+import toastr from 'toastr';
+
+Meteor.methods({
+	updateMessage(message) {
+		if (!Meteor.userId()) {
+			return false;
+		}
+
+		const originalMessage = ChatMessage.findOne(message._id);
+
+		const hasPermission = RocketChat.authz.hasAtLeastOnePermission('edit-message', message.rid);
+		const editAllowed = RocketChat.settings.get('Message_AllowEditing');
+		let editOwn = false;
+		if (originalMessage && originalMessage.u && originalMessage.u._id) {
+			editOwn = originalMessage.u._id === Meteor.userId();
+		}
+
+		const me = Meteor.users.findOne(Meteor.userId());
+
+		if (!(hasPermission || (editAllowed && editOwn))) {
+			toastr.error(t('error-action-not-allowed', { action: t('Message_editing') }));
+			return false;
+		}
+
+		const blockEditInMinutes = RocketChat.settings.get('Message_AllowEditing_BlockEditInMinutes');
+		if (_.isNumber(blockEditInMinutes) && blockEditInMinutes !== 0) {
+			if (originalMessage.ts) {
+				const msgTs = moment(originalMessage.ts);
+				if (msgTs) {
+					const currentTsDiff = moment().diff(msgTs, 'minutes');
+					if (currentTsDiff > blockEditInMinutes) {
+						toastr.error(t('error-message-editing-blocked'));
+						return false;
+					}
+				}
+			}
+		}
+
+		Tracker.nonreactive(function() {
+
+			if (isNaN(TimeSync.serverOffset())) {
+				message.editedAt = new Date();
+			} else {
+				message.editedAt = new Date(Date.now() + TimeSync.serverOffset());
+			}
+
+			message.editedBy = {
+				_id: Meteor.userId(),
+				username: me.username
+			};
+
+			message = RocketChat.callbacks.run('beforeSaveMessage', message);
+
+			ChatMessage.update({
+				_id: message._id,
+				'u._id': Meteor.userId()
+			}, {
+				$set: {
+					'editedAt': message.editedAt,
+					'editedBy': message.editedBy,
+					msg: message.msg
+				}
+			});
+		});
+	}
+});
diff --git a/client/notifications/notification.coffee b/client/notifications/notification.coffee
deleted file mode 100644
index a041691a38019c3f5ec9afcf850473d5446cf09c..0000000000000000000000000000000000000000
--- a/client/notifications/notification.coffee
+++ /dev/null
@@ -1,31 +0,0 @@
-# Show notifications and play a sound for new messages.
-# We trust the server to only send notifications for interesting messages, e.g. direct messages or
-# group messages in which the user is mentioned.
-
-Meteor.startup ->
-	Tracker.autorun ->
-		if Meteor.userId()
-			RocketChat.Notifications.onUser 'notification', (notification) ->
-
-				openedRoomId = undefined
-				if FlowRouter.getRouteName() in ['channel', 'group', 'direct']
-					openedRoomId = Session.get 'openedRoom'
-
-				# This logic is duplicated in /client/startup/unread.coffee.
-				hasFocus = readMessage.isEnable()
-				messageIsInOpenedRoom = openedRoomId is notification.payload.rid
-
-				fireGlobalEvent 'notification',
-					notification: notification
-					fromOpenedRoom: messageIsInOpenedRoom
-					hasFocus: hasFocus
-
-				if RocketChat.Layout.isEmbedded()
-					if !hasFocus and messageIsInOpenedRoom
-						# Play a sound and show a notification.
-						KonchatNotification.newMessage()
-						KonchatNotification.showDesktop notification
-				else if !(hasFocus and messageIsInOpenedRoom)
-					# Play a sound and show a notification.
-					KonchatNotification.newMessage()
-					KonchatNotification.showDesktop notification
diff --git a/client/notifications/notification.js b/client/notifications/notification.js
new file mode 100644
index 0000000000000000000000000000000000000000..15cfa755f2de019f7fac8f42fb3323255332a3dc
--- /dev/null
+++ b/client/notifications/notification.js
@@ -0,0 +1,41 @@
+/* globals KonchatNotification, fireGlobalEvent, readMessage */
+
+// Show notifications and play a sound for new messages.
+// We trust the server to only send notifications for interesting messages, e.g. direct messages or
+// group messages in which the user is mentioned.
+
+Meteor.startup(function() {
+	Tracker.autorun(function() {
+		if (Meteor.userId()) {
+			RocketChat.Notifications.onUser('notification', function(notification) {
+
+				let openedRoomId = undefined;
+				if (['channel', 'group', 'direct'].includes(FlowRouter.getRouteName())) {
+					openedRoomId = Session.get('openedRoom');
+				}
+
+				// This logic is duplicated in /client/startup/unread.coffee.
+				const hasFocus = readMessage.isEnable();
+				const messageIsInOpenedRoom = openedRoomId === notification.payload.rid;
+
+				fireGlobalEvent('notification', {
+					notification: notification,
+					fromOpenedRoom: messageIsInOpenedRoom,
+					hasFocus: hasFocus
+				});
+
+				if (RocketChat.Layout.isEmbedded()) {
+					if (!hasFocus && messageIsInOpenedRoom) {
+						// Play a sound and show a notification.
+						KonchatNotification.newMessage();
+						KonchatNotification.showDesktop(notification);
+					}
+				} else if (!(hasFocus && messageIsInOpenedRoom)) {
+					// Play a sound and show a notification.
+					KonchatNotification.newMessage();
+					KonchatNotification.showDesktop(notification);
+				}
+			});
+		}
+	});
+});
diff --git a/client/notifications/updateAvatar.coffee b/client/notifications/updateAvatar.coffee
deleted file mode 100644
index fc63c7b1a9723baf422d0221f55bac199e39ac04..0000000000000000000000000000000000000000
--- a/client/notifications/updateAvatar.coffee
+++ /dev/null
@@ -1,3 +0,0 @@
-Meteor.startup ->
-	RocketChat.Notifications.onAll 'updateAvatar', (data) ->
-		updateAvatarOfUsername data.username
diff --git a/client/notifications/updateAvatar.js b/client/notifications/updateAvatar.js
new file mode 100644
index 0000000000000000000000000000000000000000..b534f3956318eff9724d2a2fc3ed6f5a46e4b8ce
--- /dev/null
+++ b/client/notifications/updateAvatar.js
@@ -0,0 +1,7 @@
+/* globals updateAvatarOfUsername */
+
+Meteor.startup(function() {
+	RocketChat.Notifications.onAll('updateAvatar', function(data) {
+		updateAvatarOfUsername(data.username);
+	});
+});
diff --git a/client/routes/adminRouter.coffee b/client/routes/adminRouter.coffee
deleted file mode 100644
index c528ebba2175f5397a3a8f260d5c19dde13d4571..0000000000000000000000000000000000000000
--- a/client/routes/adminRouter.coffee
+++ /dev/null
@@ -1,38 +0,0 @@
-FlowRouter.route '/admin/users',
-	name: 'admin-users'
-	action: ->
-		RocketChat.TabBar.showGroup 'adminusers'
-		BlazeLayout.render 'main', {center: 'adminUsers'}
-
-FlowRouter.route '/admin/rooms',
-	name: 'admin-rooms'
-	action: ->
-		RocketChat.TabBar.showGroup 'adminrooms'
-		BlazeLayout.render 'main', {center: 'adminRooms'}
-
-FlowRouter.route '/admin/info',
-	name: 'admin-info'
-	action: ->
-		RocketChat.TabBar.showGroup 'adminInfo'
-		BlazeLayout.render 'main', {center: 'adminInfo'}
-
-FlowRouter.route '/admin/import',
-	name: 'admin-import'
-	action: ->
-		BlazeLayout.render 'main', {center: 'adminImport'}
-
-FlowRouter.route '/admin/import/prepare/:importer',
-	name: 'admin-import-prepare'
-	action: ->
-		BlazeLayout.render 'main', {center: 'adminImportPrepare'}
-
-FlowRouter.route '/admin/import/progress/:importer',
-	name: 'admin-import-progress'
-	action: ->
-		BlazeLayout.render 'main', {center: 'adminImportProgress'}
-
-FlowRouter.route '/admin/:group?',
-	name: 'admin'
-	action: ->
-		RocketChat.TabBar.showGroup 'admin'
-		BlazeLayout.render 'main', {center: 'admin'}
diff --git a/client/routes/adminRouter.js b/client/routes/adminRouter.js
new file mode 100644
index 0000000000000000000000000000000000000000..bc89c6b2104caae1cfb522ce5a5808a1646c6304
--- /dev/null
+++ b/client/routes/adminRouter.js
@@ -0,0 +1,52 @@
+FlowRouter.route('/admin/users', {
+	name: 'admin-users',
+	action() {
+		RocketChat.TabBar.showGroup('adminusers');
+		BlazeLayout.render('main', {center: 'adminUsers'});
+	}
+});
+
+FlowRouter.route('/admin/rooms', {
+	name: 'admin-rooms',
+	action() {
+		RocketChat.TabBar.showGroup('adminrooms');
+		BlazeLayout.render('main', {center: 'adminRooms'});
+	}
+});
+
+FlowRouter.route('/admin/info', {
+	name: 'admin-info',
+	action() {
+		RocketChat.TabBar.showGroup('adminInfo');
+		BlazeLayout.render('main', {center: 'adminInfo'});
+	}
+});
+
+FlowRouter.route('/admin/import', {
+	name: 'admin-import',
+	action() {
+		BlazeLayout.render('main', {center: 'adminImport'});
+	}
+});
+
+FlowRouter.route('/admin/import/prepare/:importer', {
+	name: 'admin-import-prepare',
+	action() {
+		BlazeLayout.render('main', {center: 'adminImportPrepare'});
+	}
+});
+
+FlowRouter.route('/admin/import/progress/:importer', {
+	name: 'admin-import-progress',
+	action() {
+		BlazeLayout.render('main', {center: 'adminImportProgress'});
+	}
+});
+
+FlowRouter.route('/admin/:group?', {
+	name: 'admin',
+	action() {
+		RocketChat.TabBar.showGroup('admin');
+		BlazeLayout.render('main', {center: 'admin'});
+	}
+});
diff --git a/client/routes/roomRoute.js b/client/routes/roomRoute.js
index f3a067f0a6fce606d486437d6c4fff1118429aaa..f77e4d9b70bad989411dce080c9482348c5e01bb 100644
--- a/client/routes/roomRoute.js
+++ b/client/routes/roomRoute.js
@@ -1,6 +1,6 @@
 FlowRouter.goToRoomById = (roomId) => {
 	const subscription = ChatSubscription.findOne({rid: roomId});
 	if (subscription) {
-		FlowRouter.go(RocketChat.roomTypes.getRouteLink(subscription.t, subscription), null, FlowRouter.current().queryParams);
+		RocketChat.roomTypes.openRouteLink(subscription.t, subscription, FlowRouter.current().queryParams);
 	}
 };
diff --git a/client/routes/router.coffee b/client/routes/router.coffee
deleted file mode 100644
index ec68173e0fe86e936243af1bc7cad24ed7b67df8..0000000000000000000000000000000000000000
--- a/client/routes/router.coffee
+++ /dev/null
@@ -1,119 +0,0 @@
-Blaze.registerHelper 'pathFor', (path, kw) ->
-	return FlowRouter.path path, kw.hash
-
-BlazeLayout.setRoot 'body'
-
-FlowRouter.subscriptions = ->
-	Tracker.autorun =>
-		if Meteor.userId()
-			@register 'userData', Meteor.subscribe('userData')
-			@register 'activeUsers', Meteor.subscribe('activeUsers')
-
-
-FlowRouter.route '/',
-	name: 'index'
-
-	action: ->
-		BlazeLayout.render 'main', { modal: RocketChat.Layout.isEmbedded(), center: 'loading' }
-		if not Meteor.userId()
-			return FlowRouter.go 'home'
-
-		Tracker.autorun (c) ->
-			if FlowRouter.subsReady() is true
-				Meteor.defer ->
-					if Meteor.user().defaultRoom?
-						room = Meteor.user().defaultRoom.split('/')
-						FlowRouter.go room[0], { name: room[1] }, FlowRouter.current().queryParams
-					else
-						FlowRouter.go 'home'
-				c.stop()
-
-
-FlowRouter.route '/login',
-	name: 'login'
-
-	action: ->
-		FlowRouter.go 'home'
-
-
-FlowRouter.route '/home',
-	name: 'home'
-
-	action: ->
-		RocketChat.TabBar.showGroup 'home'
-		BlazeLayout.render 'main', {center: 'home'}
-		KonchatNotification.getDesktopPermission()
-
-
-FlowRouter.route '/changeavatar',
-	name: 'changeAvatar'
-
-	action: ->
-		RocketChat.TabBar.showGroup 'changeavatar'
-		BlazeLayout.render 'main', {center: 'avatarPrompt'}
-
-FlowRouter.route '/account/:group?',
-	name: 'account'
-
-	action: (params) ->
-		unless params.group
-			params.group = 'Preferences'
-		params.group = _.capitalize params.group, true
-		RocketChat.TabBar.showGroup 'account'
-		BlazeLayout.render 'main', { center: "account#{params.group}" }
-
-
-FlowRouter.route '/history/private',
-	name: 'privateHistory'
-
-	subscriptions: (params, queryParams) ->
-		@register 'privateHistory', Meteor.subscribe('privateHistory')
-
-	action: ->
-		Session.setDefault('historyFilter', '')
-		RocketChat.TabBar.showGroup 'private-history'
-		BlazeLayout.render 'main', {center: 'privateHistory'}
-
-
-FlowRouter.route '/terms-of-service',
-	name: 'terms-of-service'
-
-	action: ->
-		Session.set 'cmsPage', 'Layout_Terms_of_Service'
-		BlazeLayout.render 'cmsPage'
-
-FlowRouter.route '/privacy-policy',
-	name: 'privacy-policy'
-
-	action: ->
-		Session.set 'cmsPage', 'Layout_Privacy_Policy'
-		BlazeLayout.render 'cmsPage'
-
-FlowRouter.route '/room-not-found/:type/:name',
-	name: 'room-not-found'
-
-	action: (params) ->
-		Session.set 'roomNotFound', {type: params.type, name: params.name}
-		BlazeLayout.render 'main', {center: 'roomNotFound'}
-
-FlowRouter.route '/fxos',
-	name: 'firefox-os-install'
-
-	action: ->
-		BlazeLayout.render 'fxOsInstallPrompt'
-
-FlowRouter.route '/register/:hash',
-	name: 'register-secret-url'
-	action: (params) ->
-		BlazeLayout.render 'secretURL'
-
-		# if RocketChat.settings.get('Accounts_RegistrationForm') is 'Secret URL'
-		# 	Meteor.call 'checkRegistrationSecretURL', params.hash, (err, success) ->
-		# 		if success
-		# 			Session.set 'loginDefaultState', 'register'
-		# 			BlazeLayout.render 'main', {center: 'home'}
-		# 			KonchatNotification.getDesktopPermission()
-		# 		else
-		# 			BlazeLayout.render 'logoLayout', { render: 'invalidSecretURL' }
-		# else
-		# 	BlazeLayout.render 'logoLayout', { render: 'invalidSecretURL' }
diff --git a/client/routes/router.js b/client/routes/router.js
new file mode 100644
index 0000000000000000000000000000000000000000..d2ee08c861d2d437af6d129d20a627675af56661
--- /dev/null
+++ b/client/routes/router.js
@@ -0,0 +1,160 @@
+/* globals KonchatNotification */
+
+Blaze.registerHelper('pathFor', function(path, kw) {
+	return FlowRouter.path(path, kw.hash);
+});
+
+BlazeLayout.setRoot('body');
+
+FlowRouter.subscriptions = function() {
+	Tracker.autorun(() => {
+		if (Meteor.userId()) {
+			this.register('userData', Meteor.subscribe('userData'));
+			this.register('activeUsers', Meteor.subscribe('activeUsers'));
+		}
+	});
+};
+
+
+FlowRouter.route('/', {
+	name: 'index',
+	action() {
+		BlazeLayout.render('main', { modal: RocketChat.Layout.isEmbedded(), center: 'loading' });
+		if (!Meteor.userId()) {
+			return FlowRouter.go('home');
+		}
+
+		Tracker.autorun(function(c) {
+			if (FlowRouter.subsReady() === true) {
+				Meteor.defer(function() {
+					if (Meteor.user().defaultRoom) {
+						const room = Meteor.user().defaultRoom.split('/');
+						FlowRouter.go(room[0], { name: room[1] }, FlowRouter.current().queryParams);
+					} else {
+						FlowRouter.go('home');
+					}
+				});
+				c.stop();
+			}
+		});
+	}
+});
+
+
+FlowRouter.route('/login', {
+	name: 'login',
+
+	action() {
+		FlowRouter.go('home');
+	}
+});
+
+FlowRouter.route('/home', {
+	name: 'home',
+
+	action(params, queryParams) {
+		RocketChat.TabBar.showGroup('home');
+		KonchatNotification.getDesktopPermission();
+		if (queryParams.saml_idp_credentialToken !== undefined) {
+			Accounts.callLoginMethod({
+				methodArguments: [{
+					saml: true,
+					credentialToken: queryParams.saml_idp_credentialToken
+				}],
+				userCallback: function() { BlazeLayout.render('main', {center: 'home'}); }
+			});
+		} else {
+			BlazeLayout.render('main', {center: 'home'});
+		}
+	}
+});
+
+FlowRouter.route('/changeavatar', {
+	name: 'changeAvatar',
+
+	action() {
+		RocketChat.TabBar.showGroup('changeavatar');
+		BlazeLayout.render('main', {center: 'avatarPrompt'});
+	}
+});
+
+FlowRouter.route('/account/:group?', {
+	name: 'account',
+
+	action(params) {
+		if (!params.group) {
+			params.group = 'Preferences';
+		}
+		params.group = _.capitalize(params.group, true);
+		RocketChat.TabBar.showGroup('account');
+		BlazeLayout.render('main', { center: `account${params.group}` });
+	}
+});
+
+FlowRouter.route('/history/private', {
+	name: 'privateHistory',
+
+	subscriptions(/*params, queryParams*/) {
+		this.register('privateHistory', Meteor.subscribe('privateHistory'));
+	},
+
+	action() {
+		Session.setDefault('historyFilter', '');
+		RocketChat.TabBar.showGroup('private-history');
+		BlazeLayout.render('main', {center: 'privateHistory'});
+	}
+});
+
+FlowRouter.route('/terms-of-service', {
+	name: 'terms-of-service',
+
+	action() {
+		Session.set('cmsPage', 'Layout_Terms_of_Service');
+		BlazeLayout.render('cmsPage');
+	}
+});
+
+FlowRouter.route('/privacy-policy', {
+	name: 'privacy-policy',
+
+	action() {
+		Session.set('cmsPage', 'Layout_Privacy_Policy');
+		BlazeLayout.render('cmsPage');
+	}
+});
+
+FlowRouter.route('/room-not-found/:type/:name', {
+	name: 'room-not-found',
+
+	action(params) {
+		Session.set('roomNotFound', {type: params.type, name: params.name});
+		BlazeLayout.render('main', {center: 'roomNotFound'});
+	}
+});
+
+FlowRouter.route('/fxos', {
+	name: 'firefox-os-install',
+
+	action() {
+		BlazeLayout.render('fxOsInstallPrompt');
+	}
+});
+
+FlowRouter.route('/register/:hash', {
+	name: 'register-secret-url',
+
+	action(/*params*/) {
+		BlazeLayout.render('secretURL');
+
+		// if RocketChat.settings.get('Accounts_RegistrationForm') is 'Secret URL'
+		// 	Meteor.call 'checkRegistrationSecretURL', params.hash, (err, success) ->
+		// 		if success
+		// 			Session.set 'loginDefaultState', 'register'
+		// 			BlazeLayout.render 'main', {center: 'home'}
+		// 			KonchatNotification.getDesktopPermission()
+		// 		else
+		// 			BlazeLayout.render 'logoLayout', { render: 'invalidSecretURL' }
+		// else
+		// 	BlazeLayout.render 'logoLayout', { render: 'invalidSecretURL' }
+	}
+});
diff --git a/client/startup/roomObserve.coffee b/client/startup/roomObserve.coffee
deleted file mode 100644
index 2cbee3b767af57aeaa249a8536d11be8812ed433..0000000000000000000000000000000000000000
--- a/client/startup/roomObserve.coffee
+++ /dev/null
@@ -1,8 +0,0 @@
-Meteor.startup ->
-	ChatRoom.find().observe
-		added: (data) ->
-			Session.set('roomData' + data._id, data)
-		changed: (data) ->
-			Session.set('roomData' + data._id, data)
-		removed: (data) ->
-			Session.set('roomData' + data._id, undefined)
diff --git a/client/startup/roomObserve.js b/client/startup/roomObserve.js
new file mode 100644
index 0000000000000000000000000000000000000000..ea3222a1fc6ed85f0d188e90e0c225739be85b20
--- /dev/null
+++ b/client/startup/roomObserve.js
@@ -0,0 +1,13 @@
+Meteor.startup(function() {
+	ChatRoom.find().observe({
+		added(data) {
+			Session.set('roomData' + data._id, data);
+		},
+		changed(data) {
+			Session.set('roomData' + data._id, data);
+		},
+		removed(data) {
+			Session.set('roomData' + data._id, undefined);
+		}
+	});
+});
diff --git a/client/startup/startup.coffee b/client/startup/startup.coffee
deleted file mode 100644
index c7c0a16986160b855100cff2cf2919683078e8b2..0000000000000000000000000000000000000000
--- a/client/startup/startup.coffee
+++ /dev/null
@@ -1,69 +0,0 @@
-import moment from 'moment'
-
-Meteor.startup ->
-	TimeSync.loggingEnabled = false
-
-	UserPresence.awayTime = 300000
-	UserPresence.start()
-	Meteor.subscribe("activeUsers")
-
-	Session.setDefault('AvatarRandom', 0)
-
-	window.lastMessageWindow = {}
-	window.lastMessageWindowHistory = {}
-
-	TAPi18n.conf.i18n_files_route = Meteor._relativeToSiteRootUrl('/tap-i18n')
-
-	@defaultAppLanguage = ->
-		lng = window.navigator.userLanguage || window.navigator.language || 'en'
-		# Fix browsers having all-lowercase language settings eg. pt-br, en-us
-		re = /([a-z]{2}-)([a-z]{2})/
-		if re.test lng
-			lng = lng.replace re, (match, parts...) -> return parts[0] + parts[1].toUpperCase()
-		return lng
-
-	@defaultUserLanguage = ->
-		return RocketChat.settings.get('Language') || defaultAppLanguage()
-
-	loadedLanguages = []
-
-	@setLanguage = (language) ->
-		if !language
-			return
-
-		if loadedLanguages.indexOf(language) > -1
-			return
-
-		loadedLanguages.push language
-
-		if isRtl language
-			$('html').addClass "rtl"
-		else
-			$('html').removeClass "rtl"
-
-		language = language.split('-').shift()
-		TAPi18n.setLanguage(language)
-
-		language = language.toLowerCase()
-		if language isnt 'en'
-			Meteor.call 'loadLocale', language, (err, localeFn) ->
-				Function(localeFn).call({moment: moment});
-				moment.locale(language)
-
-	Meteor.subscribe("userData", () ->
-		userLanguage = Meteor.user()?.language
-		userLanguage ?= defaultUserLanguage()
-
-		if localStorage.getItem('userLanguage') isnt userLanguage
-			localStorage.setItem('userLanguage', userLanguage)
-
-		setLanguage userLanguage
-
-		status = undefined
-		Tracker.autorun ->
-			return if not Meteor.userId()
-
-			if Meteor.user()?.status isnt status
-				status = Meteor.user().status
-				fireGlobalEvent('status-changed', status)
-	)
diff --git a/client/startup/startup.js b/client/startup/startup.js
new file mode 100644
index 0000000000000000000000000000000000000000..e2356a29bc03800622d4075c45eb2584bdb46239
--- /dev/null
+++ b/client/startup/startup.js
@@ -0,0 +1,95 @@
+/* globals UserPresence, fireGlobalEvent, isRtl */
+
+import moment from 'moment';
+import toastr from 'toastr';
+
+if (window.DISABLE_ANIMATION) {
+	toastr.options.timeOut = 1;
+	toastr.options.showDuration = 0;
+	toastr.options.hideDuration = 0;
+	toastr.options.extendedTimeOut = 0;
+}
+
+Meteor.startup(function() {
+	TimeSync.loggingEnabled = false;
+
+	UserPresence.awayTime = 300000;
+	UserPresence.start();
+	Meteor.subscribe('activeUsers');
+
+	Session.setDefault('AvatarRandom', 0);
+
+	window.lastMessageWindow = {};
+	window.lastMessageWindowHistory = {};
+
+	TAPi18n.conf.i18n_files_route = Meteor._relativeToSiteRootUrl('/tap-i18n');
+
+	const defaultAppLanguage = function() {
+		let lng = window.navigator.userLanguage || window.navigator.language || 'en';
+		// Fix browsers having all-lowercase language settings eg. pt-br, en-us
+		const re = /([a-z]{2}-)([a-z]{2})/;
+		if (re.test(lng)) {
+			lng = lng.replace(re, (match, ...parts) => {
+				return parts[0] + parts[1].toUpperCase();
+			});
+		}
+		return lng;
+	};
+
+	window.defaultUserLanguage = function() {
+		return RocketChat.settings.get('Language') || defaultAppLanguage();
+	};
+
+	const loadedLanguages = [];
+
+	window.setLanguage = function(language) {
+		if (!language) {
+			return;
+		}
+
+		if (loadedLanguages.indexOf(language) > -1) {
+			return;
+		}
+
+		loadedLanguages.push(language);
+
+		if (isRtl(language)) {
+			$('html').addClass('rtl');
+		} else {
+			$('html').removeClass('rtl');
+		}
+
+		language = language.split('-').shift();
+		TAPi18n.setLanguage(language);
+
+		language = language.toLowerCase();
+		if (language !== 'en') {
+			Meteor.call('loadLocale', language, (err, localeFn) => {
+				Function(localeFn).call({moment: moment});
+				moment.locale(language);
+			});
+		}
+	};
+
+	Meteor.subscribe('userData', function() {
+		const userLanguage = Meteor.user() ? Meteor.user().language : window.defaultUserLanguage();
+
+		if (localStorage.getItem('userLanguage') !== userLanguage) {
+			localStorage.setItem('userLanguage', userLanguage);
+		}
+
+		window.setLanguage(userLanguage);
+
+		let status = undefined;
+		Tracker.autorun(function() {
+			if (!Meteor.userId()) {
+				return;
+			}
+
+			if (Meteor.user() && Meteor.user().status !== status) {
+				status = Meteor.user().status;
+				fireGlobalEvent('status-changed', status);
+			}
+		});
+	});
+});
diff --git a/client/startup/unread.coffee b/client/startup/unread.coffee
deleted file mode 100644
index cca1fd734559360193de6d15596ea104c1588033..0000000000000000000000000000000000000000
--- a/client/startup/unread.coffee
+++ /dev/null
@@ -1,62 +0,0 @@
-Meteor.startup ->
-
-	Tracker.autorun ->
-
-		unreadCount = 0
-		unreadAlert = false
-
-		subscriptions = ChatSubscription.find({open: true}, { fields: { unread: 1, alert: 1, rid: 1, t: 1, name: 1, ls: 1, unreadAlert: 1 } })
-
-		openedRoomId = undefined
-		Tracker.nonreactive ->
-			if FlowRouter.getRouteName() in ['channel', 'group', 'direct']
-				openedRoomId = Session.get 'openedRoom'
-
-		for subscription in subscriptions.fetch()
-			fireGlobalEvent 'unread-changed-by-subscription', subscription
-
-			if subscription.alert or subscription.unread > 0
-				# This logic is duplicated in /client/notifications/notification.coffee.
-				hasFocus = readMessage.isEnable()
-				subscriptionIsTheOpenedRoom = openedRoomId is subscription.rid
-				if hasFocus and subscriptionIsTheOpenedRoom
-					# The user has probably read all messages in this room.
-					# TODO: readNow() should return whether it has actually marked the room as read.
-					Meteor.setTimeout ->
-						readMessage.readNow()
-					, 500
-
-				# Increment the total unread count.
-				unreadCount += subscription.unread
-				if subscription.alert is true and subscription.unreadAlert isnt 'nothing'
-					if subscription.unreadAlert == 'all' or Meteor.user()?.settings?.preferences?.unreadAlert isnt false
-						unreadAlert = '•'
-
-			if RoomManager.openedRooms[subscription.t + subscription.name]
-				readMessage.refreshUnreadMark(subscription.rid)
-
-		menu.updateUnreadBars()
-
-		if unreadCount > 0
-			if unreadCount > 999
-				Session.set 'unread', '999+'
-			else
-				Session.set 'unread', unreadCount
-		else if unreadAlert isnt false
-			Session.set 'unread', unreadAlert
-		else
-			Session.set 'unread', ''
-
-Meteor.startup ->
-
-	window.favico = new Favico
-		position: 'up'
-		animation: 'none'
-
-	Tracker.autorun ->
-		siteName = RocketChat.settings.get('Site_Name') or ''
-
-		unread = Session.get 'unread'
-		fireGlobalEvent 'unread-changed', unread
-		favico?.badge unread, bgColor: if typeof unread isnt 'number' then '#3d8a3a' else '#ac1b1b'
-		document.title = if unread == '' then siteName else '(' + unread + ') '+ siteName
diff --git a/client/startup/unread.js b/client/startup/unread.js
new file mode 100644
index 0000000000000000000000000000000000000000..c72b87e7bc9063003beedc55a6254f50d0c6cea7
--- /dev/null
+++ b/client/startup/unread.js
@@ -0,0 +1,83 @@
+/* globals fireGlobalEvent, readMessage, RoomManager, Favico, favico, menu */
+
+Meteor.startup(function() {
+	Tracker.autorun(function() {
+		let unreadCount = 0;
+		let unreadAlert = false;
+
+		const subscriptions = ChatSubscription.find({open: true}, { fields: { unread: 1, alert: 1, rid: 1, t: 1, name: 1, ls: 1, unreadAlert: 1 } });
+
+		let openedRoomId = undefined;
+		Tracker.nonreactive(function() {
+			if (['channel', 'group', 'direct'].includes(FlowRouter.getRouteName())) {
+				openedRoomId = Session.get('openedRoom');
+			}
+		});
+
+		for (let subscription of subscriptions.fetch()) {
+			fireGlobalEvent('unread-changed-by-subscription', subscription);
+
+			if (subscription.alert || subscription.unread > 0) {
+				// This logic is duplicated in /client/notifications/notification.coffee.
+				const hasFocus = readMessage.isEnable();
+				const subscriptionIsTheOpenedRoom = openedRoomId === subscription.rid;
+				if (hasFocus && subscriptionIsTheOpenedRoom) {
+					// The user has probably read all messages in this room.
+					// TODO: readNow() should return whether it has actually marked the room as read.
+					Meteor.setTimeout(function() {
+						readMessage.readNow();
+					}, 500);
+				}
+
+				// Increment the total unread count.
+				unreadCount += subscription.unread;
+				if (subscription.alert === true && subscription.unreadAlert !== 'nothing') {
+					const userUnreadAlert = Meteor.user() && Meteor.user().settings && Meteor.user().settings.preferences && Meteor.user().settings.preferences.unreadAlert;
+					if (subscription.unreadAlert === 'all' || userUnreadAlert !== false) {
+						unreadAlert = '•';
+					}
+				}
+			}
+
+			if (RoomManager.openedRooms[subscription.t + subscription.name]) {
+				readMessage.refreshUnreadMark(subscription.rid);
+			}
+		}
+
+		menu.updateUnreadBars();
+
+		if (unreadCount > 0) {
+			if (unreadCount > 999) {
+				Session.set('unread', '999+');
+			} else {
+				Session.set('unread', unreadCount);
+			}
+		} else if (unreadAlert !== false) {
+			Session.set('unread', unreadAlert);
+		} else {
+			Session.set('unread', '');
+		}
+	});
+});
+
+Meteor.startup(function() {
+	window.favico = new Favico({
+		position: 'up',
+		animation: 'none'
+	});
+
+	Tracker.autorun(function() {
+		const siteName = RocketChat.settings.get('Site_Name') || '';
+
+		const unread = Session.get('unread');
+		fireGlobalEvent('unread-changed', unread);
+
+		if (favico) {
+			favico.badge(unread, {
+				bgColor: typeof unread !== 'number' ? '#3d8a3a' : '#ac1b1b'
+			});
+		}
+
+		document.title = unread === '' ? siteName : `(${unread}) ${siteName}`;
+	});
+});
diff --git a/client/startup/usersObserve.coffee b/client/startup/usersObserve.coffee
deleted file mode 100644
index 4c5eccc4808754001aba39775556cdbc66fbc087..0000000000000000000000000000000000000000
--- a/client/startup/usersObserve.coffee
+++ /dev/null
@@ -1,11 +0,0 @@
-Meteor.startup ->
-	Meteor.users.find({}, { fields: { name: 1, username: 1, pictures: 1, status: 1, emails: 1, phone: 1, services: 1, utcOffset: 1 } }).observe
-		added: (user) ->
-			Session.set('user_' + user.username + '_status', user.status)
-			RoomManager.updateUserStatus user, user.status, user.utcOffset
-		changed: (user) ->
-			Session.set('user_' + user.username + '_status', user.status)
-			RoomManager.updateUserStatus user, user.status, user.utcOffset
-		removed: (user) ->
-			Session.set('user_' + user.username + '_status', null)
-			RoomManager.updateUserStatus user, 'offline', null
diff --git a/client/startup/usersObserve.js b/client/startup/usersObserve.js
new file mode 100644
index 0000000000000000000000000000000000000000..bb65f60304a739807f5c54f90f40d49be8717528
--- /dev/null
+++ b/client/startup/usersObserve.js
@@ -0,0 +1,18 @@
+/* globals RoomManager */
+
+Meteor.startup(function() {
+	Meteor.users.find({}, { fields: { name: 1, username: 1, pictures: 1, status: 1, emails: 1, phone: 1, services: 1, utcOffset: 1 } }).observe({
+		added(user) {
+			Session.set('user_' + user.username + '_status', user.status);
+			RoomManager.updateUserStatus(user, user.status, user.utcOffset);
+		},
+		changed(user) {
+			Session.set('user_' + user.username + '_status', user.status);
+			RoomManager.updateUserStatus(user, user.status, user.utcOffset);
+		},
+		removed(user) {
+			Session.set('user_' + user.username + '_status', null);
+			RoomManager.updateUserStatus(user, 'offline', null);
+		}
+	});
+});
diff --git a/docker-compose.yml b/docker-compose.yml
index 22d773e362c44725caeccebc9580e00bd0df9e81..44c6f8384c081bf31478040918278e592696fd87 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,64 +1,73 @@
-rocketchat:
-  image: rocketchat/rocket.chat:latest
-  volumes:
-    - ./uploads:/app/uploads
-  environment:
-    - PORT=3000
-    - ROOT_URL=http://localhost:3000
-    - MONGO_URL=mongodb://mongo:27017/rocketchat
-    - MONGO_OPLOG_URL=mongodb://mongo:27017/local
-    - MAIL_URL=smtp://smtp.email
-    - HTTP_PROXY=http://proxy.domain.com
-    - HTTPS_PROXY=http://proxy.domain.com
-  links:
-    - mongo:mongo
-  ports:
-    - 3000:3000
-  labels:
-    - "traefik.backend=rocketchat"
-    - "traefik.frontend.rule=Host: your.domain.tld"
+version: '2'
 
-mongo:
-  image: mongo:3.2
-  volumes:
-   - ./data/db:/data/db
-#    - ./data/dump:/dump
-  command: mongod --smallfiles --oplogSize 128 --replSet rs0
-  labels:
-    - "traefik.enable=false"
+services:
+  rocketchat:
+    image: rocketchat/rocket.chat:latest
+    restart: unless-stopped
+    volumes:
+      - ./uploads:/app/uploads
+    environment:
+      - PORT=3000
+      - ROOT_URL=http://localhost:3000
+      - MONGO_URL=mongodb://mongo:27017/rocketchat
+      - MONGO_OPLOG_URL=mongodb://mongo:27017/local
+      - MAIL_URL=smtp://smtp.email
+      - HTTP_PROXY=http://proxy.domain.com
+      - HTTPS_PROXY=http://proxy.domain.com
+    depends_on:
+      - mongo
+    ports:
+      - 3000:3000
+    labels:
+      - "traefik.backend=rocketchat"
+      - "traefik.frontend.rule=Host: your.domain.tld"
 
-mongo-init-replica:
-  image: mongo:3.2
-  command: 'mongo mongo/rocketchat --eval "rs.initiate({ _id: ''rs0'', members: [ { _id: 0, host: ''localhost:27017'' } ]})"'
-  links:
-    - mongo:mongo
+  mongo:
+    image: mongo:3.2
+    restart: unless-stopped
+    volumes:
+     - ./data/db:/data/db
+     #- ./data/dump:/dump
+    command: mongod --smallfiles --oplogSize 128 --replSet rs0
+    labels:
+      - "traefik.enable=false"
 
-# hubot, the popular chatbot (add the bot user first and change the password before starting this image)
-hubot:
-  image: rocketchat/hubot-rocketchat:latest
-  environment:
-    - ROCKETCHAT_URL=rocketchat:3000
-    - ROCKETCHAT_ROOM=GENERAL
-    - ROCKETCHAT_USER=bot
-    - ROCKETCHAT_PASSWORD=botpassword
-    - BOT_NAME=bot
-# you can add more scripts as you'd like here, they need to be installable by npm
-    - EXTERNAL_SCRIPTS=hubot-help,hubot-seen,hubot-links,hubot-diagnostics
-  links:
-    - rocketchat:rocketchat
-  labels:
-    - "traefik.enable=false"
-  volumes:
-    - ./scripts:/home/hubot/scripts
-# this is used to expose the hubot port for notifications on the host on port 3001, e.g. for hubot-jenkins-notifier
-  ports:
-    - 3001:8080
+  # this container's job is just run the command to initialize the replica set.
+  # it will run the command and remove himself (it will not stay running)
+  mongo-init-replica:
+    image: mongo:3.2
+    command: 'mongo mongo/rocketchat --eval "rs.initiate({ _id: ''rs0'', members: [ { _id: 0, host: ''localhost:27017'' } ]})"'
+    depends_on:
+      - mongo
 
-#traefik:
-#  image: traefik:latest
-#  command: traefik --docker --acme=true --acme.domains='your.domain.tld' --acme.email='your@email.tld' --acme.entrypoint=https --acme.storagefile=acme.json --defaultentrypoints=http --defaultentrypoints=https --entryPoints='Name:http Address::80 Redirect.EntryPoint:https' --entryPoints='Name:https Address::443 TLS.Certificates:'
-#  ports:
-#    - 80:80
-#    - 443:443
-#  volumes:
-#    - /var/run/docker.sock:/var/run/docker.sock
+  # hubot, the popular chatbot (add the bot user first and change the password before starting this image)
+  hubot:
+    image: rocketchat/hubot-rocketchat:latest
+    restart: unless-stopped
+    environment:
+      - ROCKETCHAT_URL=rocketchat:3000
+      - ROCKETCHAT_ROOM=GENERAL
+      - ROCKETCHAT_USER=bot
+      - ROCKETCHAT_PASSWORD=botpassword
+      - BOT_NAME=bot
+  # you can add more scripts as you'd like here, they need to be installable by npm
+      - EXTERNAL_SCRIPTS=hubot-help,hubot-seen,hubot-links,hubot-diagnostics
+    depends_on:
+      - rocketchat
+    labels:
+      - "traefik.enable=false"
+    volumes:
+      - ./scripts:/home/hubot/scripts
+  # this is used to expose the hubot port for notifications on the host on port 3001, e.g. for hubot-jenkins-notifier
+    ports:
+      - 3001:8080
+
+  #traefik:
+  #  image: traefik:latest
+  #  restart: unless-stopped
+  #  command: traefik --docker --acme=true --acme.domains='your.domain.tld' --acme.email='your@email.tld' --acme.entrypoint=https --acme.storagefile=acme.json --defaultentrypoints=http --defaultentrypoints=https --entryPoints='Name:http Address::80 Redirect.EntryPoint:https' --entryPoints='Name:https Address::443 TLS.Certificates:'
+  #  ports:
+  #    - 80:80
+  #    - 443:443
+  #  volumes:
+  #    - /var/run/docker.sock:/var/run/docker.sock
diff --git a/lib/RegExp.coffee b/lib/RegExp.coffee
deleted file mode 100644
index c068aefc58d9ccc7e3229b8ca064d15c351bb762..0000000000000000000000000000000000000000
--- a/lib/RegExp.coffee
+++ /dev/null
@@ -1,2 +0,0 @@
-RegExp.escape = (s) ->
-	return s.replace /[-\/\\^$*+?.()|[\]{}]/g, '\\$&'
\ No newline at end of file
diff --git a/lib/RegExp.js b/lib/RegExp.js
new file mode 100644
index 0000000000000000000000000000000000000000..60d252508d3d68367f8ae37a4d674a690569766a
--- /dev/null
+++ b/lib/RegExp.js
@@ -0,0 +1,3 @@
+RegExp.escape = function(s) {
+	return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
+};
diff --git a/lib/fileUpload.coffee b/lib/fileUpload.coffee
deleted file mode 100644
index ee0f2dc75046e72e0b28570bf8c78ac7ac600f91..0000000000000000000000000000000000000000
--- a/lib/fileUpload.coffee
+++ /dev/null
@@ -1,69 +0,0 @@
-if UploadFS?
-	RocketChat.models.Uploads.allow
-		insert: (userId, doc) ->
-			return userId
-
-		update: (userId, doc) ->
-			return userId is doc.userId
-
-		remove: (userId, doc) ->
-			return userId is doc.userId
-
-	initFileStore = ->
-		cookie = new Cookies()
-		if Meteor.isClient
-			document.cookie = 'rc_uid=' + escape(Meteor.userId()) + '; path=/'
-			document.cookie = 'rc_token=' + escape(Accounts._storedLoginToken()) + '; path=/'
-
-		Meteor.fileStore = new UploadFS.store.GridFS
-			collection: RocketChat.models.Uploads.model
-			name: 'rocketchat_uploads'
-			collectionName: 'rocketchat_uploads'
-			filter: new UploadFS.Filter
-				onCheck: FileUpload.validateFileUpload
-			transformWrite: (readStream, writeStream, fileId, file) ->
-				if RocketChatFile.enabled is false or not /^image\/.+/.test(file.type)
-					return readStream.pipe writeStream
-
-				stream = undefined
-
-				identify = (err, data) ->
-					if err?
-						return stream.pipe writeStream
-
-					file.identify =
-						format: data.format
-						size: data.size
-
-					if data.Orientation? and data.Orientation not in ['', 'Unknown', 'Undefined']
-						RocketChatFile.gm(stream).autoOrient().stream().pipe(writeStream)
-					else
-						stream.pipe writeStream
-
-				stream = RocketChatFile.gm(readStream).identify(identify).stream()
-
-			onRead: (fileId, file, req, res) ->
-				if RocketChat.settings.get 'FileUpload_ProtectFiles'
-					rawCookies = req.headers.cookie if req?.headers?.cookie?
-					uid = cookie.get('rc_uid', rawCookies) if rawCookies?
-					token = cookie.get('rc_token', rawCookies) if rawCookies?
-
-					if not uid?
-						uid = req.query.rc_uid
-						token = req.query.rc_token
-
-					unless uid and token and RocketChat.models.Users.findOneByIdAndLoginToken(uid, token)
-						res.writeHead 403
-						return false
-
-				res.setHeader 'content-disposition', "attachment; filename=\"#{ encodeURIComponent(file.name) }\""
-				return true
-
-	Meteor.startup ->
-		if Meteor.isServer
-			initFileStore()
-		else
-			Tracker.autorun (c) ->
-				if Meteor.userId() and RocketChat.settings.cachedCollection.ready.get()
-					initFileStore()
-					c.stop()
diff --git a/lib/fileUpload.js b/lib/fileUpload.js
new file mode 100644
index 0000000000000000000000000000000000000000..e4503669686624f356b4849cc567975f29641bad
--- /dev/null
+++ b/lib/fileUpload.js
@@ -0,0 +1,87 @@
+/* globals UploadFS, Cookies, FileUpload */
+
+if (UploadFS) {
+	const initFileStore = function() {
+		const cookie = new Cookies();
+		if (Meteor.isClient) {
+			document.cookie = 'rc_uid=' + escape(Meteor.userId()) + '; path=/';
+			document.cookie = 'rc_token=' + escape(Accounts._storedLoginToken()) + '; path=/';
+		}
+
+		Meteor.fileStore = new UploadFS.store.GridFS({
+			collection: RocketChat.models.Uploads.model,
+			name: 'rocketchat_uploads',
+			collectionName: 'rocketchat_uploads',
+			filter: new UploadFS.Filter({
+				onCheck: FileUpload.validateFileUpload
+			}),
+			transformWrite(readStream, writeStream, fileId, file) {
+				if (RocketChatFile.enabled === false || !/^image\/.+/.test(file.type)) {
+					return readStream.pipe(writeStream);
+				}
+
+				let stream = undefined;
+
+				const identify = function(err, data) {
+					if (err) {
+						return stream.pipe(writeStream);
+					}
+
+					file.identify = {
+						format: data.format,
+						size: data.size
+					};
+
+					if (data.Orientation && !['', 'Unknown', 'Undefined'].includes(data.Orientation)) {
+						RocketChatFile.gm(stream).autoOrient().stream().pipe(writeStream);
+					} else {
+						stream.pipe(writeStream);
+					}
+				};
+
+				stream = RocketChatFile.gm(readStream).identify(identify).stream();
+			},
+
+			onRead(fileId, file, req, res) {
+				if (RocketChat.settings.get('FileUpload_ProtectFiles')) {
+					let uid, token;
+
+					if (req && req.headers && req.headers.cookie) {
+						const rawCookies = req.headers.cookie;
+
+						if (rawCookies) {
+							uid = cookie.get('rc_uid', rawCookies) ;
+							token = cookie.get('rc_token', rawCookies);
+						}
+					}
+
+					if (!uid) {
+						uid = req.query.rc_uid;
+						token = req.query.rc_token;
+					}
+
+					if (!uid || !token || !RocketChat.models.Users.findOneByIdAndLoginToken(uid, token)) {
+						res.writeHead(403);
+						return false;
+					}
+				}
+
+				res.setHeader('content-disposition', `attachment; filename="${ encodeURIComponent(file.name) }"`);
+				return true;
+			}
+		});
+	};
+
+	Meteor.startup(function() {
+		if (Meteor.isServer) {
+			initFileStore();
+		} else {
+			Tracker.autorun(function(c) {
+				if (Meteor.userId() && RocketChat.settings.cachedCollection.ready.get()) {
+					initFileStore();
+					c.stop();
+				}
+			});
+		}
+	});
+}
diff --git a/lib/francocatena_fix.coffee b/lib/francocatena_fix.coffee
deleted file mode 100644
index a2ef678fb65b074b0af12cf5a7596260fa475d78..0000000000000000000000000000000000000000
--- a/lib/francocatena_fix.coffee
+++ /dev/null
@@ -1,2 +0,0 @@
-@i18n_status_func = (key,options) ->
-	return TAPi18n.__(key,options)
diff --git a/lib/francocatena_fix.js b/lib/francocatena_fix.js
new file mode 100644
index 0000000000000000000000000000000000000000..12125e91853975bc793ba249edb0fd3e61ef0fff
--- /dev/null
+++ b/lib/francocatena_fix.js
@@ -0,0 +1,3 @@
+this.i18n_status_func = function(key, options) {
+	return TAPi18n.__(key, options);
+};
diff --git a/lib/underscore.string.coffee b/lib/underscore.string.coffee
deleted file mode 100644
index f0845a77574636b0103f03e14383aaa7084a6570..0000000000000000000000000000000000000000
--- a/lib/underscore.string.coffee
+++ /dev/null
@@ -1,15 +0,0 @@
-# This will add underscore.string methods to Underscore.js
-# except for include, contains, reverse and join that are 
-# dropped because they collide with the functions already 
-# defined by Underscore.js.
-
-mixin = (obj) ->
-	_.each _.functions(obj), (name) ->
-		if not _[name] and not _.prototype[name]?
-			func = _[name] = obj[name]
-			_.prototype[name] = ->
-				args = [this._wrapped]
-				push.apply(args, arguments)
-				return result.call(this, func.apply(_, args))
-
-mixin(s.exports())
\ No newline at end of file
diff --git a/lib/underscore.string.js b/lib/underscore.string.js
new file mode 100644
index 0000000000000000000000000000000000000000..f92095c585c7b05a287a280b8e7a3170529422ee
--- /dev/null
+++ b/lib/underscore.string.js
@@ -0,0 +1,16 @@
+/* globals mixin */
+
+// This will add underscore.string methods to Underscore.js
+// except for include, contains, reverse and join that are
+// dropped because they collide with the functions already
+// defined by Underscore.js.
+
+mixin = function(obj) {
+	_.each(_.functions(obj), function(name) {
+		if (!_[name] && !_.prototype[name]) {
+			_[name] = obj[name];
+		}
+	});
+};
+
+mixin(s.exports());
diff --git a/package.json b/package.json
index 1a42814e6956d6c0030a25061f821d5858b657a6..930626c966813252eedabcecc5e2c8cec20856e5 100644
--- a/package.json
+++ b/package.json
@@ -1,72 +1,79 @@
 {
-  "name": "Rocket.Chat",
-  "description": "The Ultimate Open Source WebChat Platform",
-  "version": "0.47.0-develop",
-  "author": {
-    "name": "Rocket.Chat",
-    "url": "https://rocket.chat/"
-  },
-  "contributors": [
-    {
-      "name": "Aaron Ogle",
-      "email": "aaron.ogle@rocket.chat"
-    },
-    {
-      "name": "Bradley Hilton",
-      "email": "bradley.hilton@rocket.chat"
-    },
-    {
-      "name": "Diego Sampaio",
-      "email": "diego.sampaio@rocket.chat"
-    },
-    {
-      "name": "Gabriel Engel",
-      "email": "gabriel.engel@rocket.chat"
-    },
-    {
-      "name": "Marcelo Schmidt",
-      "email": "marcelo.schmidt@rocket.chat"
-    },
-    {
-      "name": "Rodrigo Nascimento",
-      "email": "rodrigo.nascimento@rocket.chat"
-    },
-    {
-      "name": "Sing Li",
-      "email": "sing.li@rocket.chat"
-    }
-  ],
-  "keywords": [
-    "rocketchat",
-    "rocket",
-    "chat"
-  ],
-  "scripts": {
-    "start": "meteor npm i && meteor",
-    "lint": "eslint .",
-    "deploy": "npm run build && pm2 startOrRestart pm2.json",
-    "chimp-watch": "chimp --ddp=http://localhost:3000 --watch --mocha --path=tests",
-    "chimp-test": "chimp --mocha --path=tests --mochaSlow=0"
-  },
-  "license": "MIT",
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/RocketChat/Rocket.Chat.git"
-  },
-  "bugs": {
-    "url": "https://github.com/RocketChat/Rocket.Chat/issues",
-    "email": "support@rocket.chat"
-  },
-  "devDependencies": {
-    "chimp": "^0.42.0",
-    "eslint": "^3.10.2"
-  },
-  "dependencies": {
-    "babel-runtime": "^6.18.0",
-    "bcrypt": "^0.8.7",
-    "moment": "^2.16.0",
-    "moment-timezone": "^0.5.9",
-    "jquery": "^2.1.0",
-    "toastr": "^2.1.2"
-  }
+	"name": "Rocket.Chat",
+	"description": "The Ultimate Open Source WebChat Platform",
+	"version": "0.50.0-develop",
+	"author": {
+		"name": "Rocket.Chat",
+		"url": "https://rocket.chat/"
+	},
+	"contributors": [
+		{
+			"name": "Aaron Ogle",
+			"email": "aaron.ogle@rocket.chat"
+		},
+		{
+			"name": "Bradley Hilton",
+			"email": "bradley.hilton@rocket.chat"
+		},
+		{
+			"name": "Diego Sampaio",
+			"email": "diego.sampaio@rocket.chat"
+		},
+		{
+			"name": "Gabriel Engel",
+			"email": "gabriel.engel@rocket.chat"
+		},
+		{
+			"name": "Marcelo Schmidt",
+			"email": "marcelo.schmidt@rocket.chat"
+		},
+		{
+			"name": "Rodrigo Nascimento",
+			"email": "rodrigo.nascimento@rocket.chat"
+		},
+		{
+			"name": "Sing Li",
+			"email": "sing.li@rocket.chat"
+		}
+	],
+	"keywords": [
+		"rocketchat",
+		"rocket",
+		"chat"
+	],
+	"scripts": {
+		"start": "meteor npm i && meteor",
+		"lint": "eslint .",
+		"stylelint": "stylelint **/*.less",
+		"test": "node .scripts/start.js",
+		"deploy": "npm run build && pm2 startOrRestart pm2.json",
+		"chimp-watch": "chimp --ddp=http://localhost:3000 --watch --mocha --path=tests/steps",
+		"chimp-test": "chimp tests/chimp-config.js"
+	},
+	"license": "MIT",
+	"repository": {
+		"type": "git",
+		"url": "https://github.com/RocketChat/Rocket.Chat.git"
+	},
+	"bugs": {
+		"url": "https://github.com/RocketChat/Rocket.Chat/issues",
+		"email": "support@rocket.chat"
+	},
+	"devDependencies": {
+		"chimp": "^0.45.1",
+		"eslint": "^3.13.1",
+		"stylelint": "^7.7.1",
+		"supertest": "^2.0.1"
+	},
+	"dependencies": {
+		"jquery": "^2.1.0",
+		"babel-runtime": "^6.20.0",
+		"bcrypt": "^1.0.2",
+		"moment": "^2.17.1",
+		"moment-timezone": "^0.5.11",
+		"toastr": "^2.1.2",
+		"mime-types": "2.1.13",
+		"file-type": "4.0.0",
+		"codemirror": "5.22.0"
+	}
 }
diff --git a/packages/meteor-accounts-saml/CHANGELOG.md b/packages/meteor-accounts-saml/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..c9c2caa094a58a229758916266b36faabf240c52
--- /dev/null
+++ b/packages/meteor-accounts-saml/CHANGELOG.md
@@ -0,0 +1,57 @@
+# Changelog
+
+This is a changelog of changes made to the saml package for RocketChat.
+The package is originally based on https://github.com/steffow/meteor-accounts-saml .
+
+## 9-Nov-2016 danb@catalyst-au.net
+
+* Only do `logoutWithSaml` if we are doing single logout (ie
+  `idpSLORedirectURL` is set).  We get an error if we do
+  `logoutWithSaml` and `idpSLORedirectURL` is not set.  This was
+  discovered when testing with simplesamlphp.  In this latter case,
+  `logoutWithSaml` will try to use the standard saml endpoint to
+  request the logout resulting in an error.
+* **TODO:** doing the standard `Meteor.logout` doesn't seem to be
+  enough when logging out.  If the user logs back into RocketChat from
+  the same window, they will be automatically logged back in to
+  RocketChat, no credentials required.  If you enable single logout
+  (ie set `idpSLORedirectURL`), then `logoutWithSaml` will be called
+  and the client should be properly logged out.
+* Switch to using `Cookies` for the client when recording the saml
+  provider and whether single logout is enabled.  If the client has
+  multiple rocketchat tabs or windows, this will ensure they all
+  log out properly with the idp - but only when single logout
+  (`idpSLORedirectURL`) is enabled.
+
+## 31-Oct-2016 danb@catalyst-au.net
+
+* Attempt at SP-initiated logout (**requires more work**).
+  * Added configuration setting for SLO (single logout) redirect url
+    to the IDP.
+  * A `Session` key is set called `saml_provider`; it is unset at
+    logout.  Is there a better way?
+  * `Meteor.logout` on the client is overridden so that
+    `Meteor.logoutWithSaml` is called if `saml_provider` is set.  This
+    isn't great - is there a better way?
+  * Tested using simplesamlphp as the idp
+    * login in using saml
+    * then logout using the normal RocketChat logout
+    * after some time, you should see the RocketChat login screen
+    * if you try to login again, you will have to login to the idp again
+      repeating the previous login flow
+  * **TODO:** If a user has 2 independent browser login sessions using
+    saml, both will log out, but only the one the user logged out from
+    appears to be properly logged out of the idp.
+    * this might be because we shouldn't be logging out the second session
+      but RocketChat / meteor is doing this.
+
+## 17-Oct-2016
+
+* Fixed signing for redirect to idp.
+  * At login time, if the idp is configured to verify the redirect to its login screen, it will
+    expect `RelayState` as part of the signature.
+    Tested with **simplesamlphp** with `'redirect.validate' => TRUE` in the `sp-remote` metadata file
+  * Added `privateKey` - `SAML_Custom_Private_Key`
+  * Added `privateCert` - `SAML_Custom_Public_Cert`
+  * These input fields should point to locations on the the server eg `/path/to/private/certs/`.
+  * `privateKey` is used by RocketChat to sign saml requests.
diff --git a/packages/meteor-accounts-saml/saml_client.js b/packages/meteor-accounts-saml/saml_client.js
index 35bbe93151b1d098eb5460e141220c0b7ec03bef..325f84909e357e868eaf3d5f3c7c2fc46d3edfe0 100644
--- a/packages/meteor-accounts-saml/saml_client.js
+++ b/packages/meteor-accounts-saml/saml_client.js
@@ -4,6 +4,30 @@ if (!Accounts.saml) {
 	Accounts.saml = {};
 }
 
+// Override the standard logout behaviour.
+//
+// If we find a samlProvider, and we are using single
+// logout we will initiate logout from rocketchat via saml.
+// If not using single logout, we just do the standard logout.
+//
+// TODO: This may need some work as it is not clear if we are really
+// logging out of the idp when doing the standard logout.
+
+var MeteorLogout = Meteor.logout;
+
+Meteor.logout = function() {
+	var samlService = ServiceConfiguration.configurations.findOne({service: 'saml'});
+	if (samlService) {
+		var provider = samlService.clientConfig && samlService.clientConfig.provider;
+		if (provider) {
+			if (samlService.idpSLORedirectURL) {
+				return Meteor.logoutWithSaml({ provider: provider });
+			}
+		}
+	}
+	return MeteorLogout.apply(Meteor, arguments);
+};
+
 var openCenteredPopup = function(url, width, height) {
 	var newwindow;
 
@@ -74,6 +98,7 @@ Accounts.saml.initiateLogin = function(options, callback, dimensions) {
 	}, 100);
 };
 
+
 Meteor.loginWithSaml = function(options, callback) {
 	options = options || {};
 	var credentialToken = Random.id();
@@ -93,7 +118,10 @@ Meteor.loginWithSaml = function(options, callback) {
 Meteor.logoutWithSaml = function(options/*, callback*/) {
 	//Accounts.saml.idpInitiatedSLO(options, callback);
 	Meteor.call('samlLogout', options.provider, function(err, result) {
-		console.log('LOC ' + result);
+		if (err || !result) {
+			MeteorLogout.apply(Meteor);
+			return;
+		}
 		// A nasty bounce: 'result' has the SAML LogoutRequest but we need a proper 302 to redirected from the server.
 		//window.location.replace(Meteor.absoluteUrl('_saml/sloRedirect/' + options.provider + '/?redirect='+result));
 		window.location.replace(Meteor.absoluteUrl('_saml/sloRedirect/' + options.provider + '/?redirect=' + encodeURIComponent(result)));
diff --git a/packages/meteor-accounts-saml/saml_rocketchat.coffee b/packages/meteor-accounts-saml/saml_rocketchat.coffee
index f5913eb3e4286264832a307dc545d33304395fe3..fbaff439b819a796c825ad2cc04dec2fa133539f 100644
--- a/packages/meteor-accounts-saml/saml_rocketchat.coffee
+++ b/packages/meteor-accounts-saml/saml_rocketchat.coffee
@@ -1,3 +1,5 @@
+fs = Npm.require('fs')
+
 logger = new Logger 'steffo:meteor-accounts-saml',
 	methods:
 		updated:
@@ -5,55 +7,107 @@ logger = new Logger 'steffo:meteor-accounts-saml',
 
 RocketChat.settings.addGroup 'SAML'
 Meteor.methods
+
+  # Define configuration settings for each provider (name) in the
+  # admin SAML form.
+
 	addSamlService: (name) ->
-		RocketChat.settings.add "SAML_Custom_#{name}"                   , false                                                         , { type: 'boolean', group: 'SAML', section: name, i18nLabel: 'Accounts_OAuth_Custom_Enable'}
-		RocketChat.settings.add "SAML_Custom_#{name}_provider"          , 'openidp'                                                     , { type: 'string' , group: 'SAML', section: name, i18nLabel: 'SAML_Custom_Provider'}
-		RocketChat.settings.add "SAML_Custom_#{name}_entry_point"       , 'https://openidp.feide.no/simplesaml/saml2/idp/SSOService.php', { type: 'string' , group: 'SAML', section: name, i18nLabel: 'SAML_Custom_Entry_point'}
-		RocketChat.settings.add "SAML_Custom_#{name}_issuer"            , 'https://rocket.chat/'                                        , { type: 'string' , group: 'SAML', section: name, i18nLabel: 'SAML_Custom_Issuer'}
-		RocketChat.settings.add "SAML_Custom_#{name}_cert"              , ''                                                            , { type: 'string' , group: 'SAML', section: name, i18nLabel: 'SAML_Custom_Cert'}
+		RocketChat.settings.add "SAML_Custom_#{name}"                      , false                                                             , { type: 'boolean', group: 'SAML', section: name, i18nLabel: 'Accounts_OAuth_Custom_Enable'}
+		RocketChat.settings.add "SAML_Custom_#{name}_provider"             , 'provider-name'                                                   , { type: 'string' , group: 'SAML', section: name, i18nLabel: 'SAML_Custom_Provider'}
+		RocketChat.settings.add "SAML_Custom_#{name}_entry_point"          , 'https://example.com/simplesaml/saml2/idp/SSOService.php'         , { type: 'string' , group: 'SAML', section: name, i18nLabel: 'SAML_Custom_Entry_point'}
+		RocketChat.settings.add "SAML_Custom_#{name}_idp_slo_redirect_url" , 'https://example.com/simplesaml/saml2/idp/SingleLogoutService.php', { type: 'string' , group: 'SAML', section: name, i18nLabel: 'SAML_Custom_IDP_SLO_Redirect_URL'}
+		RocketChat.settings.add "SAML_Custom_#{name}_issuer"               , 'https://your-rocket-chat/_saml/metadata/provider-name'           , { type: 'string' , group: 'SAML', section: name, i18nLabel: 'SAML_Custom_Issuer'}
+		RocketChat.settings.add "SAML_Custom_#{name}_cert"                 , ''                                                                , { type: 'string' , group: 'SAML', section: name, i18nLabel: 'SAML_Custom_Cert', multiline: true}
+		RocketChat.settings.add "SAML_Custom_#{name}_public_cert", '', {
+			type: 'string' ,
+			group: 'SAML',
+			section: name,
+			multiline: true,
+			i18nLabel: 'SAML_Custom_Public_Cert'
+		}
+		RocketChat.settings.add "SAML_Custom_#{name}_private_key", '', {
+			type: 'string' ,
+			group: 'SAML',
+			section: name,
+			multiline: true,
+			i18nLabel: 'SAML_Custom_Private_Key'
+		}
 		RocketChat.settings.add "SAML_Custom_#{name}_button_label_text" , ''                                                            , { type: 'string' , group: 'SAML', section: name, i18nLabel: 'Accounts_OAuth_Custom_Button_Label_Text'}
 		RocketChat.settings.add "SAML_Custom_#{name}_button_label_color", '#FFFFFF'                                                     , { type: 'string' , group: 'SAML', section: name, i18nLabel: 'Accounts_OAuth_Custom_Button_Label_Color'}
 		RocketChat.settings.add "SAML_Custom_#{name}_button_color"      , '#13679A'                                                     , { type: 'string' , group: 'SAML', section: name, i18nLabel: 'Accounts_OAuth_Custom_Button_Color'}
 		RocketChat.settings.add "SAML_Custom_#{name}_generate_username" , false                                                         , { type: 'boolean', group: 'SAML', section: name, i18nLabel: 'SAML_Custom_Generate_Username'}
 
 timer = undefined
+
+# Find existing SAML services (idp's) in RocketChat settings and
+# update the system.
+#
+# Updating the system includes:
+# 1) Appending enabled providers to Accounts.saml.settings.providers.
+# 2) Appending enabled providers to ServiceConfiguration.configurations.
+# 3) Removing disabled providers from ServiceConfiguration.configurations.
+
 updateServices = ->
 	Meteor.clearTimeout timer if timer?
-
 	timer = Meteor.setTimeout ->
 		services = RocketChat.settings.get(/^(SAML_Custom_)[a-z]+$/i)
-
 		Accounts.saml.settings.providers = []
-
 		for service in services
-			logger.updated service.key
-
 			serviceName = 'saml'
-
 			if service.value is true
-				data =
-					buttonLabelText: RocketChat.settings.get("#{service.key}_button_label_text")
-					buttonLabelColor: RocketChat.settings.get("#{service.key}_button_label_color")
-					buttonColor: RocketChat.settings.get("#{service.key}_button_color")
-					clientConfig:
-						provider: RocketChat.settings.get("#{service.key}_provider")
-
-				Accounts.saml.settings.generateUsername = RocketChat.settings.get("#{service.key}_generate_username")
-
-				Accounts.saml.settings.providers.push
-					provider: data.clientConfig.provider
-					entryPoint: RocketChat.settings.get("#{service.key}_entry_point")
-					issuer: RocketChat.settings.get("#{service.key}_issuer")
-					cert: RocketChat.settings.get("#{service.key}_cert")
-
-				ServiceConfiguration.configurations.upsert {service: serviceName.toLowerCase()}, $set: data
+				samlConfigs = getSamlConfigs(service)
+				configureSamlService(samlConfigs)
+				ServiceConfiguration.configurations.upsert {service: serviceName.toLowerCase()}, $set: samlConfigs
 			else
 				ServiceConfiguration.configurations.remove {service: serviceName.toLowerCase()}
+			logger.updated service.key
 	, 2000
 
+# Fetch config settings from RocketChat for a given SAML service "SAML_Custom_<name>".
+
+getSamlConfigs = (service) ->
+	buttonLabelText: RocketChat.settings.get("#{service.key}_button_label_text")
+	buttonLabelColor: RocketChat.settings.get("#{service.key}_button_label_color")
+	buttonColor: RocketChat.settings.get("#{service.key}_button_color")
+	clientConfig:
+		provider: RocketChat.settings.get("#{service.key}_provider")
+	entryPoint: RocketChat.settings.get("#{service.key}_entry_point")
+	idpSLORedirectURL: RocketChat.settings.get("#{service.key}_idp_slo_redirect_url")
+	generateUsername: RocketChat.settings.get("#{service.key}_generate_username")
+	issuer: RocketChat.settings.get("#{service.key}_issuer")
+	secret:
+		privateKey: RocketChat.settings.get("#{service.key}_private_key")
+		publicCert: RocketChat.settings.get("#{service.key}_public_cert")
+		cert: RocketChat.settings.get("#{service.key}_cert")
+
+# Configure Meteor SAML.
+#
+# Get private key for signing and update Accounts.saml.settings.
+# Meteor saml package uses Accounts.saml.settings.
+
+configureSamlService = (samlConfigs) ->
+	privateKey = false
+	privateCert = false
+	if samlConfigs.secret.privateKey and samlConfigs.secret.publicCert
+		privateKey = samlConfigs.secret.privateKey
+		privateCert = samlConfigs.secret.publicCert
+	else
+		if samlConfigs.secret.privateKey or samlConfigs.secret.publicCert
+			logger.error "You must specify both cert and key files."
+			privateKey = false
+			privateCert = false
+	Accounts.saml.settings.generateUsername = samlConfigs.generateUsername
+	Accounts.saml.settings.providers.push
+		provider: samlConfigs.clientConfig.provider
+		entryPoint: samlConfigs.entryPoint
+		idpSLORedirectURL: samlConfigs.idpSLORedirectURL
+		issuer: samlConfigs.issuer
+		cert: samlConfigs.secret.cert
+		privateCert: privateCert
+		privateKey: privateKey
+
 RocketChat.settings.get /^SAML_.+/, (key, value) ->
 	updateServices()
 
 Meteor.startup ->
-	if RocketChat.settings.get(/^(SAML_Custom)_[a-z]+$/i)?.length is 0
-		Meteor.call 'addSamlService', 'Default'
+	Meteor.call 'addSamlService', 'Default'
diff --git a/packages/meteor-accounts-saml/saml_server.js b/packages/meteor-accounts-saml/saml_server.js
index e5d6359200d1f9abb6b77cb628449b595cc2c610..7213171015092f4541a53ee54b7c4f82cf4d7391 100644
--- a/packages/meteor-accounts-saml/saml_server.js
+++ b/packages/meteor-accounts-saml/saml_server.js
@@ -15,16 +15,28 @@ var fiber = Npm.require('fibers');
 var connect = Npm.require('connect');
 RoutePolicy.declare('/_saml/', 'network');
 
+/**
+ * Fetch SAML provider configs for given 'provider'.
+ */
+function getSamlProviderConfig(provider) {
+	if (! provider) {
+		throw new Meteor.Error('no-saml-provider',
+														'SAML internal error',
+														{ method: 'getSamlProviderConfig' });
+	}
+	var samlProvider = function(element) {
+		return (element.provider === provider);
+	};
+	return Accounts.saml.settings.providers.filter(samlProvider)[0];
+}
+
 Meteor.methods({
 	samlLogout: function(provider) {
 		// Make sure the user is logged in before initiate SAML SLO
 		if (!Meteor.userId()) {
 			throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'samlLogout' });
 		}
-		var samlProvider = function(element) {
-			return (element.provider === provider);
-		};
-		var providerConfig = Accounts.saml.settings.providers.filter(samlProvider)[0];
+		var providerConfig = getSamlProviderConfig(provider);
 
 		if (Accounts.saml.settings.debug) {
 			console.log('Logout request from ' + JSON.stringify(providerConfig));
@@ -185,7 +197,8 @@ var samlUrlToObject = function(url) {
 		return null;
 	}
 
-	var splitPath = url.split('/');
+	var splitUrl = url.split('?');
+	var splitPath = splitUrl[0].split('/');
 
 	// Any non-saml request will continue down the default
 	// middlewares.
@@ -320,12 +333,22 @@ var middleware = function(req, res, next) {
 
 					var credentialToken = profile.inResponseToId || profile.InResponseTo || samlObject.credentialToken;
 					if (!credentialToken) {
-						throw new Error('Unable to determine credentialToken');
+						// No credentialToken in IdP-initiated SSO
+						var saml_idp_credentialToken = Random.id();
+						Accounts.saml._loginResultForCredentialToken[saml_idp_credentialToken] = {
+							profile: profile
+						};
+						var url = Meteor.absoluteUrl('home') + '?saml_idp_credentialToken='+saml_idp_credentialToken;
+						res.writeHead(302, {
+							'Location': url
+						});
+						res.end();
+					} else {
+						Accounts.saml._loginResultForCredentialToken[credentialToken] = {
+							profile: profile
+						};
+						closePopup(res);
 					}
-					Accounts.saml._loginResultForCredentialToken[credentialToken] = {
-						profile: profile
-					};
-					closePopup(res);
 				});
 				break;
 			default:
diff --git a/packages/meteor-accounts-saml/saml_utils.js b/packages/meteor-accounts-saml/saml_utils.js
index 90ab63d4382c52d1377e6080bcebd9085954ed8e..09e299a0acd174588da8da97b382ef887cb289ad 100644
--- a/packages/meteor-accounts-saml/saml_utils.js
+++ b/packages/meteor-accounts-saml/saml_utils.js
@@ -166,15 +166,6 @@ SAML.prototype.requestToUrl = function(request, operation, callback) {
 			target += '?';
 		}
 
-		var samlRequest = {
-			SAMLRequest: base64
-		};
-
-		if (self.options.privateCert) {
-			samlRequest.SigAlg = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
-			samlRequest.Signature = self.signRequest(querystring.stringify(samlRequest));
-		}
-
 		// TBD. We should really include a proper RelayState here
 		var relayState;
 		if (operation === 'logout') {
@@ -183,7 +174,18 @@ SAML.prototype.requestToUrl = function(request, operation, callback) {
 		} else {
 			relayState = self.options.provider;
 		}
-		target += querystring.stringify(samlRequest) + '&RelayState=' + relayState;
+
+		var samlRequest = {
+			SAMLRequest: base64,
+			RelayState: relayState
+		};
+
+		if (self.options.privateCert) {
+			samlRequest.SigAlg = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
+			samlRequest.Signature = self.signRequest(querystring.stringify(samlRequest));
+		}
+
+		target += querystring.stringify(samlRequest);
 
 		if (Meteor.settings.debug) {
 			console.log('requestToUrl: ' + target);
diff --git a/packages/rocketchat-action-links/client/stylesheets/actionLinks.less b/packages/rocketchat-action-links/client/stylesheets/actionLinks.less
index 6a0a00aad2d7243d72168108bc43cb1a1a7b8be3..4d6eea113a9a2eb99848b4cd727c9870ce2b06b9 100644
--- a/packages/rocketchat-action-links/client/stylesheets/actionLinks.less
+++ b/packages/rocketchat-action-links/client/stylesheets/actionLinks.less
@@ -4,24 +4,23 @@
 		margin-top: 4px;
 		margin-bottom: 4px;
 		text-align: center;
+
 		li {
 			cursor: pointer;
 			position: relative;
 			padding-right: 2px;
-			color: @primary-action-color;
-
 			list-style: none;
 			display: inline;
 
 			.action-link {
-				background-color: @primary-action-color;
 				padding: 5px;
 				border-radius: 7px;
-				color: @tertiary-font-color;
 				margin: 0 2px;
 			}
 		}
 
-		li:last-child:after { content: none; }
+		li:last-child::after {
+			content: none;
+		}
 	}
 }
diff --git a/packages/rocketchat-action-links/loadStylesheets.js b/packages/rocketchat-action-links/loadStylesheets.js
deleted file mode 100644
index e580080b6dc727d07b2db1104e1898e1d56e85ff..0000000000000000000000000000000000000000
--- a/packages/rocketchat-action-links/loadStylesheets.js
+++ /dev/null
@@ -1,3 +0,0 @@
-RocketChat.theme.addPackageAsset(function() {
-	return Assets.getText('client/stylesheets/actionLinks.less');
-});
diff --git a/packages/rocketchat-action-links/package.js b/packages/rocketchat-action-links/package.js
index 3039842b48b2e9bd7c6af58cbafebb2251a56c93..d8f12c9c181433ef6da0b4302bfb08678c20b41a 100644
--- a/packages/rocketchat-action-links/package.js
+++ b/packages/rocketchat-action-links/package.js
@@ -11,10 +11,10 @@ Package.onUse(function(api) {
 	api.use('rocketchat:lib');
 	api.use('rocketchat:theme');
 	api.use('rocketchat:ui');
+	api.use('less');
 
 	api.addFiles('client/init.js', 'client');
-	api.addAssets('client/stylesheets/actionLinks.less', 'server');
-	api.addFiles('loadStylesheets.js', 'server');
+	api.addFiles('client/stylesheets/actionLinks.less', 'client');
 
 	api.addFiles('server/registerActionLinkFuncts.js', ['server', 'client']);
 	api.addFiles('server/actionLinkHandler.js', ['server', 'client']);
diff --git a/packages/rocketchat-api/package.js b/packages/rocketchat-api/package.js
index b40fbeb8710776b1ba0ea5ee9a24166e6d28d1f4..023e3b6a3c75e2a9df8c8fddf7b6dfd07f8c9330 100644
--- a/packages/rocketchat-api/package.js
+++ b/packages/rocketchat-api/package.js
@@ -7,16 +7,31 @@ Package.describe({
 
 Package.onUse(function(api) {
 	api.use([
-		'coffeescript',
 		'underscore',
 		'ecmascript',
 		'rocketchat:lib',
 		'nimble:restivus'
 	]);
 
-	api.addFiles('server/api.coffee', 'server');
-	api.addFiles('server/routes.coffee', 'server');
+	api.addFiles('server/api.js', 'server');
 	api.addFiles('server/settings.js', 'server');
+
+	//Register v1 helpers
+	api.addFiles('server/v1/helpers/getPaginationItems.js', 'server');
+	api.addFiles('server/v1/helpers/getUserFromParams.js', 'server');
+	api.addFiles('server/v1/helpers/parseJsonQuery.js', 'server');
+
+	api.addFiles('server/default/info.js', 'server');
+
+	//Add v1 routes
+	api.addFiles('server/v1/channels.js', 'server');
+	api.addFiles('server/v1/chat.js', 'server');
+	api.addFiles('server/v1/groups.js', 'server');
+	api.addFiles('server/v1/im.js', 'server');
+	api.addFiles('server/v1/integrations.js', 'server');
+	api.addFiles('server/v1/misc.js', 'server');
+	api.addFiles('server/v1/users.js', 'server');
+	api.addFiles('server/v1/settings.js', 'server');
 });
 
 Npm.depends({
diff --git a/packages/rocketchat-api/server/api.coffee b/packages/rocketchat-api/server/api.coffee
deleted file mode 100644
index 2b600dba87d5a9e309f239e79aeb748fc8a4b8f7..0000000000000000000000000000000000000000
--- a/packages/rocketchat-api/server/api.coffee
+++ /dev/null
@@ -1,61 +0,0 @@
-class API extends Restivus
-	constructor: ->
-		@authMethods = []
-		super
-
-	addAuthMethod: (method) ->
-		@authMethods.push method
-
-	success: (result={}) ->
-		if _.isObject(result)
-			result.success = true
-
-		return {} =
-			statusCode: 200
-			body: result
-
-	failure: (result) ->
-		if _.isObject(result)
-			result.success = false
-		else
-			result =
-				success: false
-				error: result
-
-		return {} =
-			statusCode: 400
-			body: result
-
-	unauthorized: (msg) ->
-		return {} =
-			statusCode: 403
-			body:
-				success: false
-				error: msg or 'unauthorized'
-
-
-RocketChat.API = {}
-
-
-RocketChat.API.v1 = new API
-	version: 'v1'
-	useDefaultAuth: true
-	prettyJson: true
-	enableCors: false
-	auth:
-		token: 'services.resume.loginTokens.hashedToken'
-		user: ->
-			if @bodyParams?.payload?
-				@bodyParams = JSON.parse @bodyParams.payload
-
-			for method in RocketChat.API.v1.authMethods
-				result = method.apply @, arguments
-				if result not in [undefined, null, false]
-					return result
-
-			if @request.headers['x-auth-token']
-				token = Accounts._hashLoginToken @request.headers['x-auth-token']
-
-			return {} =
-				userId: @request.headers['x-user-id']
-				token: token
diff --git a/packages/rocketchat-api/server/api.js b/packages/rocketchat-api/server/api.js
new file mode 100644
index 0000000000000000000000000000000000000000..eba3aff4f77128d43cc9acf56d662051f1d169c5
--- /dev/null
+++ b/packages/rocketchat-api/server/api.js
@@ -0,0 +1,151 @@
+/* global Restivus */
+class API extends Restivus {
+	constructor(properties) {
+		super(properties);
+		this.logger = new Logger(`API ${properties.version ? properties.version : 'default'} Logger`, {});
+		this.authMethods = [];
+		this.helperMethods = new Map();
+		this.defaultFieldsToExclude = {
+			joinCode: 0,
+			$loki: 0,
+			meta: 0
+		};
+	}
+
+	addAuthMethod(method) {
+		this.authMethods.push(method);
+	}
+
+	success(result={}) {
+		if (_.isObject(result)) {
+			result.success = true;
+		}
+
+		return {
+			statusCode: 200,
+			body: result
+		};
+	}
+
+	failure(result, errorType) {
+		if (_.isObject(result)) {
+			result.success = false;
+		} else {
+			result = {
+				success: false,
+				error: result
+			};
+
+			if (errorType) {
+				result.errorType = errorType;
+			}
+		}
+
+		return {
+			statusCode: 400,
+			body: result
+		};
+	}
+
+
+	unauthorized(msg) {
+		return {
+			statusCode: 403,
+			body: {
+				success: false,
+				error: msg ? msg : 'unauthorized'
+			}
+		};
+	}
+
+	addRoute(route, options, endpoints) {
+		//Note: required if the developer didn't provide options
+		if (typeof endpoints === 'undefined') {
+			endpoints = options;
+			options = {};
+		}
+
+		//Note: This is required due to Restivus calling `addRoute` in the constructor of itself
+		if (this.helperMethods) {
+			Object.keys(endpoints).forEach((method) => {
+				if (typeof endpoints[method] === 'function') {
+					endpoints[method] = { action: endpoints[method] };
+				}
+
+				//Add a try/catch for each much
+				const originalAction = endpoints[method].action;
+				endpoints[method].action = function() {
+					let result;
+					try {
+						result = originalAction.apply(this);
+					} catch (e) {
+						this.logger.debug(`${method} ${route} threw an error:`, e);
+						return RocketChat.API.v1.failure(e.message, e.error);
+					}
+
+					return result ? result : RocketChat.API.v1.success();
+				};
+
+				for (const [name, helperMethod] of this.helperMethods) {
+					endpoints[method][name] = helperMethod;
+				}
+
+				//Allow the endpoints to make usage of the logger which respects the user's settings
+				endpoints[method].logger = this.logger;
+				endpoints[method].method = method.toUpperCase();
+			});
+		}
+
+		super.addRoute(route, options, endpoints);
+	}
+}
+
+RocketChat.API = {};
+
+const getUserAuth = function _getUserAuth() {
+	const invalidResults = [undefined, null, false];
+	return {
+		token: 'services.resume.loginTokens.hashedToken',
+		user: function() {
+			if (this.bodyParams && this.bodyParams.payload) {
+				this.bodyParams = JSON.parse(this.bodyParams.payload);
+			}
+
+			for (let i = 0; i < RocketChat.API.v1.authMethods.length; i++) {
+				const method = RocketChat.API.v1.authMethods[i];
+
+				if (typeof method === 'function') {
+					const result = method.apply(this, arguments);
+					if (!invalidResults.includes(result)) {
+						return result;
+					}
+				}
+			}
+
+			let token;
+			if (this.request.headers['x-auth-token']) {
+				token = Accounts._hashLoginToken(this.request.headers['x-auth-token']);
+			}
+
+			return {
+				userId: this.request.headers['x-user-id'],
+				token
+			};
+		}
+	};
+};
+
+RocketChat.API.v1 = new API({
+	version: 'v1',
+	useDefaultAuth: true,
+	prettyJson: true,
+	enableCors: false,
+	auth: getUserAuth()
+});
+
+RocketChat.API.default = new API({
+	useDefaultAuth: true,
+	prettyJson: true,
+	enableCors: false,
+	auth: getUserAuth()
+});
diff --git a/packages/rocketchat-api/server/default/info.js b/packages/rocketchat-api/server/default/info.js
new file mode 100644
index 0000000000000000000000000000000000000000..adf7a094db0d341d1d6523d2a9435eb366a5d82d
--- /dev/null
+++ b/packages/rocketchat-api/server/default/info.js
@@ -0,0 +1,5 @@
+RocketChat.API.default.addRoute('info', { authRequired: false }, {
+	get: function() {
+		return RocketChat.Info;
+	}
+});
diff --git a/packages/rocketchat-api/server/routes.coffee b/packages/rocketchat-api/server/routes.coffee
deleted file mode 100644
index 10b34d05b93b67868e9eccfed09996e423b1c6fd..0000000000000000000000000000000000000000
--- a/packages/rocketchat-api/server/routes.coffee
+++ /dev/null
@@ -1,293 +0,0 @@
-RocketChat.API.v1.addRoute 'info', authRequired: false,
-	get: -> RocketChat.Info
-
-
-RocketChat.API.v1.addRoute 'me', authRequired: true,
-	get: ->
-		return _.pick @user, [
-			'_id'
-			'name'
-			'emails'
-			'status'
-			'statusConnection'
-			'username'
-			'utcOffset'
-			'active'
-			'language'
-		]
-
-
-# Send Channel Message
-RocketChat.API.v1.addRoute 'chat.messageExamples', authRequired: true,
-	get: ->
-		return RocketChat.API.v1.success
-			body: [
-				token: Random.id(24)
-				channel_id: Random.id()
-				channel_name: 'general'
-				timestamp: new Date
-				user_id: Random.id()
-				user_name: 'rocket.cat'
-				text: 'Sample text 1'
-				trigger_word: 'Sample'
-			,
-				token: Random.id(24)
-				channel_id: Random.id()
-				channel_name: 'general'
-				timestamp: new Date
-				user_id: Random.id()
-				user_name: 'rocket.cat'
-				text: 'Sample text 2'
-				trigger_word: 'Sample'
-			,
-				token: Random.id(24)
-				channel_id: Random.id()
-				channel_name: 'general'
-				timestamp: new Date
-				user_id: Random.id()
-				user_name: 'rocket.cat'
-				text: 'Sample text 3'
-				trigger_word: 'Sample'
-			]
-
-
-# Send Channel Message
-RocketChat.API.v1.addRoute 'chat.postMessage', authRequired: true,
-	post: ->
-		try
-			messageReturn = processWebhookMessage @bodyParams, @user
-
-			if not messageReturn?
-				return RocketChat.API.v1.failure 'unknown-error'
-
-			return RocketChat.API.v1.success
-				ts: Date.now()
-				channel: messageReturn.channel
-				message: messageReturn.message
-		catch e
-			return RocketChat.API.v1.failure e.error
-
-# Set Channel Topic
-RocketChat.API.v1.addRoute 'channels.setTopic', authRequired: true,
-	post: ->
-		if not @bodyParams.channel?
-			return RocketChat.API.v1.failure 'Body param "channel" is required'
-
-		if not @bodyParams.topic?
-			return RocketChat.API.v1.failure 'Body param "topic" is required'
-
-		unless RocketChat.authz.hasPermission(@userId, 'edit-room', @bodyParams.channel)
-			return RocketChat.API.v1.unauthorized()
-
-		if not RocketChat.saveRoomTopic(@bodyParams.channel, @bodyParams.topic, @user)
-			return RocketChat.API.v1.failure 'invalid_channel'
-
-		return RocketChat.API.v1.success
-			topic: @bodyParams.topic
-
-
-# Create Channel
-RocketChat.API.v1.addRoute 'channels.create', authRequired: true,
-	post: ->
-		if not @bodyParams.name?
-			return RocketChat.API.v1.failure 'Body param "name" is required'
-
-		if not RocketChat.authz.hasPermission(@userId, 'create-c')
-			return RocketChat.API.v1.unauthorized()
-
-		id = undefined
-		try
-			Meteor.runAsUser this.userId, =>
-				id = Meteor.call 'createChannel', @bodyParams.name, []
-		catch e
-			return RocketChat.API.v1.failure e.name + ': ' + e.message
-
-		return RocketChat.API.v1.success
-			channel: RocketChat.models.Rooms.findOneById(id.rid)
-
-# List Private Groups a user has access to
-RocketChat.API.v1.addRoute 'groups.list', authRequired: true,
-	get: ->
-		roomIds = _.pluck RocketChat.models.Subscriptions.findByTypeAndUserId('p', @userId).fetch(), 'rid'
-		return { groups: RocketChat.models.Rooms.findByIds(roomIds).fetch() }
-
-# Add All Users to Channel
-RocketChat.API.v1.addRoute 'channel.addall', authRequired: true,
-	post: ->
-
-		id = undefined
-		try
-			Meteor.runAsUser this.userId, =>
-				id = Meteor.call 'addAllUserToRoom', @bodyParams.roomId, []
-		catch e
-			return RocketChat.API.v1.failure e.name + ': ' + e.message
-
-		return RocketChat.API.v1.success
-			channel: RocketChat.models.Rooms.findOneById(@bodyParams.roomId)
-
-# List all users
-RocketChat.API.v1.addRoute 'users.list', authRequired: true,
-	get: ->
-		if RocketChat.authz.hasRole(@userId, 'admin') is false
-			return RocketChat.API.v1.unauthorized()
-
-		return { users: RocketChat.models.Users.find().fetch() }
-
-# Create user
-RocketChat.API.v1.addRoute 'users.create', authRequired: true,
-	post: ->
-		try
-			check @bodyParams,
-				email: String
-				name: String
-				password: String
-				username: String
-				role: Match.Maybe(String)
-				joinDefaultChannels: Match.Maybe(Boolean)
-				requirePasswordChange: Match.Maybe(Boolean)
-				sendWelcomeEmail: Match.Maybe(Boolean)
-				verified: Match.Maybe(Boolean)
-				customFields: Match.Maybe(Object)
-
-			# check username availability first (to not create an user without a username)
-			try
-				nameValidation = new RegExp '^' + RocketChat.settings.get('UTF8_Names_Validation') + '$'
-			catch
-				nameValidation = new RegExp '^[0-9a-zA-Z-_.]+$'
-
-			if not nameValidation.test @bodyParams.username
-				return RocketChat.API.v1.failure 'Invalid username'
-
-			unless RocketChat.checkUsernameAvailability @bodyParams.username
-				return RocketChat.API.v1.failure 'Username not available'
-
-			userData = {}
-
-			newUserId = RocketChat.saveUser(@userId, @bodyParams)
-
-			if @bodyParams.customFields?
-				RocketChat.saveCustomFields(newUserId, @bodyParams.customFields)
-
-			user = RocketChat.models.Users.findOneById(newUserId)
-
-			if typeof @bodyParams.joinDefaultChannels is 'undefined' or @bodyParams.joinDefaultChannels
-				RocketChat.addUserToDefaultChannels(user)
-
-			return RocketChat.API.v1.success
-				user: user
-		catch e
-			return RocketChat.API.v1.failure e.name + ': ' + e.message
-
-# Update user
-RocketChat.API.v1.addRoute 'user.update', authRequired: true,
-	post: ->
-		try
-			check @bodyParams,
-				userId: String
-				data:
-					email: Match.Maybe(String)
-					name: Match.Maybe(String)
-					password: Match.Maybe(String)
-					username: Match.Maybe(String)
-					role: Match.Maybe(String)
-					joinDefaultChannels: Match.Maybe(Boolean)
-					requirePasswordChange: Match.Maybe(Boolean)
-					sendWelcomeEmail: Match.Maybe(Boolean)
-					verified: Match.Maybe(Boolean)
-					customFields: Match.Maybe(Object)
-
-			userData = _.extend({ _id: @bodyParams.userId }, @bodyParams.data)
-
-			RocketChat.saveUser(@userId, userData)
-
-			if @bodyParams.data.customFields?
-				RocketChat.saveCustomFields(@bodyParams.userId, @bodyParams.data.customFields)
-
-			return RocketChat.API.v1.success
-				user: RocketChat.models.Users.findOneById(@bodyParams.userId)
-		catch e
-			return RocketChat.API.v1.failure e.name + ': ' + e.message
-
-# Get User Information
-RocketChat.API.v1.addRoute 'user.info', authRequired: true,
-	post: ->
-		if RocketChat.authz.hasRole(@userId, 'admin') is false
-			return RocketChat.API.v1.unauthorized()
-
-		return { user: RocketChat.models.Users.findOneByUsername @bodyParams.name }
-
-# Get User Presence
-RocketChat.API.v1.addRoute 'user.getpresence', authRequired: true,
-	post: ->
-		return { user: RocketChat.models.Users.findOne( { username: @bodyParams.name} , {fields: {status: 1}} ) }
-
-# Delete User
-RocketChat.API.v1.addRoute 'users.delete', authRequired: true,
-	post: ->
-		if not @bodyParams.userId?
-			return RocketChat.API.v1.failure 'Body param "userId" is required'
-
-		if not RocketChat.authz.hasPermission(@userId, 'delete-user')
-			return RocketChat.API.v1.unauthorized()
-
-		id = undefined
-		try
-			Meteor.runAsUser this.userId, =>
-				id = Meteor.call 'deleteUser', @bodyParams.userId, []
-		catch e
-			return RocketChat.API.v1.failure e.name + ': ' + e.message
-
-		return RocketChat.API.v1.success
-
-# Set user's avatar
-RocketChat.API.v1.addRoute 'users.setAvatar', authRequired: true,
-	post: ->
-		try
-			Busboy = Npm.require('busboy')
-
-			busboy = new Busboy headers: @request.headers
-
-			user = Meteor.users.findOne(@userId)
-
-			Meteor.wrapAsync((callback) =>
-				busboy.on 'file', Meteor.bindEnvironment (fieldname, file, filename, encoding, mimetype) =>
-					if fieldname isnt 'image'
-						return callback(new Meteor.Error 'invalid-field')
-
-					imageData = []
-					file.on 'data', Meteor.bindEnvironment (data) ->
-						imageData.push data
-
-					file.on 'end', Meteor.bindEnvironment () =>
-						RocketChat.setUserAvatar(user, Buffer.concat(imageData), mimetype, 'rest')
-						callback()
-
-				@request.pipe busboy
-			)()
-		catch e
-			return RocketChat.API.v1.failure e.name + ': ' + e.message
-
-		return RocketChat.API.v1.success()
-
-# Create Private Group
-RocketChat.API.v1.addRoute 'groups.create', authRequired: true,
-	post: ->
-		if not @bodyParams.name?
-			return RocketChat.API.v1.failure 'Body param "name" is required'
-
-		if not RocketChat.authz.hasPermission(@userId, 'create-p')
-			return RocketChat.API.v1.unauthorized()
-
-		id = undefined
-		try
-			if not @bodyParams.members?
-				Meteor.runAsUser this.userId, =>
-					id = Meteor.call 'createPrivateGroup', @bodyParams.name, []
-			else
-				Meteor.runAsUser this.userId, =>
-					id = Meteor.call 'createPrivateGroup', @bodyParams.name, @bodyParams.members, []
-		catch e
-			return RocketChat.API.v1.failure e.name + ': ' + e.message
-
-		return RocketChat.API.v1.success
-			group: RocketChat.models.Rooms.findOneById(id.rid)
diff --git a/packages/rocketchat-api/server/settings.js b/packages/rocketchat-api/server/settings.js
index b80df858c217b12e1c80b41038860e9e6d9b0e3f..238f4d0d11d7c965e02f15f5598a4f04e6cc4c26 100644
--- a/packages/rocketchat-api/server/settings.js
+++ b/packages/rocketchat-api/server/settings.js
@@ -1,29 +1,7 @@
-// settings endpoints
-RocketChat.API.v1.addRoute('settings/:_id', { authRequired: true }, {
-	get() {
-		if (!RocketChat.authz.hasPermission(this.userId, 'view-privileged-setting')) {
-			return RocketChat.API.v1.unauthorized();
-		}
-
-		return RocketChat.API.v1.success(_.pick(RocketChat.models.Settings.findOneNotHiddenById(this.urlParams._id), '_id', 'value'));
-	},
-	post() {
-		if (!RocketChat.authz.hasPermission(this.userId, 'edit-privileged-setting')) {
-			return RocketChat.API.v1.unauthorized();
-		}
-
-		try {
-			check(this.bodyParams, {
-				value: Match.Any
-			});
-
-			if (RocketChat.models.Settings.updateValueNotHiddenById(this.urlParams._id, this.bodyParams.value)) {
-				return RocketChat.API.v1.success();
-			}
-
-			return RocketChat.API.v1.failure();
-		} catch (e) {
-			return RocketChat.API.v1.failure(e.message);
-		}
-	}
+RocketChat.settings.addGroup('General', function() {
+	this.section('REST API', function() {
+		this.add('API_Upper_Count_Limit', 100, { type: 'int', public: false });
+		this.add('API_Default_Count', 50, { type: 'int', public: false });
+		this.add('API_Allow_Infinite_Count', true, { type: 'boolean', public: false });
+	});
 });
diff --git a/packages/rocketchat-api/server/v1/channels.js b/packages/rocketchat-api/server/v1/channels.js
new file mode 100644
index 0000000000000000000000000000000000000000..1e091fc7b82db404c59ce1d09f94681432442644
--- /dev/null
+++ b/packages/rocketchat-api/server/v1/channels.js
@@ -0,0 +1,587 @@
+//Returns the channel IF found otherwise it will return the failure of why it didn't. Check the `statusCode` property
+function findChannelById({ roomId, checkedArchived = true }) {
+	if (!roomId || !roomId.trim()) {
+		throw new Meteor.Error('error-roomid-param-not-provided', 'The parameter "roomId" is required');
+	}
+
+	const room = RocketChat.models.Rooms.findOneById(roomId, { fields: RocketChat.API.v1.defaultFieldsToExclude });
+
+	if (!room || room.t !== 'c') {
+		throw new Meteor.Error('error-room-not-found', `No channel found by the id of: ${roomId}`);
+	}
+
+	if (checkedArchived && room.archived) {
+		throw new Meteor.Error('error-room-aquived', `The channel, ${room.name}, is archived`);
+	}
+
+	return room;
+}
+
+RocketChat.API.v1.addRoute('channels.addAll', { authRequired: true }, {
+	post: function() {
+		const findResult = findChannelById({ roomId: this.bodyParams.roomId });
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('addAllUserToRoom', findResult._id);
+		});
+
+		return RocketChat.API.v1.success({
+			channel: RocketChat.models.Rooms.findOneById(findResult._id, { fields: RocketChat.API.v1.defaultFieldsToExclude })
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.addModerator', { authRequired: true }, {
+	post: function() {
+		const findResult = findChannelById({ roomId: this.bodyParams.roomId });
+
+		const user = this.getUserFromParams();
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('addRoomModerator', findResult._id, user._id);
+		});
+
+		return RocketChat.API.v1.success();
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.addOwner', { authRequired: true }, {
+	post: function() {
+		const findResult = findChannelById({ roomId: this.bodyParams.roomId });
+
+		const user = this.getUserFromParams();
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('addRoomOwner', findResult._id, user._id);
+		});
+
+		return RocketChat.API.v1.success();
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.archive', { authRequired: true }, {
+	post: function() {
+		const findResult = findChannelById({ roomId: this.bodyParams.roomId });
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('archiveRoom', findResult._id);
+		});
+
+		return RocketChat.API.v1.success();
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.cleanHistory', { authRequired: true }, {
+	post: function() {
+		const findResult = findChannelById({ roomId: this.bodyParams.roomId });
+
+		if (!this.bodyParams.latest) {
+			return RocketChat.API.v1.failure('Body parameter "latest" is required.');
+		}
+
+		if (!this.bodyParams.oldest) {
+			return RocketChat.API.v1.failure('Body parameter "oldest" is required.');
+		}
+
+		const latest = new Date(this.bodyParams.latest);
+		const oldest = new Date(this.bodyParams.oldest);
+
+		let inclusive = false;
+		if (typeof this.bodyParams.inclusive !== 'undefined') {
+			inclusive = this.bodyParams.inclusive;
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('cleanChannelHistory', { roomId: findResult._id, latest, oldest, inclusive });
+		});
+
+		return RocketChat.API.v1.success();
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.close', { authRequired: true }, {
+	post: function() {
+		const findResult = findChannelById({ roomId: this.bodyParams.roomId, checkedArchived: false });
+
+		const sub = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(findResult._id, this.userId);
+
+		if (!sub) {
+			return RocketChat.API.v1.failure(`The user/callee is not in the channel "${findResult.name}.`);
+		}
+
+		if (!sub.open) {
+			return RocketChat.API.v1.failure(`The channel, ${findResult.name}, is already closed to the sender`);
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('hideRoom', findResult._id);
+		});
+
+		return RocketChat.API.v1.success();
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.create', { authRequired: true }, {
+	post: function() {
+		if (!RocketChat.authz.hasPermission(this.userId, 'create-p')) {
+			return RocketChat.API.v1.unauthorized();
+		}
+
+		if (!this.bodyParams.name) {
+			return RocketChat.API.v1.failure('Body param "name" is required');
+		}
+
+		if (this.bodyParams.members && !_.isArray(this.bodyParams.members)) {
+			return RocketChat.API.v1.failure('Body param "members" must be an array if provided');
+		}
+
+		let readOnly = false;
+		if (typeof this.bodyParams.readOnly !== 'undefined') {
+			readOnly = this.bodyParams.readOnly;
+		}
+
+		let id;
+		Meteor.runAsUser(this.userId, () => {
+			id = Meteor.call('createChannel', this.bodyParams.name, this.bodyParams.members ? this.bodyParams.members : [], readOnly);
+		});
+
+		return RocketChat.API.v1.success({
+			channel: RocketChat.models.Rooms.findOneById(id.rid, { fields: RocketChat.API.v1.defaultFieldsToExclude })
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.delete', { authRequired: true }, {
+	post: function() {
+		const findResult = findChannelById({ roomId: this.bodyParams.roomId, checkedArchived: false });
+
+		//The find method returns either with the group or the failur
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('eraseRoom', findResult._id);
+		});
+
+		return RocketChat.API.v1.success({
+			channel: findResult
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.getIntegrations', { authRequired: true }, {
+	get: function() {
+		if (!RocketChat.authz.hasPermission(this.userId, 'manage-integrations')) {
+			return RocketChat.API.v1.unauthorized();
+		}
+
+		const findResult = findChannelById({ roomId: this.queryParams.roomId, checkedArchived: false });
+
+		let includeAllPublicChannels = true;
+		if (typeof this.queryParams.includeAllPublicChannels !== 'undefined') {
+			includeAllPublicChannels = this.queryParams.includeAllPublicChannels === 'true';
+		}
+
+		let ourQuery = {
+			channel: `#${findResult.name}`
+		};
+
+		if (includeAllPublicChannels) {
+			ourQuery.channel = {
+				$in: [ourQuery.channel, 'all_public_channels']
+			};
+		}
+
+		const { offset, count } = this.getPaginationItems();
+		const { sort, fields, query } = this.parseJsonQuery();
+
+		ourQuery = Object.assign({}, query, ourQuery);
+
+		const integrations = RocketChat.models.Integrations.find(ourQuery, {
+			sort: sort ? sort : { _createdAt: 1 },
+			skip: offset,
+			limit: count,
+			fields: Object.assign({}, fields, RocketChat.API.v1.defaultFieldsToExclude)
+		}).fetch();
+
+		return RocketChat.API.v1.success({
+			integrations,
+			count: integrations.length,
+			offset,
+			total: RocketChat.models.Integrations.find(ourQuery).count()
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.history', { authRequired: true }, {
+	get: function() {
+		const findResult = findChannelById({ roomId: this.queryParams.roomId, checkedArchived: false });
+
+		let latestDate = new Date();
+		if (this.queryParams.latest) {
+			latestDate = new Date(this.queryParams.latest);
+		}
+
+		let oldestDate = undefined;
+		if (this.queryParams.oldest) {
+			oldestDate = new Date(this.queryParams.oldest);
+		}
+
+		let inclusive = false;
+		if (this.queryParams.inclusive) {
+			inclusive = this.queryParams.inclusive;
+		}
+
+		let count = 20;
+		if (this.queryParams.count) {
+			count = parseInt(this.queryParams.count);
+		}
+
+		let unreads = false;
+		if (this.queryParams.unreads) {
+			unreads = this.queryParams.unreads;
+		}
+
+		let result;
+		Meteor.runAsUser(this.userId, () => {
+			result = Meteor.call('getChannelHistory', { rid: findResult._id, latest: latestDate, oldest: oldestDate, inclusive, count, unreads });
+		});
+
+		return RocketChat.API.v1.success({
+			messages: result && result.messages ? result.messages : []
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.info', { authRequired: true }, {
+	get: function() {
+		const findResult = findChannelById({ roomId: this.queryParams.roomId, checkedArchived: false });
+
+		return RocketChat.API.v1.success({
+			channel: RocketChat.models.Rooms.findOneById(findResult._id, { fields: RocketChat.API.v1.defaultFieldsToExclude })
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.invite', { authRequired: true }, {
+	post: function() {
+		const findResult = findChannelById({ roomId: this.bodyParams.roomId });
+
+		const user = this.getUserFromParams();
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('addUserToRoom', { rid: findResult._id, username: user.username });
+		});
+
+		return RocketChat.API.v1.success({
+			channel: RocketChat.models.Rooms.findOneById(findResult._id, { fields: RocketChat.API.v1.defaultFieldsToExclude })
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.join', { authRequired: true }, {
+	post: function() {
+		const findResult = findChannelById({ roomId: this.bodyParams.roomId });
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('joinRoom', findResult._id, this.bodyParams.joinCode);
+		});
+
+		return RocketChat.API.v1.success({
+			channel: RocketChat.models.Rooms.findOneById(findResult._id, { fields: RocketChat.API.v1.defaultFieldsToExclude })
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.kick', { authRequired: true }, {
+	post: function() {
+		const findResult = findChannelById({ roomId: this.bodyParams.roomId });
+
+		const user = this.getUserFromParams();
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('removeUserFromRoom', { rid: findResult._id, username: user.username });
+		});
+
+		return RocketChat.API.v1.success({
+			channel: RocketChat.models.Rooms.findOneById(findResult._id, { fields: RocketChat.API.v1.defaultFieldsToExclude })
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.leave', { authRequired: true }, {
+	post: function() {
+		const findResult = findChannelById({ roomId: this.bodyParams.roomId });
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('leaveRoom', findResult._id);
+		});
+
+		return RocketChat.API.v1.success({
+			channel: RocketChat.models.Rooms.findOneById(findResult._id, { fields: RocketChat.API.v1.defaultFieldsToExclude })
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.list', { authRequired: true }, {
+	get: {
+		//This is like this only to provide an example of how we routes can be defined :X
+		action: function() {
+			const { offset, count } = this.getPaginationItems();
+			const { sort, fields, query } = this.parseJsonQuery();
+
+			const ourQuery = Object.assign({}, query, { t: 'c' });
+
+			const rooms = RocketChat.models.Rooms.find(ourQuery, {
+				sort: sort ? sort : { name: 1 },
+				skip: offset,
+				limit: count,
+				fields: Object.assign({}, fields, RocketChat.API.v1.defaultFieldsToExclude)
+			}).fetch();
+
+			return RocketChat.API.v1.success({
+				channels: rooms,
+				count: rooms.length,
+				offset,
+				total: RocketChat.models.Rooms.find(ourQuery).count()
+			});
+		}
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.list.joined', { authRequired: true }, {
+	get: function() {
+		const { offset, count } = this.getPaginationItems();
+		const { sort, fields } = this.parseJsonQuery();
+		let rooms = _.pluck(RocketChat.models.Subscriptions.findByTypeAndUserId('c', this.userId).fetch(), '_room');
+		const totalCount = rooms.length;
+
+		rooms = RocketChat.models.Rooms.processQueryOptionsOnResult(rooms, {
+			sort: sort ? sort : { name: 1 },
+			skip: offset,
+			limit: count,
+			fields: Object.assign({}, fields, RocketChat.API.v1.defaultFieldsToExclude)
+		});
+
+		return RocketChat.API.v1.success({
+			channels: rooms,
+			offset,
+			count: rooms.length,
+			total: totalCount
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.open', { authRequired: true }, {
+	post: function() {
+		const findResult = findChannelById({ roomId: this.bodyParams.roomId, checkedArchived: false });
+
+		const sub = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(findResult._id, this.userId);
+
+		if (!sub) {
+			return RocketChat.API.v1.failure(`The user/callee is not in the channel "${findResult.name}".`);
+		}
+
+		if (sub.open) {
+			return RocketChat.API.v1.failure(`The channel, ${findResult.name}, is already open to the sender`);
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('openRoom', findResult._id);
+		});
+
+		return RocketChat.API.v1.success();
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.removeModerator', { authRequired: true }, {
+	post: function() {
+		const findResult = findChannelById({ roomId: this.bodyParams.roomId });
+
+		const user = this.getUserFromParams();
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('removeRoomModerator', findResult._id, user._id);
+		});
+
+		return RocketChat.API.v1.success();
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.removeOwner', { authRequired: true }, {
+	post: function() {
+		const findResult = findChannelById({ roomId: this.bodyParams.roomId });
+
+		const user = this.getUserFromParams();
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('removeRoomOwner', findResult._id, user._id);
+		});
+
+		return RocketChat.API.v1.success();
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.rename', { authRequired: true }, {
+	post: function() {
+		if (!this.bodyParams.name || !this.bodyParams.name.trim()) {
+			return RocketChat.API.v1.failure('The bodyParam "name" is required');
+		}
+
+		const findResult = findChannelById({ roomId: this.bodyParams.roomId });
+
+		if (findResult.name === this.bodyParams.name) {
+			return RocketChat.API.v1.failure('The channel name is the same as what it would be renamed to.');
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('saveRoomSettings', findResult._id, 'roomName', this.bodyParams.name);
+		});
+
+		return RocketChat.API.v1.success({
+			channel: RocketChat.models.Rooms.findOneById(findResult._id, { fields: RocketChat.API.v1.defaultFieldsToExclude })
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.setDescription', { authRequired: true }, {
+	post: function() {
+		if (!this.bodyParams.description || !this.bodyParams.description.trim()) {
+			return RocketChat.API.v1.failure('The bodyParam "description" is required');
+		}
+
+		const findResult = findChannelById({ roomId: this.bodyParams.roomId });
+
+		if (findResult.description === this.bodyParams.description) {
+			return RocketChat.API.v1.failure('The channel description is the same as what it would be changed to.');
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('saveRoomSettings', findResult._id, 'roomDescription', this.bodyParams.description);
+		});
+
+		return RocketChat.API.v1.success({
+			description: this.bodyParams.description
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.setJoinCode', { authRequired: true }, {
+	post: function() {
+		if (!this.bodyParams.joinCode || !this.bodyParams.joinCode.trim()) {
+			return RocketChat.API.v1.failure('The bodyParam "joinCode" is required');
+		}
+
+		const findResult = findChannelById({ roomId: this.bodyParams.roomId });
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('saveRoomSettings', findResult._id, 'joinCode', this.bodyParams.joinCode);
+		});
+
+		return RocketChat.API.v1.success({
+			channel: RocketChat.models.Rooms.findOneById(findResult._id, { fields: RocketChat.API.v1.defaultFieldsToExclude })
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.setPurpose', { authRequired: true }, {
+	post: function() {
+		if (!this.bodyParams.purpose || !this.bodyParams.purpose.trim()) {
+			return RocketChat.API.v1.failure('The bodyParam "purpose" is required');
+		}
+
+		const findResult = findChannelById({ roomId: this.bodyParams.roomId });
+
+		if (findResult.description === this.bodyParams.purpose) {
+			return RocketChat.API.v1.failure('The channel purpose (description) is the same as what it would be changed to.');
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('saveRoomSettings', findResult._id, 'roomDescription', this.bodyParams.purpose);
+		});
+
+		return RocketChat.API.v1.success({
+			purpose: this.bodyParams.purpose
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.setReadOnly', { authRequired: true }, {
+	post: function() {
+		if (typeof this.bodyParams.readOnly === 'undefined') {
+			return RocketChat.API.v1.failure('The bodyParam "readOnly" is required');
+		}
+
+		const findResult = findChannelById({ roomId: this.bodyParams.roomId });
+
+		if (findResult.ro === this.bodyParams.readOnly) {
+			return RocketChat.API.v1.failure('The channel read only setting is the same as what it would be changed to.');
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('saveRoomSettings', findResult._id, 'readOnly', this.bodyParams.readOnly);
+		});
+
+		return RocketChat.API.v1.success({
+			channel: RocketChat.models.Rooms.findOneById(findResult._id, { fields: RocketChat.API.v1.defaultFieldsToExclude })
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.setTopic', { authRequired: true }, {
+	post: function() {
+		if (!this.bodyParams.topic || !this.bodyParams.topic.trim()) {
+			return RocketChat.API.v1.failure('The bodyParam "topic" is required');
+		}
+
+		const findResult = findChannelById({ roomId: this.bodyParams.roomId });
+
+		if (findResult.topic === this.bodyParams.topic) {
+			return RocketChat.API.v1.failure('The channel topic is the same as what it would be changed to.');
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('saveRoomSettings', findResult._id, 'roomTopic', this.bodyParams.topic);
+		});
+
+		return RocketChat.API.v1.success({
+			topic: this.bodyParams.topic
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.setType', { authRequired: true }, {
+	post: function() {
+		if (!this.bodyParams.type || !this.bodyParams.type.trim()) {
+			return RocketChat.API.v1.failure('The bodyParam "type" is required');
+		}
+
+		const findResult = findChannelById({ roomId: this.bodyParams.roomId });
+
+		if (findResult.t === this.bodyParams.type) {
+			return RocketChat.API.v1.failure('The channel type is the same as what it would be changed to.');
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('saveRoomSettings', findResult._id, 'roomType', this.bodyParams.type);
+		});
+
+		return RocketChat.API.v1.success({
+			channel: RocketChat.models.Rooms.findOneById(findResult._id, { fields: RocketChat.API.v1.defaultFieldsToExclude })
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('channels.unarchive', { authRequired: true }, {
+	post: function() {
+		const findResult = findChannelById({ roomId: this.bodyParams.roomId, checkedArchived: false });
+
+		if (!findResult.archived) {
+			return RocketChat.API.v1.failure(`The channel, ${findResult.name}, is not archived`);
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('unarchiveRoom', findResult._id);
+		});
+
+		return RocketChat.API.v1.success();
+	}
+});
diff --git a/packages/rocketchat-api/server/v1/chat.js b/packages/rocketchat-api/server/v1/chat.js
new file mode 100644
index 0000000000000000000000000000000000000000..90569eda69461326cba0e62fd609da77a8d65ea7
--- /dev/null
+++ b/packages/rocketchat-api/server/v1/chat.js
@@ -0,0 +1,76 @@
+/* global processWebhookMessage */
+RocketChat.API.v1.addRoute('chat.delete', { authRequired: true }, {
+	post: function() {
+		check(this.bodyParams, Match.ObjectIncluding({
+			msgId: String,
+			roomId: String,
+			asUser: Match.Maybe(Boolean)
+		}));
+
+		const msg = RocketChat.models.Messages.findOneById(this.bodyParams.msgId, { fields: { u: 1, rid: 1 }});
+
+		if (!msg) {
+			return RocketChat.API.v1.failure(`No message found with the id of "${this.bodyParams.msgId}".`);
+		}
+
+		if (this.bodyParams.roomId !== msg.rid) {
+			return RocketChat.API.v1.failure('The room id provided does not match where the message is from.');
+		}
+
+		Meteor.runAsUser(this.bodyParams.asUser ? msg.u._id : this.userId, () => {
+			Meteor.call('deleteMessage', { _id: msg._id });
+		});
+
+		return RocketChat.API.v1.success({
+			_id: msg._id,
+			ts: Date.now()
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('chat.postMessage', { authRequired: true }, {
+	post: function() {
+		const messageReturn = processWebhookMessage(this.bodyParams, this.user)[0];
+
+		if (!messageReturn) {
+			return RocketChat.API.v1.failure('unknown-error');
+		}
+
+		return RocketChat.API.v1.success({
+			ts: Date.now(),
+			channel: messageReturn.channel,
+			message: messageReturn.message
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('chat.update', { authRequired: true }, {
+	post: function() {
+		check(this.bodyParams, Match.ObjectIncluding({
+			roomId: String,
+			msgId: String,
+			text: String //Using text to be consistant with chat.postMessage
+		}));
+
+		const msg = RocketChat.models.Messages.findOneById(this.bodyParams.msgId);
+
+		//Ensure the message exists
+		if (!msg) {
+			return RocketChat.API.v1.failure(`No message found with the id of "${this.bodyParams.msgId}".`);
+		}
+
+		if (this.bodyParams.roomId !== msg.rid) {
+			return RocketChat.API.v1.failure('The room id provided does not match where the message is from.');
+		}
+
+		//Permission checks are already done in the updateMessage method, so no need to duplicate them
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('updateMessage', { _id: msg._id, msg: this.bodyParams.text, rid: msg.rid });
+
+		});
+
+		return RocketChat.API.v1.success({
+			message: RocketChat.models.Messages.findOneById(msg._id)
+		});
+	}
+});
diff --git a/packages/rocketchat-api/server/v1/groups.js b/packages/rocketchat-api/server/v1/groups.js
new file mode 100644
index 0000000000000000000000000000000000000000..abef31491b29c1d4b3e384d9371372a71b93ca90
--- /dev/null
+++ b/packages/rocketchat-api/server/v1/groups.js
@@ -0,0 +1,540 @@
+//Returns the private group subscription IF found otherwise it will reutrn the failure of why it didn't. Check the `statusCode` property
+function findPrivateGroupById({ roomId, userId, checkedArchived = true }) {
+	if (!roomId || !roomId.trim()) {
+		return RocketChat.API.v1.failure('Body param "roomId" is required');
+	}
+
+	const roomSub = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(roomId, userId);
+
+	if (!roomSub || roomSub.t !== 'p') {
+		return RocketChat.API.v1.failure(`No private group found by the id of: ${roomId}`);
+	}
+
+	if (checkedArchived && roomSub.archived) {
+		return RocketChat.API.v1.failure(`The private group, ${roomSub.name}, is already archived`);
+	}
+
+	return roomSub;
+}
+
+RocketChat.API.v1.addRoute('groups.addModerator', { authRequired: true }, {
+	post: function() {
+		const findResult = findPrivateGroupById({ roomId: this.bodyParams.roomId, userId: this.userId });
+
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		const user = this.getUserFromParams();
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('addRoomModerator', findResult.rid, user._id);
+		});
+
+		return RocketChat.API.v1.success();
+	}
+});
+
+RocketChat.API.v1.addRoute('groups.addOwner', { authRequired: true }, {
+	post: function() {
+		const findResult = findPrivateGroupById({ roomId: this.bodyParams.roomId, userId: this.userId });
+
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		const user = this.getUserFromParams();
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('addRoomOwner', findResult.rid, user._id);
+		});
+
+		return RocketChat.API.v1.success();
+	}
+});
+
+//Archives a private group only if it wasn't
+RocketChat.API.v1.addRoute('groups.archive', { authRequired: true }, {
+	post: function() {
+		const findResult = findPrivateGroupById({ roomId: this.bodyParams.roomId, userId: this.userId });
+
+		//The find method returns either with the group or the failure
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('archiveRoom', findResult.rid);
+		});
+
+		return RocketChat.API.v1.success();
+	}
+});
+
+RocketChat.API.v1.addRoute('groups.close', { authRequired: true }, {
+	post: function() {
+		const findResult = findPrivateGroupById({ roomId: this.bodyParams.roomId, userId: this.userId, checkedArchived: false });
+
+		//The find method returns either with the group or the failure
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		if (!findResult.open) {
+			return RocketChat.API.v1.failure(`The private group with an id "${this.bodyParams.roomId}" is already closed to the sender`);
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('hideRoom', findResult.rid);
+		});
+
+		return RocketChat.API.v1.success();
+	}
+});
+
+//Create Private Group
+RocketChat.API.v1.addRoute('groups.create', { authRequired: true }, {
+	post: function() {
+		if (!RocketChat.authz.hasPermission(this.userId, 'create-p')) {
+			return RocketChat.API.v1.unauthorized();
+		}
+
+		if (!this.bodyParams.name) {
+			return RocketChat.API.v1.failure('Body param "name" is required');
+		}
+
+		if (this.bodyParams.members && !_.isArray(this.bodyParams.members)) {
+			return RocketChat.API.v1.failure('Body param "members" must be an array if provided');
+		}
+
+		let id;
+		Meteor.runAsUser(this.userId, () => {
+			id = Meteor.call('createPrivateGroup', this.bodyParams.name, this.bodyParams.members ? this.bodyParams.members : []);
+		});
+
+		return RocketChat.API.v1.success({
+			group: RocketChat.models.Rooms.findOneById(id.rid, { fields: RocketChat.API.v1.defaultFieldsToExclude })
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('groups.delete', { authRequired: true }, {
+	post: function() {
+		const findResult = findPrivateGroupById({ roomId: this.bodyParams.roomId, userId: this.userId, checkedArchived: false });
+
+		//The find method returns either with the group or the failure
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('eraseRoom', findResult.rid);
+		});
+
+		return RocketChat.API.v1.success({
+			group: RocketChat.models.Rooms.processQueryOptionsOnResult([findResult._room], { fields: RocketChat.API.v1.defaultFieldsToExclude })[0]
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('groups.getIntegrations', { authRequired: true }, {
+	get: function() {
+		if (!RocketChat.authz.hasPermission(this.userId, 'manage-integrations')) {
+			return RocketChat.API.v1.unauthorized();
+		}
+
+		const findResult = findPrivateGroupById({ roomId: this.queryParams.roomId, userId: this.userId, checkedArchived: false });
+
+		//The find method returns either with the group or the failure
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		let includeAllPrivateGroups = true;
+		if (typeof this.queryParams.includeAllPrivateGroups !== 'undefined') {
+			includeAllPrivateGroups = this.queryParams.includeAllPrivateGroups === 'true';
+		}
+
+		const channelsToSearch = [`#${findResult.name}`];
+		if (includeAllPrivateGroups) {
+			channelsToSearch.push('all_private_groups');
+		}
+
+		const { offset, count } = this.getPaginationItems();
+		const { sort, fields, query } = this.parseJsonQuery();
+
+		const ourQuery = Object.assign({}, query, { channel: { $in: channelsToSearch } });
+		const integrations = RocketChat.models.Integrations.find(ourQuery, {
+			sort: sort ? sort : { _createdAt: 1 },
+			skip: offset,
+			limit: count,
+			fields: Object.assign({}, fields, RocketChat.API.v1.defaultFieldsToExclude)
+		}).fetch();
+
+		return RocketChat.API.v1.success({
+			integrations,
+			count: integrations.length,
+			offset,
+			total: RocketChat.models.Integrations.find(ourQuery).count()
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('groups.history', { authRequired: true }, {
+	get: function() {
+		const findResult = findPrivateGroupById({ roomId: this.queryParams.roomId, userId: this.userId, checkedArchived: false });
+
+		//The find method returns either with the group or the failure
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		let latestDate = new Date();
+		if (this.queryParams.latest) {
+			latestDate = new Date(this.queryParams.latest);
+		}
+
+		let oldestDate = undefined;
+		if (this.queryParams.oldest) {
+			oldestDate = new Date(this.queryParams.oldest);
+		}
+
+		let inclusive = false;
+		if (this.queryParams.inclusive) {
+			inclusive = this.queryParams.inclusive;
+		}
+
+		let count = 20;
+		if (this.queryParams.count) {
+			count = parseInt(this.queryParams.count);
+		}
+
+		let unreads = false;
+		if (this.queryParams.unreads) {
+			unreads = this.queryParams.unreads;
+		}
+
+		let result;
+		Meteor.runAsUser(this.userId, () => {
+			result = Meteor.call('getChannelHistory', { rid: findResult.rid, latest: latestDate, oldest: oldestDate, inclusive, count, unreads });
+		});
+
+		return RocketChat.API.v1.success({
+			messages: result && result.messages ? result.messages : []
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('groups.info', { authRequired: true }, {
+	get: function() {
+		const findResult = findPrivateGroupById({ roomId: this.queryParams.roomId, userId: this.userId, checkedArchived: false });
+
+		//The find method returns either with the group or the failure
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		return RocketChat.API.v1.success({
+			group: RocketChat.models.Rooms.findOneById(findResult.rid, { fields: RocketChat.API.v1.defaultFieldsToExclude })
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('groups.invite', { authRequired: true }, {
+	post: function() {
+		const findResult = findPrivateGroupById({ roomId: this.bodyParams.roomId, userId: this.userId });
+
+		//The find method returns either with the group or the failure
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		const user = this.getUserFromParams();
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('addUserToRoom', { rid: findResult.rid, username: user.username });
+		});
+
+		return RocketChat.API.v1.success({
+			group: RocketChat.models.Rooms.findOneById(findResult.rid, { fields: RocketChat.API.v1.defaultFieldsToExclude })
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('groups.kick', { authRequired: true }, {
+	post: function() {
+		const findResult = findPrivateGroupById({ roomId: this.bodyParams.roomId, userId: this.userId });
+
+		//The find method returns either with the group or the failure
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		const user = this.getUserFromParams();
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('removeUserFromRoom', { rid: findResult.rid, username: user.username });
+		});
+
+		return RocketChat.API.v1.success();
+	}
+});
+
+RocketChat.API.v1.addRoute('groups.leave', { authRequired: true }, {
+	post: function() {
+		const findResult = findPrivateGroupById({ roomId: this.bodyParams.roomId, userId: this.userId });
+
+		//The find method returns either with the group or the failure
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('leaveRoom', findResult.rid);
+		});
+
+		return RocketChat.API.v1.success();
+	}
+});
+
+//List Private Groups a user has access to
+RocketChat.API.v1.addRoute('groups.list', { authRequired: true }, {
+	get: function() {
+		const { offset, count } = this.getPaginationItems();
+		const { sort, fields } = this.parseJsonQuery();
+		let rooms = _.pluck(RocketChat.models.Subscriptions.findByTypeAndUserId('p', this.userId).fetch(), '_room');
+		const totalCount = rooms.length;
+
+		rooms = RocketChat.models.Rooms.processQueryOptionsOnResult(rooms, {
+			sort: sort ? sort : { name: 1 },
+			skip: offset,
+			limit: count,
+			fields: Object.assign({}, fields, RocketChat.API.v1.defaultFieldsToExclude)
+		});
+
+		return RocketChat.API.v1.success({
+			groups: rooms,
+			offset,
+			count: rooms.length,
+			total: totalCount
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('groups.open', { authRequired: true }, {
+	post: function() {
+		const findResult = findPrivateGroupById({ roomId: this.bodyParams.roomId, userId: this.userId, checkedArchived: false });
+
+		//The find method returns either with the group or the failure
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		if (findResult.open) {
+			return RocketChat.API.v1.failure(`The private group, ${this.bodyParams.name}, is already open for the sender`);
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('openRoom', findResult.rid);
+		});
+
+		return RocketChat.API.v1.success();
+	}
+});
+
+RocketChat.API.v1.addRoute('groups.removeModerator', { authRequired: true }, {
+	post: function() {
+		const findResult = findPrivateGroupById({ roomId: this.bodyParams.roomId, userId: this.userId });
+
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		const user = this.getUserFromParams();
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('removeRoomModerator', findResult.rid, user._id);
+		});
+
+		return RocketChat.API.v1.success();
+	}
+});
+
+RocketChat.API.v1.addRoute('groups.removeOwner', { authRequired: true }, {
+	post: function() {
+		const findResult = findPrivateGroupById({ roomId: this.bodyParams.roomId, userId: this.userId });
+
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		const user = this.getUserFromParams();
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('removeRoomOwner', findResult.rid, user._id);
+		});
+
+		return RocketChat.API.v1.success();
+	}
+});
+
+RocketChat.API.v1.addRoute('groups.rename', { authRequired: true }, {
+	post: function() {
+		if (!this.bodyParams.name || !this.bodyParams.name.trim()) {
+			return RocketChat.API.v1.failure('The bodyParam "name" is required');
+		}
+
+		const findResult = findPrivateGroupById({ roomId: this.bodyParams.roomId, userId: this.userId });
+
+		//The find method returns either with the group or the failure
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('saveRoomSettings', findResult.rid, 'roomName', this.bodyParams.name);
+		});
+
+		return RocketChat.API.v1.success({
+			channel: RocketChat.models.Rooms.findOneById(findResult.rid, { fields: RocketChat.API.v1.defaultFieldsToExclude })
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('groups.setDescription', { authRequired: true }, {
+	post: function() {
+		if (!this.bodyParams.description || !this.bodyParams.description.trim()) {
+			return RocketChat.API.v1.failure('The bodyParam "description" is required');
+		}
+
+		const findResult = findPrivateGroupById({ roomId: this.bodyParams.roomId, userId: this.userId });
+
+		//The find method returns either with the group or the failure
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('saveRoomSettings', findResult.rid, 'roomDescription', this.bodyParams.description);
+		});
+
+		return RocketChat.API.v1.success({
+			description: this.bodyParams.description
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('groups.setPurpose', { authRequired: true }, {
+	post: function() {
+		if (!this.bodyParams.purpose || !this.bodyParams.purpose.trim()) {
+			return RocketChat.API.v1.failure('The bodyParam "purpose" is required');
+		}
+
+		const findResult = findPrivateGroupById({ roomId: this.bodyParams.roomId, userId: this.userId });
+
+		//The find method returns either with the group or the failure
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('saveRoomSettings', findResult.rid, 'roomDescription', this.bodyParams.purpose);
+		});
+
+		return RocketChat.API.v1.success({
+			purpose: this.bodyParams.purpose
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('groups.setReadOnly', { authRequired: true }, {
+	post: function() {
+		if (typeof this.bodyParams.readOnly === 'undefined') {
+			return RocketChat.API.v1.failure('The bodyParam "readOnly" is required');
+		}
+
+		const findResult = findPrivateGroupById({ roomId: this.bodyParams.roomId, userId: this.userId });
+
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		if (findResult.ro === this.bodyParams.readOnly) {
+			return RocketChat.API.v1.failure('The private group read only setting is the same as what it would be changed to.');
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('saveRoomSettings', findResult._id, 'readOnly', this.bodyParams.readOnly);
+		});
+
+		return RocketChat.API.v1.success({
+			group: RocketChat.models.Rooms.findOneById(findResult._id, { fields: RocketChat.API.v1.defaultFieldsToExclude })
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('groups.setTopic', { authRequired: true }, {
+	post: function() {
+		if (!this.bodyParams.topic || !this.bodyParams.topic.trim()) {
+			return RocketChat.API.v1.failure('The bodyParam "topic" is required');
+		}
+
+		const findResult = findPrivateGroupById({ roomId: this.bodyParams.roomId, userId: this.userId });
+
+		//The find method returns either with the group or the failure
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('saveRoomSettings', findResult.rid, 'roomTopic', this.bodyParams.topic);
+		});
+
+		return RocketChat.API.v1.success({
+			topic: this.bodyParams.topic
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('groups.setType', { authRequired: true }, {
+	post: function() {
+		if (!this.bodyParams.type || !this.bodyParams.type.trim()) {
+			return RocketChat.API.v1.failure('The bodyParam "type" is required');
+		}
+
+		const findResult = findPrivateGroupById({ roomId: this.bodyParams.roomId, userId: this.userId });
+
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		if (findResult.t === this.bodyParams.type) {
+			return RocketChat.API.v1.failure('The private group type is the same as what it would be changed to.');
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('saveRoomSettings', findResult._id, 'roomType', this.bodyParams.type);
+		});
+
+		return RocketChat.API.v1.success({
+			group: RocketChat.models.Rooms.findOneById(findResult._id, { fields: RocketChat.API.v1.defaultFieldsToExclude })
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('groups.unarchive', { authRequired: true }, {
+	post: function() {
+		const findResult = findPrivateGroupById({ roomId: this.bodyParams.roomId, userId: this.userId });
+
+		//The find method returns either with the group or the failure
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('unarchiveRoom', findResult.rid);
+		});
+
+		return RocketChat.API.v1.success();
+	}
+});
diff --git a/packages/rocketchat-api/server/v1/helpers/getPaginationItems.js b/packages/rocketchat-api/server/v1/helpers/getPaginationItems.js
new file mode 100644
index 0000000000000000000000000000000000000000..dd1732df6c73657826654e4aee212be4cd2ab869
--- /dev/null
+++ b/packages/rocketchat-api/server/v1/helpers/getPaginationItems.js
@@ -0,0 +1,30 @@
+// If the count query param is higher than the "API_Upper_Count_Limit" setting, then we limit that
+// If the count query param isn't defined, then we set it to the "API_Default_Count" setting
+// If the count is zero, then that means unlimited and is only allowed if the setting "API_Allow_Infinite_Count" is true
+
+RocketChat.API.v1.helperMethods.set('getPaginationItems', function _getPaginationItems() {
+	const hardUpperLimit = RocketChat.settings.get('API_Upper_Count_Limit') <= 0 ? 100 : RocketChat.settings.get('API_Upper_Count_Limit');
+	const defaultCount = RocketChat.settings.get('API_Default_Count') <= 0 ? 50 : RocketChat.settings.get('API_Default_Count');
+	const offset = this.queryParams.offset ? parseInt(this.queryParams.offset) : 0;
+	let count = defaultCount;
+
+	// Ensure count is an appropiate amount
+	if (typeof this.queryParams.count !== 'undefined') {
+		count = parseInt(this.queryParams.count);
+	} else {
+		count = defaultCount;
+	}
+
+	if (count > hardUpperLimit) {
+		count = hardUpperLimit;
+	}
+
+	if (count === 0 && !RocketChat.settings.get('API_Allow_Infinite_Count')) {
+		count = defaultCount;
+	}
+
+	return {
+		offset,
+		count
+	};
+});
diff --git a/packages/rocketchat-api/server/v1/helpers/getUserFromParams.js b/packages/rocketchat-api/server/v1/helpers/getUserFromParams.js
new file mode 100644
index 0000000000000000000000000000000000000000..8774549a7e15bf04ac0397e0cc6bdf37359da0d3
--- /dev/null
+++ b/packages/rocketchat-api/server/v1/helpers/getUserFromParams.js
@@ -0,0 +1,35 @@
+//Convience method, almost need to turn it into a middleware of sorts
+RocketChat.API.v1.helperMethods.set('getUserFromParams', function _getUserFromParams() {
+	const doesntExist = { _doesntExist: true };
+	let user;
+
+	switch (this.method) {
+		case 'POST':
+		case 'PUT':
+			if (this.bodyParams.userId && this.bodyParams.userId.trim()) {
+				user = RocketChat.models.Users.findOneById(this.bodyParams.userId) || doesntExist;
+			} else if (this.bodyParams.username && this.bodyParams.username.trim()) {
+				user = RocketChat.models.Users.findOneByUsername(this.bodyParams.username) || doesntExist;
+			} else if (this.bodyParams.user && this.bodyParams.user.trim()) {
+				user = RocketChat.models.Users.findOneByUsername(this.bodyParams.user) || doesntExist;
+			}
+			break;
+		default:
+			if (this.queryParams.userId && this.queryParams.userId.trim()) {
+				user = RocketChat.models.Users.findOneById(this.queryParams.userId) || doesntExist;
+			} else if (this.queryParams.username && this.queryParams.username.trim()) {
+				user = RocketChat.models.Users.findOneByUsername(this.queryParams.username) || doesntExist;
+			} else if (this.queryParams.user && this.queryParams.user.trim()) {
+				user = RocketChat.models.Users.findOneByUsername(this.queryParams.user) || doesntExist;
+			}
+			break;
+	}
+
+	if (!user) {
+		throw new Meteor.Error('error-user-param-not-provided', 'The required "userId" or "username" param was not provided');
+	} else if (user._doesntExist) {
+		throw new Meteor.Error('error-invalid-user', 'The required "userId" or "username" param provided does not match any users');
+	}
+
+	return user;
+});
diff --git a/packages/rocketchat-api/server/v1/helpers/parseJsonQuery.js b/packages/rocketchat-api/server/v1/helpers/parseJsonQuery.js
new file mode 100644
index 0000000000000000000000000000000000000000..073ebf4e83f9aa6a255e82a25f22092e9f51eb71
--- /dev/null
+++ b/packages/rocketchat-api/server/v1/helpers/parseJsonQuery.js
@@ -0,0 +1,37 @@
+RocketChat.API.v1.helperMethods.set('parseJsonQuery', function _parseJsonQuery() {
+	let sort;
+	if (this.queryParams.sort) {
+		try {
+			sort = JSON.parse(this.queryParams.sort);
+		} catch (e) {
+			this.logger.warn(`Invalid sort parameter provided "${this.queryParams.sort}":`, e);
+			throw new Meteor.Error('error-invalid-sort', `Invalid sort parameter provided: "${this.queryParams.sort}"`, { helperMethod: 'parseJsonQuery' });
+		}
+	}
+
+	let fields;
+	if (this.queryParams.fields) {
+		try {
+			fields = JSON.parse(this.queryParams.fields);
+		} catch (e) {
+			this.logger.warn(`Invalid fields parameter provided "${this.queryParams.fields}":`, e);
+			throw new Meteor.Error('error-invalid-fields', `Invalid fields parameter provided: "${this.queryParams.fields}"`, { helperMethod: 'parseJsonQuery' });
+		}
+	}
+
+	let query;
+	if (this.queryParams.query) {
+		try {
+			query = JSON.parse(this.queryParams.query);
+		} catch (e) {
+			this.logger.warn(`Invalid query parameter provided "${this.queryParams.query}":`, e);
+			throw new Meteor.Error('error-invalid-query', `Invalid query parameter provided: "${this.queryParams.query}"`, { helperMethod: 'parseJsonQuery' });
+		}
+	}
+
+	return {
+		sort,
+		fields,
+		query
+	};
+});
diff --git a/packages/rocketchat-api/server/v1/im.js b/packages/rocketchat-api/server/v1/im.js
new file mode 100644
index 0000000000000000000000000000000000000000..78f2762cab65927d86455ebe6d230ccbd6e17db7
--- /dev/null
+++ b/packages/rocketchat-api/server/v1/im.js
@@ -0,0 +1,174 @@
+function findDirectMessageRoomById(roomId, userId) {
+	if (!roomId || !roomId.trim()) {
+		return RocketChat.API.v1.failure('Body param "roomId" is required');
+	}
+
+	const roomSub = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(roomId, userId);
+
+	if (!roomSub || roomSub.t !== 'd') {
+		return RocketChat.API.v1.failure(`No direct message room found by the id of: ${roomId}`);
+	}
+
+	return roomSub;
+}
+
+RocketChat.API.v1.addRoute('im.close', { authRequired: true }, {
+	post: function() {
+		const findResult = findDirectMessageRoomById(this.bodyParams.roomId, this.userId);
+
+		//The find method returns either with the dm or the failure
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		if (!findResult.open) {
+			return RocketChat.API.v1.failure(`The direct message room, ${this.bodyParams.name}, is already closed to the sender`);
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('hideRoom', findResult.rid);
+		});
+
+		return RocketChat.API.v1.success();
+	}
+});
+
+RocketChat.API.v1.addRoute('im.history', { authRequired: true }, {
+	get: function() {
+		const findResult = findDirectMessageRoomById(this.queryParams.roomId, this.userId);
+
+		//The find method returns either with the group or the failure
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		let latestDate = new Date();
+		if (this.queryParams.latest) {
+			latestDate = new Date(this.queryParams.latest);
+		}
+
+		let oldestDate = undefined;
+		if (this.queryParams.oldest) {
+			oldestDate = new Date(this.queryParams.oldest);
+		}
+
+		let inclusive = false;
+		if (this.queryParams.inclusive) {
+			inclusive = this.queryParams.inclusive;
+		}
+
+		let count = 20;
+		if (this.queryParams.count) {
+			count = parseInt(this.queryParams.count);
+		}
+
+		let unreads = false;
+		if (this.queryParams.unreads) {
+			unreads = this.queryParams.unreads;
+		}
+
+		let result;
+		Meteor.runAsUser(this.userId, () => {
+			result = Meteor.call('getChannelHistory', { rid: findResult.rid, latest: latestDate, oldest: oldestDate, inclusive, count, unreads });
+		});
+
+		return RocketChat.API.v1.success({
+			messages: result && result.messages ? result.messages : []
+		});
+	}
+});
+
+
+RocketChat.API.v1.addRoute('im.list', { authRequired: true }, {
+	get: function() {
+		const { offset, count } = this.getPaginationItems();
+		const { sort, fields } = this.parseJsonQuery();
+		let rooms = _.pluck(RocketChat.models.Subscriptions.findByTypeAndUserId('d', this.userId).fetch(), '_room');
+		const totalCount = rooms.length;
+
+		rooms = RocketChat.models.Rooms.processQueryOptionsOnResult(rooms, {
+			sort: sort ? sort : { name: 1 },
+			skip: offset,
+			limit: count,
+			fields: Object.assign({}, fields, RocketChat.API.v1.defaultFieldsToExclude)
+		});
+
+		return RocketChat.API.v1.success({
+			ims: rooms,
+			offset,
+			count: rooms.length,
+			total: totalCount
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('im.list.everyone', { authRequired: true }, {
+	get: function() {
+		if (!RocketChat.authz.hasPermission(this.userId, 'view-room-administration')) {
+			return RocketChat.API.v1.unauthorized();
+		}
+
+		const { offset, count } = this.getPaginationItems();
+		const { sort, fields, query } = this.parseJsonQuery();
+
+		const ourQuery = Object.assign({}, query, { t: 'd' });
+
+		const rooms = RocketChat.models.Rooms.find(ourQuery, {
+			sort: sort ? sort : { name: 1 },
+			skip: offset,
+			limit: count,
+			fields: Object.assign({}, fields, RocketChat.API.v1.defaultFieldsToExclude)
+		}).fetch();
+
+		return RocketChat.API.v1.success({
+			ims: rooms,
+			offset,
+			count: rooms.length,
+			total: RocketChat.models.Rooms.find(ourQuery).count()
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('im.open', { authRequired: true }, {
+	post: function() {
+		const findResult = findDirectMessageRoomById(this.bodyParams.roomId, this.userId);
+
+		//The find method returns either with the group or the failure
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		if (findResult.open) {
+			return RocketChat.API.v1.failure(`The direct message room, ${this.bodyParams.name}, is already open for the sender`);
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('openRoom', findResult.rid);
+		});
+
+		return RocketChat.API.v1.success();
+	}
+});
+
+RocketChat.API.v1.addRoute('im.setTopic', { authRequired: true }, {
+	post: function() {
+		if (!this.bodyParams.topic || !this.bodyParams.topic.trim()) {
+			return RocketChat.API.v1.failure('The bodyParam "topic" is required');
+		}
+
+		const findResult = findDirectMessageRoomById(this.bodyParams.roomId, this.userId);
+
+		//The find method returns either with the group or the failure
+		if (findResult.statusCode) {
+			return findResult;
+		}
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('saveRoomSettings', findResult.rid, 'roomTopic', this.bodyParams.topic);
+		});
+
+		return RocketChat.API.v1.success({
+			topic: this.bodyParams.topic
+		});
+	}
+});
diff --git a/packages/rocketchat-api/server/v1/integrations.js b/packages/rocketchat-api/server/v1/integrations.js
new file mode 100644
index 0000000000000000000000000000000000000000..9294dbb54135c1aa0799affe94d3dadce4930b77
--- /dev/null
+++ b/packages/rocketchat-api/server/v1/integrations.js
@@ -0,0 +1,98 @@
+RocketChat.API.v1.addRoute('integrations.create', { authRequired: true }, {
+	post: function() {
+		check(this.bodyParams, Match.ObjectIncluding({
+			type: String,
+			name: String,
+			enabled: Boolean,
+			username: String,
+			urls: [String],
+			channel: Match.Maybe(String),
+			triggerWords: Match.Maybe([String]),
+			alias: Match.Maybe(String),
+			avatar: Match.Maybe(String),
+			emoji: Match.Maybe(String),
+			token: Match.Maybe(String),
+			scriptEnabled: Boolean,
+			script: Match.Maybe(String)
+		}));
+
+		let integration;
+
+		switch (this.bodyParams.type) {
+			case 'webhook-outgoing':
+				Meteor.runAsUser(this.userId, () => {
+					integration = Meteor.call('addOutgoingIntegration', this.bodyParams);
+				});
+				break;
+			default:
+				return RocketChat.API.v1.failure('Invalid integration type.');
+		}
+
+		return RocketChat.API.v1.success({ integration });
+	}
+});
+
+RocketChat.API.v1.addRoute('integrations.list', { authRequired: true }, {
+	get: function() {
+		if (!RocketChat.authz.hasPermission(this.userId, 'manage-integrations')) {
+			return RocketChat.API.v1.unauthorized();
+		}
+
+		const { offset, count } = this.getPaginationItems();
+		const { sort, fields, query } = this.parseJsonQuery();
+
+		const ourQuery = Object.assign({}, query);
+		const integrations = RocketChat.models.Integrations.find(ourQuery, {
+			sort: sort ? sort : { ts: -1 },
+			skip: offset,
+			limit: count,
+			fields
+		}).fetch();
+
+		return RocketChat.API.v1.success({
+			integrations: integrations,
+			offset,
+			items: integrations.length,
+			total: RocketChat.models.Integrations.find(ourQuery).count()
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('integrations.remove', { authRequired: true }, {
+	post: function() {
+		check(this.bodyParams, Match.ObjectIncluding({
+			type: String,
+			target_url: Match.Maybe(String),
+			integrationId: Match.Maybe(String)
+		}));
+
+		if (!this.bodyParams.target_url && !this.bodyParams.integrationId) {
+			return RocketChat.API.v1.failure('An integrationId or target_url needs to be provided.');
+		}
+
+		switch (this.bodyParams.type) {
+			case 'webhook-outgoing':
+				let integration;
+
+				if (this.bodyParams.target_url) {
+					integration = RocketChat.models.Integrations.findOne({ urls: this.bodyParams.target_url });
+				} else if (this.bodyParams.integrationId) {
+					integration = RocketChat.models.Integrations.findOne({ _id: this.bodyParams.integrationId });
+				}
+
+				if (!integration) {
+					return RocketChat.API.v1.failure('No integration found.');
+				}
+
+				Meteor.runAsUser(this.userId, () => {
+					Meteor.call('deleteOutgoingIntegration', integration._id);
+				});
+
+				return RocketChat.API.v1.success({
+					integration: integration
+				});
+			default:
+				return RocketChat.API.v1.failure('Invalid integration type.');
+		}
+	}
+});
diff --git a/packages/rocketchat-api/server/v1/misc.js b/packages/rocketchat-api/server/v1/misc.js
new file mode 100644
index 0000000000000000000000000000000000000000..6a2a58027694e6240a9e7352cef74a940bf09aad
--- /dev/null
+++ b/packages/rocketchat-api/server/v1/misc.js
@@ -0,0 +1,23 @@
+RocketChat.API.v1.addRoute('info', { authRequired: false }, {
+	get: function() {
+		return RocketChat.API.v1.success({
+			info: RocketChat.Info
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('me', { authRequired: true }, {
+	get: function() {
+		return RocketChat.API.v1.success(_.pick(this.user, [
+			'_id',
+			'name',
+			'emails',
+			'status',
+			'statusConnection',
+			'username',
+			'utcOffset',
+			'active',
+			'language'
+		]));
+	}
+});
diff --git a/packages/rocketchat-api/server/v1/settings.js b/packages/rocketchat-api/server/v1/settings.js
new file mode 100644
index 0000000000000000000000000000000000000000..3f6af353d7a3bddb9197f74900b1c4d832f1cd5b
--- /dev/null
+++ b/packages/rocketchat-api/server/v1/settings.js
@@ -0,0 +1,56 @@
+// settings endpoints
+RocketChat.API.v1.addRoute('settings', { authRequired: true }, {
+	get() {
+		const { offset, count } = this.getPaginationItems();
+		const { sort, fields, query } = this.parseJsonQuery();
+
+		let ourQuery = {
+			hidden: { $ne: true }
+		};
+
+		if (!RocketChat.authz.hasPermission(this.userId, 'view-privileged-setting')) {
+			ourQuery.public = true;
+		}
+
+		ourQuery = Object.assign({}, query, ourQuery);
+
+		const settings = RocketChat.models.Settings.find(ourQuery, {
+			sort: sort ? sort : { _id: 1 },
+			skip: offset,
+			limit: count,
+			fields: Object.assign({ _id: 1, value: 1 }, fields)
+		}).fetch();
+
+		return RocketChat.API.v1.success({
+			settings,
+			count: settings.length,
+			offset,
+			total: RocketChat.models.Settings.find(ourQuery).count()
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('settings/:_id', { authRequired: true }, {
+	get() {
+		if (!RocketChat.authz.hasPermission(this.userId, 'view-privileged-setting')) {
+			return RocketChat.API.v1.unauthorized();
+		}
+
+		return RocketChat.API.v1.success(_.pick(RocketChat.models.Settings.findOneNotHiddenById(this.urlParams._id), '_id', 'value'));
+	},
+	post() {
+		if (!RocketChat.authz.hasPermission(this.userId, 'edit-privileged-setting')) {
+			return RocketChat.API.v1.unauthorized();
+		}
+
+		check(this.bodyParams, {
+			value: Match.Any
+		});
+
+		if (RocketChat.models.Settings.updateValueNotHiddenById(this.urlParams._id, this.bodyParams.value)) {
+			return RocketChat.API.v1.success();
+		}
+
+		return RocketChat.API.v1.failure();
+	}
+});
diff --git a/packages/rocketchat-api/server/v1/users.js b/packages/rocketchat-api/server/v1/users.js
new file mode 100644
index 0000000000000000000000000000000000000000..151effe1d7a1b77f5a242e603d2ca9f22151a7ad
--- /dev/null
+++ b/packages/rocketchat-api/server/v1/users.js
@@ -0,0 +1,213 @@
+RocketChat.API.v1.addRoute('users.create', { authRequired: true }, {
+	post: function() {
+		check(this.bodyParams, {
+			email: String,
+			name: String,
+			password: String,
+			username: String,
+			active: Match.Maybe(Boolean),
+			roles: Match.Maybe(Array),
+			joinDefaultChannels: Match.Maybe(Boolean),
+			requirePasswordChange: Match.Maybe(Boolean),
+			sendWelcomeEmail: Match.Maybe(Boolean),
+			verified: Match.Maybe(Boolean),
+			customFields: Match.Maybe(Object)
+		});
+
+		//New change made by pull request #5152
+		if (typeof this.bodyParams.joinDefaultChannels === 'undefined') {
+			this.bodyParams.joinDefaultChannels = true;
+		}
+
+		const newUserId = RocketChat.saveUser(this.userId, this.bodyParams);
+
+		if (this.bodyParams.customFields) {
+			RocketChat.saveCustomFields(newUserId, this.bodyParams.customFields);
+		}
+
+		if (typeof this.bodyParams.active !== 'undefined') {
+			Meteor.runAsUser(this.userId, () => {
+				Meteor.call('setUserActiveStatus', newUserId, this.bodyParams.active);
+			});
+		}
+
+		return RocketChat.API.v1.success({ user: RocketChat.models.Users.findOneById(newUserId, { fields: RocketChat.API.v1.defaultFieldsToExclude }) });
+	}
+});
+
+RocketChat.API.v1.addRoute('users.delete', { authRequired: true }, {
+	post: function() {
+		if (!RocketChat.authz.hasPermission(this.userId, 'delete-user')) {
+			return RocketChat.API.v1.unauthorized();
+		}
+
+		const user = this.getUserFromParams();
+
+		Meteor.runAsUser(this.userId, () => {
+			Meteor.call('deleteUser', user._id);
+		});
+
+		return RocketChat.API.v1.success();
+	}
+});
+
+RocketChat.API.v1.addRoute('users.getPresence', { authRequired: true }, {
+	get: function() {
+		//BLAHHHHHHHHHH :'(
+		if ((this.queryParams.userId && this.userId !== this.queryParams.userId) || (this.queryParams.username && this.user.username !== this.queryParams.username) || (this.queryParams.user && this.user.username !== this.queryParams.user)) {
+			const user = this.getUserFromParams();
+
+			return RocketChat.API.v1.success({
+				presence: user.status
+			});
+		}
+
+		const user = RocketChat.models.Users.findOneById(this.userId);
+		return RocketChat.API.v1.success({
+			presence: user.status,
+			connectionStatus: user.statusConnection,
+			lastLogin: user.lastLogin
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('users.info', { authRequired: true }, {
+	get: function() {
+		const user = this.getUserFromParams();
+
+		let result;
+		Meteor.runAsUser(this.userId, () => {
+			result = Meteor.call('getFullUserData', { filter: user.username, limit: 1 });
+		});
+
+		if (!result || result.length !== 1) {
+			return RocketChat.API.v1.failure(`Failed to get the user data for the userId of "${user._id}".`);
+		}
+
+		return RocketChat.API.v1.success({
+			user: result[0]
+		});
+	}
+});
+
+RocketChat.API.v1.addRoute('users.list', { authRequired: true }, {
+	get: function() {
+		const { offset, count } = this.getPaginationItems();
+		const { sort, fields, query } = this.parseJsonQuery();
+
+		let fieldsToKeepFromRegularUsers;
+		if (!RocketChat.authz.hasPermission(this.userId, 'view-full-other-user-info')) {
+			fieldsToKeepFromRegularUsers = {
+				avatarOrigin: 0,
+				emails: 0,
+				phone: 0,
+				statusConnection: 0,
+				createdAt: 0,
+				lastLogin: 0,
+				services: 0,
+				requirePasswordChange: 0,
+				requirePasswordChangeReason: 0,
+				roles: 0,
+				statusDefault: 0,
+				_updatedAt: 0,
+				customFields: 0
+			};
+		}
+
+		const ourQuery = Object.assign({}, query);
+		const ourFields = Object.assign({}, fields, fieldsToKeepFromRegularUsers, RocketChat.API.v1.defaultFieldsToExclude);
+
+		const users = RocketChat.models.Users.find(ourQuery, {
+			sort: sort ? sort : { username: 1 },
+			skip: offset,
+			limit: count,
+			fields: ourFields
+		}).fetch();
+
+		return RocketChat.API.v1.success({
+			users,
+			count: users.length,
+			offset,
+			total: RocketChat.models.Users.find(ourQuery).count()
+		});
+	}
+});
+
+//TODO: Make this route work with support for usernames
+RocketChat.API.v1.addRoute('users.setAvatar', { authRequired: true }, {
+	post: function() {
+		check(this.bodyParams, { avatarUrl: Match.Maybe(String), userId: Match.Maybe(String) });
+
+		if (typeof this.bodyParams.userId !== 'undefined' && this.userId !== this.bodyParams.userId && !RocketChat.authz.hasPermission(this.userId, 'edit-other-user-info')) {
+			return RocketChat.API.v1.unauthorized();
+		}
+
+		const user = Meteor.users.findOne(this.bodyParams.userId ? this.bodyParams.userId : this.userId);
+
+		if (this.bodyParams.avatarUrl) {
+			RocketChat.setUserAvatar(user, this.bodyParams.avatarUrl, '', 'url');
+		} else {
+			const Busboy = Npm.require('busboy');
+			const busboy = new Busboy({ headers: this.request.headers });
+
+			Meteor.wrapAsync((callback) => {
+				busboy.on('file', Meteor.bindEnvironment((fieldname, file, filename, encoding, mimetype) => {
+					if (fieldname !== 'image') {
+						return callback(new Meteor.Error('invalid-field'));
+					}
+
+					const imageData = [];
+					file.on('data', Meteor.bindEnvironment((data) => {
+						imageData.push(data);
+					}));
+
+					file.on('end', Meteor.bindEnvironment(() => {
+						RocketChat.setUserAvatar(user, Buffer.concat(imageData), mimetype, 'rest');
+						callback();
+					}));
+
+					this.request.pipe(busboy);
+				}));
+			})();
+		}
+
+		return RocketChat.API.v1.success();
+	}
+});
+
+RocketChat.API.v1.addRoute('users.update', { authRequired: true }, {
+	post: function() {
+		check(this.bodyParams, {
+			userId: String,
+			data: Match.ObjectIncluding({
+				email: Match.Maybe(String),
+				name: Match.Maybe(String),
+				password: Match.Maybe(String),
+				username: Match.Maybe(String),
+				active: Match.Maybe(Boolean),
+				roles: Match.Maybe(Array),
+				joinDefaultChannels: Match.Maybe(Boolean),
+				requirePasswordChange: Match.Maybe(Boolean),
+				sendWelcomeEmail: Match.Maybe(Boolean),
+				verified: Match.Maybe(Boolean),
+				customFields: Match.Maybe(Object)
+			})
+		});
+
+		const userData = _.extend({ _id: this.bodyParams.userId }, this.bodyParams.data);
+
+		RocketChat.saveUser(this.userId, userData);
+
+		if (this.bodyParams.data.customFields) {
+			RocketChat.saveCustomFields(this.bodyParams.userId, this.bodyParams.data.customFields);
+		}
+
+		if (typeof this.bodyParams.data.active !== 'undefined') {
+			Meteor.runAsUser(this.userId, () => {
+				Meteor.call('setUserActiveStatus', this.bodyParams.userId, this.bodyParams.data.active);
+			});
+		}
+
+		return RocketChat.API.v1.success({ user: RocketChat.models.Users.findOneById(this.bodyParams.userId, { fields: RocketChat.API.v1.defaultFieldsToExclude }) });
+	}
+});
diff --git a/packages/rocketchat-assets/package.js b/packages/rocketchat-assets/package.js
index c39b215d6d2c249a81bede0272e640b711876cce..ff71e218bea3d92cdf26caecbd1171e33915711a 100644
--- a/packages/rocketchat-assets/package.js
+++ b/packages/rocketchat-assets/package.js
@@ -20,6 +20,5 @@ Package.onUse(function(api) {
 });
 
 Npm.depends({
-	'image-size': '0.4.0',
-	'mime-types': '2.1.9'
+	'image-size': '0.4.0'
 });
diff --git a/packages/rocketchat-assets/server/assets.coffee b/packages/rocketchat-assets/server/assets.coffee
index f7104791838b6b0850acf7ab6dca729f47c1f2ca..e210bdb5c9597c78826565f67b0291ecf1047bb4 100644
--- a/packages/rocketchat-assets/server/assets.coffee
+++ b/packages/rocketchat-assets/server/assets.coffee
@@ -18,7 +18,7 @@ assets =
 			width: undefined
 			height: undefined
 	'favicon_ico':
-		label: 'favicon.ico'
+		label: 'favicon (ico)'
 		defaultUrl: 'favicon.ico'
 		constraints:
 			type: 'image'
@@ -26,53 +26,101 @@ assets =
 			width: undefined
 			height: undefined
 	'favicon':
-		label: 'favicon.svg'
+		label: 'favicon (svg)'
 		defaultUrl: 'images/logo/icon.svg'
 		constraints:
 			type: 'image'
 			extensions: ['svg']
 			width: undefined
 			height: undefined
-	'favicon_64':
-		label: 'favicon.png (64x64)'
-		defaultUrl: 'images/logo/favicon-64x64.png'
+	'favicon_16':
+		label: 'favicon 16x16 (png)'
+		defaultUrl: 'images/logo/favicon-16x16.png'
 		constraints:
 			type: 'image'
 			extensions: ['png']
-			width: 64
-			height: 64
-	'favicon_96':
-		label: 'favicon.png (96x96)'
-		defaultUrl: 'images/logo/favicon-96x96.png'
+			width: 16
+			height: 16
+	'favicon_32':
+		label: 'favicon 32x32 (png)'
+		defaultUrl: 'images/logo/favicon-32x32.png'
 		constraints:
 			type: 'image'
 			extensions: ['png']
-			width: 96
-			height: 96
-	'favicon_128':
-		label: 'favicon.png (128x128)'
-		defaultUrl: 'images/logo/favicon-128x128.png'
-		constraints:
-			type: 'image'
-			extensions: ['png']
-			width: 128
-			height: 128
+			width: 32
+			height: 32
 	'favicon_192':
-		label: 'favicon.png (192x192)'
+		label: 'android-chrome 192x192 (png)'
 		defaultUrl: 'images/logo/android-chrome-192x192.png'
 		constraints:
 			type: 'image'
 			extensions: ['png']
 			width: 192
 			height: 192
-	'favicon_256':
-		label: 'favicon.png (256x256)'
-		defaultUrl: 'images/logo/favicon-256x256.png'
+	'favicon_512':
+		label: 'android-chrome 512x512 (png)'
+		defaultUrl: 'images/logo/512x512.png'
+		constraints:
+			type: 'image'
+			extensions: ['png']
+			width: 512
+			height: 512
+	'touchicon_180':
+		label: 'apple-touch-icon 180x180 (png)'
+		defaultUrl: 'images/logo/apple-touch-icon.png'
+		constraints:
+			type: 'image'
+			extensions: ['png']
+			width: 180
+			height: 180
+	'touchicon_180_pre':
+		label: 'apple-touch-icon-precomposed 180x180 (png)'
+		defaultUrl: 'images/logo/apple-touch-icon-precomposed.png'
+		constraints:
+			type: 'image'
+			extensions: ['png']
+			width: 180
+			height: 180
+	'tile_144':
+		label: 'mstile 144x144 (png)'
+		defaultUrl: 'images/logo/mstile-144x144.png'
+		constraints:
+			type: 'image'
+			extensions: ['png']
+			width: 144
+			height: 144
+	'tile_150':
+		label: 'mstile 150x150 (png)'
+		defaultUrl: 'images/logo/mstile-150x150.png'
 		constraints:
 			type: 'image'
 			extensions: ['png']
-			width: 256
-			height: 256
+			width: 150
+			height: 150
+	'tile_310_square':
+		label: 'mstile 310x310 (png)'
+		defaultUrl: 'images/logo/mstile-310x310.png'
+		constraints:
+			type: 'image'
+			extensions: ['png']
+			width: 310
+			height: 310
+	'tile_310_wide':
+		label: 'mstile 310x150 (png)'
+		defaultUrl: 'images/logo/mstile-310x150.png'
+		constraints:
+			type: 'image'
+			extensions: ['png']
+			width: 310
+			height: 150
+	'safari_pinned':
+		label: 'safari pinneed tab (svg)'
+		defaultUrl: 'images/logo/safari-pinned-tab.svg'
+		constraints:
+			type: 'image'
+			extensions: ['svg']
+			width: undefined
+			height: undefined
 
 
 RocketChat.Assets = new class
diff --git a/packages/rocketchat-authorization/client/hasPermission.coffee b/packages/rocketchat-authorization/client/hasPermission.coffee
index 14fcd42ec36badc55816a0da71798be55c3095d2..c9861bebc2e91d43b5d614de2d8e51c0f9476a7c 100644
--- a/packages/rocketchat-authorization/client/hasPermission.coffee
+++ b/packages/rocketchat-authorization/client/hasPermission.coffee
@@ -1,7 +1,7 @@
 atLeastOne = (permissions, scope) ->
 	return _.some permissions, (permissionId) ->
 		permission = ChatPermissions.findOne permissionId
-		return _.some permission.roles, (roleName) ->
+		return permission and _.some permission.roles, (roleName) ->
 			role = RocketChat.models.Roles.findOne roleName
 			roleScope = role?.scope
 			return RocketChat.models[roleScope]?.isUserInRole?(Meteor.userId(), roleName, scope)
diff --git a/packages/rocketchat-authorization/client/requiresPermission.html b/packages/rocketchat-authorization/client/requiresPermission.html
new file mode 100644
index 0000000000000000000000000000000000000000..db71b5643888d1b2f0891412ca7a85be42041b21
--- /dev/null
+++ b/packages/rocketchat-authorization/client/requiresPermission.html
@@ -0,0 +1,11 @@
+<template name="requiresPermission">
+	{{#if hasPermission this}}
+		{{> Template.contentBlock}}
+	{{else}}
+		{{#if Template.elseBlock}}
+			{{> Template.elseBlock}}
+		{{else}}
+			{{_ "Not_found_or_not_allowed"}}
+		{{/if}}
+	{{/if}}
+</template>
diff --git a/packages/rocketchat-authorization/client/stylesheets/load.coffee b/packages/rocketchat-authorization/client/stylesheets/load.coffee
deleted file mode 100644
index 1e284cb4903eed0dc1dda7fd5c1aad79e537f3b6..0000000000000000000000000000000000000000
--- a/packages/rocketchat-authorization/client/stylesheets/load.coffee
+++ /dev/null
@@ -1 +0,0 @@
-RocketChat.theme.addPackageAsset -> Assets.getText 'client/stylesheets/permissions.less'
diff --git a/packages/rocketchat-authorization/client/stylesheets/permissions.less b/packages/rocketchat-authorization/client/stylesheets/permissions.less
index 756999f86a30d262860fa3a1bf2aac18269bb287..c970dbf8d1f2056a4eb8fcaf59e082ab8d8929c0 100644
--- a/packages/rocketchat-authorization/client/stylesheets/permissions.less
+++ b/packages/rocketchat-authorization/client/stylesheets/permissions.less
@@ -4,27 +4,29 @@
 		font-size: 16px;
 		margin-top: 1em !important;
 		margin-bottom: 1em !important;
-		border-bottom: 1px solid @tertiary-background-color;
+		border-bottom-width: 1px;
 	}
 
 	.permission-grid {
 		th {
 			white-space: normal;
-	    text-align: center;
-	    position: relative;
-	    padding-top: 20px;
+			text-align: center;
+			position: relative;
+			padding-top: 20px;
 		}
+
 		td {
 			text-align: center;
 			width: 10%;
 		}
+
 		.icon-edit {
 			font-size: 80%;
 			position: absolute;
-	    padding-left: 2px;
-	    top: 0;
-	    left: 50%;
-	    transform: translateX(-50%);
+			padding-left: 2px;
+			top: 0;
+			left: 50%;
+			transform: translateX(-50%);
 		}
 	}
 
diff --git a/packages/rocketchat-authorization/client/views/permissions.html b/packages/rocketchat-authorization/client/views/permissions.html
index e9162bb589725ea969ced9cfe7102d4109b69438..3d53eb803e4227320ab43ed49ecedfb9b9529d92 100644
--- a/packages/rocketchat-authorization/client/views/permissions.html
+++ b/packages/rocketchat-authorization/client/views/permissions.html
@@ -2,12 +2,12 @@
 	<div class="permissions-manager">
 		{{#if hasPermission}}
 			<a href="{{pathFor "admin-permissions-new"}}" class="button primary new-role">{{_ "New_role"}}</a>
-			<table border="1" class="permission-grid">
-				<thead>
+			<table border="1" class="permission-grid secondary-background-color">
+				<thead class="content-background-color">
 					<tr>
-						<th>&nbsp;</th>
+						<th class="border-component-color">&nbsp;</th>
 						{{#each role}}
-							<th title="{{description}}">
+							<th class="border-component-color" title="{{description}}">
 								<a href="{{pathFor "admin-permissions-edit" name=_id}}">
 									{{_id}}
 									<i class="icon-edit"></i>
@@ -18,10 +18,10 @@
 				</thead>
 				<tbody>
 					{{#each permission}}
-						<tr>
-							<td>{{_id}}</td>
+						<tr class="admin-table-row">
+							<td class="border-component-color">{{_id}}</td>
 							{{#each role}}
-								<td>
+								<td class="border-component-color">
 									<input type="checkbox" name="perm[{{_id}}][{{../_id}}]" class="role-permission" value="1" checked="{{granted ../roles}}" data-role="{{_id}}" data-permission="{{../_id}}">
 								</td>
 							{{/each}}
diff --git a/packages/rocketchat-authorization/client/views/permissionsRole.html b/packages/rocketchat-authorization/client/views/permissionsRole.html
index dd602f8794168d250cdd1caeb677cfda3950eede..4aaa9f69243162626bdbf1f78d6f8db612cd38b5 100644
--- a/packages/rocketchat-authorization/client/views/permissionsRole.html
+++ b/packages/rocketchat-authorization/client/views/permissionsRole.html
@@ -30,7 +30,7 @@
 				</form>
 			{{/with}}
 			{{#if editing}}
-				<h2>{{_ "Users_in_role"}}</h2>
+				<h2 class="border-tertiary-background-color">{{_ "Users_in_role"}}</h2>
 				{{#if $eq role.scope 'Subscriptions'}}
 					<form id="form-search-room" class="inline">
 						<label>{{_ "Choose_a_room"}}</label>
diff --git a/packages/rocketchat-authorization/package.js b/packages/rocketchat-authorization/package.js
index 8dac681dc7df62a3a84d488afbb1dc3794bdcbdc..6838b9aeed6b99a15365929074d2418a576fbebc 100644
--- a/packages/rocketchat-authorization/package.js
+++ b/packages/rocketchat-authorization/package.js
@@ -11,7 +11,8 @@ Package.onUse(function(api) {
 		'ecmascript',
 		'coffeescript',
 		'underscore',
-		'rocketchat:lib'
+		'rocketchat:lib',
+		'less'
 	]);
 
 	api.use('mongo', ['client', 'server']);
@@ -31,6 +32,7 @@ Package.onUse(function(api) {
 	api.addFiles('client/startup.coffee', ['client']);
 	api.addFiles('client/hasPermission.coffee', ['client']);
 	api.addFiles('client/hasRole.coffee', ['client']);
+	api.addFiles('client/requiresPermission.html', ['client']);
 
 	api.addFiles('client/route.coffee', ['client']);
 
@@ -41,8 +43,7 @@ Package.onUse(function(api) {
 	api.addFiles('client/views/permissionsRole.coffee', ['client']);
 
 	// stylesheets
-	api.addAssets('client/stylesheets/permissions.less', 'server');
-	api.addFiles('client/stylesheets/load.coffee', 'server');
+	api.addFiles('client/stylesheets/permissions.less', 'client');
 
 	api.addFiles('server/models/Permissions.coffee', ['server']);
 	api.addFiles('server/models/Roles.coffee', ['server']);
diff --git a/packages/rocketchat-authorization/server/functions/addUserRoles.coffee b/packages/rocketchat-authorization/server/functions/addUserRoles.coffee
index 647c25d68269ad8695e18755c716f0dbd883d241..626b1769f235c781766001d716e95faa069b8707 100644
--- a/packages/rocketchat-authorization/server/functions/addUserRoles.coffee
+++ b/packages/rocketchat-authorization/server/functions/addUserRoles.coffee
@@ -2,7 +2,7 @@ RocketChat.authz.addUserRoles = (userId, roleNames, scope) ->
 	if not userId or not roleNames
 		return false
 
-	user = RocketChat.models.Users.findOneById(userId)
+	user = RocketChat.models.Users.db.findOneById(userId)
 	if not user
 		throw new Meteor.Error 'error-invalid-user', 'Invalid user', { function: 'RocketChat.authz.addUserRoles' }
 
diff --git a/packages/rocketchat-authorization/server/functions/canAccessRoom.js b/packages/rocketchat-authorization/server/functions/canAccessRoom.js
index e010678f67a80daf25a4d476dc0d229646760f64..5e41811e28f8a01c27db33af1e19bedca1174e38 100644
--- a/packages/rocketchat-authorization/server/functions/canAccessRoom.js
+++ b/packages/rocketchat-authorization/server/functions/canAccessRoom.js
@@ -1,7 +1,10 @@
 /* globals RocketChat */
 RocketChat.authz.roomAccessValidators = [
 	function(room, user) {
-		return room.usernames.indexOf(user.username) !== -1;
+		const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, user._id);
+		if (subscription) {
+			return subscription._room;
+		}
 	},
 	function(room, user) {
 		if (room.t === 'c') {
diff --git a/packages/rocketchat-authorization/server/models/Permissions.coffee b/packages/rocketchat-authorization/server/models/Permissions.coffee
index 096917c69bb69e613c28aec2c1d0dfbee9756f57..3da9a835bef94db1bd6581141111317dbee7c133 100644
--- a/packages/rocketchat-authorization/server/models/Permissions.coffee
+++ b/packages/rocketchat-authorization/server/models/Permissions.coffee
@@ -22,4 +22,5 @@ class ModelPermissions extends RocketChat.models._Base
 		@update({ _id: permission }, { $pull: { roles: role } })
 
 
-RocketChat.models.Permissions = new ModelPermissions('permissions')
+RocketChat.models.Permissions = new ModelPermissions('permissions', true)
+RocketChat.models.Permissions.cache.load()
diff --git a/packages/rocketchat-authorization/server/publications/permissions.js b/packages/rocketchat-authorization/server/publications/permissions.js
index e1e3072e13b4e6218522d0a16dc6f1b3cb226cdd..5180f9e852ca154861014db9853e4db58bd0c2bd 100644
--- a/packages/rocketchat-authorization/server/publications/permissions.js
+++ b/packages/rocketchat-authorization/server/publications/permissions.js
@@ -2,19 +2,22 @@ Meteor.methods({
 	'permissions/get'(updatedAt) {
 		this.unblock();
 
+		const records = RocketChat.models.Permissions.find().fetch();
+
 		if (updatedAt instanceof Date) {
-			return RocketChat.models.Permissions.dinamicFindChangesAfter('find', updatedAt);
+			return {
+				update: records.filter((record) => {
+					return record._updatedAt > updatedAt;
+				}),
+				remove: RocketChat.models.Permissions.trashFindDeletedAfter(updatedAt, {}, {fields: {_id: 1, _deletedAt: 1}}).fetch()
+			};
 		}
 
-		return RocketChat.models.Permissions.find().fetch();
+		return records;
 	}
 });
 
 
-RocketChat.models.Permissions.on('change', (type, ...args) => {
-	const records = RocketChat.models.Permissions.getChangedRecords(type, args[0]);
-
-	for (const record of records) {
-		RocketChat.Notifications.notifyAll('permissions-changed', type, record);
-	}
+RocketChat.models.Permissions.on('changed', (type, permission) => {
+	RocketChat.Notifications.notifyAllInThisInstance('permissions-changed', type, permission);
 });
diff --git a/packages/rocketchat-authorization/server/startup.coffee b/packages/rocketchat-authorization/server/startup.coffee
index a6beed9bbd3a71cbc62d889be3b9e97a3d2f8e3e..1037dcaf5e8c76bcf980d6c2b35056e2fcf4fb97 100644
--- a/packages/rocketchat-authorization/server/startup.coffee
+++ b/packages/rocketchat-authorization/server/startup.coffee
@@ -13,10 +13,11 @@ Meteor.startup ->
 		{ _id: 'ban-user',                      roles : ['admin', 'owner', 'moderator'] }
 		{ _id: 'bulk-create-c',                 roles : ['admin'] }
 		{ _id: 'bulk-register-user',            roles : ['admin'] }
-		{ _id: 'create-c',                      roles : ['admin', 'user'] }
-		{ _id: 'create-d',                      roles : ['admin', 'user'] }
-		{ _id: 'create-p',                      roles : ['admin', 'user'] }
+		{ _id: 'create-c',                      roles : ['admin', 'user', 'bot'] }
+		{ _id: 'create-d',                      roles : ['admin', 'user', 'bot'] }
+		{ _id: 'create-p',                      roles : ['admin', 'user', 'bot'] }
 		{ _id: 'create-user',                   roles : ['admin'] }
+		{ _id: 'clean-channel-history',         roles : ['admin'] } # special permission to bulk delete a channel's mesages
 		{ _id: 'delete-c',                      roles : ['admin'] }
 		{ _id: 'delete-d',                      roles : ['admin'] }
 		{ _id: 'delete-message',                roles : ['admin', 'owner', 'moderator'] }
diff --git a/packages/rocketchat-autolinker/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-autolinker/.npm/package/npm-shrinkwrap.json
index 8bb6ab9d7a171af420d02223b5c0ac1fd886c8ed..469351e76fd8e7a6dc8a1fcb7e20db31ef742583 100644
--- a/packages/rocketchat-autolinker/.npm/package/npm-shrinkwrap.json
+++ b/packages/rocketchat-autolinker/.npm/package/npm-shrinkwrap.json
@@ -1,9 +1,9 @@
 {
   "dependencies": {
     "autolinker": {
-      "version": "1.3.2",
-      "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-1.3.2.tgz",
-      "from": "autolinker@1.3.2"
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-1.4.0.tgz",
+      "from": "autolinker@1.4.0"
     }
   }
 }
diff --git a/packages/rocketchat-autolinker/package.js b/packages/rocketchat-autolinker/package.js
index eca73cbc98c88588c6cc9917a6083730909da9cf..5ce89297d45c8a36dda337bf8ccb6772aa854238 100644
--- a/packages/rocketchat-autolinker/package.js
+++ b/packages/rocketchat-autolinker/package.js
@@ -6,7 +6,7 @@ Package.describe({
 });
 
 Npm.depends({
-	autolinker: '1.3.2'
+	autolinker: '1.4.0'
 });
 
 Package.onUse(function(api) {
diff --git a/packages/rocketchat-bot-helpers/server/index.js b/packages/rocketchat-bot-helpers/server/index.js
index 9e514f880c6d8389f1ff7565ce120e22c6b19042..98fe5e9951f5759da1194ddb35fcb6ee05c24657 100644
--- a/packages/rocketchat-bot-helpers/server/index.js
+++ b/packages/rocketchat-bot-helpers/server/index.js
@@ -76,7 +76,7 @@ class BotHelpers {
 	// "public" properties accessed by getters
 	// allUsers / onlineUsers return whichever properties are enabled by settings
 	get allUsers() {
-		if (!this.userFields.length) {
+		if (!Object.keys(this.userFields).length) {
 			this.requestError();
 			return false;
 		} else {
@@ -84,7 +84,7 @@ class BotHelpers {
 		}
 	}
 	get onlineUsers() {
-		if (!this.userFields.length) {
+		if (!Object.keys(this.userFields).length) {
 			this.requestError();
 			return false;
 		} else {
diff --git a/packages/rocketchat-cas/cas_server.js b/packages/rocketchat-cas/cas_server.js
index 4a37df7c2e1dd4d087570827997c2445c4fc86ab..555fa638307cff0222244a3e1a89c0ea9cd5daba 100644
--- a/packages/rocketchat-cas/cas_server.js
+++ b/packages/rocketchat-cas/cas_server.js
@@ -236,11 +236,6 @@ Accounts.registerLoginHandler(function(options) {
 		logger.debug('Created new user for \'' + result.username + '\' with id: ' + user._id);
 		//logger.debug(JSON.stringify(user, undefined, 4));
 
-		logger.debug('Joining user to default channels');
-		Meteor.runAsUser(user._id, function() {
-			Meteor.call('joinDefaultChannels');
-		});
-
 		logger.debug('Joining user to attribute channels: ' + int_attrs.rooms);
 		if (int_attrs.rooms) {
 			_.each(int_attrs.rooms.split(','), function(room_name) {
diff --git a/packages/rocketchat-channel-settings-mail-messages/client/views/mailMessagesInstructions.html b/packages/rocketchat-channel-settings-mail-messages/client/views/mailMessagesInstructions.html
index f6cf39d656df845c0cebcedb346975d1c78b12b1..50c148705a456dc2b5314a567cc6430a142fa962 100644
--- a/packages/rocketchat-channel-settings-mail-messages/client/views/mailMessagesInstructions.html
+++ b/packages/rocketchat-channel-settings-mail-messages/client/views/mailMessagesInstructions.html
@@ -37,13 +37,13 @@
 					</div>
 				</fieldset>
 			</form>
-			<div class="error error-missing-to alert alert-danger" style="display: none">
+			<div class="error error-missing-to alert error-color error-background error-border" style="display: none">
 				{{_ "Mail_Message_Missing_to"}}
 			</div>
-			<div class="error error-invalid-emails alert alert-danger" style="display: none">
+			<div class="error error-invalid-emails alert error-color error-background error-border" style="display: none">
 				{{_ "Mail_Message_Invalid_emails" erroredEmails}}
 			</div>
-			<div class="error error-select alert alert-danger" style="display: none">
+			<div class="error error-select alert error-color error-background error-border" style="display: none">
 				{{{_ "Mail_Message_No_messages_selected_select_all"}}}
 			</div>
 			<p style="margin-top: 30px">
diff --git a/packages/rocketchat-channel-settings/client/stylesheets/channel-settings.less b/packages/rocketchat-channel-settings/client/stylesheets/channel-settings.less
index bbe3c25fc8ba328ab7b2c9cc475c68cd2485c475..5bfe3351fd9b6144f3a26dbfc72cbd8fe02b2107 100644
--- a/packages/rocketchat-channel-settings/client/stylesheets/channel-settings.less
+++ b/packages/rocketchat-channel-settings/client/stylesheets/channel-settings.less
@@ -6,29 +6,93 @@
 			}
 		}
 
-		form {
-			label {
-				display: block;
-				font-weight: bold;
-				margin-bottom: 5px;
+		label {
+			display: block;
+			font-weight: bold;
+			margin-bottom: 5px;
+			font-size: 14px;
+		}
+
+		.current-setting {
+			font-size: 14px;
+			width: calc(~"100% - 38px");
+			display: inline-block;
+			vertical-align: middle;
+			min-height: 20px;
+			cursor: pointer;
+			margin-top: 3px;
+
+			&[data-edit="false"] {
+				cursor: inherit;
+				user-select: initial;
 			}
+		}
 
-			div span {
-				font-size: 14px;
-				i.icon-pencil {
-					font-size: 12px;
-					margin-left: 3px;
-				}
+		.editing {
+			padding-right: 80px;
+			font-size: 14px;
+			margin: -2px 0 -1px -9px;
+		}
+
+		.buttons {
+			position: absolute;
+			top: -1px;
+			bottom: 0;
+			right: 10px;
+			border-radius: 0 4px 4px 0;
+
+			.button {
+				padding: 8px;
 			}
 		}
 
+		.button.edit {
+			padding: 8px;
+			font-size: 12px;
+			vertical-align: middle;
+			display: inline-block;
+			visibility: hidden;
+		}
+
 		.submit {
 			margin-top: 30px;
 			text-align: center;
 		}
 
-		[data-edit] {
-			cursor: pointer;
+		.boolean {
+			font-size: 0;
+
+			> label {
+				width: calc(~"100% - 45px");
+				display: inline-block;
+				vertical-align: middle;
+			}
+
+			.setting-block {
+				width: 40px;
+				display: inline-block;
+				vertical-align: middle;
+				margin-left: -5px;
+			}
+		}
+
+		.setting-block {
+			position: relative;
+			font-size: 0;
+
+			.loading-animation {
+				top: 30px;
+			}
+
+			&:hover {
+				.button.edit {
+					visibility: visible;
+				}
+			}
+		}
+
+		nav {
+			text-align: right;
 		}
 	}
 }
diff --git a/packages/rocketchat-channel-settings/client/views/channelSettings.coffee b/packages/rocketchat-channel-settings/client/views/channelSettings.coffee
index b4670ec92ecc4c392ed3354077a8baaba13ef7e5..17bc6334bf42f0d24ff3f2fd096bdabd160229db 100644
--- a/packages/rocketchat-channel-settings/client/views/channelSettings.coffee
+++ b/packages/rocketchat-channel-settings/client/views/channelSettings.coffee
@@ -25,6 +25,9 @@ Template.channelSettings.helpers
 	editing: (field) ->
 		return Template.instance().editing.get() is field
 
+	isDisabled: (field, room) ->
+		return Template.instance().settings[field].processing.get() or !RocketChat.authz.hasAllPermission('edit-room', room._id)
+
 	channelSettings: ->
 		return RocketChat.ChannelSettings.getOptions()
 
@@ -34,8 +37,10 @@ Template.channelSettings.helpers
 	canDeleteRoom: ->
 		roomType = ChatRoom.findOne(@rid, { fields: { t: 1 }})?.t
 		return roomType? and RocketChat.authz.hasAtLeastOnePermission("delete-#{roomType}", @rid)
+
 	readOnly: ->
 		return  ChatRoom.findOne(@rid, { fields: { ro: 1 }})?.ro
+
 	readOnlyDescription: ->
 		readOnly = ChatRoom.findOne(@rid, { fields: { ro: 1 }})?.ro
 		if readOnly is true
@@ -79,8 +84,16 @@ Template.channelSettings.events
 
 	'click [data-edit]': (e, t) ->
 		e.preventDefault()
-		t.editing.set($(e.currentTarget).data('edit'))
-		setTimeout (-> t.$('input.editing').focus().select()), 100
+		if $(e.currentTarget).data('edit')
+			t.editing.set($(e.currentTarget).data('edit'))
+			setTimeout (-> t.$('input.editing').focus().select()), 100
+
+	'change [type="radio"]': (e, t) ->
+		t.editing.set($(e.currentTarget).attr('name'))
+
+	'change [type="checkbox"]': (e, t) ->
+		t.editing.set($(e.currentTarget).attr('name'))
+		t.saveSetting()
 
 	'click .cancel': (e, t) ->
 		e.preventDefault()
@@ -138,48 +151,86 @@ Template.channelSettings.onCreated ->
 					toastr.success TAPi18n.__ 'Room_description_changed_successfully'
 
 		t:
-			type: 'select'
-			label: 'Type'
-			options:
-				c: 'Channel'
-				p: 'Private_Group'
-			canView: (room) => room.t in ['c', 'p']
+			type: 'boolean'
+			label: 'Private'
+			isToggle: true
+			processing: new ReactiveVar(false)
+			canView: (room) ->
+				if not room.t in ['c', 'p']
+					return false
+				else if room.t is 'p' and not RocketChat.authz.hasAllPermission('create-c')
+					return false
+				else if room.t is 'c' and not RocketChat.authz.hasAllPermission('create-p')
+					return false
+				return true
 			canEdit: (room) => RocketChat.authz.hasAllPermission('edit-room', room._id)
 			save: (value, room) ->
-				if value not in ['c', 'p']
-					return toastr.error t('error-invalid-room-type', value)
-
+				@processing.set(true)
+				value = if value then 'p' else 'c'
 				RocketChat.callbacks.run 'roomTypeChanged', room
-				Meteor.call 'saveRoomSettings', room._id, 'roomType', value, (err, result) ->
+				Meteor.call 'saveRoomSettings', room._id, 'roomType', value, (err, result) =>
 					return handleError err if err
+					@processing.set(false)
 					toastr.success TAPi18n.__ 'Room_type_changed_successfully'
 
 		ro:
 			type: 'boolean'
 			label: 'Read_only'
+			isToggle: true
+			processing: new ReactiveVar(false)
 			canView: (room) => room.t isnt 'd'
 			canEdit: (room) => RocketChat.authz.hasAllPermission('set-readonly', room._id)
 			save: (value, room) ->
-				Meteor.call 'saveRoomSettings', room._id, 'readOnly', value, (err, result) ->
+				@processing.set(true)
+				Meteor.call 'saveRoomSettings', room._id, 'readOnly', value, (err, result) =>
 					return handleError err if err
+					@processing.set(false)
 					toastr.success TAPi18n.__ 'Read_only_changed_successfully'
 
+		reactWhenReadOnly:
+			type: 'boolean'
+			label: 'React_when_read_only'
+			canView: (room) => room.t isnt 'd' and room.ro
+			canEdit: (room) => RocketChat.authz.hasAllPermission('set-react-when-readonly', room._id)
+			save: (value, room) ->
+				Meteor.call 'saveRoomSettings', room._id, 'reactWhenReadOnly', value, (err, result) ->
+					return handleError err if err
+					toastr.success TAPi18n.__ 'React_when_read_only_changed_successfully'
+
 		archived:
 			type: 'boolean'
 			label: 'Room_archivation_state_true'
+			isToggle: true,
+			processing: new ReactiveVar(false)
 			canView: (room) => room.t isnt 'd'
 			canEdit: (room) => RocketChat.authz.hasAtLeastOnePermission(['archive-room', 'unarchive-room'], room._id)
-			save: (value, room) ->
-				if value is true
-					Meteor.call 'archiveRoom', room._id, (err, results) ->
-						return handleError err if err
-						toastr.success TAPi18n.__ 'Room_archived'
-						RocketChat.callbacks.run 'archiveRoom', room
-				else
-					Meteor.call 'unarchiveRoom', room._id, (err, results) ->
-						return handleError err if err
-						toastr.success TAPi18n.__ 'Room_unarchived'
-						RocketChat.callbacks.run 'unarchiveRoom', room
+			save: (value, room) =>
+				swal {
+					title: t('Are_you_sure')
+					type: 'warning'
+					showCancelButton: true
+					confirmButtonColor: '#DD6B55'
+					confirmButtonText: if value then t('Yes_archive_it') else t('Yes_unarchive_it')
+					cancelButtonText: t('Cancel')
+					closeOnConfirm: false
+					html: false
+				}, (confirmed) =>
+					swal.disableButtons()
+					if (confirmed)
+						action = if value then 'archiveRoom' else 'unarchiveRoom'
+						Meteor.call action, room._id, (err, results) =>
+							if err
+								swal.enableButtons()
+								handleError err
+							swal
+								title: if value then t('Room_archived') else t('Room_has_been_archived')
+								text: if value then t('Room_has_been_archived') else t('Room_has_been_unarchived')
+								type: 'success'
+								timer: 2000
+								showConfirmButton: false
+							RocketChat.callbacks.run action, room
+					else
+						$(".channel-settings form [name='archived']").prop('checked', room.archived)
 
 		joinCode:
 			type: 'text'
@@ -200,7 +251,7 @@ Template.channelSettings.onCreated ->
 		if @settings[field].type is 'select'
 			value = @$(".channel-settings form [name=#{field}]:checked").val()
 		else if @settings[field].type is 'boolean'
-			value = @$(".channel-settings form [name=#{field}]:checked").val() is 'true'
+			value = @$(".channel-settings form [name=#{field}]").is(":checked")
 		else
 			value = @$(".channel-settings form [name=#{field}]").val()
 
diff --git a/packages/rocketchat-channel-settings/client/views/channelSettings.html b/packages/rocketchat-channel-settings/client/views/channelSettings.html
index b253a257b16d24e6ffeb40c4beb438028fbd5748..562590be0c78605fdd7f4eed3920e782267466ad 100644
--- a/packages/rocketchat-channel-settings/client/views/channelSettings.html
+++ b/packages/rocketchat-channel-settings/client/views/channelSettings.html
@@ -11,63 +11,68 @@
 
 							{{#if $value.canView room}}
 								{{#let value=(valueOf room $key)}}
-									<li>
+									<li class="{{$value.type}}">
 										<label>{{_ $value.label}}</label>
-										<div>
+										<div class="setting-block">
 											{{#if $eq $value.type 'text'}}
 												{{#if editing $key}}
-													<input type="text" name="{{$key}}" value="{{value}}" class="editing" />
+													{{#if $value.canEdit room}}
+														<input type="text" name="{{$key}}" value="{{value}}" class="content-background-color editing" />
+													{{/if}}
 												{{else}}
-													<span class='current-setting'>{{value}}</span>
+													<span class='current-setting' data-edit="{{#if $value.canEdit room}}{{$key}}{{else}}false{{/if}}">{{value}}</span>
 												{{/if}}
 											{{/if}}
 
 											{{#if $eq $value.type 'markdown'}}
 												{{#if editing $key}}
-													<input type="text" name="{{$key}}" value="{{unscape value}}" class="editing" />
+													{{#if $value.canEdit room}}
+														<input type="text" name="{{$key}}" value="{{unscape value}}" class="content-background-color editing" />
+													{{/if}}
 												{{else}}
-													<span class='current-setting'>{{{RocketChatMarkdown value}}}</span>
+													<span class='current-setting' data-edit="{{#if $value.canEdit room}}{{$key}}{{else}}false{{/if}}">{{{RocketChatMarkdown value}}}</span>
 												{{/if}}
 											{{/if}}
 
 											{{#if $eq $value.type 'select'}}
-												{{#if editing $key}}
-													{{#each toArray $value.options}}
-														<label>
-															<input type="radio" name="{{../$key}}" value="{{$key}}" checked="{{$eq value $key}}" class="editing" />
-															{{_ $value}}
-														</label>
-													{{/each}}
-												{{else}}
-													<span class='current-setting'>{{_ (valueOf $value.options value)}}</span>
-												{{/if}}
+												{{#each toArray $value.options}}
+													<div class="input radio">
+														<input type="radio" id="{{$key}}" name="{{../$key}}" value="{{$key}}" checked="{{$eq value $key}}" disabled="{{isDisabled $key room}}" />
+														<label for="{{$key}}">{{_ $value}}</label>
+													</div>
+												{{/each}}
 											{{/if}}
 
 											{{#if $eq $value.type 'boolean'}}
-												{{#if editing $key}}
-													<label>
-														<input type="radio" name="{{$key}}" value="true" checked="{{$eq value true}}" class="editing" />
-														{{_ 'True'}}
-													</label>
-													<label>
-														<input type="radio" name="{{$key}}" value="false" checked="{{$neq value true}}" class="editing" />
-														{{_ 'False'}}
-													</label>
-												{{else}}
-													{{#if value}}
-														<span class='current-setting'>{{_ 'True'}}</span>
-													{{else}}
-														<span class='current-setting'>{{_ 'False'}}</span>
+												<div class="input checkbox toggle">
+													<input type="checkbox" id="{{$key}}" name="{{$key}}" value="{{value}}" checked="{{$eq value true}}" disabled="{{isDisabled $key room}}" />
+													<label for="{{$key}}"></label>
+												</div>
+												{{#if $value.canEdit room}}
+													{{#if $value.processing.get}}
+														{{> loading}}
 													{{/if}}
 												{{/if}}
 											{{/if}}
 
-											{{#if editing $key}}
-												<button type="button" class="button cancel">{{_ "Cancel"}}</button>
-												<button type="button" class="button primary save">{{_ "Save"}}</button>
-											{{else}}
-												<span>{{#if $value.canEdit room}} <i class="icon-pencil" data-edit="{{$key}}"></i>{{/if}}</span>
-											{{/if}}
+											{{#unless $value.isToggle}}
+												{{#if $value.canEdit room}}
+													{{#if editing $key}}
+														<div class="buttons secondary-background-color">
+															<button type="button" class="button cancel">
+																<i class="icon-cancel"></i>
+															</button>
+															<button type="button" class="button primary save">
+																<i class="icon-ok success-color"></i>
+															</button>
+														</div>
+													{{else}}
+														<button type="button" class="button edit">
+															<i class="icon-pencil" data-edit="{{$key}}"></i>
+														</button>
+													{{/if}}
+												{{/if}}
+											{{/unless}}
 										</div>
 									</li>
 								{{/let}}
@@ -81,9 +86,9 @@
 				</ul>
 			</form>
 			{{#if canDeleteRoom}}
-			<nav>
-				<button class='button danger delete'><span><i class='icon-trash'></i> {{_ "Delete"}}</span></button>
-			</nav>
+				<nav>
+					<button class="button danger delete" title="{{_ 'Delete'}}"><i class="icon-trash"></i></button>
+				</nav>
 			{{/if}}
 		</div>
 	</div>
diff --git a/packages/rocketchat-channel-settings/package.js b/packages/rocketchat-channel-settings/package.js
index dfc77ee32bfc53d6e2968db43a2e029fc0ccb259..3f42e734af3ffc157c307ce48e1ad588259e2ce5 100644
--- a/packages/rocketchat-channel-settings/package.js
+++ b/packages/rocketchat-channel-settings/package.js
@@ -27,6 +27,7 @@ Package.onUse(function(api) {
 	], 'client');
 
 	api.addFiles([
+		'server/functions/saveReactWhenReadOnly.js',
 		'server/functions/saveRoomType.coffee',
 		'server/functions/saveRoomTopic.coffee',
 		'server/functions/saveRoomName.coffee',
diff --git a/packages/rocketchat-channel-settings/server/functions/saveReactWhenReadOnly.js b/packages/rocketchat-channel-settings/server/functions/saveReactWhenReadOnly.js
new file mode 100644
index 0000000000000000000000000000000000000000..61cf8128df04d81cfe6bce4b7762c7c897aec66d
--- /dev/null
+++ b/packages/rocketchat-channel-settings/server/functions/saveReactWhenReadOnly.js
@@ -0,0 +1,7 @@
+RocketChat.saveReactWhenReadOnly = function(rid, allowReact) {
+	if (!Match.test(rid, String)) {
+		throw new Meteor.Error('invalid-room', 'Invalid room', { function: 'RocketChat.saveReactWhenReadOnly' });
+	}
+
+	return RocketChat.models.Rooms.setAllowReactingWhenReadOnlyById(rid, allowReact);
+};
diff --git a/packages/rocketchat-channel-settings/server/methods/saveRoomSettings.coffee b/packages/rocketchat-channel-settings/server/methods/saveRoomSettings.coffee
index c2aadcadd3a68a6257ed1f4c0374b72db7f2398b..f51a06949452d3394301bc73bf014097ead5cb84 100644
--- a/packages/rocketchat-channel-settings/server/methods/saveRoomSettings.coffee
+++ b/packages/rocketchat-channel-settings/server/methods/saveRoomSettings.coffee
@@ -6,7 +6,7 @@ Meteor.methods
 		unless Match.test rid, String
 			throw new Meteor.Error 'error-invalid-room', 'Invalid room', { method: 'saveRoomSettings' }
 
-		if setting not in ['roomName', 'roomTopic', 'roomDescription', 'roomType', 'readOnly', 'systemMessages', 'default', 'joinCode']
+		if setting not in ['roomName', 'roomTopic', 'roomDescription', 'roomType', 'readOnly', 'reactWhenReadOnly', 'systemMessages', 'default', 'joinCode']
 			throw new Meteor.Error 'error-invalid-settings', 'Invalid settings provided', { method: 'saveRoomSettings' }
 
 		unless RocketChat.authz.hasPermission(Meteor.userId(), 'edit-room', rid)
@@ -17,6 +17,12 @@ Meteor.methods
 
 		room = RocketChat.models.Rooms.findOneById rid
 		if room?
+			if setting is 'roomType' and value isnt room.t and value is 'c' and not RocketChat.authz.hasPermission(@userId, 'create-c')
+				throw new Meteor.Error 'error-action-not-allowed', 'Changing a private group to a public channel is not allowed', { method: 'saveRoomSettings', action: 'Change_Room_Type' }
+
+			if setting is 'roomType' and value isnt room.t and value is 'p' and not RocketChat.authz.hasPermission(@userId, 'create-p')
+				throw new Meteor.Error 'error-action-not-allowed', 'Changing a public channel to a private room is not allowed', { method: 'saveRoomSettings', action: 'Change_Room_Type' }
+
 			switch setting
 				when 'roomName'
 					name = RocketChat.saveRoomName rid, value, Meteor.user()
@@ -32,6 +38,9 @@ Meteor.methods
 				when 'readOnly'
 					if value isnt room.ro
 						RocketChat.saveRoomReadOnly rid, value, Meteor.user()
+				when 'reactWhenReadOnly'
+					if value isnt room.reactWhenReadOnly
+						RocketChat.saveReactWhenReadOnly rid, value, Meteor.user()
 				when 'systemMessages'
 					if value isnt room.sysMes
 						RocketChat.saveRoomSystemMessages rid, value, Meteor.user()
diff --git a/packages/rocketchat-channel-settings/server/models/Rooms.coffee b/packages/rocketchat-channel-settings/server/models/Rooms.coffee
index f4328cebf9d531d8132b71446b6fe43694e830ad..d277959fe754678795f4261a174c083a90a4a0b4 100644
--- a/packages/rocketchat-channel-settings/server/models/Rooms.coffee
+++ b/packages/rocketchat-channel-settings/server/models/Rooms.coffee
@@ -19,9 +19,11 @@ RocketChat.models.Rooms.setReadOnlyById = (_id, readOnly) ->
 	if readOnly
 		# we want to mute all users without the post-readonly permission
 
-		usernames = @findOne(query, { fields: { usernames: 1 }})
-		users = RocketChat.models.Users.findUsersByUsernames usernames?.usernames, {fields: {username: 1}}
-		users.forEach (user) ->
+		RocketChat.models.Subscriptions.findByRoomId(_id).forEach (subscription) ->
+			if not subscription._user?
+				return
+
+			user = subscription._user
 			if RocketChat.authz.hasPermission(user._id, 'post-readonly') is false
 				# create a new array if necessary
 				update.$set.muted = [] if !update.$set.muted
@@ -32,6 +34,16 @@ RocketChat.models.Rooms.setReadOnlyById = (_id, readOnly) ->
 
 	return @update query, update
 
+RocketChat.models.Rooms.setAllowReactingWhenReadOnlyById = (_id, allowReacting) ->
+	query =
+		_id: _id
+
+	update =
+		$set:
+			reactWhenReadOnly: allowReacting
+
+	return @update query, update
+
 RocketChat.models.Rooms.setSystemMessagesById = (_id, systemMessages) ->
 	query =
 		_id: _id
diff --git a/packages/rocketchat-channel-settings/server/startup.js b/packages/rocketchat-channel-settings/server/startup.js
index a881ce9496a4439481bdfafd7ed081760b92bba0..b63c0fabf67fcf666427f6492de7558a3faf3175 100644
--- a/packages/rocketchat-channel-settings/server/startup.js
+++ b/packages/rocketchat-channel-settings/server/startup.js
@@ -1,4 +1,5 @@
 Meteor.startup(function() {
 	RocketChat.models.Permissions.upsert('post-readonly', {$set: { roles: ['admin', 'owner', 'moderator'] } });
 	RocketChat.models.Permissions.upsert('set-readonly', {$set: { roles: ['admin', 'owner'] } });
+	RocketChat.models.Permissions.upsert('set-react-when-readonly', {$set: { roles: ['admin', 'owner'] }});
 });
diff --git a/packages/rocketchat-chatops/client/views/codemirror.html b/packages/rocketchat-chatops/client/views/codemirror.html
index e185ab09607e1c814ab5769449534498f2cf28ef..6333d8416805ffd7063f8b4675834783e4be01e4 100644
--- a/packages/rocketchat-chatops/client/views/codemirror.html
+++ b/packages/rocketchat-chatops/client/views/codemirror.html
@@ -4,7 +4,7 @@
 		<form class="search-form" role="form">
 			<div class="input-line search">
 				<input type="text" id="room-search" class="search" placeholder="{{tQuickSearch}}" autocomplete="off" />
-				<i class="icon-search"></i>
+				<i class="icon-search secondary-font-color"></i>
 			</div>
 		</form>
 	</div>
diff --git a/packages/rocketchat-crowd/server/crowd.js b/packages/rocketchat-crowd/server/crowd.js
index d30fe4307d016b1f43fd47387f48947dd51c1978..65c6f5427260f1482f9258a86737ffa0d97758f1 100644
--- a/packages/rocketchat-crowd/server/crowd.js
+++ b/packages/rocketchat-crowd/server/crowd.js
@@ -170,10 +170,6 @@ const CROWD = class CROWD {
 			});
 		}
 
-		Meteor.runAsUser(crowdUser._id, function() {
-			Meteor.call('joinDefaultChannels');
-		});
-
 		return {
 			userId: crowdUser._id
 		};
diff --git a/packages/rocketchat-custom-oauth/custom_oauth_client.coffee b/packages/rocketchat-custom-oauth/custom_oauth_client.coffee
deleted file mode 100644
index f0d7338cfc74ee98e75c60dbbc3e253581a3ed6a..0000000000000000000000000000000000000000
--- a/packages/rocketchat-custom-oauth/custom_oauth_client.coffee
+++ /dev/null
@@ -1,79 +0,0 @@
-# Request custom OAuth credentials for the user
-# @param options {optional}
-# @param credentialRequestCompleteCallback {Function} Callback function to call on
-#   completion. Takes one argument, credentialToken on success, or Error on
-#   error.
-class CustomOAuth
-	constructor: (@name, options) ->
-		if not Match.test @name, String
-			return throw new Meteor.Error 'CustomOAuth: Name is required and must be String'
-
-		@configure options
-
-		Accounts.oauth.registerService @name
-
-		@configureLogin()
-
-	configure: (options) ->
-		if not Match.test options, Object
-			return throw new Meteor.Error 'CustomOAuth: Options is required and must be Object'
-
-		if not Match.test options.serverURL, String
-			return throw new Meteor.Error 'CustomOAuth: Options.serverURL is required and must be String'
-
-		if not Match.test options.authorizePath, String
-			options.authorizePath = '/oauth/authorize'
-
-		if not Match.test options.scope, String
-			options.scope = 'openid'
-
-		@serverURL = options.serverURL
-		@authorizePath = options.authorizePath
-		@scope = options.scope
-
-		if not /^https?:\/\/.+/.test @authorizePath
-			@authorizePath = @serverURL + @authorizePath
-
-	configureLogin: ->
-		self = @
-		loginWithService = "loginWith" + s.capitalize(@name)
-
-		Meteor[loginWithService] = (options, callback) ->
-			# support a callback without options
-			if not callback and typeof options is "function"
-				callback = options
-				options = null
-
-			credentialRequestCompleteCallback = Accounts.oauth.credentialRequestCompleteHandler(callback)
-			self.requestCredential(options, credentialRequestCompleteCallback)
-
-	requestCredential: (options, credentialRequestCompleteCallback) ->
-		# support both (options, callback) and (callback).
-		if not credentialRequestCompleteCallback and typeof options is 'function'
-			credentialRequestCompleteCallback = options
-			options = {}
-
-		config = ServiceConfiguration.configurations.findOne service: @name
-		if not config
-			credentialRequestCompleteCallback? new ServiceConfiguration.ConfigError()
-			return
-
-		credentialToken = Random.secret()
-		loginStyle = OAuth._loginStyle @name, config, options
-
-		loginUrl = @authorizePath +
-			'?client_id=' + config.clientId +
-			'&redirect_uri=' + OAuth._redirectUri(@name, config) +
-			'&response_type=code' +
-			'&state=' + OAuth._stateParam(loginStyle, credentialToken, options.redirectUrl) +
-			'&scope=' + @scope
-
-		OAuth.launchLogin
-			loginService: @name
-			loginStyle: loginStyle
-			loginUrl: loginUrl
-			credentialRequestCompleteCallback: credentialRequestCompleteCallback
-			credentialToken: credentialToken
-			popupOptions:
-				width: 900
-				height: 450
diff --git a/packages/rocketchat-custom-oauth/custom_oauth_client.js b/packages/rocketchat-custom-oauth/custom_oauth_client.js
new file mode 100644
index 0000000000000000000000000000000000000000..b3c88e9955d8af19761ce25f466c57536136e97f
--- /dev/null
+++ b/packages/rocketchat-custom-oauth/custom_oauth_client.js
@@ -0,0 +1,100 @@
+/*globals OAuth*/
+// Request custom OAuth credentials for the user
+// @param options {optional}
+// @param credentialRequestCompleteCallback {Function} Callback function to call on
+//   completion. Takes one argument, credentialToken on success, or Error on
+//   error.
+
+export class CustomOAuth {
+	constructor(name, options) {
+		this.name = name;
+		if (!Match.test(this.name, String)) {
+			throw new Meteor.Error('CustomOAuth: Name is required and must be String');
+		}
+
+		this.configure(options);
+
+		Accounts.oauth.registerService(this.name);
+
+		this.configureLogin();
+	}
+
+	configure(options) {
+		if (!Match.test(options, Object)) {
+			throw new Meteor.Error('CustomOAuth: Options is required and must be Object');
+		}
+
+		if (!Match.test(options.serverURL, String)) {
+			throw new Meteor.Error('CustomOAuth: Options.serverURL is required and must be String');
+		}
+
+		if (!Match.test(options.authorizePath, String)) {
+			options.authorizePath = '/oauth/authorize';
+		}
+
+		if (!Match.test(options.scope, String)) {
+			options.scope = 'openid';
+		}
+
+		this.serverURL = options.serverURL;
+		this.authorizePath = options.authorizePath;
+		this.scope = options.scope;
+
+		if (!/^https?:\/\/.+/.test(this.authorizePath)) {
+			this.authorizePath = this.serverURL + this.authorizePath;
+		}
+	}
+
+	configureLogin() {
+		const loginWithService = 'loginWith' + s.capitalize(this.name);
+
+		Meteor[loginWithService] = (options, callback) => {
+			// support a callback without options
+			if (!callback && typeof options === 'function') {
+				callback = options;
+				options = null;
+			}
+
+			const credentialRequestCompleteCallback = Accounts.oauth.credentialRequestCompleteHandler(callback);
+			this.requestCredential(options, credentialRequestCompleteCallback);
+		};
+	}
+
+	requestCredential(options, credentialRequestCompleteCallback) {
+		// support both (options, callback) and (callback).
+		if (!credentialRequestCompleteCallback && typeof options === 'function') {
+			credentialRequestCompleteCallback = options;
+			options = {};
+		}
+
+		const config = ServiceConfiguration.configurations.findOne({service: this.name});
+		if (!config) {
+			if (credentialRequestCompleteCallback) {
+				credentialRequestCompleteCallback(new ServiceConfiguration.ConfigError());
+			}
+			return;
+		}
+
+		const credentialToken = Random.secret();
+		const loginStyle = OAuth._loginStyle(this.name, config, options);
+
+		const loginUrl = this.authorizePath +
+			'?client_id=' + config.clientId +
+			'&redirect_uri=' + OAuth._redirectUri(this.name, config) +
+			'&response_type=code' +
+			'&state=' + OAuth._stateParam(loginStyle, credentialToken, options.redirectUrl) +
+			'&scope=' + this.scope;
+
+		OAuth.launchLogin({
+			loginService: this.name,
+			loginStyle: loginStyle,
+			loginUrl: loginUrl,
+			credentialRequestCompleteCallback: credentialRequestCompleteCallback,
+			credentialToken: credentialToken,
+			popupOptions: {
+				width: 900,
+				height: 450
+			}
+		});
+	}
+}
diff --git a/packages/rocketchat-custom-oauth/custom_oauth_server.coffee b/packages/rocketchat-custom-oauth/custom_oauth_server.coffee
deleted file mode 100644
index e556ff0b72e73af17c7311a5b546f2d5c905e258..0000000000000000000000000000000000000000
--- a/packages/rocketchat-custom-oauth/custom_oauth_server.coffee
+++ /dev/null
@@ -1,162 +0,0 @@
-Services = {}
-
-class CustomOAuth
-	constructor: (@name, options) ->
-		if not Match.test @name, String
-			return throw new Meteor.Error 'CustomOAuth: Name is required and must be String'
-
-		if Services[@name]?
-			Services[@name].configure options
-			return
-
-		Services[@name] = @
-
-		@configure options
-
-		@userAgent = "Meteor"
-		if Meteor.release
-			@userAgent += '/' + Meteor.release
-
-		Accounts.oauth.registerService @name
-		@registerService()
-
-	configure: (options) ->
-		if not Match.test options, Object
-			return throw new Meteor.Error 'CustomOAuth: Options is required and must be Object'
-
-		if not Match.test options.serverURL, String
-			return throw new Meteor.Error 'CustomOAuth: Options.serverURL is required and must be String'
-
-		if not Match.test options.tokenPath, String
-			options.tokenPath = '/oauth/token'
-
-		if not Match.test options.identityPath, String
-			options.identityPath = '/me'
-
-		@serverURL = options.serverURL
-		@tokenPath = options.tokenPath
-		@identityPath = options.identityPath
-		@tokenSentVia = options.tokenSentVia
-
-		if not /^https?:\/\/.+/.test @tokenPath
-			@tokenPath = @serverURL + @tokenPath
-
-		if not /^https?:\/\/.+/.test @identityPath
-			@identityPath = @serverURL + @identityPath
-
-		if Match.test options.addAutopublishFields, Object
-			Accounts.addAutopublishFields options.addAutopublishFields
-
-	getAccessToken: (query) ->
-		config = ServiceConfiguration.configurations.findOne service: @name
-		if not config?
-			throw new ServiceConfiguration.ConfigError()
-
-		response = undefined
-		try
-			response = HTTP.post @tokenPath,
-				auth: config.clientId + ':' + OAuth.openSecret(config.secret)
-				headers:
-					Accept: 'application/json'
-					'User-Agent': @userAgent
-				params:
-					code: query.code
-					client_id: config.clientId
-					client_secret: OAuth.openSecret(config.secret)
-					redirect_uri: OAuth._redirectUri(@name, config)
-					grant_type: 'authorization_code'
-					state: query.state
-
-		catch err
-			error = new Error("Failed to complete OAuth handshake with #{@name} at #{@tokenPath}. " + err.message)
-			throw _.extend error, {response: err.response}
-
-		if response.data.error #if the http response was a json object with an error attribute
-			throw new Error("Failed to complete OAuth handshake with #{@name} at #{@tokenPath}. " + response.data.error)
-		else
-			return response.data.access_token
-
-	getIdentity: (accessToken) ->
-		params = {}
-		headers =
-			'User-Agent': @userAgent # http://doc.gitlab.com/ce/api/users.html#Current-user
-
-		if @tokenSentVia is 'header'
-			headers['Authorization'] = 'Bearer ' + accessToken
-		else
-			params['access_token'] = accessToken
-
-		try
-			response = HTTP.get @identityPath,
-				headers: headers
-				params: params
-
-			if response.data
-				return response.data
-			else
-				return JSON.parse response.content
-
-		catch err
-			error = new Error("Failed to fetch identity from #{@name} at #{@identityPath}. " + err.message)
-			throw _.extend error, {response: err.response}
-
-	registerService: ->
-		self = @
-		OAuth.registerService @name, 2, null, (query) ->
-			accessToken = self.getAccessToken query
-			# console.log 'at:', accessToken
-
-			identity = self.getIdentity accessToken
-
-			# Fix for Reddit
-			if identity?.result
-				identity = identity.result
-
-			# Fix WordPress-like identities having 'ID' instead of 'id'
-			if identity?.ID and not identity.id
-				identity.id = identity.ID
-
-			# Fix Auth0-like identities having 'user_id' instead of 'id'
-			if identity?.user_id and not identity.id
-				identity.id = identity.user_id
-
-			if identity?.CharacterID and not identity.id
-				identity.id = identity.CharacterID
-
-			# Fix Dataporten having 'user.userid' instead of 'id'
-			if identity?.user?.userid and not identity.id
-				identity.id = identity.user.userid
-				identity.email = identity.user.email
-
-			# Fix general 'phid' instead of 'id' from phabricator
-			if identity?.phid and not identity.id
-				identity.id = identity.phid
-
-			# Fix Keycloak-like identities having 'sub' instead of 'id'
-			if identity?.sub and not identity.id
-				identity.id = identity.sub
-
-			# Fix general 'userid' instead of 'id' from provider
-			if identity?.userid and not identity.id
-				identity.id = identity.userid
-
-			# console.log 'id:', JSON.stringify identity, null, '  '
-
-			serviceData =
-				_OAuthCustom: true
-				accessToken: accessToken
-
-			_.extend serviceData, identity
-
-			data =
-				serviceData: serviceData
-				options:
-					profile:
-						name: identity.name or identity.username or identity.nickname or identity.CharacterName or identity.userName or identity.preferred_username or identity.user?.name
-
-			# console.log data
-
-			return data
-
-	retrieveCredential: (credentialToken, credentialSecret) ->
-		return OAuth.retrieveCredential credentialToken, credentialSecret
diff --git a/packages/rocketchat-custom-oauth/custom_oauth_server.js b/packages/rocketchat-custom-oauth/custom_oauth_server.js
new file mode 100644
index 0000000000000000000000000000000000000000..84abcb7df8b2f82a7d4aa592cf025379f97be942
--- /dev/null
+++ b/packages/rocketchat-custom-oauth/custom_oauth_server.js
@@ -0,0 +1,298 @@
+/*globals OAuth*/
+
+const logger = new Logger('CustomOAuth');
+
+const Services = {};
+const BeforeUpdateOrCreateUserFromExternalService = [];
+
+export class CustomOAuth {
+	constructor(name, options) {
+		logger.debug('Init CustomOAuth', name, options);
+
+		this.name = name;
+		if (!Match.test(this.name, String)) {
+			throw new Meteor.Error('CustomOAuth: Name is required and must be String');
+		}
+
+		if (Services[this.name]) {
+			Services[this.name].configure(options);
+			return;
+		}
+
+		Services[this.name] = this;
+
+		this.configure(options);
+
+		this.userAgent = 'Meteor';
+		if (Meteor.release) {
+			this.userAgent += '/' + Meteor.release;
+		}
+
+		Accounts.oauth.registerService(this.name);
+		this.registerService();
+		this.addHookToProcessUser();
+	}
+
+	configure(options) {
+		if (!Match.test(options, Object)) {
+			throw new Meteor.Error('CustomOAuth: Options is required and must be Object');
+		}
+
+		if (!Match.test(options.serverURL, String)) {
+			throw new Meteor.Error('CustomOAuth: Options.serverURL is required and must be String');
+		}
+
+		if (!Match.test(options.tokenPath, String)) {
+			options.tokenPath = '/oauth/token';
+		}
+
+		if (!Match.test(options.identityPath, String)) {
+			options.identityPath = '/me';
+		}
+
+		this.serverURL = options.serverURL;
+		this.tokenPath = options.tokenPath;
+		this.identityPath = options.identityPath;
+		this.tokenSentVia = options.tokenSentVia;
+		this.usernameField = (options.usernameField || '').trim();
+		this.mergeUsers = options.mergeUsers;
+
+		if (!/^https?:\/\/.+/.test(this.tokenPath)) {
+			this.tokenPath = this.serverURL + this.tokenPath;
+		}
+
+		if (!/^https?:\/\/.+/.test(this.identityPath)) {
+			this.identityPath = this.serverURL + this.identityPath;
+		}
+
+		if (Match.test(options.addAutopublishFields, Object)) {
+			Accounts.addAutopublishFields(options.addAutopublishFields);
+		}
+	}
+
+	getAccessToken(query) {
+		const config = ServiceConfiguration.configurations.findOne({service: this.name});
+		if (!config) {
+			throw new ServiceConfiguration.ConfigError();
+		}
+
+		let response = undefined;
+		try {
+			response = HTTP.post(this.tokenPath, {
+				auth: config.clientId + ':' + OAuth.openSecret(config.secret),
+				headers: {
+					Accept: 'application/json',
+					'User-Agent': this.userAgent
+				},
+				params: {
+					code: query.code,
+					client_id: config.clientId,
+					client_secret: OAuth.openSecret(config.secret),
+					redirect_uri: OAuth._redirectUri(this.name, config),
+					grant_type: 'authorization_code',
+					state: query.state
+				}
+			});
+		} catch (err) {
+			const error = new Error(`Failed to complete OAuth handshake with ${this.name} at ${this.tokenPath}. ${err.message}`);
+			throw _.extend(error, {response: err.response});
+		}
+
+		if (response.data.error) { //if the http response was a json object with an error attribute
+			throw new Error(`Failed to complete OAuth handshake with ${this.name} at ${this.tokenPath}. ${response.data.error}`);
+		} else {
+			return response.data.access_token;
+		}
+	}
+
+	getIdentity(accessToken) {
+		const params = {};
+		const headers = {
+			'User-Agent': this.userAgent // http://doc.gitlab.com/ce/api/users.html#Current-user
+		};
+
+		if (this.tokenSentVia === 'header') {
+			headers['Authorization'] = 'Bearer ' + accessToken;
+		} else {
+			params['access_token'] = accessToken;
+		}
+
+		try {
+			const response = HTTP.get(this.identityPath, {
+				headers: headers,
+				params: params
+			});
+
+			let data;
+
+			if (response.data) {
+				data = response.data;
+			} else {
+				data = JSON.parse(response.content);
+			}
+
+			logger.debug('Identity response', JSON.stringify(data, null, 2));
+
+			return data;
+		} catch (err) {
+			const error = new Error(`Failed to fetch identity from ${this.name} at ${this.identityPath}. ${err.message}`);
+			throw _.extend(error, {response: err.response});
+		}
+	}
+
+	registerService() {
+		const self = this;
+		OAuth.registerService(this.name, 2, null, (query) => {
+			const accessToken = self.getAccessToken(query);
+			// console.log 'at:', accessToken
+
+			let identity = self.getIdentity(accessToken);
+
+			if (identity) {
+				// Fix for Reddit
+				if (identity.result) {
+					identity = identity.result;
+				}
+
+				// Fix WordPress-like identities having 'ID' instead of 'id'
+				if (identity.ID && !identity.id) {
+					identity.id = identity.ID;
+				}
+
+				// Fix Auth0-like identities having 'user_id' instead of 'id'
+				if (identity.user_id && !identity.id) {
+					identity.id = identity.user_id;
+				}
+
+				if (identity.CharacterID && !identity.id) {
+					identity.id = identity.CharacterID;
+				}
+
+				// Fix Dataporten having 'user.userid' instead of 'id'
+				if (identity.user && identity.user.userid && !identity.id) {
+					identity.id = identity.user.userid;
+					identity.email = identity.user.email;
+				}
+
+				// Fix general 'phid' instead of 'id' from phabricator
+				if (identity.phid && !identity.id) {
+					identity.id = identity.phid;
+				}
+
+				// Fix Keycloak-like identities having 'sub' instead of 'id'
+				if (identity.sub && !identity.id) {
+					identity.id = identity.sub;
+				}
+
+				// Fix general 'userid' instead of 'id' from provider
+				if (identity.userid && !identity.id) {
+					identity.id = identity.userid;
+				}
+			}
+
+			// console.log 'id:', JSON.stringify identity, null, '  '
+
+			const serviceData = {
+				_OAuthCustom: true,
+				accessToken: accessToken
+			};
+
+			_.extend(serviceData, identity);
+
+			const data = {
+				serviceData: serviceData,
+				options: {
+					profile: {
+						name: identity.name || identity.username || identity.nickname || identity.CharacterName || identity.userName || identity.preferred_username || (identity.user && identity.user.name)
+					}
+				}
+			};
+
+			// console.log data
+
+			return data;
+		});
+	}
+
+	retrieveCredential(credentialToken, credentialSecret) {
+		return OAuth.retrieveCredential(credentialToken, credentialSecret);
+	}
+
+	getUsername(data) {
+		let username = '';
+
+		if (this.usernameField.indexOf('#{') > -1) {
+			username = this.usernameField.replace(/#{(.+?)}/g, function(match, field) {
+				if (!data[field]) {
+					throw new Meteor.Error('field_not_found', `Username template item "${field}" not found in data`, data);
+				}
+				return data[field];
+			});
+		} else {
+			username = data[this.usernameField];
+			if (!username) {
+				throw new Meteor.Error('field_not_found', `Username field "${this.usernameField}" not found in data`, data);
+			}
+		}
+
+		return username;
+	}
+
+	addHookToProcessUser() {
+		BeforeUpdateOrCreateUserFromExternalService.push((serviceName, serviceData/*, options*/) => {
+			if (serviceName !== this.name) {
+				return;
+			}
+
+			if (this.usernameField) {
+				const username = this.getUsername(serviceData);
+
+				const user = RocketChat.models.Users.findOneByUsername(username);
+				if (!user) {
+					return;
+				}
+
+				// User already created or merged
+				if (user.services && user.services[serviceName] && user.services[serviceName].id === serviceData.id) {
+					return;
+				}
+
+				if (this.mergeUsers !== true) {
+					throw new Meteor.Error('CustomOAuth', `User with username ${user.username} already exists`);
+				}
+
+				const serviceIdKey = `services.${serviceName}.id`;
+				const update = {
+					$set: {
+						[serviceIdKey]: serviceData.id
+					}
+				};
+
+				RocketChat.models.Users.update({_id: user._id}, update);
+			}
+		});
+
+		Accounts.validateNewUser((user) => {
+			if (!user.services || !user.services[this.name] || !user.services[this.name].id) {
+				return true;
+			}
+
+			if (this.usernameField) {
+				user.username = this.getUsername(user.services[this.name]);
+			}
+
+			return true;
+		});
+
+	}
+}
+
+
+const updateOrCreateUserFromExternalService = Accounts.updateOrCreateUserFromExternalService;
+Accounts.updateOrCreateUserFromExternalService = function(/*serviceName, serviceData, options*/) {
+	for (const hook of BeforeUpdateOrCreateUserFromExternalService) {
+		hook.apply(this, arguments);
+	}
+
+	return updateOrCreateUserFromExternalService.apply(this, arguments);
+};
diff --git a/packages/rocketchat-custom-oauth/package.js b/packages/rocketchat-custom-oauth/package.js
index bf9f3219d4704e15852c0a139b5cef8e38461c73..e4a397f479e8ecba55c29f2c2f53bf527a2ee848 100644
--- a/packages/rocketchat-custom-oauth/package.js
+++ b/packages/rocketchat-custom-oauth/package.js
@@ -5,12 +5,12 @@ Package.describe({
 });
 
 Package.onUse(function(api) {
+	api.use('modules');
 	api.use('check');
 	api.use('oauth');
 	api.use('oauth2');
 	api.use('underscore');
 	api.use('ecmascript');
-	api.use('coffeescript');
 	api.use('accounts-oauth');
 	api.use('service-configuration');
 	api.use('underscorestring:underscore.string');
@@ -20,9 +20,9 @@ Package.onUse(function(api) {
 	api.use('http', 'server');
 
 
-	api.addFiles('custom_oauth_client.coffee', 'client');
+	api.mainModule('custom_oauth_client.js', 'client');
 
-	api.addFiles('custom_oauth_server.coffee', 'server');
+	api.mainModule('custom_oauth_server.js', 'server');
 
 	api.export('CustomOAuth');
 });
diff --git a/packages/rocketchat-emoji-custom/admin/adminEmoji.html b/packages/rocketchat-emoji-custom/admin/adminEmoji.html
index 1af79f80f4709b7fdfb77997da877ed1ab54ad1b..32c7844b6baa817465e0bc48d844e71bf6bd4f9d 100644
--- a/packages/rocketchat-emoji-custom/admin/adminEmoji.html
+++ b/packages/rocketchat-emoji-custom/admin/adminEmoji.html
@@ -1,6 +1,6 @@
 <template name="adminEmoji">
 	<section class="page-container page-list">
-		<header class="fixed-title">
+		<header class="fixed-title border-component-color">
 			{{> burger}}
 			<h2>
 				<span class="room-title">{{_ "Custom_Emoji"}}</span>
@@ -13,7 +13,7 @@
 				<form class="search-form" role="form">
 					<div class="input-line search">
 						<input type="text" id="emoji-filter" placeholder="{{_ "Search"}}" dir="auto">
-						<i class="icon-search"></i>
+						<i class="icon-search secondary-font-color"></i>
 						{{#unless isReady}}<i class="icon-spin"></i>{{/unless}}
 					</div>
 				</form>
@@ -21,24 +21,24 @@
 					{{{_ "Showing_results" customemoji.length}}}
 				</div>
 				<div class="list">
-					<table>
+					<table class="secondary-background-color">
 						<thead>
-							<tr>
-								<th>&nbsp;</th>
-								<th width="51%">{{_ "Name"}}</th>
-								<th width="49%">{{_ "Aliases"}}</th>
+							<tr class="admin-table-row">
+								<th class="content-background-color border-component-color">&nbsp;</th>
+								<th class="content-background-color border-component-color" width="51%">{{_ "Name"}}</th>
+								<th class="content-background-color border-component-color" width="49%">{{_ "Aliases"}}</th>
 							</tr>
 						</thead>
 						<tbody>
 							{{#each customemoji}}
-							<tr class="emoji-info row-link">
-								<td>
+							<tr class="emoji-info row-link admin-table-row">
+								<td class="border-component-color">
 									<div class="emojiAdminPreview-image">
 										{{> emojiPreview name=name extension=extension}}
 									</div>
 								</td>
-								<td>{{name}}</td>
-								<td>{{aliases}}</td>
+								<td class="border-component-color">{{name}}</td>
+								<td class="border-component-color">{{aliases}}</td>
 							</tr>
 							{{/each}}
 						</tbody>
@@ -50,7 +50,7 @@
 			{{/unless}}
 		</div>
 	</section>
-	<section class="flex-tab">
+	<section class="flex-tab secondary-background-color">
 		{{> Template.dynamic template=flexTemplate data=flexData}}
 	</section>
 </template>
diff --git a/packages/rocketchat-emoji-custom/admin/emojiEdit.html b/packages/rocketchat-emoji-custom/admin/emojiEdit.html
index b16d900d02351c311bd3bccc89ce9b13e3d0a5b6..76b938cdf5b192617e94f9104e5c86c4e41dd866 100644
--- a/packages/rocketchat-emoji-custom/admin/emojiEdit.html
+++ b/packages/rocketchat-emoji-custom/admin/emojiEdit.html
@@ -11,11 +11,11 @@
 				{{/if}}
 				<div class="input-line">
 					<label for="name">{{_ "Name"}}</label>
-					<input type="text" id="name" autocomplete="off" value="{{emoji.name}}">
+					<input type="text" id="name" autocomplete="off" value="{{emoji.name}}" class="content-background-color">
 				</div>
 				<div class="input-line">
 					<label for="aliases">{{_ "Aliases"}}</label>
-					<input type="text" id="aliases" autocomplete="off" value="{{emoji.aliases}}">
+					<input type="text" id="aliases" autocomplete="off" value="{{emoji.aliases}}"  class="content-background-color">
 				</div>
 				<div class="input-line">
 					<label for="image">{{_ "Image"}}</label>
diff --git a/packages/rocketchat-emoji-custom/assets/stylesheets/emojiCustomAdmin.less b/packages/rocketchat-emoji-custom/assets/stylesheets/emojiCustomAdmin.less
index 1a6dfc8d2f11dbd68cf7d59ccd1d4a1a7c01c322..1eb732ff8e50537b7dab08ae24c4072292a5ae58 100644
--- a/packages/rocketchat-emoji-custom/assets/stylesheets/emojiCustomAdmin.less
+++ b/packages/rocketchat-emoji-custom/assets/stylesheets/emojiCustomAdmin.less
@@ -4,6 +4,7 @@
 	overflow: hidden;
 	position: relative;
 	border-radius: 4px;
+
 	.emojiAdminPreview-image {
 		height: 100%;
 		width: 100%;
@@ -22,17 +23,21 @@
 	z-index: 15;
 	overflow-y: auto;
 	overflow-x: hidden;
+
 	.thumb {
 		width: 100%;
 		height: 350px;
 		padding: 20px;
 	}
+
 	nav {
 		padding: 0 20px;
 	}
+
 	.info {
 		white-space: normal;
 		padding: 0 20px;
+
 		h3 {
 			-webkit-user-select: text;
 			-moz-user-select: text;
@@ -45,7 +50,8 @@
 			width: 100%;
 			overflow: hidden;
 			white-space: nowrap;
-			i:after {
+
+			i::after {
 				content: " ";
 				display: inline-block;
 				width: 8px;
@@ -53,19 +59,8 @@
 				border-radius: 4px;
 				vertical-align: middle;
 			}
-			i.status-offline {
-				&:after {}
-			}
-			i.status-online {
-				&:after {}
-			}
-			i.status-away {
-				&:after {}
-			}
-			i.status-busy {
-				&:after {}
-			}
 		}
+
 		p {
 			-webkit-user-select: text;
 			-moz-user-select: text;
@@ -76,22 +71,27 @@
 			font-weight: 300;
 		}
 	}
+
 	.edit-form {
-		padding: 20px 20px 0 20px;
+		padding: 20px 20px 0;
 		white-space: normal;
+
 		h3 {
 			font-size: 24px;
 			margin-bottom: 8px;
 			line-height: 22px;
 		}
+
 		p {
 			line-height: 18px;
 			font-size: 12px;
 			font-weight: 300;
 		}
+
 		> .input-line {
 			margin-top: 20px;
 		}
+
 		nav {
 			padding: 0;
 
@@ -110,7 +110,8 @@
 			}
 		}
 	}
+
 	.room-info-content > div {
-		margin: 0 0 20px 0;
+		margin: 0 0 20px;
 	}
 }
diff --git a/packages/rocketchat-emoji-emojione/emojiPicker.js b/packages/rocketchat-emoji-emojione/emojiPicker.js
index db9771e476d80a5cbc5f61afd7c2f216eb529138..6a7a2dab3c327a950caecf7275b363ef5b935fdb 100644
--- a/packages/rocketchat-emoji-emojione/emojiPicker.js
+++ b/packages/rocketchat-emoji-emojione/emojiPicker.js
@@ -1523,13 +1523,6 @@ emojisByCategory = {
 		'flag_ss',
 		'flag_tc',
 		'flag_mf'
-	],
-	'modifier': [
-		'tone1',
-		'tone2',
-		'tone3',
-		'tone4',
-		'tone5'
 	]
 };
 
diff --git a/packages/rocketchat-emoji/emojiPicker.html b/packages/rocketchat-emoji/emojiPicker.html
index 3603525d5e38b8a8d475838dfcbbfe44cf613530..8ac2e5e66b256dcfc558e9d14de2404651382297 100644
--- a/packages/rocketchat-emoji/emojiPicker.html
+++ b/packages/rocketchat-emoji/emojiPicker.html
@@ -1,32 +1,31 @@
 <template name="emojiPicker">
-	<div class="emoji-picker">
+	<div class="emoji-picker secondary-background-color">
+		<div class="emoji-top">
+			<form class="emoji-filter input-line search search-form">
+				<input type="text" class="search content-background-color" autocomplete="off">
+				<i class="icon-search secondary-font-color"></i>
+			</form>
+			<div class="change-tone">
+				<a href="#change-tone"><span class="current-tone {{currentTone}}"></span></a>
+				<ul class="tone-selector secondary-background-color">
+					<li><a href="#tone" class="tone" data-tone="0"><span class="tone-0"></span></a></li>
+					<li><a href="#tone" class="tone" data-tone="1"><span class="tone-1"></span></a></li>
+					<li><a href="#tone" class="tone" data-tone="2"><span class="tone-2"></span></a></li>
+					<li><a href="#tone" class="tone" data-tone="3"><span class="tone-3"></span></a></li>
+					<li><a href="#tone" class="tone" data-tone="4"><span class="tone-4"></span></a></li>
+					<li><a href="#tone" class="tone" data-tone="5"><span class="tone-5"></span></a></li>
+				</ul>
+			</div>
+		</div>
 		<div class="filter">
-			<ul>
+			<ul class="filter-list">
 				{{#each category}}
-					<li class="{{activeCategory .}}" title="{{categoryName .}}">
-						<a href="#{{.}}" class="category-link"><i class="icon-{{.}}"></i></a>
+					<li class="filter-item border-secondary-background-color {{activeCategory .}}" title="{{categoryName .}}">
+						<a href="#{{.}}" class="category-link color-info-font-color"><i class="category-icon icon-{{.}}"></i></a>
 					</li>
 				{{/each}}
-				<li class="change-tone">
-					<a href="#change-tone"><span class="current-tone {{currentTone}}"></span></a>
-					<ul class="tone-selector">
-						<li><a href="#tone" class="tone" data-tone="0"><span class="tone-0"></span></a></li>
-						<li><a href="#tone" class="tone" data-tone="1"><span class="tone-1"></span></a></li>
-						<li><a href="#tone" class="tone" data-tone="2"><span class="tone-2"></span></a></li>
-						<li><a href="#tone" class="tone" data-tone="3"><span class="tone-3"></span></a></li>
-						<li><a href="#tone" class="tone" data-tone="4"><span class="tone-4"></span></a></li>
-						<li><a href="#tone" class="tone" data-tone="5"><span class="tone-5"></span></a></li>
-					</ul>
-				</li>
 			</ul>
 		</div>
-		<form class="emoji-filter input-line search search-form">
-			<input type="text" class="search" placeholder="{{_ 'Search Emoji'}}" autocomplete="off">
-			<i class="icon-right-open-small"></i>
-		</form>
-		<h2 class="current-category-header">
-			{{ currentCategory }}
-		</h2>
 		<div class="emojis">
 			{{#each category}}
 				<ul class="{{.}} emoji-list {{isVisible .}}">
diff --git a/packages/rocketchat-emoji/emojiPicker.js b/packages/rocketchat-emoji/emojiPicker.js
index f09437bdaeb2af6667133ed8371900ddcf322ae4..d960b86639eb8a89575940ef3827f356557e8fec 100644
--- a/packages/rocketchat-emoji/emojiPicker.js
+++ b/packages/rocketchat-emoji/emojiPicker.js
@@ -178,6 +178,8 @@ Template.emojiPicker.events({
 		event.stopPropagation();
 		event.preventDefault();
 
+		instance.$('.emoji-filter .search').val('').change();
+
 		instance.currentCategory.set(event.currentTarget.hash.substr(1));
 
 		return false;
@@ -247,7 +249,7 @@ Template.emojiPicker.events({
 			event.preventDefault();
 		}
 	},
-	'keyup .emoji-filter .search'(event, instance) {
+	'keyup .emoji-filter .search, change .emoji-filter .search'(event, instance) {
 		const value = event.target.value.trim();
 		const cst = instance.currentSearchTerm;
 		if (value === cst.get()) {
diff --git a/packages/rocketchat-emoji/emojiPicker.less b/packages/rocketchat-emoji/emojiPicker.less
index 8db8c68f993a99aab410205167b5130bee398ef5..d4a06e938886572691846510ceee3ee8fbe2d1c7 100644
--- a/packages/rocketchat-emoji/emojiPicker.less
+++ b/packages/rocketchat-emoji/emojiPicker.less
@@ -1,29 +1,30 @@
+@import "lesshat.less";
+
 .emoji-picker-icon {
 	cursor: pointer;
-
 	font-size: 18px;
-	color: @info-font-color;
 
-	&:before {
-		.transition(transform 0.2s ease);
+	&::before {
+		transition: transform 0.2s ease;
 	}
+
 	&:hover {
-		&:before {
+		&::before {
 			.transform(scale(1.2));
 		}
 	}
 }
+
 .emoji-picker {
 	width: 100%;
 	max-width: 365px;
-	background-color: @secondary-background-color;
 	border-radius: 5px;
-	box-shadow: 0px 1px 1px 0 rgba(0,0,0,0.2), 0 2px 10px 0 rgba(0,0,0,.16);
+	box-shadow:
+		0 1px 1px 0 rgba(0, 0, 0, 0.2),
+		0 2px 10px 0 rgba(0, 0, 0, 0.16);
 	position: absolute;
 	z-index: 200;
-
-	.transition(transform 0.2s ease, visibility 0.2s ease, opacity 0.2s ease);
-
+	transition: transform 0.2s ease, visibility 0.2s ease, opacity 0.2s ease;
 	.transform(translateY(30px));
 	opacity: 0;
 	visibility: hidden;
@@ -36,142 +37,51 @@
 	}
 
 	.filter {
-		text-align: center;
-		box-shadow: 0px 2px 2px -1px rgba(0,0,0,0.2);
-
-		> ul {
-			display: table;
-			width: 100%;
-
-			> li {
-				display: table-cell;
-				margin: 0 2px;
-				padding: 6px 0;
-
-				border-bottom: 2px solid @secondary-background-color;
-
-				.category-link {
-					i {
-						color: @info-font-color;
-						font-size: 20px;
-					}
-				}
+		box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.2);
+	}
 
-				&:hover {
-					border-bottom: 2px solid @info-font-color;
-				}
+	.filter-list {
+		display: flex;
+		width: 100%;
+		padding: 0 5px;
+	}
 
-				&.active {
-					border-bottom: 2px solid @primary-background-color;
-				}
+	.filter-item {
+		padding: 6px 0;
+		border-style: solid;
+		border-width: 0 0 2px;
+		display: flex;
+		justify-content: center;
+		flex-grow: 1;
 
-				&.change-tone {
-					opacity: 1;
-					border-bottom: 2px solid transparent;
-
-					> a {
-						position: relative;
-						z-index: 10;
-					}
-
-					.current-tone {
-						display: inline-block;
-						width: 20px;
-						height: 20px;
-						border-radius: 10px;
-					}
-
-					.tone-selector {
-						position: absolute;
-						background-color: @secondary-background-color;
-						border-radius: 4px;
-						box-shadow: 0px 1px 1px 0 rgba(0,0,0,0.2), 0 2px 10px 0 rgba(0,0,0,.16);
-
-						padding: 4px 2px;
-						margin-left: -4px;
-						z-index: 8;
-
-						.transition(transform 0.2s ease, visibility 0.2s ease, opacity 0.2s ease);
-
-						.transform(translateY(-20px));
-						opacity: 0;
-						visibility: hidden;
-
-						&.show {
-							.transform(translateY(0px));
-							opacity: 1;
-							display: block;
-							visibility: visible;
-						}
-
-						li {
-							display: block;
-							padding: 0 4px;
-						}
-
-						span {
-							display: inline-block;
-							width: 20px;
-							height: 20px;
-							border-radius: 10px;
-
-							.transition(transform 0.2s ease);
-						}
-					}
-
-					.tone-0 {
-						background-color: #ffcf11;
-					}
-
-					.tone-1 {
-						background-color: #fae3c3;
-					}
-
-					.tone-2 {
-						background-color: #e2cfa1;
-					}
-
-					.tone-3 {
-						background-color: #dba373;
-					}
-
-					.tone-4 {
-						background-color: #a88054;
-					}
-
-					.tone-5 {
-						background-color: #5f4e43;
-					}
-				}
-			}
+		.category-icon {
+			font-size: 20px;
 		}
 	}
 
 	.current-category-header {
-		padding: 3px 6px 2px 6px;
+		padding: 3px 5px;
 	}
 
 	.emojis {
 		height: 160px;
 		overflow-y: auto;
-		padding: 3px 0px 0px 2px;
+		padding: 3px 0 0 2px;
 
-		.custom-scroll(transparent, #DDD);
 		.emoji-list {
 			display: none;
 
 			li {
 				display: inline-block;
 				margin: 2px;
-				padding: 4px 2px 2px 2px;
+				padding: 4px 2px 2px;
 				border-radius: 4px;
 				cursor: pointer;
-
-				.transition(transform 0.2s ease);
+				transition: transform 0.2s ease;
 
 				&:hover {
 					.transform(scale(1.2));
-					background-color: #DDD;
+					background-color: #dddddd;
 				}
 			}
 
@@ -181,3 +91,92 @@
 		}
 	}
 }
+
+.emoji-top {
+	display: flex;
+	align-items: center;
+	padding: 5px;
+
+	.emoji-filter {
+		width: 90%;
+		margin-bottom: 0;
+	}
+
+	.change-tone {
+		width: 10%;
+		display: flex;
+		justify-content: center;
+		position: relative;
+
+		a {
+			position: relative;
+			z-index: 10;
+		}
+
+		.current-tone {
+			display: block;
+			width: 20px;
+			height: 20px;
+			border-radius: 10px;
+		}
+
+		.tone-selector {
+			position: absolute;
+			border-radius: 4px;
+			box-shadow:
+				0 1px 1px 0 rgba(0, 0, 0, 0.2),
+				0 2px 10px 0 rgba(0, 0, 0, 0.16);
+			padding: 4px 2px;
+			top: 25px;
+			z-index: 1;
+			transition: transform 0.2s ease, visibility 0.2s ease, opacity 0.2s ease;
+			.transform(translateY(-20px));
+			opacity: 0;
+			visibility: hidden;
+
+			&.show {
+				.transform(translateY(0px));
+				opacity: 1;
+				display: block;
+				visibility: visible;
+			}
+
+			li {
+				display: block;
+				padding: 0 4px;
+			}
+
+			span {
+				display: inline-block;
+				width: 20px;
+				height: 20px;
+				border-radius: 10px;
+				transition: transform 0.2s ease;
+			}
+		}
+
+		.tone-0 {
+			background-color: #ffcf11;
+		}
+
+		.tone-1 {
+			background-color: #fae3c3;
+		}
+
+		.tone-2 {
+			background-color: #e2cfa1;
+		}
+
+		.tone-3 {
+			background-color: #dba373;
+		}
+
+		.tone-4 {
+			background-color: #a88054;
+		}
+
+		.tone-5 {
+			background-color: #5f4e43;
+		}
+	}
+}
diff --git a/packages/rocketchat-emoji/lesshat.less b/packages/rocketchat-emoji/lesshat.less
new file mode 100644
index 0000000000000000000000000000000000000000..7c9f0ae86a267eb3660d2381a0bba2620f0488f4
--- /dev/null
+++ b/packages/rocketchat-emoji/lesshat.less
@@ -0,0 +1,17 @@
+//  lesshat - The best mixin library in the world
+//
+// version: v4.1.0 (2016-07-19)
+
+.calc(...) {
+	@process: ~`(function(a){function c(c,t){var r=");\n",s=e.split(","),l=s[0]+":"+c+"("+(s[1].trim()||0)+r;"start"==t?a="0;\n"+l:a+=l}a=a||8121991;var t="@{state}",e=a;if(8121991==a)return a;switch(t){case"1":c("-webkit-calc","start"),c("-moz-calc"),c("calc");break;case"2":c("-webkit-calc","start"),c("-moz-calc");break;case"3":c("-webkit-calc","start"),c("calc");break;case"4":c("-webkit-calc","start");break;case"5":c("-moz-calc","start"),c("calc");break;case"6":c("-moz-calc","start");break;case"7":c("calc","start")}return a=a.replace(/;$/g,"")})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
+	@state: 1; -lh-property: @process;
+}
+
+.transform(...) {
+	@process: ~`(function(e){e=e||"none";var r={translate:"px",rotate:"deg",rotate3d:"deg",skew:"deg"};/^\w*\(?[a-z0-9.]*\)?/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,""));for(var t in r)e.indexOf(t)>=0&&(e=e.replace(new RegExp(t+"[\\w]?\\([a-z0-9, %]*\\)"),function(e){var n=/(\d+\.?\d*)(?!\w|%)/g;return"rotate3d"==t&&(n=/,\s*\d+$/),e.replace(n,function(e){return e+r[t]})}));return e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
+	-webkit-transform: @process;
+	-moz-transform: @process;
+	-ms-transform: @process;
+	-o-transform: @process;
+	transform: @process;
+}
diff --git a/packages/rocketchat-emoji/lib/EmojiPicker.js b/packages/rocketchat-emoji/lib/EmojiPicker.js
index dc3bd9dd04f58ce09e4afe2b28eac5961c2f05f9..02ad077052a04c7b6bee87ae932a635a7ea3c054 100644
--- a/packages/rocketchat-emoji/lib/EmojiPicker.js
+++ b/packages/rocketchat-emoji/lib/EmojiPicker.js
@@ -53,21 +53,30 @@ RocketChat.EmojiPicker = {
 	},
 	setPosition() {
 		let sourcePos = $(this.source).offset();
-		let left = (sourcePos.left - this.width + 65);
+		let left = sourcePos.left;
 		let top = (sourcePos.top - this.height - 5);
+		let cssProperties = {
+			top: top,
+			left: left
+		};
 
-		if (left < 0) {
-			left = 10;
-		}
 		if (top < 0) {
-			top = 10;
+			cssProperties.top = 10;
+		}
+
+		if (left < 35) {
+			cssProperties.left = 0;
+		} else {
+			let windowSize = $(window).width();
+			let pickerWidth = $('.emoji-picker').width();
+
+			if (left + pickerWidth > windowSize) {
+				let emojiButtonSize = $('.reaction-message.message-action').outerWidth();
+				cssProperties.left = left - pickerWidth + emojiButtonSize;
+			}
 		}
 
-		return $('.emoji-picker')
-			.css({
-				top: top + 'px',
-				left: left + 'px'
-			});
+		return $('.emoji-picker').css(cssProperties);
 	},
 	open(source, callback) {
 		if (!this.initiated) {
diff --git a/packages/rocketchat-emoji/loadStylesheet.js b/packages/rocketchat-emoji/loadStylesheet.js
deleted file mode 100644
index 323238e1975b36e924773d34e78bb10f8eb5df43..0000000000000000000000000000000000000000
--- a/packages/rocketchat-emoji/loadStylesheet.js
+++ /dev/null
@@ -1,3 +0,0 @@
-RocketChat.theme.addPackageAsset(function() {
-	return Assets.getText('emojiPicker.less');
-});
diff --git a/packages/rocketchat-emoji/package.js b/packages/rocketchat-emoji/package.js
index ed234d141dc0b67ddb894c6f1750a613010b3d82..48cb5dc9e691a8db26cc2c4302a9933281f75c55 100644
--- a/packages/rocketchat-emoji/package.js
+++ b/packages/rocketchat-emoji/package.js
@@ -22,9 +22,8 @@ Package.onUse(function(api) {
 
 	api.addFiles('emojiPicker.html', 'client');
 	api.addFiles('emojiPicker.js', 'client');
+	api.addFiles('emojiPicker.less', 'client');
 
-	api.addAssets('emojiPicker.less', 'server');
-	api.addFiles('loadStylesheet.js', 'server');
 	api.addFiles('emoji.css', 'client');
 
 	api.addFiles('lib/emojiRenderer.js', 'client');
diff --git a/packages/rocketchat-favico/favico.js b/packages/rocketchat-favico/favico.js
index 711c16559ca02374785b0fd06529848aa1b7844e..1cef87bd2c1fa2e61e42d4d1214c9b0b87105724 100644
--- a/packages/rocketchat-favico/favico.js
+++ b/packages/rocketchat-favico/favico.js
@@ -96,12 +96,13 @@
 			}
 			_opt.type = (type['' + _opt.type]) ? _opt.type : _def.type;
 
-			_orig = link.getIcon();
+			_orig = link.getIcons();
 			//create temp canvas
 			_canvas = document.createElement('canvas');
 			//create temp image
 			_img = document.createElement('img');
-			if (_orig.hasAttribute('href')) {
+			var lastIcon = _orig[_orig.length - 1];
+			if (lastIcon.hasAttribute('href')) {
 				_img.setAttribute('crossOrigin', 'anonymous');
 				//get width/height
 				_img.onload = function() {
@@ -112,7 +113,7 @@
 					_context = _canvas.getContext('2d');
 					icon.ready();
 				};
-				_img.setAttribute('src', _orig.getAttribute('href'));
+				_img.setAttribute('src', lastIcon.getAttribute('href'));
 			} else {
 				_img.onload = function() {
 					_h = 32;
@@ -461,37 +462,40 @@
 
 		var link = {};
 		/**
-		 * Get icon from HEAD tag or create a new <link> element
+		 * Get icons from HEAD tag or create a new <link> element
 		 */
-		link.getIcon = function() {
-			var elm = false;
+		link.getIcons = function() {
+			var elms = [];
 			//get link element
-			var getLink = function() {
-				var link = _doc.getElementsByTagName('head')[0].getElementsByTagName('link');
-				for (var l = link.length, i = (l - 1); i >= 0; i--) {
-					if ((/(^|\s)icon(\s|$)/i).test(link[i].getAttribute('rel'))) {
-						return link[i];
+			var getLinks = function() {
+				var icons = [];
+				var links = _doc.getElementsByTagName('head')[0].getElementsByTagName('link');
+				for (var i = 0; i < links.length; i++) {
+					if ((/(^|\s)icon(\s|$)/i).test(links[i].getAttribute('rel'))) {
+						icons.push(links[i]);
 					}
 				}
-				return false;
+				return icons;
 			};
 			if (_opt.element) {
-				elm = _opt.element;
+				elms = [_opt.element];
 			} else if (_opt.elementId) {
 				//if img element identified by elementId
-				elm = _doc.getElementById(_opt.elementId);
-				elm.setAttribute('href', elm.getAttribute('src'));
+				elms = [_doc.getElementById(_opt.elementId)];
+				elms[0].setAttribute('href', elms[0].getAttribute('src'));
 			} else {
 				//if link element
-				elm = getLink();
-				if (elm === false) {
-					elm = _doc.createElement('link');
-					elm.setAttribute('rel', 'icon');
-					_doc.getElementsByTagName('head')[0].appendChild(elm);
+				elms = getLinks();
+				if (elms.length === 0) {
+					elms = [_doc.createElement('link')];
+					elms[0].setAttribute('rel', 'icon');
+					_doc.getElementsByTagName('head')[0].appendChild(elms[0]);
 				}
 			}
-			elm.setAttribute('type', 'image/png');
-			return elm;
+			elms.forEach(function(item) {
+				item.setAttribute('type', 'image/png');
+			});
+			return elms;
 		};
 		link.setIcon = function(canvas) {
 			var url = canvas.toDataURL('image/png');
@@ -512,21 +516,24 @@
 				if (_browser.ff || _browser.opera) {
 					//for FF we need to "recreate" element, atach to dom and remove old <link>
 					//var originalType = _orig.getAttribute('rel');
-					var old = _orig;
-					_orig = _doc.createElement('link');
+					var old = _orig[_orig.length - 1];
+					var newIcon = _doc.createElement('link');
+					_orig = [newIcon];
 					//_orig.setAttribute('rel', originalType);
 					if (_browser.opera) {
-						_orig.setAttribute('rel', 'icon');
+						newIcon.setAttribute('rel', 'icon');
 					}
-					_orig.setAttribute('rel', 'icon');
-					_orig.setAttribute('type', 'image/png');
-					_doc.getElementsByTagName('head')[0].appendChild(_orig);
-					_orig.setAttribute('href', url);
+					newIcon.setAttribute('rel', 'icon');
+					newIcon.setAttribute('type', 'image/png');
+					_doc.getElementsByTagName('head')[0].appendChild(newIcon);
+					newIcon.setAttribute('href', url);
 					if (old.parentNode) {
 						old.parentNode.removeChild(old);
 					}
 				} else {
-					_orig.setAttribute('href', url);
+					_orig.forEach(function(icon) {
+						icon.setAttribute('href', url);
+					});
 				}
 			}
 		};
diff --git a/packages/rocketchat-file-upload/client/lib/FileUploadAmazonS3.js b/packages/rocketchat-file-upload/client/lib/FileUploadAmazonS3.js
index 9ca22909f0635169661c79047e41f42028f5acc0..3fdae7c30b746062aeffee51986db1a5b84058bc 100644
--- a/packages/rocketchat-file-upload/client/lib/FileUploadAmazonS3.js
+++ b/packages/rocketchat-file-upload/client/lib/FileUploadAmazonS3.js
@@ -25,7 +25,7 @@ FileUpload.AmazonS3 = class FileUploadAmazonS3 extends FileUploadBase {
 					Session.set('uploading', uploading);
 				}
 			} else {
-				file = _.pick(this.meta, 'type', 'size', 'name', 'identify');
+				file = _.pick(this.meta, 'type', 'size', 'name', 'identify', 'description');
 				file._id = downloadUrl.substr(downloadUrl.lastIndexOf('/') + 1);
 				file.url = downloadUrl;
 
diff --git a/packages/rocketchat-file-upload/client/lib/FileUploadFileSystem.js b/packages/rocketchat-file-upload/client/lib/FileUploadFileSystem.js
index 80949d670277aea4a351bb2995a3049c5d8b9b9e..39ddae6a388345b06e9e32471b597110acf6f028 100644
--- a/packages/rocketchat-file-upload/client/lib/FileUploadFileSystem.js
+++ b/packages/rocketchat-file-upload/client/lib/FileUploadFileSystem.js
@@ -29,7 +29,7 @@ FileUpload.FileSystem = class FileUploadFileSystem extends FileUploadBase {
 				}
 			},
 			onComplete: (fileData) => {
-				var file = _.pick(fileData, '_id', 'type', 'size', 'name', 'identify');
+				var file = _.pick(fileData, '_id', 'type', 'size', 'name', 'identify', 'description');
 
 				file.url = fileData.url.replace(Meteor.absoluteUrl(), '/');
 
diff --git a/packages/rocketchat-file-upload/client/lib/FileUploadGridFS.js b/packages/rocketchat-file-upload/client/lib/FileUploadGridFS.js
index 06a3dcf7988401504954572248fa8f6a58a16034..d78faf8d81759e6adb3df5036f2b9280ced2f988 100644
--- a/packages/rocketchat-file-upload/client/lib/FileUploadGridFS.js
+++ b/packages/rocketchat-file-upload/client/lib/FileUploadGridFS.js
@@ -20,7 +20,7 @@ FileUpload.GridFS = class FileUploadGridFS extends FileUploadBase {
 				}
 			},
 			onComplete: (fileData) => {
-				var file = _.pick(fileData, '_id', 'type', 'size', 'name', 'identify');
+				var file = _.pick(fileData, '_id', 'type', 'size', 'name', 'identify', 'description');
 
 				file.url = fileData.url.replace(Meteor.absoluteUrl(), '/');
 
diff --git a/packages/rocketchat-file-upload/lib/FileUploadBase.js b/packages/rocketchat-file-upload/lib/FileUploadBase.js
index fb79799d74e961636f3ee159e80837bd80a71acc..2e93fcfa166edced447f2231a211bf0ff884b4fc 100644
--- a/packages/rocketchat-file-upload/lib/FileUploadBase.js
+++ b/packages/rocketchat-file-upload/lib/FileUploadBase.js
@@ -1,6 +1,19 @@
-/* globals FileUploadBase:true */
+/* globals FileUploadBase:true, UploadFS */
 /* exported FileUploadBase */
 
+UploadFS.config.defaultStorePermissions = new UploadFS.StorePermissions({
+	insert: function(userId/*, doc*/) {
+		return userId;
+	},
+	update: function(userId, doc) {
+		return userId === doc.userId;
+	},
+	remove: function(userId, doc) {
+		return userId === doc.userId;
+	}
+});
+
+
 FileUploadBase = class FileUploadBase {
 	constructor(meta, file) {
 		this.id = Random.id();
diff --git a/packages/rocketchat-file-upload/package.js b/packages/rocketchat-file-upload/package.js
index bbd3bfedbd5808c7a39871e98a7e02aa418ad7d6..55491f0e8229dea99d59955bc8eaf7e69112fc88 100644
--- a/packages/rocketchat-file-upload/package.js
+++ b/packages/rocketchat-file-upload/package.js
@@ -47,6 +47,5 @@ Package.onUse(function(api) {
 });
 
 Npm.depends({
-	'mime-types': '2.1.11',
 	'filesize': '3.3.0'
 });
diff --git a/packages/rocketchat-file-upload/server/config/configFileUploadGridFS.js b/packages/rocketchat-file-upload/server/config/configFileUploadGridFS.js
index 4675716b39633ba191424ed4782f06be78ab5a06..3e7f45798d14bac533f548c4656ac6204bae389c 100644
--- a/packages/rocketchat-file-upload/server/config/configFileUploadGridFS.js
+++ b/packages/rocketchat-file-upload/server/config/configFileUploadGridFS.js
@@ -1,6 +1,62 @@
 /* globals FileUpload, UploadFS */
-var stream = Npm.require('stream');
-var zlib = Npm.require('zlib');
+const stream = Npm.require('stream');
+const zlib = Npm.require('zlib');
+const util = Npm.require('util');
+const logger = new Logger('FileUpload');
+
+function ExtractRange(options) {
+	if (!(this instanceof ExtractRange)) {
+		return new ExtractRange(options);
+	}
+
+	this.start = options.start;
+	this.stop = options.stop;
+	this.bytes_read = 0;
+
+	stream.Transform.call(this, options);
+}
+util.inherits(ExtractRange, stream.Transform);
+
+
+ExtractRange.prototype._transform = function(chunk, enc, cb) {
+	if (this.bytes_read > this.stop) {
+		// done reading
+		this.end();
+	} else if (this.bytes_read + chunk.length < this.start) {
+		// this chunk is still before the start byte
+	} else {
+		var start, stop;
+		if (this.start <= this.bytes_read) {
+			start = 0;
+		} else {
+			start = this.start - this.bytes_read;
+		}
+		if ((this.stop - this.bytes_read + 1) < chunk.length) {
+			stop = this.stop - this.bytes_read + 1;
+		} else {
+			stop = chunk.length;
+		}
+		var newchunk = chunk.slice(start, stop);
+		this.push(newchunk);
+	}
+	this.bytes_read += chunk.length;
+	cb();
+};
+
+
+var getByteRange = function(header) {
+	if (header) {
+		var matches = header.match(/(\d+)-(\d+)/);
+		if (matches) {
+			return {
+				start: parseInt(matches[1], 10),
+				stop: parseInt(matches[2], 10)
+			};
+		}
+	}
+	return null;
+};
+
 
 // code from: https://github.com/jalik/jalik-ufs/blob/master/ufs-server.js#L91
 var readFromGridFS = function(storeName, fileId, file, headers, req, res) {
@@ -26,20 +82,42 @@ var readFromGridFS = function(storeName, fileId, file, headers, req, res) {
 	// Transform stream
 	store.transformRead(rs, ws, fileId, file, req, headers);
 
+	var h = req.headers;
+	var range = getByteRange(h.range);
+	var out_of_range = false;
+	if (range) {
+		out_of_range = (range.start > file.size) || (range.stop <= range.start) || (range.stop > file.size);
+	}
+
 	// Compress data using gzip
-	if (accept.match(/\bgzip\b/)) {
+	if (accept.match(/\bgzip\b/) && range === null) {
 		headers['Content-Encoding'] = 'gzip';
 		delete headers['Content-Length'];
 		res.writeHead(200, headers);
 		ws.pipe(zlib.createGzip()).pipe(res);
-	} else if (accept.match(/\bdeflate\b/)) {
+	} else if (accept.match(/\bdeflate\b/) && range === null) {
 		// Compress data using deflate
 		headers['Content-Encoding'] = 'deflate';
 		delete headers['Content-Length'];
 		res.writeHead(200, headers);
 		ws.pipe(zlib.createDeflate()).pipe(res);
+	} else if (range && out_of_range) {
+		// out of range request, return 416
+		delete headers['Content-Length'];
+		delete headers['Content-Type'];
+		delete headers['Content-Disposition'];
+		delete headers['Last-Modified'];
+		headers['Content-Range'] = 'bytes */' + file.size;
+		res.writeHead(416, headers);
+		res.end();
+	} else if (range) {
+		headers['Content-Range'] = 'bytes ' + range.start + '-' + range.stop + '/' + file.size;
+		delete headers['Content-Length'];
+		headers['Content-Length'] = range.stop - range.start + 1;
+		res.writeHead(206, headers);
+		logger.debug('File upload extracting range');
+		ws.pipe(new ExtractRange({ start: range.start, stop: range.stop })).pipe(res);
 	} else {
-		// Send raw data
 		res.writeHead(200, headers);
 		ws.pipe(res);
 	}
@@ -60,3 +138,4 @@ FileUpload.addHandler('rocketchat_uploads', {
 		return Meteor.fileStore.delete(file._id);
 	}
 });
+
diff --git a/packages/rocketchat-file-upload/server/methods/sendFileMessage.js b/packages/rocketchat-file-upload/server/methods/sendFileMessage.js
index c44e433ad4057c93a718cfc119eb09202bf283a1..b50028dfd286c28c923236c507441bd81feedc58 100644
--- a/packages/rocketchat-file-upload/server/methods/sendFileMessage.js
+++ b/packages/rocketchat-file-upload/server/methods/sendFileMessage.js
@@ -1,5 +1,5 @@
 Meteor.methods({
-	'sendFileMessage'(roomId, store, file) {
+	'sendFileMessage'(roomId, store, file, msgData = {}) {
 		if (!Meteor.userId()) {
 			throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'sendFileMessage' });
 		}
@@ -10,12 +10,21 @@ Meteor.methods({
 			return false;
 		}
 
+		check(msgData, {
+			avatar: Match.Optional(String),
+			emoji: Match.Optional(String),
+			alias: Match.Optional(String),
+			groupable: Match.Optional(Boolean),
+			msg: Match.Optional(String)
+		});
+
 		RocketChat.models.Uploads.updateFileComplete(file._id, Meteor.userId(), _.omit(file, '_id'));
 
 		var fileUrl = '/file-upload/' + file._id + '/' + file.name;
 
 		var attachment = {
 			title: `${TAPi18n.__('Attachment_File_Uploaded')}: ${file.name}`,
+			description: file.description,
 			title_link: fileUrl,
 			title_link_download: true
 		};
@@ -37,7 +46,7 @@ Meteor.methods({
 			attachment.video_size = file.size;
 		}
 
-		const msg = {
+		const msg = Object.assign({
 			_id: Random.id(),
 			rid: roomId,
 			msg: '',
@@ -46,7 +55,7 @@ Meteor.methods({
 			},
 			groupable: false,
 			attachments: [attachment]
-		};
+		}, msgData);
 
 		return Meteor.call('sendMessage', msg);
 	}
diff --git a/packages/rocketchat-highlight/highlight.coffee b/packages/rocketchat-highlight/highlight.coffee
deleted file mode 100644
index c27d83616b85be45987f538eff97f2f46e73cdee..0000000000000000000000000000000000000000
--- a/packages/rocketchat-highlight/highlight.coffee
+++ /dev/null
@@ -1,65 +0,0 @@
-###
-# Highlight is a named function that will highlight ``` messages
-# @param {Object} message - The message object
-###
-
-class Highlight
-
-	constructor: (message) ->
-
-		if s.trim message.html
-			message.tokens ?= []
-
-			# Count occurencies of ```
-			count = (message.html.match(/```/g) || []).length
-
-			if count
-
-				# Check if we need to add a final ```
-				if (count % 2 > 0)
-					message.html = message.html + "\n```"
-					message.msg = message.msg + "\n```"
-
-				# Separate text in code blocks and non code blocks
-				msgParts = message.html.split(/^\s*(```(?:[a-zA-Z]+)?(?:(?:.|\n)*?)```)(?:\n)?$/gm)
-
-				for part, index in msgParts
-					# Verify if this part is code
-					codeMatch = part.match(/^```(\w*[\n\ ]?)([\s\S]*?)```+?$/)
-					if codeMatch?
-						# Process highlight if this part is code
-						singleLine = codeMatch[0].indexOf('\n') is -1
-
-						if singleLine
-							lang = ''
-							code = _.unescapeHTML codeMatch[1] + codeMatch[2]
-						else
-							lang = codeMatch[1]
-							code = _.unescapeHTML codeMatch[2]
-
-						if s.trim(lang) is ''
-							lang = ''
-
-						if s.trim(lang) not in hljs.listLanguages()
-							result = hljs.highlightAuto (lang + code)
-						else
-							result = hljs.highlight s.trim(lang), code
-
-						token = "=&=#{Random.id()}=&="
-
-						message.tokens.push
-							highlight: true
-							token: token
-							text: "<pre><code class='hljs " + result.language + "'><span class='copyonly'>```<br></span>" + result.value + "<span class='copyonly'><br>```</span></code></pre>"
-
-						msgParts[index] = token
-					else
-						msgParts[index] = part
-
-				# Re-mount message
-				message.html = msgParts.join('')
-
-		return message
-
-RocketChat.callbacks.add 'renderMessage', Highlight, RocketChat.callbacks.priority.HIGH, 'highlight'
-RocketChat.Highlight = true
diff --git a/packages/rocketchat-i18n/i18n/ar.i18n.json b/packages/rocketchat-i18n/i18n/ar.i18n.json
index a0fadb62d37808bc262ea34db17a78f65f99c458..3dbd8af238ace9d58bd7615a609ccbd816e7a2bd 100644
--- a/packages/rocketchat-i18n/i18n/ar.i18n.json
+++ b/packages/rocketchat-i18n/i18n/ar.i18n.json
@@ -447,9 +447,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "تعطي اسما فريدا لأوث مخصصة",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "إعطاء التطبيق اسما. وسوف يظهر هذا من قبل المستخدمين.",
   "Global": "عالمي",
-  "GoogleSiteVerification_id": "رقم تحقق من موقع Google",
   "GoogleTagManager_id": "جوجل مدير العلامات معرف",
-  "Has_more": "يوجد المزيد",
   "Hash": "مزيج",
   "Header": "رأس",
   "Hidden": "مخفي",
@@ -707,7 +705,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "الروبوتات",
   "minutes": "دقيقة",
-  "Mobile_push": "دفع المحمول",
   "More_channels": "المزيد من القنوات",
   "More_direct_messages": "المزيد من الرسائل الخاصة",
   "More_groups": "المزيد من المجموعات الخاصة",
@@ -925,8 +922,6 @@
   "Script_Enabled": "السيناريو ممكن",
   "Search": "بحث",
   "Search_by_username": "البحث عن طريق اسم المستخدم",
-  "Search_Channels": "بحث في القنوات",
-  "Search_Direct_Messages": "البحث في الرسائل الخاصة",
   "Search_Messages": "بحث في الرسائل",
   "Search_Private_Groups": "البحث في المجموعات الخاصة",
   "seconds": "ثواني",
diff --git a/packages/rocketchat-i18n/i18n/ca.i18n.json b/packages/rocketchat-i18n/i18n/ca.i18n.json
index d22b1ca29afeba0b824b7826b138e321b83f02e0..fc6c35c7f0df2074a06abef74b17152e73dff17d 100644
--- a/packages/rocketchat-i18n/i18n/ca.i18n.json
+++ b/packages/rocketchat-i18n/i18n/ca.i18n.json
@@ -56,10 +56,12 @@
   "Accounts_OAuth_Custom_id": "ID",
   "Accounts_OAuth_Custom_Identity_Path": "Ruta de la identitat",
   "Accounts_OAuth_Custom_Login_Style": "Estil d'entrada",
+  "Accounts_OAuth_Custom_Merge_Users": "Uneix usuaris",
   "Accounts_OAuth_Custom_Scope": "Àmbit (scope)",
   "Accounts_OAuth_Custom_Secret": "Secret",
   "Accounts_OAuth_Custom_Token_Path": "Ruta del token",
   "Accounts_OAuth_Custom_Token_Sent_Via": "Token enviat via",
+  "Accounts_OAuth_Custom_Username_Field": "Camp de nom d'usuari",
   "Accounts_OAuth_Facebook": "Inici de sessió amb Facebook",
   "Accounts_OAuth_Facebook_callback_url": "URL de retorn (callback) de Facebook",
   "Accounts_OAuth_Facebook_id": "App ID de Facebook",
@@ -107,6 +109,8 @@
   "Accounts_RegistrationForm_SecretURL_Description": "Cal proporcionar una cadena de text aleatori que s'afegirà a l'URL de registre. Exemple: https://demo.rocket.chat/register/[secret_hash]",
   "Accounts_RequireNameForSignUp": "Requerir el nom per registrar-se",
   "Accounts_RequirePasswordConfirmation": "Requereix confirmació de la contrasenya",
+  "Accounts_SetDefaultAvatar": "Avatar per defecte",
+  "Accounts_SetDefaultAvatar_Description": "Prova de determinar l'avatar per defecte basant-se en el compte d'OAuth o bé Gravatar",
   "Accounts_ShowFormLogin": "Mostra inici de sessió basat en formulari",
   "Accounts_UseDefaultBlockedDomainsList": "Utilitza la llista predeterminada de dominis bloquejats",
   "Accounts_UseDNSDomainCheck": "Utilitza la comprovació DNS de dominis",
@@ -142,6 +146,7 @@
   "All_messages": "Tots els missatges",
   "Allow_Invalid_SelfSigned_Certs": "Permetre certificats auto-signats invàlids",
   "Allow_Invalid_SelfSigned_Certs_Description": "Permetre certificats SSL auto-signats i invàlids per a enllaços de validació i vistes prèvies.",
+  "Always_open_in_new_window": "Obre sempre en finestra nova",
   "Analytics_features_enabled": "Funcionalitats habilitades",
   "Analytics_features_messages_Description": "Monitoritza esdeveniments personalitzats relacionats amb accions que els usuaris fan als missatges.",
   "Analytics_features_rooms_Description": "Monitoritza esdeveniments personalitzats relacionats amb accions en un canal o grup (crear, abandonar, eliminar...).",
@@ -150,7 +155,11 @@
   "And_more": "I __length__ més",
   "Animals_and_Nature": "Animals i natura",
   "API": "API",
+  "API_Allow_Infinite_Count": "Permet obtenir tot",
+  "API_Allow_Infinite_Count_Description": "Les peticions a la API REST haurien de permetre retornar-ho tot en una sola petició?",
   "API_Analytics": "Analítiques",
+  "API_Default_Count": "Comptador per defecte",
+  "API_Default_Count_Description": "El comptador per defecte per als resultats de les peticions API REST si el consumidor no n'ha especificat cap.",
   "API_Embed": "Incrusta (embed)",
   "API_Embed_Description": "Activa o no les previsualitzacions d'enllaços quan un usuari publica l'enllaç a un web.",
   "API_EmbedCacheExpirationDays": "Caducitat de la memòria cau de les incrustacions (en dies)",
@@ -164,6 +173,8 @@
   "API_GitHub_Enterprise_URL_Description": "Exemple: http://domain.com (sense la barra final)",
   "API_Gitlab_URL": "URL de GitLab",
   "API_Token": "API Token",
+  "API_Upper_Count_Limit": "Nombre màxim de registres",
+  "API_Upper_Count_Limit_Description": "Quin és el nombre màxim de registres que la API REST pot retornar (si no és il·limitat)?",
   "API_User_Limit": "Límit d'usuaris per afegir tots els usuaris a un canal",
   "API_Wordpress_URL": "URL de WordPress",
   "Apiai_Key": "Clau Api.ai ",
@@ -214,6 +225,7 @@
   "Back_to_login": "Torna a identificar-me",
   "Back_to_permissions": "Torna a permisos",
   "Beta_feature_Depends_on_Video_Conference_to_be_enabled": "Característica Beta. Requereix que la videoconferència estigui activa.",
+  "Block_User": "Bloqueja usuari",
   "Body": "Cos",
   "bold": "negreta",
   "bot_request": "Sol·licitud Bot",
@@ -252,6 +264,7 @@
   "CDN_PREFIX": "Prefix CDN",
   "Certificates_and_Keys": "Certificats i claus",
   "Changing_email": "Canvi de correu-e",
+  "Change_Room_Type": "Canvi de tipus de sala",
   "channel": "canal",
   "Channel": "Canal",
   "Channel_already_exist": "El canal '#%s' ja existeix.",
@@ -325,6 +338,8 @@
   "Custom_Translations_Description": "Ha de ser un objecte JSON vàlid on les claus són el codi de l'idioma i contenen un diccionari de clau (key) i traduccions. Exemple:</br><code>{\n \"en\": {\n  \"key\": \"translation\"\n },\n \"ca\": {\n  \"key\": \"traducció\"\n }\n}</code> ",
   "Dashboard": "Tauler",
   "Date": "Data",
+  "Date_From": "De",
+  "Date_to": "a",
   "days": "dies",
   "DB_Migration": "Migració de base de dades",
   "DB_Migration_Date": "Data de migració de la BD",
@@ -368,6 +383,7 @@
   "Edit": "Edita",
   "Edit_Custom_Field": "Edita camp personalitzat",
   "Edit_Department": "Edita departament",
+  "Edit_Trigger": "Edita disparador",
   "edited": "editat",
   "Editing_room": "Edició de sala",
   "Editing_user": "Edició d'usuari",
@@ -424,9 +440,11 @@
   "error-invalid-channel-start-with-chars": "Canal no vàlid. Comenceu amb @ o #",
   "error-invalid-custom-field": "Camp personalitzat invàlid",
   "error-invalid-custom-field-name": "Nom del camp personalitzat invàlid. Utilitzeu només lletres, números, guions i guions baixos.",
+  "error-invalid-date": "La data introduïda no és vàlida.",
   "error-invalid-description": "Descripció invàlida",
   "error-invalid-domain": "Domini invàlid",
   "error-invalid-email": "L'adreça __email__ no és vàlida",
+  "error-invalid-email-address": "Adreça de correu-e invàlida",
   "error-invalid-file-height": "Alçada de la imatge invàlida",
   "error-invalid-file-type": "Tipus d'arxiu no vàlid",
   "error-direct-message-file-upload-not-allowed": "Compartició d'arxius no permesa als missatges directes",
@@ -513,6 +531,8 @@
   "Food_and_Drink": "Menjar i beure",
   "Footer": "Peu de pàgina",
   "For_your_security_you_must_enter_your_current_password_to_continue": "Per a la seva seguretat, ha de tornar a introduir la contrasenya per continuar",
+  "Force_Disable_OpLog_For_Cache": "Força la inhabilitació de OpLog per la cache",
+  "Force_Disable_OpLog_For_Cache_Description": "No s'utilitzarà OpLog per sincronitzar la cache tot i estar disponible",
   "Force_SSL": "Força SSL",
   "Force_SSL_Description": "*Atenció!* _Force SSL_ mai ha de ser usat amb servidor intermediari invers. Si s'utilitza un proxy invers, s'ha de fer la redirecció AL PROXY. Aquesta opció existeix per a les instal·lacions tipus Heroku, que no permeten la configuració de redireccions al proxy invers.",
   "Forgot_password": "No recordes la contrasenya?",
@@ -530,10 +550,8 @@
   "Give_a_unique_name_for_the_custom_oauth": "Estableix un nom únic per al OAuth personalitzat",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Bateja l'aplicació. El nom escollit serà visible als usuaris.",
   "Global": "Global",
-  "GoogleSiteVerification_id": "Verificació de la identificació del lloc de Google",
   "GoogleTagManager_id": "ID de Google Tag Manager",
   "Guest_Pool": "Llista de clients",
-  "Has_more": "Més",
   "Hash": "Hash",
   "Header": "Encapçalament",
   "Hidden": "Ocult",
@@ -569,6 +587,8 @@
   "Iframe_Integration_send_target_origin_Description": "Només les pàgines amb l'origen proporcionat podran rebre esdeveniments o `*` per a totes.  Exemple `http://localhost`",
   "Importer_Archived": "Arxivat",
   "Importer_CSV_Information": "L'importador CSV requereix un format específic, si us plau llegiu la documentació sobre com estructurar l'arxiu .zip:",
+  "Importer_HipChatEnterprise_Information": "L'arxiu pujat ha de ser un tar.gz desencriptat. Si us plau, llegiu la documentació per a més informació:",
+  "Importer_HipChatEnterprise_BetaWarning": "Tingueu en compte que aquest sistema d'importació encara està en desenvolupament. Si us plau, notifiqueu-nos a GitHub els errors que es produeixin:",
   "Importer_done": "Importació completa!",
   "Importer_finishing": "Finalitza la importació.",
   "Importer_From_Description": "Importa les dades de __from__ a Rocket.Chat.",
@@ -764,6 +784,7 @@
   "Livechat_managers": "Supervisors de xat en viu",
   "Livechat_offline": "Xat en viu fora de línia",
   "Livechat_online": "Xat en viu connectat",
+  "Livechat_open_inquiery_show_connecting": "Mostra un missatge de connectant enlloc de l'entrada de text quan el client encara no està connectat amb un agent.",
   "Livechat_Queue": "Cua del xat en xiu",
   "Livechat_room_count": "Sala de recompte del xat en viu",
   "Livechat_Routing_Method": "Mètode d'enrutament del xat en viu",
@@ -864,13 +885,14 @@
   "Messages_that_are_sent_to_the_Incoming_WebHook_will_be_posted_here": "Els missatges enviats al WebHook d'entrada seran publicats aquí.",
   "Meta": "Meta",
   "Meta_fb_app_id": "App ID de Facebook",
+  "Meta_custom": "Etiquetes Meta personalitzades",
   "Meta_google-site-verification": "Verificació del lloc web a Google (google-site-verification)",
   "Meta_language": "Idioma",
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "Robots",
   "Min_length_is": "La llargada mínima és %s",
   "minutes": "minuts",
-  "Mobile_push": "Push mòbil ",
+  "Mobile": "Mòbil",
   "Monday": "dilluns",
   "Monitor_history_for_changes_on": "Monitoritza l'historial per canvis a ",
   "More_channels": "Més canals",
@@ -901,6 +923,7 @@
   "New_role": "Nou rol",
   "New_Room_Notification": "Nova notificació de sala",
   "New_videocall_request": "Nova petició de vídeo trucada",
+  "New_Trigger": "Nou disparador",
   "No_available_agents_to_transfer": "No hi ha agents disponibles per a transferir",
   "No_channel_with_name_%s_was_found": "No s'ha trobat cap canal amb el nom <strong>\"%s\"</strong>!",
   "No_channels_yet": "Encara no ets a cap canal.",
@@ -956,6 +979,7 @@
   "Open_days_of_the_week": "Dies d'obertura",
   "Open_Livechats": "LiveChats oberts",
   "Opened": "Obert",
+  "Opened_in_a_new_window": "Obert en una nova finestra.",
   "Opens_a_channel_group_or_direct_message": "Obrir un canal, grup o missatge directe",
   "optional": "opcional",
   "Use_minor_colors": "Utilitza la paleta de colors secundària (per defecte s'hereta de la primària)",
@@ -1044,6 +1068,8 @@
   "quote": "cita",
   "Quote": "Cita",
   "Random": "Aleatori",
+  "React_when_read_only": "Permetre reaccions",
+  "React_when_read_only_changed_successfully": "Permetre reaccions en 'només lectura'",
   "Reacted_with": "es fa reaccionar amb",
   "Reactions": "Reaccions",
   "Read_only": "Només lectura",
@@ -1052,6 +1078,7 @@
   "Read_only_group": "Grup de només lectura",
   "Record": "Gravar",
   "Redirect_URI": "URI de redireccionament (Redirect URI)",
+  "Refresh_oauth_services": "Refresca serveis OAuth",
   "Refresh_keys": "Refresca les claus",
   "Refresh_your_page_after_install_to_enable_screen_sharing": "Per poder compartir la pantalla refresqui la pàgina després de la instal·lació ",
   "Register": "Crea un compte nou",
@@ -1074,6 +1101,7 @@
   "Require_password_change": "Requerir el canvi de la contrasenya",
   "Resend_verification_email": "Reenviar el correu-e de verificació",
   "Reset": "Reinicialitza (reset)",
+  "Reset_section_settings": "Reinicialitza els ajustos de la secció",
   "Reset_password": "Reinicialitza la contrasenya",
   "Restart": "Reinicia (restart)",
   "Restart_the_server": "Reinicia el servidor",
@@ -1090,7 +1118,10 @@
   "room_changed_topic": "Tema de la sala canviat a: <em>__room_topic__</em> per <em>__user_by__</em>.",
   "Room_description_changed_successfully": "Descripció de la sala canviada correctament",
   "Room_has_been_deleted": "La sala s'ha eliminat",
+  "Room_has_been_archived": "La sala s'ha arxivat",
+  "Room_has_been_unarchived": "La sala s'ha desarxivat",
   "Room_Info": "Informació de la sala",
+  "room_is_blocked": "Aquesta sala està bloquejada",
   "room_is_read_only": "Aquesta sala és de només lectura",
   "room_name": "nom de la sala",
   "Room_name_changed": "Nom de la sala canviat a: <em>__room_name__</em> per <em>__user_by__</em>.",
@@ -1108,8 +1139,11 @@
   "SAML_Custom_Cert": "Certificat personalitzat",
   "SAML_Custom_Entry_point": "Punt d'entrada (Entry Point) personalitzat",
   "SAML_Custom_Generate_Username": "Generar nom d'usuari",
+  "SAML_Custom_IDP_SLO_Redirect_URL": "Redirecció URL IDP SLO",
   "SAML_Custom_Issuer": "Emissor (issuer) personalitzat",
   "SAML_Custom_Provider": "Proveïdor (provider) personalitzat",
+  "SAML_Custom_Public_Cert": "Contingut del certificat públic",
+  "SAML_Custom_Private_Key": "Contingut de la clau privada",
   "Sandstorm_Powerbox_Share": "Comparteix un gra de Sandstorm",
   "Saturday": "dissabte",
   "Save": "Desa",
@@ -1123,8 +1157,6 @@
   "Script_Enabled": "Script actiu",
   "Search": "Cerca",
   "Search_by_username": "Cerca per nom d'usuari",
-  "Search_Channels": "Cerca canals",
-  "Search_Direct_Messages": "Cerca missatges directes",
   "Search_Messages": "Cerca missatges",
   "Search_Private_Groups": "Cerca grups privats",
   "seconds": "segons",
@@ -1167,6 +1199,7 @@
   "Show_all": "Veure tots",
   "Show_more": "Veure més",
   "show_offline_users": "Mostra els usuaris desconnectats",
+  "Show_on_registration_page": "Mostra a la pàgina de registre",
   "Show_only_online": "Veure només connectats",
   "Show_preregistration_form": "Veure formulari de pre-registre",
   "Show_queue_list_to_all_agents": "Mostra la cua a tots els agents",
@@ -1278,6 +1311,7 @@
   "theme-color-transparent-dark": "Transparent fosc",
   "theme-color-transparent-light": "Transparent clar",
   "theme-color-transparent-lighter": "Transparent més clar",
+  "theme-color-transparent-lightest": "Transparent el més clar",
   "theme-color-content-background-color": "Color del fons del contingut",
   "theme-color-primary-background-color": "Color primari del fons",
   "theme-color-primary-font-color": "Color primari del text",
@@ -1338,6 +1372,7 @@
   "UI_DisplayRoles": "Mostra rols",
   "UI_Merge_Channels_Groups": "Uneix grups privats amb canals",
   "Unarchive": "Desarxiva",
+  "Unblock_User": "Desbloqueja usuari",
   "Unmute_someone_in_room": "Torna a donar veu a algú de la sala",
   "Unmute_user": "Dóna veu a l'usuari",
   "Unnamed": "Sense nom",
@@ -1346,10 +1381,13 @@
   "Unread_Rooms": "Sales no llegides",
   "Unread_Rooms_Mode": "Mode de sales no llegides",
   "Unstar_Message": "Esborra el destacat",
+  "Upload_file_description": "Descripció de l'arxiu",
+  "Upload_file_name": "Nom de l'arxiu",
   "Upload_file_question": "Pujar l'arxiu?",
   "Uploading_file": "Pujant l'arxiu...",
   "Uptime": "Temps en funcionament",
   "URL": "URL",
+  "URL_room_prefix": "Prefix de l'adreça URL de les sales",
   "Use_account_preference": "Utilitza la preferència del compte",
   "Use_Emojis": "Utilitza emojis",
   "Use_Global_Settings": "Usa la configuració global",
@@ -1373,8 +1411,10 @@
   "User_has_been_muted_in_s": "L'usuari ha sigut silenciat a %s",
   "User_has_been_removed_from_s": "L'usuari s'ha eliminat de %s",
   "User_Info": "Informació de l'usuari",
+  "User_is_blocked": "L'usuari està bloquejat",
   "User_is_no_longer_an_admin": "L'usuari ja no és administrador",
   "User_is_now_an_admin": "L'usuari ara és administrador",
+  "User_is_unblocked": "L'usuari està desbloquejat",
   "User_joined_channel": "S'ha unit al canal.",
   "User_joined_channel_female": "S'ha unit al canal.",
   "User_joined_channel_male": "S'ha unit al canal.",
@@ -1412,10 +1452,12 @@
   "UTF8_Names_Slugify": "Slugify de noms UTF8",
   "UTF8_Names_Validation": "Validació de noms UTF8",
   "UTF8_Names_Validation_Description": "RegExp que s'utilitzarà per validar noms d'usuari i de sala",
+  "Validate_email_address": "Valida l'adreça de correu-e",
   "Verification_email_sent": "Missatge de correu-e de verificació enviat",
   "Verified": "Verificat",
   "Version": "Versió",
   "Video_Chat_Window": "Vídeo-xat",
+  "Video_Conference": "Videoconferència",
   "Videocall_declined": "Vídeo trucada rebutjada.",
   "Videocall_enabled": "Vídeo trucada activa",
   "View_All": "Veure tot",
@@ -1449,6 +1491,8 @@
   "will_be_able_to": "podrà",
   "Would_you_like_to_return_the_inquiry": "Vols retornar la sol·licitud?",
   "Yes": "Sí",
+  "Yes_archive_it": "Sí, arxiva'l!",
+  "Yes_unarchive_it": "Sí, desarxiva'l!",
   "Yes_clear_all": "Sí, esborra!",
   "Yes_delete_it": "Sí, elimina!",
   "Yes_hide_it": "Sí, oculta!",
diff --git a/packages/rocketchat-i18n/i18n/cs.i18n.json b/packages/rocketchat-i18n/i18n/cs.i18n.json
index ec0b5a475b6cc64b3fcdea18b32b1d8ea92cc015..95d9f6284f20f063d252b31caa90aa99f730abc8 100644
--- a/packages/rocketchat-i18n/i18n/cs.i18n.json
+++ b/packages/rocketchat-i18n/i18n/cs.i18n.json
@@ -9,6 +9,7 @@
   "@username_message": "@uživatel <message>",
   "__username__is_no_longer__role__defined_by__user_by_": "__username__ již není __role__ (odebral/a __user_by__ )",
   "__username__was_set__role__by__user_by_": "__username__ je nyní __role__ (nastavil/a __user_by__)",
+  "Accept": "Přijmout",
   "Accept_incoming_livechat_requests_even_if_there_are_no_online_agents": "Přijímat livechat požadavky i pokud není online žádný operátor",
   "Accept_with_no_online_agents": "Přijímat i bez aktivních operátorů",
   "Access_not_authorized": "Přístup není povolen",
@@ -40,6 +41,7 @@
   "Accounts_Enrollment_Email_Default": "<h2>Vítejte v <h1>[Site_Name]</h1></h2><p> Přejděte na [Site_URL] a zkuste to nejlepší open source chat řešení na trhu!</p>",
   "Accounts_Enrollment_Email_Description": "Můžete použít [name], [fname], [lname] pro uživatelské jména, křestní jméno a příjmení, <br/> pro e-mail uživatele, můžete použít [email].",
   "Accounts_Enrollment_Email_Subject_Default": "Vítejte na stránkách [Site_Name]",
+  "Accounts_ForgetUserSessionOnWindowClose": "Zapomenout session uživatele při zavření okna",
   "Accounts_Iframe_api_method": "Api Metoda",
   "Accounts_Iframe_api_url": "Api URL",
   "Accounts_iframe_enabled": "Povoleno",
@@ -54,10 +56,12 @@
   "Accounts_OAuth_Custom_id": "ID",
   "Accounts_OAuth_Custom_Identity_Path": "Cesta k identitÄ›",
   "Accounts_OAuth_Custom_Login_Style": "Styl přihlášení",
+  "Accounts_OAuth_Custom_Merge_Users": "Sloučit uživatele",
   "Accounts_OAuth_Custom_Scope": "Prostor",
   "Accounts_OAuth_Custom_Secret": "Secret",
   "Accounts_OAuth_Custom_Token_Path": "Cesta k tokenu",
   "Accounts_OAuth_Custom_Token_Sent_Via": "Token odesílány přes",
+  "Accounts_OAuth_Custom_Username_Field": "Pole uživatelské jméno",
   "Accounts_OAuth_Facebook": "Facebook Přihlášení",
   "Accounts_OAuth_Facebook_callback_url": "Facebook Callback URL",
   "Accounts_OAuth_Facebook_id": "Facebook App Id",
@@ -140,6 +144,7 @@
   "All_messages": "Všechny zprávy",
   "Allow_Invalid_SelfSigned_Certs": "Umožnit nevalidní či self-signed certifikáty",
   "Allow_Invalid_SelfSigned_Certs_Description": "Umožňují použít neplatné/self-signed SSL certifikáty pro ověření odkazů a náhledů.",
+  "Always_open_in_new_window": "Vždy otevírat v novém okně",
   "Analytics_features_enabled": "Funkce Povoleny",
   "Analytics_features_messages_Description": "Sleduje vlastní události spojené s uživatelskými akcemi u zpráv.",
   "Analytics_features_rooms_Description": "Sleduje vlastní události spojené s uživatelskými akcemi na místnosti nebo skupině (vytvoření, odchod, smazání).",
@@ -151,6 +156,7 @@
   "API_Analytics": "Analytika",
   "API_Embed": "Náhled vložených odkazů",
   "API_Embed_Description": "Zda zobrazit náhled stránky když uživatel pošle odkaz",
+  "API_EmbedCacheExpirationDays": "Počet dní expirace cache embed",
   "API_EmbedDisabledFor": "Zakázat vložený obsah pro uživatele",
   "API_EmbedDisabledFor_Description": "Čárkami oddělený seznam uživatelských jmen",
   "API_EmbedIgnoredHosts": "Seznam zakázaných adres pro vložený obsah",
@@ -210,6 +216,7 @@
   "Back_to_integrations": "Zpět k integracím",
   "Back_to_login": "Zpět na přihlašovací formulář",
   "Back_to_permissions": "Zpět na práva",
+  "Beta_feature_Depends_on_Video_Conference_to_be_enabled": "Beta funkcionalita. Videohovory musí být povoleny.",
   "Body": "Obsah",
   "bold": "tučný",
   "bot_request": "Request bota",
@@ -224,12 +231,31 @@
   "busy_male": "zaneprázdněný",
   "Busy_male": "Zaneprázdněný",
   "by": "od",
+  "cache_cleared": "Cache vyčistěna",
   "Cancel": "Zrušit",
   "Cancel_message_input": "Zrušit",
   "Cannot_invite_users_to_direct_rooms": "Do přímé konverzace nelze pozvat uživatele.",
+  "CAS_autoclose": "Automaticky zavřít přihlašovací popup",
+  "CAS_base_url": "SSO URL",
+  "CAS_base_url_Description": "Adresa vaší externí SSO služby např: https://sso.priklad.cz/sso/",
+  "CAS_button_color": "Barva pozadí tlačítka přihlásit",
+  "CAS_button_label_color": "Barva textu login přihlásit",
+  "CAS_button_label_text": "Text tlačítka přihlásit",
+  "CAS_enabled": "Povoleno",
+  "CAS_login_url": "SSO přihlašovací URL",
+  "CAS_login_url_Description": "Adresa přihlášení vaší externí SSO služby např: https://sso.priklad.cz/sso/login",
+  "CAS_popup_height": "Výška přihlašovacího popupu",
+  "CAS_popup_width": "Šířka přihlašovacího popupu",
+  "CAS_Sync_User_Data_Enabled": "Vždy synchronizovat uživatelská data",
+  "CAS_Sync_User_Data_Enabled_Description": "Vždy synchronizovat externí CAS data uživatele do dostupných atributů po přihlášení. Poznámka: Atributy jsou synchronizovány vždy při vytvoření účtu",
+  "CAS_Sync_User_Data_FieldMap": "Mapa atributů",
+  "CAS_Sync_User_Data_FieldMap_Description": "Použijte toto pole pro vložení JSON mapování interních atributů (klíč) na externí atributy (hodnota). Externí atributy obaleny '%' vloží hodnotu proměnné.<br/>Například, `{\"email\":\"%email%\", \"name\":\"%firstname%, %lastname%\"}`<br/><br/>V CAS 1.0 lze použít pouze atribut `username`. Dostupné interní atributy jsou: username, name, email, rooms; V proměnné `rooms` je čárkami oddělený seznam místností do kterých má být uživatel po vytvoření účtu připojen např: `{\"rooms\": \"%team%,%oddeleni%\"}` připojí CAS uživatele po vytvoření do místnosti jejich teamu a oddělení.",
+  "CAS_version": "CAS verze",
+  "CAS_version_Description": "Zvolte verzi CAS podporovanou vaší CAS SSO službou",
   "CDN_PREFIX": "CDN Prefix",
   "Certificates_and_Keys": "Certifikáty a klíče",
   "Changing_email": "Změna e-mailu",
+  "Change_Room_Type": "Změna typu místnosti",
   "channel": "místnost",
   "Channel": "Místnost",
   "Channel_already_exist": "Místnost '#%s' již existuje.",
@@ -250,6 +276,8 @@
   "Choose_messages": "Výberte zprávy",
   "Choose_the_alias_that_will_appear_before_the_username_in_messages": "Vyberte alias, který se objeví před uživatelským jménem ve zprávách.",
   "Choose_the_username_that_this_integration_will_post_as": "Vyberte uživatelské jméno, za které bude tato integrace posílat zprávy.",
+  "clear": "Vyčistit",
+  "clear_cache_now": "Vyčistit cache",
   "Clear_all_unreads_question": "Označit vše jako přečtené?",
   "Click_here": "Klikněte zde",
   "Client_ID": "ID klienta",
@@ -305,6 +333,7 @@
   "DB_Migration": "Migrace databáze",
   "DB_Migration_Date": "Datum migrace databáze",
   "Deactivate": "Deaktivovat",
+  "Decline": "Zamítnout",
   "Default": "Výchozí",
   "Delete": "Smazat",
   "Delete_message": "Smazat zprávu",
@@ -331,6 +360,7 @@
   "Do_you_want_to_change_to_s_question": "Chcete změnit na <strong>%s?</strong>",
   "Domain": "Doména",
   "Domains": "Domény",
+  "Download_Snippet": "Stáhnout",
   "Drop_to_upload_file": "Pusťe soubor do okna pro jeho nahrání",
   "Dry_run": "Zkouška",
   "Dry_run_description": "Odešle pouze jeden e-mail, na stejnou adresu jako ve formuláři. K e-mailu musí patřit platný uživatel.",
@@ -342,6 +372,7 @@
   "Edit": "Editovat",
   "Edit_Custom_Field": "Upravit vlastní pole",
   "Edit_Department": "Upravit oddělení",
+  "Edit_Trigger": "Upravit trigger",
   "edited": "upraveno",
   "Editing_room": "Úprava místnosti",
   "Editing_user": "Úprava uživatele",
@@ -398,11 +429,13 @@
   "error-invalid-channel-start-with-chars": "Neplatná místnost. Začněte s @ nebo #",
   "error-invalid-custom-field": "Neplatné vlastní pole",
   "error-invalid-custom-field-name": "Neplatný název vlastního pole. Používejte pouze písmena, číslice, pomlčky a podtržítka.",
+  "error-invalid-date": "Nevalidní vstup",
   "error-invalid-description": "Neplatný popis",
   "error-invalid-domain": "Neplatná doména",
   "error-invalid-email": "Neplatný email __email__",
   "error-invalid-file-height": "Neplatná výška souboru",
   "error-invalid-file-type": "Neplatný typ souboru",
+  "error-direct-message-file-upload-not-allowed": "Sdílení souborů není v přímé konverzaci povoleno",
   "error-invalid-file-width": "Neplatná šířka souboru",
   "error-invalid-from-address": "Špatná adresa FROM.",
   "error-invalid-integration": "Neplatná integrace",
@@ -457,9 +490,12 @@
   "Field_removed": "Pole odebráno",
   "Field_required": "Pole vyžadováno",
   "File_exceeds_allowed_size_of_bytes": "Soubor překračuje povolenou velikost __size__ bajtů",
+  "File_not_allowed_direct_messages": "Sdílení souborů není v přímé konverzaci povoleno.",
   "File_type_is_not_accepted": "Neplatný typ souboru",
   "FileUpload": "Nahrání souboru",
   "FileUpload_Enabled": "Nahrávání souborů povoleno",
+  "FileUpload_Disabled": "Nahrávání souborů je zakázáno.",
+  "FileUpload_Enabled_Direct": "Nahrávání souborů povoleno v přímé konverzaci",
   "FileUpload_File_Empty": "Soubor je prázdný",
   "FileUpload_FileSystemPath": "Cesta pro nahrávané soubory",
   "FileUpload_MaxFileSize": "Maximální velikost nahrávaného souboru (v bytech)",
@@ -500,10 +536,8 @@
   "Give_a_unique_name_for_the_custom_oauth": "Zadejte jedinečný název pro vlastní OAuth",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Pojmenujte jak se bude aplikace jmenovat pro Vaše uživatele.",
   "Global": "Globální",
-  "GoogleSiteVerification_id": "ID Google site ověření",
   "GoogleTagManager_id": "ID Google tag manageru",
   "Guest_Pool": "Skupina hostů",
-  "Has_more": "Více...",
   "Hash": "Hash",
   "Header": "Hlavička",
   "Hidden": "Schovaný",
@@ -538,6 +572,9 @@
   "Iframe_Integration_send_target_origin": "Odesílat cílovou doménu",
   "Iframe_Integration_send_target_origin_Description": "Jen stránky z povolených domén můžou čekat na události. `*` pro povolení všech domén. Lze vložit více hodnot oddělených `,`. Například `http://localhost,https://localhost`",
   "Importer_Archived": "Archivováno",
+  "Importer_CSV_Information": "CSV import vyžaduje specifický formát. Informace o tom, jak strukturovat váš zip soubor najdete v dokumentaci:",
+  "Importer_HipChatEnterprise_Information": "Nahraný soubor musí být nešifrovaný tar.gz, Více informací naleznete v dokumentaci:",
+  "Importer_HipChatEnterprise_BetaWarning": "Mějte prosím na paměti, že tato funkcionalita je stále ve vývoji, prosím nahlašte nám jakékoliv chyby přes github:",
   "Importer_done": "Import dokončen!",
   "Importer_finishing": "Dokončuji import.",
   "Importer_From_Description": "Import dat __from__ do Rocket.Chat.",
@@ -548,12 +585,14 @@
   "Importer_importing_started": "Spouštím import.",
   "Importer_importing_users": "Importuji uživatele.",
   "Importer_not_in_progress": "Importovaná služba v současné době neběží.",
+  "Importer_not_setup": "Import pravděpodobně není správně nastaven, protože nevrátil žádná data",
   "Importer_Prepare_Restart_Import": "Restartovat import",
   "Importer_Prepare_Start_Import": "Spustit Import",
   "Importer_Prepare_Uncheck_Archived_Channels": "Odškrtnout Archivováné místnosti",
   "Importer_Prepare_Uncheck_Deleted_Users": "Odškrtnout smazané uživatele",
   "Importer_progress_error": "Nepodařilo se získat postup importu.",
   "Importer_setup_error": "Při nastavování nástroje pro import došlo k chybě.",
+  "Importer_Source_File": "Výběr zdrojového souboru",
   "Incoming_Livechats": "Příchozí požadavky na livechat",
   "inline_code": "vlozeny_kod",
   "Install_Extension": "Nainstalovat rozšíření",
@@ -564,12 +603,15 @@
   "Installation": "Instalace",
   "Installed_at": "instalováno v",
   "Instructions_to_your_visitor_fill_the_form_to_send_a_message": "Pokyny pro Vaše návštěvníky k vyplnění formulář pro odeslání zprávy",
+  "Impersonate_user": "Vydávat se za uživatele",
+  "Impersonate_user_description": "Pokud je povoleno, integrace posílá za uživatele, který ji vyvolal",
   "Integration_added": "Integrace byla přidána",
   "Integration_Incoming_WebHook": "Příchozí WebHook Integrace",
   "Integration_New": "Nová integrace",
   "Integration_Outgoing_WebHook": "Odchozí WebHook Integrace",
   "Integration_updated": "Integrace byla aktualizována",
   "Integrations": "Integrace",
+  "Integrations_for_all_channels": "Zadejte <strong>all_public_channels</strong> pro poslouchání nad všemi otevřenými místnostmi, <strong>all_private_groups</strong> pro všechny soukromé místnosti a <strong>all_direct_messages</strong> pro poslouchání přímých konverzací",
   "InternalHubot": "Interní Hubot",
   "InternalHubot_ScriptsToLoad": "Načíst skripty",
   "InternalHubot_ScriptsToLoad_Description": "Prosím, zadejte čárkami oddělený seznam skriptů k načtení z https://github.com/github/hubot-scripts/tree/master/src/scripts",
@@ -598,6 +640,19 @@
   "is_typing": "píše",
   "is_typing_female": "píše",
   "is_typing_male": "píše",
+  "IRC_Channel_Join": "Výstup JOIN příkazu",
+  "IRC_Channel_Leave": "Výstup PART příkazu",
+  "IRC_Description": "Internet Relay Chat (IRC) je nástroj pro textovou komunikaci. Uživatelé komunikují otevřeně v unikátně pojmenovaných místnostech. IRC také podporuje přímé zprávy mezi dvěma uživateli a sdílení souborů. Tento modul integruje tyto vlastnosti do Rocket.Chatu.",
+  "IRC_Enabled": "Pokusit se integrovat IRC. Změna vyžaduje restart Rocket.Chatu",
+  "IRC_Private_Message": "Výstup PRIVMSG příkazu",
+  "IRC_Channel_Users": "Výstup NAMES příkazu",
+  "IRC_Channel_Users_End": "Konec výstupu NAMES příkazu",
+  "IRC_Hostname": "IRC server ke kterému se připojit",
+  "IRC_Login_Fail": "Výstup nezdařeného připojení k IRC serveru",
+  "IRC_Login_Success": "Výstup úspěšného připojení k IRC serveru",
+  "IRC_Message_Cache_Size": "Limit cache pro zpracování odchozích zpráv",
+  "IRC_Port": "Port k připojení na IRC serveru",
+  "IRC_Quit": "Výstup při rozpojení IRC session",
   "It_works": "Funguje to",
   "italics": "kurzíva",
   "Jitsi_Chrome_Extension": "ID Chrome rozšíření",
@@ -636,6 +691,7 @@
   "Layout_Terms_of_Service": "Podmínky služby",
   "LDAP": "LDAP",
   "LDAP_CA_Cert": "CA Certifikát",
+  "LDAP_Connect_Timeout": "Prodleva připojení (ms)",
   "LDAP_Custom_Domain_Search": "Vyhledávání ve vlastní doméně",
   "LDAP_Custom_Domain_Search_Description": "JSON, který řídí vazby a informací o připojení a je ve tvaru: <br/> <code>{\"filter\": \"(&(objectCategory=person)(objectclass=user)(memberOf=CN=ROCKET_ACCESS,CN=Users,DC=domain,DC=com)(sAMAccountName=#{username}))\", \"scope\": \"sub\", \"userDN\": \"rocket.service@domain.com\", \"password\": \"urpass\"}</code>",
   "LDAP_Default_Domain": "Výchozí doména",
@@ -660,6 +716,7 @@
   "LDAP_Encryption_Description": "Metoda šifrování používaná k zabezpečené komunikace se serverem LDAP. Jako příklady lze uvést `plain` (bez šifrování),` SSL/LDAPS` (šifrovaný od začátku), a `StartTLS` (Šifrovaná komunikaci až po připojení).",
   "LDAP_Host": "Hostitel",
   "LDAP_Host_Description": "Hostitel LDAP, například `ldap.example.com` nebo 10.0.0.30`.",
+  "LDAP_Idle_Timeout": "Prodleva nečinnosti (ms)",
   "LDAP_Import_Users": "Importovat LDAP uživatele",
   "LDAP_Import_Users_Description": "Pokud povoleno, všichni LDAP uživatelé budou naimportováni<br /> *POZOR* Nastavte filtr pokud chcete omezit počet uživatelů.",
   "LDAP_Login_Fallback": "Alternativní login",
@@ -682,6 +739,18 @@
   "LDAP_Use_Custom_Domain_Search_Description": "Napište svůj vlastní filtr pro vyhledávání uživatelů v LDAP serveru.",
   "LDAP_Username_Field": "Pole Uživatelského jména",
   "LDAP_Username_Field_Description": "Které pole budou použity jako *Jméno* pro nové uživatele. Ponechte prázdné pro použítí jména z přihlašovací stránky. <br/> Můžete použít šablony a tagy jako například `#{givenName}.#{sn}`.<br/>Výchozí hodnota je `sAMAccountName`.",
+  "LDAP_Group_Filter_Enable": "Povolit LDAP filtr uživatelské skupiny",
+  "LDAP_Group_Filter_Enable_Description": "Omezit přístup uživatelům z LDAP skupiny<br/>Hodí se pro OpenLDAP servery kde nelze použít *memberOf* filtr",
+  "LDAP_Group_Filter_ObjectClass": "ObjectClass Skupiny",
+  "LDAP_Group_Filter_ObjectClass_Description": "*objectclass* která identifikuje skupiny.<br/> Např. OpenLDAP:groupOfUniqueNames",
+  "LDAP_Group_Filter_Group_Id_Attribute": "Atribut ID skupiny",
+  "LDAP_Group_Filter_Group_Id_Attribute_Description": "NapÅ™.: *OpenLDAP:*cn",
+  "LDAP_Group_Filter_Group_Member_Attribute": "Atribut uživatele skupiny",
+  "LDAP_Group_Filter_Group_Member_Attribute_Description": "NapÅ™.: *OpenLDAP:*uniqueMember",
+  "LDAP_Group_Filter_Group_Member_Format": "Formát uživatele skupiny",
+  "LDAP_Group_Filter_Group_Member_Format_Description": "NapÅ™.: *OpenLDAP:*uid=#{username},ou=users,o=Company,c=com",
+  "LDAP_Group_Filter_Group_Name": "Jméno skupiny",
+  "LDAP_Group_Filter_Group_Name_Description": "Jméno skupiny do které uživatel patří",
   "Least_Amount": "Nejmenším počet",
   "Leave_Group_Warning": "Jste si jisti, že chcete opustit skupinu \"%s\"?",
   "Leave_Private_Warning": "Jste si jisti, že chcete opustit diskusi s \"%s\"?",
@@ -701,6 +770,7 @@
   "Livechat_managers": "Manažeři Livechatu",
   "Livechat_offline": "Livechat offline",
   "Livechat_online": "Livechat online",
+  "Livechat_open_inquiery_show_connecting": "Zobrazit informaci o čekajícím připojení místo pole zprávy pokud uživatel ještě nebyl propojen s operátorem",
   "Livechat_Queue": "Livechat fronta",
   "Livechat_room_count": "Livechat počet místností",
   "Livechat_Routing_Method": "Metoda rozřazení livechatů",
@@ -761,6 +831,7 @@
   "Message_AllowEditing_BlockEditInMinutesDescription": "Zadáním hodnoty 0 vypnete blokování.",
   "Message_AllowPinning": "Povolit připnutí zprávy",
   "Message_AllowPinning_Description": "Povolení připnutí zpráv, k místnosti.",
+  "Message_AllowSnippeting": "Povolit předvolené zprávy",
   "Message_AllowStarring": "Povolit hvězdičkování zpráv",
   "Message_AllowUnrecognizedSlashCommand": "Povolit nerozpoznané lomítkové příkazy",
   "Message_AlwaysSearchRegExp": "Vždy hledat pomocí regulárních výrazů",
@@ -775,6 +846,11 @@
   "Message_editing": "Editace zprávy",
   "Message_GroupingPeriod": "Seskupovat zprávy v rozmezí (v sekundách)",
   "Message_GroupingPeriodDescription": "Zprávy budou seskupeny s předchozí zprávou, pokud jsou obě od stejného uživatele a uplynulá doba byla kratší než specifikovaný čas v sekundách.",
+  "Message_HideType_au": "Schovat zprávu o \"přidání uživatele\"",
+  "Message_HideType_mute_unmute": "Schovat zprávu o \"od/ztišení uživatele\"",
+  "Message_HideType_ru": "Schovat zprávu o \"odebrání uživatele\"",
+  "Message_HideType_uj": "Schovat zprávu o \"připojení uživatele\"",
+  "Message_HideType_ul": "Schovat zprávu o \"odchodu uživatele\"",
   "Message_KeepHistory": "Udržovat historie zpráv",
   "Message_MaxAll": "Maximální velikost místnosti pro všechny zprávy",
   "Message_MaxAllowedSize": "Maximální povolená velikost zprávy",
@@ -795,13 +871,13 @@
   "Messages_that_are_sent_to_the_Incoming_WebHook_will_be_posted_here": "Zprávy, které jsou odesílány do příchozí WebHook integrace budou zveřejněny zde.",
   "Meta": "Meta",
   "Meta_fb_app_id": "Facebook App Id",
+  "Meta_custom": "Vlastní meta tagy",
   "Meta_google-site-verification": "Ověření stránek Google",
   "Meta_language": "Jazyk",
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "Roboti",
   "Min_length_is": "Minimální délka je %s",
   "minutes": "minuty",
-  "Mobile_push": "Mobilní notifikace",
   "Monday": "Pondělí",
   "Monitor_history_for_changes_on": "Sledovat historii na změny:",
   "More_channels": "Více místností",
@@ -831,6 +907,8 @@
   "New_password": "Nové heslo",
   "New_role": "Nová role",
   "New_Room_Notification": "Oznámení o nové místnosti",
+  "New_videocall_request": "Nový požadavek videohovoru",
+  "New_Trigger": "Nový trigger",
   "No_available_agents_to_transfer": "Žádní operátoři k dispozici",
   "No_channel_with_name_%s_was_found": "Nebyla nalezena žádná místnost s názvem <strong>\"%s\"</strong>!",
   "No_channels_yet": "Zatím nejste v žádné místnosti.",
@@ -844,6 +922,7 @@
   "No_results_found": "Nebyly nalezeny žádné výsledky",
   "No_starred_messages": "Žádné zprávy s hvězdičkou",
   "No_such_command": "Příkaz `__comand__` neexistuje",
+  "No_snippet_messages": "Žádné předvolby",
   "No_user_with_username_%s_was_found": "Nebyl nalezen žádný uživatel s uživatelským jménem <strong>\"%s\"</strong>!",
   "Nobody_available": "Nikdo není dostupný",
   "Node_version": "Verze Node",
@@ -857,6 +936,7 @@
   "Notification_Duration": "Délka zobrazení oznámení",
   "Notifications": "Oznámení",
   "Notify_all_in_this_room": "Oznámit všem v této místnosti",
+  "Notify_active_in_this_room": "Notifikovat aktivní uživatele v místnosti",
   "Num_Agents": "# Operátorů",
   "Number_of_messages": "Počet zpráv",
   "OAuth_Application": "OAuth Aplikace",
@@ -884,8 +964,10 @@
   "Open_days_of_the_week": "Otevírací doba přes týden",
   "Open_Livechats": "Otevřené livechaty",
   "Opened": "Otevřený",
+  "Opened_in_a_new_window": "Otevřeno v novém okně",
   "Opens_a_channel_group_or_direct_message": "Otevře místnost, skupinu nebo přímou zprávu",
   "optional": "volitelný",
+  "Use_minor_colors": "Použít nevýraznou barevnou baletu (ve výchozím stavu podědí výraznou paletu)",
   "or": "nebo",
   "Order": "Objednat",
   "OS_Arch": "Architektura OS",
@@ -971,6 +1053,8 @@
   "quote": "citovat",
   "Quote": "Citovat",
   "Random": "Náhodný",
+  "React_when_read_only": "Povolit reakce",
+  "React_when_read_only_changed_successfully": "Povolit reakce po úspěšné změně povolení ke čtení",
   "Reacted_with": "zanechal/a reakci",
   "Reactions": "Reakce",
   "Read_only": "Pouze pro čtení",
@@ -979,6 +1063,7 @@
   "Read_only_group": "Skupina pouze pro čtení",
   "Record": "Záznam",
   "Redirect_URI": "URI Přesměrování",
+  "Refresh_oauth_services": "Obnovit služby OAuth",
   "Refresh_keys": "Obnovit klíče",
   "Refresh_your_page_after_install_to_enable_screen_sharing": "Po instalaci obnovte stránku aby sdílení stránky fungovalo",
   "Register": "Zaregistrovat nový účet",
@@ -1017,6 +1102,8 @@
   "room_changed_topic": "<em>__user_by__</em> změnil/a téma místnosti na: <em>__room_topic__</em>",
   "Room_description_changed_successfully": "Popis místnosti změněn",
   "Room_has_been_deleted": "Místnost smazána",
+  "Room_has_been_archived": "Místnost byla archivována",
+  "Room_has_been_unarchived": "Místnost již není archivována",
   "Room_Info": "Informace o místnosti",
   "room_is_read_only": "Tato místnost je pouze pro čtení",
   "room_name": "jméno místnosti",
@@ -1035,8 +1122,11 @@
   "SAML_Custom_Cert": "Vlastní Certifikát",
   "SAML_Custom_Entry_point": "Vlastní vstupní bod",
   "SAML_Custom_Generate_Username": "Generovat uživatelské jméno",
+  "SAML_Custom_IDP_SLO_Redirect_URL": "IDP SLO přesměrovací URL",
   "SAML_Custom_Issuer": "Vlastní vydavatel",
   "SAML_Custom_Provider": "Vlastní poskytovatel",
+  "SAML_Custom_Public_Cert": "Obsah veřejného certifikátu",
+  "SAML_Custom_Private_Key": "Obsah privátního klíče",
   "Sandstorm_Powerbox_Share": "Sdílet Sandstorm grain",
   "Saturday": "Sobota",
   "Save": "Uložit",
@@ -1050,8 +1140,6 @@
   "Script_Enabled": "Skript Povolen",
   "Search": "Vyhledávání",
   "Search_by_username": "Vyhledávání podle jména",
-  "Search_Channels": "Vyhledávání místností",
-  "Search_Direct_Messages": "Vyhledávání přímých konverací",
   "Search_Messages": "Hledat zprávy",
   "Search_Private_Groups": "Vyhledávání soukromých skupin",
   "seconds": "sekundy",
@@ -1094,6 +1182,7 @@
   "Show_all": "Ukázat vše",
   "Show_more": "Zobrazit více",
   "show_offline_users": "zobrazit offline uživatele",
+  "Show_on_registration_page": "Zobrazit na registrační stránce",
   "Show_only_online": "Pouze on-line",
   "Show_preregistration_form": "Ukázat před-registrační formulář",
   "Show_queue_list_to_all_agents": "Zobrazit frontu všech operátorů",
@@ -1106,7 +1195,13 @@
   "Site_Url_Description": "Například: https://chat.domain.com/",
   "Skip": "Přeskočit",
   "SlackBridge_error": "SlackBridge narazil na chybu při importu zpráv ve %s: %s",
+  "SlackBridge_Out_All": "Slackbridge Odesílat Vše",
+  "SlackBridge_Out_All_Description": "Odesílat zprávy ze všech místností které existují i na slacku a bot je v nich připojen",
+  "SlackBridge_Out_Channels": "Slackbridge Odesílat místnosti",
+  "SlackBridge_Out_Channels_Description": "Vyberte které místnosti budou odesílány",
   "SlackBridge_finish": "Slackbridge dokončil import zpráv ve %s. Prosím obnovte stránku pro zobrazení všech zpráv.",
+  "SlackBridge_Out_Enabled": "SlackBridge Odesáílání povoleno",
+  "SlackBridge_Out_Enabled_Description": "Zvolit zda by měl SlackBridge také odesílat zprávy zpět do Slacku",
   "SlackBridge_start": "@%s spustil import přes SlackBridge ve `#%s`. Dáme vědět až to bude hotové.",
   "Slash_Gimme_Description": "Zobrazí ༼ つ ◕_◕ ༽つ před Vaší zprávou",
   "Slash_LennyFace_Description": "Zobrazí ( ͡° ͜ʖ ͡°) za Vaší zprávou",
@@ -1131,6 +1226,9 @@
   "SMTP_Port": "Port SMTP",
   "SMTP_Test_Button": "Test nastavení SMTP",
   "SMTP_Username": "Uživatelské jméno SMTP",
+  "Snippet_Added": "Vytvořeno v %s",
+  "Snippet_Messages": "Předvolené zprávy",
+  "Snippeted_a_message": "Vytvořena předvolená zpráva __snippetLink__",
   "Sound": "Zvuk",
   "SSL": "SSL",
   "Star_Message": "Ohvězdičkovat zprávu",
@@ -1161,6 +1259,8 @@
   "Stats_Total_Users": "Celkem uživatelů",
   "Status": "Stav",
   "Stop_Recording": "Zastavit záznam",
+  "Stream_Cast_Address": "Adresa Stream Castu",
+  "Stream_Cast_Address_Description": "IP nebo Server vaší Rocket.Chat hlavního Stream Castu. Např. `192.168.1.1:3000` or `localhost:4000`",
   "strike": "přeškrtnuté",
   "Subject": "Předmět",
   "Submit": "Odeslat",
@@ -1190,11 +1290,23 @@
   "The_user_will_be_removed_from_s": "Uživatel bude odstraněn z %s",
   "The_user_wont_be_able_to_type_in_s": "Uživatel nebude moci psát v %s",
   "Theme": "Barevné nastavení",
+  "theme-color-transparent-darker": "Průhledná tmavší",
+  "theme-color-transparent-dark": "Průhledná tmavá",
+  "theme-color-transparent-light": "Průhledná světlá",
+  "theme-color-transparent-lighter": "Průhledná světlejší",
+  "theme-color-transparent-lightest": "Průhledná nejsvětlejší",
   "theme-color-content-background-color": "Barva pozadí obsahu",
   "theme-color-primary-background-color": "Primární Barva pozadí",
   "theme-color-primary-font-color": "Primární Barva písma",
+  "theme-color-primary-action-color": "Primární barva akce",
   "theme-color-secondary-background-color": "Sekundární Barva pozadí",
   "theme-color-secondary-font-color": "Sekundární Barva písma",
+  "theme-color-secondary-action-color": "Sekundární barva akce",
+  "theme-color-component-color": "Barva komponenty",
+  "theme-color-success-color": "Barva zdařené akce",
+  "theme-color-pending-color": "Barva čekající akce",
+  "theme-color-error-color": "Barva chybové akce",
+  "theme-color-selection-color": "Barva výběru",
   "theme-color-tertiary-background-color": "Terciární Barva pozadí",
   "theme-color-tertiary-font-color": "Terciární Barva písma",
   "theme-color-link-font-color": "Barva písma odkazů",
@@ -1227,6 +1339,9 @@
   "To_users": "Uživatelům",
   "Topic": "Téma",
   "Travel_and_Places": "Cestování & Místa",
+  "Transcript_Enabled": "Zeptat se po skončení chatu, zda uživateli odeslat kopii konverzace",
+  "Transcript_message": "Zpráva kterou zobrazit jako dotaz zda odeslat kopii konverzace",
+  "Transcript_of_your_livechat_conversation": "Kopie Vaší livechat konverzace",
   "Trigger_removed": "Trigger odstraněn",
   "Trigger_Words": "Klíčová slova",
   "Triggers": "Trigery",
@@ -1313,11 +1428,14 @@
   "Users_in_role": "Uživatelé v roli",
   "UTF8_Names_Slugify": "Url podoba UTF8 jmen",
   "UTF8_Names_Validation": "UTF8 validace jmen",
-  "UTF8_Names_Validation_Description": "Nelze použít speciální znaky a mezery. Můžete použít - _ a . ale ne na konci jména",
+  "UTF8_Names_Validation_Description": "Regulární výraz validující uživatelská jména a jména místností",
   "Verification_email_sent": "Ověřovací email odeslán",
   "Verified": "Ověřený",
   "Version": "Verze",
   "Video_Chat_Window": "Video chat",
+  "Video_Conference": "Video konference",
+  "Videocall_declined": "Videohovor odmítnut",
+  "Videocall_enabled": "Videohovor povolen",
   "View_All": "Zobrazit vše",
   "View_Logs": "Zobrazit logy",
   "View_mode": "Režim zobrazení",
@@ -1331,6 +1449,7 @@
   "Visitor_page_URL": "URL Stránky pro návštěvníky",
   "Visitor_time_on_site": "Doba návštěvníka na stránce",
   "Wait_activation_warning": "Předtím, než se můžete přihlásit, Váš účet musí být ručně aktivován správcem.",
+  "Warnings": "Varování",
   "We_are_offline_Sorry_for_the_inconvenience": "Jsme offline. Omlouváme se za nepříjemnosti.",
   "We_have_sent_password_email": "Poslali jsme vám e-mail s pokyny k obnovení hesla. Pokud neobdržíte e-mail v blízké době, zkuste to prosím znovu.",
   "We_have_sent_registration_email": "Poslali jsme vám e-mail pro potvrzení registrace. Pokud e-mail neobdržíte v blízké době, zkuste to prosím znovu.",
@@ -1348,6 +1467,8 @@
   "will_be_able_to": "bude moci",
   "Would_you_like_to_return_the_inquiry": "Chcete požadavek zamítnout?",
   "Yes": "Ano",
+  "Yes_archive_it": "Ano archivovat",
+  "Yes_unarchive_it": "Ano zrušit archivaci",
   "Yes_clear_all": "Ano, vyčistit všechny!",
   "Yes_delete_it": "Ano, smazat!",
   "Yes_hide_it": "Ano, skrýt!",
diff --git a/packages/rocketchat-i18n/i18n/de-AT.i18n.json b/packages/rocketchat-i18n/i18n/de-AT.i18n.json
index 1522fdc8c1ba2a152daf4d37bffcdfb07574392e..d5e5f6368e34a03adbd56e6f42df9d6564e65c13 100644
--- a/packages/rocketchat-i18n/i18n/de-AT.i18n.json
+++ b/packages/rocketchat-i18n/i18n/de-AT.i18n.json
@@ -271,7 +271,7 @@
   "Created_at_s_by_s": "Erstellt am <strong>%s</strong> von <strong>%s</strong>",
   "Current_Chats": "Aktuelle Chats",
   "Custom": "Benutzerdefiniert",
-  "Custom_Emoji": "Plattformspezifischer Emoji",
+  "Custom_Emoji": "Plattformspezifische Emoji",
   "Custom_Emoji_Add": "Neuen Emoji hinzufügen",
   "Custom_Emoji_Added_Successfully": "Benutzerdefinierter Emoji erfolgreich hinzugefügt",
   "Custom_Emoji_Delete_Warning": "Das Löschen eines Emojis kann nicht rückgängig gemacht werden.",
@@ -467,9 +467,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "Geben Sie dem benutzerdefinierten OAuth-Konto einen eindeutigen Namen.",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Geben Sie der Anwendung einen Namen. Die Nutzer können den Namen sehen.",
   "Global": "Global",
-  "GoogleSiteVerification_id": "Verifikations-ID für Googleseite",
   "GoogleTagManager_id": "Google-Tag-Manager-ID",
-  "Has_more": "Mehr",
   "Hash": "Hash",
   "Header": "Kopfzeile",
   "Hidden": "Versteckt",
@@ -707,6 +705,11 @@
   "Message_editing": "Bearbeiten von Nachrichten",
   "Message_GroupingPeriod": "Gruppierungsdauer (in Sekunden)",
   "Message_GroupingPeriodDescription": "Nachrichten werden einer vorherigen Nachricht zugeordnet, wenn beide Nachrichten von dem gleichen Benutzer kommen und die abgelaufene Zeit kleiner als die mitgeteilte Zeit in Sekunden war.",
+  "Message_HideType_au": "\"Benutzer hinzugeben\" Nachrichten verstecken",
+  "Message_HideType_mute_unmute": "\"Benutzer stillgeschalten\" Nachrichten verstecken",
+  "Message_HideType_ru": "\"Benutzer entfernt\" Nachrichten verstecken",
+  "Message_HideType_uj": "\"Benutzer beigetreten\" Nachrichten verstecken",
+  "Message_HideType_ul": "\"Benutzer verlassen\" Nachrichten verstecken",
   "Message_KeepHistory": "Nachrichtenverlauf behalten",
   "Message_MaxAll": "Maximale Kanalgröße für ALL Nachricht",
   "Message_MaxAllowedSize": "Maximal zulässige Größe der Nachrichten\n",
@@ -732,7 +735,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "Roboter",
   "minutes": "Minuten",
-  "Mobile_push": "mobile Push-Benachrichtigungen",
   "Monitor_history_for_changes_on": "Verlaufsänderungen beobachten für",
   "More_channels": "Weitere Kanäle",
   "More_direct_messages": "Mehr Direktnachrichten",
@@ -961,8 +963,6 @@
   "Script_Enabled": "Das Script ist aktiviert.",
   "Search": "Suche",
   "Search_by_username": "Anhand des Nutzernamen suchen",
-  "Search_Channels": "Kanäle suchen",
-  "Search_Direct_Messages": "Durchsuche Direktnachrichten",
   "Search_Messages": "Nachrichten durchsuchen",
   "Search_Private_Groups": "Durchsuche private Chatgruppen",
   "seconds": "Sekunden",
@@ -1123,6 +1123,7 @@
   "Unmute_user": "Benutzern das Chatten erlauben ",
   "Unnamed": "Unbenannt",
   "Unpin_Message": "Nachicht nicht mehr fixieren",
+  "Unread_Alert": "Über Ungelesenes benachrichtigen",
   "Unread_Rooms": "Ungelesene Räume",
   "Unread_Rooms_Mode": "Ungelesene Räume aufgelistet anzeigen ",
   "Unstar_Message": "Markierung entfernen",
@@ -1227,7 +1228,7 @@
   "Yes": "Ja",
   "Yes_clear_all": "Ja!",
   "Yes_delete_it": "Ja!",
-  "Yes_hide_it": "Ja!",
+  "Yes_hide_it": "Ja, verstecken!",
   "Yes_leave_it": "Ja!",
   "Yes_mute_user": "Ja, Benutzer stumm schalten!\n",
   "Yes_remove_user": "Ja, Nutzer entfernen!",
diff --git a/packages/rocketchat-i18n/i18n/de.i18n.json b/packages/rocketchat-i18n/i18n/de.i18n.json
index adb712db329236558f14e319e47a46a46decad9a..4270f720c9a2c23df29aff13016bcdc8b3726673 100644
--- a/packages/rocketchat-i18n/i18n/de.i18n.json
+++ b/packages/rocketchat-i18n/i18n/de.i18n.json
@@ -281,7 +281,7 @@
   "Created_at_s_by_s": "Erstellt am <strong>%s</strong> von <strong>%s</strong>",
   "Current_Chats": "Aktuelle Chats",
   "Custom": "Benutzerdefiniert",
-  "Custom_Emoji": "Benutzerdefinierter Emoji",
+  "Custom_Emoji": "Benutzerdefinierte Emoji",
   "Custom_Emoji_Add": "Neuen Emoji hinzufügen",
   "Custom_Emoji_Added_Successfully": "Benutzerdefinierter Emoji erfolgreich hinzugefügt",
   "Custom_Emoji_Delete_Warning": "Das Löschen eines Emojis kann nicht rückgänig gemacht werden.",
@@ -397,7 +397,7 @@
   "error-invalid-domain": "Ungültige Domain",
   "error-invalid-email": "Ungültige E-Mail-Adresse: __email__",
   "error-invalid-file-height": "Ungültige Dateihöhe",
-  "error-invalid-file-type": "Ungültiges Dateiformat.",
+  "error-invalid-file-type": "Ungültiges Dateiformat",
   "error-invalid-file-width": "Ungültige Dateibreite",
   "error-invalid-from-address": "Sie haben eine ungültige E-Mail-Adresse als Empfänger angegeben.",
   "error-invalid-integration": "Ungültige Integration",
@@ -426,7 +426,7 @@
   "error-not-allowed": "Nicht erlaubt",
   "error-not-authorized": "Nicht berechtigt",
   "error-push-disabled": "Push-Benachrichtigungen sind deaktiviert",
-  "error-remove-last-owner": "Das ist der letzte Besitzer. Bitte bestimmen Sie einen neuen Besitzer, bevor Sie diesen Raum löschen.",
+  "error-remove-last-owner": "Das ist der letzte Besitzer. Bitte bestimmen Sie einen neuen Besitzer, bevor Sie diesen entfernen.",
   "error-role-in-use": "Die Rolle kann nicht gelöscht werden, da sie gerade verwendet wird.",
   "error-role-name-required": "Ein Rollenname muss angegeben werden",
   "error-the-field-is-required": "Das Feld __field__ ist erforderlich.",
@@ -494,10 +494,8 @@
   "Give_a_unique_name_for_the_custom_oauth": "Geben Sie dem benutzerdefinierten OAuth-Konto einen eindeutigen Namen.",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Geben Sie der Anwendung einen Namen. Die Nutzer können den Namen sehen.",
   "Global": "Global",
-  "GoogleSiteVerification_id": "Verifikations-ID für Googleseite",
   "GoogleTagManager_id": "Google-Tag-Manager-ID",
   "Guest_Pool": "Gästepool",
-  "Has_more": "Mehr",
   "Hash": "Hash",
   "Header": "Kopfzeile",
   "Hidden": "Versteckt",
@@ -747,6 +745,11 @@
   "Message_editing": "Bearbeiten von Nachrichten",
   "Message_GroupingPeriod": "Gruppierungsdauer (in Sekunden)",
   "Message_GroupingPeriodDescription": "Nachrichten werden einer vorherigen Nachricht zugeordnet, wenn beide Nachrichten von dem gleichen Benutzer kommen und die abgelaufene Zeit kleiner als die mitgeteilte Zeit in Sekunden war.",
+  "Message_HideType_au": "\"Benutzer hinzugeben\" Nachrichten verstecken",
+  "Message_HideType_mute_unmute": "\"Benutzer stillgeschalten\" Nachrichten verstecken",
+  "Message_HideType_ru": "\"Benutzer entfernt\" Nachrichten verstecken",
+  "Message_HideType_uj": "\"Benutzer beigetreten\" Nachrichten verstecken",
+  "Message_HideType_ul": "\"Benutzer verlassen\" Nachrichten verstecken",
   "Message_KeepHistory": "Nachrichtenverlauf behalten",
   "Message_MaxAll": "Maximale Kanalgröße für ALL Nachricht",
   "Message_MaxAllowedSize": "Maximal zulässige Größe der Nachrichten\n",
@@ -772,7 +775,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "Roboter",
   "minutes": "Minuten",
-  "Mobile_push": "mobile Push-Benachrichtigungen",
   "Monday": "Montag",
   "Monitor_history_for_changes_on": "Verlaufsänderungen beobachten für",
   "More_channels": "Mehr Kanäle",
@@ -1008,8 +1010,6 @@
   "Script_Enabled": "Das Script ist aktiviert.",
   "Search": "Suche",
   "Search_by_username": "Anhand des Nutzernamen suchen",
-  "Search_Channels": "Kanäle suchen",
-  "Search_Direct_Messages": "Durchsuche Direktnachrichten",
   "Search_Messages": "Nachrichten durchsuchen",
   "Search_Private_Groups": "Durchsuche private Gruppen",
   "seconds": "Sekunden",
@@ -1185,6 +1185,7 @@
   "Unmute_user": "Benutzern das Chatten erlauben ",
   "Unnamed": "Unbenannt",
   "Unpin_Message": "Nachicht nicht mehr fixieren",
+  "Unread_Alert": "Über Ungelesenes benachrichtigen",
   "Unread_Rooms": "Ungelesene Räume",
   "Unread_Rooms_Mode": "Ungelesene Räume aufgelistet anzeigen ",
   "Unstar_Message": "Markierung entfernen",
@@ -1290,7 +1291,7 @@
   "Yes": "Ja",
   "Yes_clear_all": "Ja!",
   "Yes_delete_it": "Ja!",
-  "Yes_hide_it": "Ja!",
+  "Yes_hide_it": "Ja, verstecken!",
   "Yes_leave_it": "Ja!",
   "Yes_mute_user": "Ja, Benutzer stumm schalten!\n",
   "Yes_remove_user": "Ja, Nutzer entfernen!",
diff --git a/packages/rocketchat-i18n/i18n/el.i18n.json b/packages/rocketchat-i18n/i18n/el.i18n.json
index 8a3512d53ec89e31229bffc075d0c9e550f9c47a..b3edc3db5529061e58066985f6544a02e42012fe 100644
--- a/packages/rocketchat-i18n/i18n/el.i18n.json
+++ b/packages/rocketchat-i18n/i18n/el.i18n.json
@@ -449,9 +449,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "Δώστε ένα μοναδικό όνομα για την προσαρμοσμένη OAuth",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Δώστε στην εφαρμογή ένα όνομα. Αυτό θα φανεί από τους χρήστες σας.",
   "Global": "Παγκόσμια",
-  "GoogleSiteVerification_id": "Id επαλήθευσης Google Site",
   "GoogleTagManager_id": "Id στο Google Tag Manager",
-  "Has_more": "έχει περισσότερα",
   "Hash": "Χασίσι",
   "Header": "Επί κεφαλής",
   "Hidden": "Κεκρυμμένος",
@@ -710,7 +708,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "Ρομπότ",
   "minutes": "λεπτά",
-  "Mobile_push": "κινητό ώθηση",
   "More_channels": "Περισσότερα κανάλια",
   "More_direct_messages": "Πιο άμεσα μηνύματα",
   "More_groups": "Περισσότερες ιδιωτικές ομάδες",
@@ -927,8 +924,6 @@
   "Script_Enabled": "script Enabled",
   "Search": "Αναζήτηση",
   "Search_by_username": "Αναζήτηση με το όνομα χρήστη",
-  "Search_Channels": "Αναζήτηση καναλιών",
-  "Search_Direct_Messages": "Απευθείας Μηνύματα",
   "Search_Messages": "Αναζήτηση μηνυμάτων",
   "Search_Private_Groups": "Αναζήτηση ιδιωτικούς ομίλους",
   "seconds": "δευτερόλεπτα",
diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json
index 046e16834409fe8c688f9bbf1f284b429344b202..2a9c0e0648c99580f4cb5e500453d62345f29d30 100644
--- a/packages/rocketchat-i18n/i18n/en.i18n.json
+++ b/packages/rocketchat-i18n/i18n/en.i18n.json
@@ -56,10 +56,12 @@
   "Accounts_OAuth_Custom_id": "Id",
   "Accounts_OAuth_Custom_Identity_Path": "Identity Path",
   "Accounts_OAuth_Custom_Login_Style": "Login Style",
+  "Accounts_OAuth_Custom_Merge_Users": "Merge users",
   "Accounts_OAuth_Custom_Scope": "Scope",
   "Accounts_OAuth_Custom_Secret": "Secret",
   "Accounts_OAuth_Custom_Token_Path": "Token Path",
   "Accounts_OAuth_Custom_Token_Sent_Via": "Token Sent Via",
+  "Accounts_OAuth_Custom_Username_Field": "Username field",
   "Accounts_OAuth_Facebook": "Facebook Login",
   "Accounts_OAuth_Facebook_callback_url": "Facebook Callback URL",
   "Accounts_OAuth_Facebook_id": "Facebook App Id",
@@ -107,6 +109,8 @@
   "Accounts_RegistrationForm_SecretURL_Description": "You must provide a random string that will be added to your registration URL. Example: https://demo.rocket.chat/register/[secret_hash]",
   "Accounts_RequireNameForSignUp": "Require Name For Signup",
   "Accounts_RequirePasswordConfirmation": "Require Password Confirmation",
+  "Accounts_SetDefaultAvatar": "Set Default Avatar",
+  "Accounts_SetDefaultAvatar_Description": "Tries to determine default avatar based on OAuth Account or Gravatar",
   "Accounts_ShowFormLogin": "Show form-based Login",
   "Accounts_UseDefaultBlockedDomainsList": "Use Default Blocked Domains List",
   "Accounts_UseDNSDomainCheck": "Use DNS Domain Check",
@@ -118,6 +122,7 @@
   "Add": "Add",
   "Add_agent": "Add agent",
   "Add_custom_oauth": "Add custom oauth",
+  "Add_Domain": "Add Domain",
   "Add_manager": "Add manager",
   "Add_user": "Add user",
   "Add_User": "Add User",
@@ -142,6 +147,7 @@
   "All_messages": "All messages",
   "Allow_Invalid_SelfSigned_Certs": "Allow Invalid Self-Signed Certs",
   "Allow_Invalid_SelfSigned_Certs_Description": "Allow invalid and self-signed SSL certificate's for link validation and previews.",
+  "Always_open_in_new_window": "Always open in new window",
   "Analytics_features_enabled": "Features Enabled",
   "Analytics_features_messages_Description": "Tracks custom events related to actions a user does on messages.",
   "Analytics_features_rooms_Description": "Tracks custom events related to actions on a channel or group (create, leave, delete).",
@@ -150,7 +156,11 @@
   "And_more": "And __length__ more",
   "Animals_and_Nature": "Animals & Nature",
   "API": "API",
+  "API_Allow_Infinite_Count": "Allow Getting Everything",
+  "API_Allow_Infinite_Count_Description": "Should calls to the REST API be allowed to return everything in one call?",
   "API_Analytics": "Analytics",
+  "API_Default_Count": "Default Count",
+  "API_Default_Count_Description": "The default count for REST API results if the consumer did not provided any.",
   "API_Embed": "Embed Link Previews",
   "API_Embed_Description": "Whether embedded link previews are enabled or not when a user posts a link to a website.",
   "API_EmbedCacheExpirationDays": "Embed cache expiration days",
@@ -164,6 +174,8 @@
   "API_GitHub_Enterprise_URL_Description": "Example: http://domain.com (excluding trailing slash)",
   "API_Gitlab_URL": "GitLab URL",
   "API_Token": "API Token",
+  "API_Upper_Count_Limit": "Max Record Amount",
+  "API_Upper_Count_Limit_Description": "What is the maximum number of records the REST API should return (when not unlimited)?",
   "API_User_Limit": "User Limit for adding all Users to Channel",
   "API_Wordpress_URL": "WordPress URL",
   "Apiai_Key": "Api.ai Key",
@@ -214,6 +226,7 @@
   "Back_to_login": "Back to login",
   "Back_to_permissions": "Back to permissions",
   "Beta_feature_Depends_on_Video_Conference_to_be_enabled": "Beta feature. Depends on Video Conference to be enabled.",
+  "Block_User": "Block User",
   "Body": "Body",
   "bold": "bold",
   "bot_request": "Bot request",
@@ -252,6 +265,7 @@
   "CDN_PREFIX": "CDN Prefix",
   "Certificates_and_Keys": "Certificates and Keys",
   "Changing_email": "Changing email",
+  "Change_Room_Type": "Changing the Room Type",
   "channel": "channel",
   "Channel": "Channel",
   "Channel_already_exist": "The channel '#%s' already exists.",
@@ -325,6 +339,8 @@
   "Custom_Translations_Description": "Should be a valid JSON where keys are languages containing a dictionary of key and translations. Example:</br><code>{\n\t\"en\": {\n\t\t\"key\": \"translation\"\n\t},\n\t\"pt\": {\n\t\t\"key\": \"tradução\"\n\t}\n}</code> ",
   "Dashboard": "Dashboard",
   "Date": "Date",
+  "Date_From": "From",
+  "Date_to": "to",
   "days": "days",
   "DB_Migration": "Database Migration",
   "DB_Migration_Date": "Database Migration Date",
@@ -355,6 +371,8 @@
   "Displays_action_text": "Displays action text",
   "Do_you_want_to_change_to_s_question": "Do you want to change to <strong>%s</strong>?",
   "Domain": "Domain",
+  "Domain_added": "domain Added",
+  "Domain_removed": "Domain Removed",
   "Domains": "Domains",
   "Download_Snippet": "Download",
   "Drop_to_upload_file": "Drop to upload file",
@@ -368,6 +386,7 @@
   "Edit": "Edit",
   "Edit_Custom_Field": "Edit Custom Field",
   "Edit_Department": "Edit Department",
+  "Edit_Trigger": "Edit Trigger",
   "edited": "edited",
   "Editing_room": "Editing room",
   "Editing_user": "Editing user",
@@ -424,9 +443,11 @@
   "error-invalid-channel-start-with-chars": "Invalid channel. Start with @ or #",
   "error-invalid-custom-field": "Invalid custom field",
   "error-invalid-custom-field-name": "Invalid custom field name. Use only letters, numbers, hyphens and underscores.",
+  "error-invalid-date": "Invalid date provided.",
   "error-invalid-description": "Invalid description",
   "error-invalid-domain": "Invalid domain",
   "error-invalid-email": "Invalid email __email__",
+  "error-invalid-email-address": "Invalid email address",
   "error-invalid-file-height": "Invalid file height",
   "error-invalid-file-type": "Invalid file type",
   "error-direct-message-file-upload-not-allowed": "File sharing not allowed in direct messages",
@@ -513,6 +534,8 @@
   "Food_and_Drink": "Food & Drink",
   "Footer": "Footer",
   "For_your_security_you_must_enter_your_current_password_to_continue": "For your security, you must enter your current password to continue",
+  "Force_Disable_OpLog_For_Cache": "Force disable OpLog for Cache",
+  "Force_Disable_OpLog_For_Cache_Description": "Will not use OpLog to sync cache even when it's available",
   "Force_SSL": "Force SSL",
   "Force_SSL_Description": "*Caution!* _Force SSL_ should never be used with reverse proxy. If you have a reverse proxy, you should do the redirect THERE. This option exists for deployments like Heroku, that does not allow the redirect configuration at the reverse proxy.",
   "Forgot_password": "Forgot your password",
@@ -530,10 +553,8 @@
   "Give_a_unique_name_for_the_custom_oauth": "Give a unique name for the custom oauth",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Give the application a name. This will be seen by your users.",
   "Global": "Global",
-  "GoogleSiteVerification_id": "Google Site Verification Id",
   "GoogleTagManager_id": "Google Tag Manager Id",
   "Guest_Pool": "Guest Pool",
-  "Has_more": "Has more",
   "Hash": "Hash",
   "Header": "Header",
   "Hidden": "Hidden",
@@ -569,6 +590,8 @@
   "Iframe_Integration_send_target_origin_Description": "Only pages with given origin will be able to listen to events or `*` for all origins. Example `http://localhost`",
   "Importer_Archived": "Archived",
   "Importer_CSV_Information": "The CSV importer requires a specific format, please read the documentation for how to structure your zip file:",
+  "Importer_HipChatEnterprise_Information": "The file uploaded must be a decrypted tar.gz, please read the documentation for further information:",
+  "Importer_HipChatEnterprise_BetaWarning": "Please be aware that this import is still a work in progress, please report any errors which occur in GitHub:",
   "Importer_done": "Importing complete!",
   "Importer_finishing": "Finishing up the import.",
   "Importer_From_Description": "Imports __from__ data into Rocket.Chat.",
@@ -755,6 +778,8 @@
   "List_of_Channels": "List of Channels",
   "List_of_Direct_Messages": "List of Direct Messages",
   "Livechat_agents": "Livechat agents",
+  "Livechat_AllowedDomainsList": "Livechat allowed domains",
+  "Domains_allowed_to_embed_the_livechat_widget": "Comma-separated list of domains allowed to embed the livechat widget. Leave blank to allow all domains.",
   "Livechat_Dashboard": "Livechat Dashboard",
   "Livechat_enabled": "Livechat enabled",
   "Livechat_forward_open_chats": "Forward open chats",
@@ -764,6 +789,7 @@
   "Livechat_managers": "Livechat managers",
   "Livechat_offline": "Livechat offline",
   "Livechat_online": "Livechat online",
+  "Livechat_open_inquiery_show_connecting": "Show connecting message instead of input when guest is not yet connected to an agent",
   "Livechat_Queue": "Livechat Queue",
   "Livechat_room_count": "Livechat room count",
   "Livechat_Routing_Method": "Livechat Routing Method",
@@ -864,13 +890,14 @@
   "Messages_that_are_sent_to_the_Incoming_WebHook_will_be_posted_here": "Messages that are sent to the Incoming WebHook will be posted here.",
   "Meta": "Meta",
   "Meta_fb_app_id": "Facebook App Id",
+  "Meta_custom": "Custom Meta Tags",
   "Meta_google-site-verification": "Google Site Verification",
   "Meta_language": "Language",
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "Robots",
   "Min_length_is": "Min length is %s",
   "minutes": "minutes",
-  "Mobile_push": "Mobile push",
+  "Mobile": "Mobile",
   "Monday": "Monday",
   "Monitor_history_for_changes_on": "Monitor history for changes on",
   "More_channels": "More channels",
@@ -901,6 +928,7 @@
   "New_role": "New role",
   "New_Room_Notification": "New Room Notification",
   "New_videocall_request": "New videocall request",
+  "New_Trigger": "New Trigger",
   "No_available_agents_to_transfer": "No available agents to transfer",
   "No_channel_with_name_%s_was_found": "No channel with name <strong>\"%s\"</strong> was found!",
   "No_channels_yet": "You aren't part of any channel yet.",
@@ -956,6 +984,7 @@
   "Open_days_of_the_week": "Open Days of the Week",
   "Open_Livechats": "Open Livechats",
   "Opened": "Opened",
+  "Opened_in_a_new_window": "Opened in a new window.",
   "Opens_a_channel_group_or_direct_message": "Opens a channel, group or direct message",
   "optional": "optional",
   "Use_minor_colors": "Use minor color palette (defaults inherit major colors)",
@@ -997,6 +1026,7 @@
   "Please_enter_value_for_url": "Please enter a value for the url of your avatar.",
   "Please_enter_your_new_password_below": "Please enter your new password below:",
   "Please_enter_your_password": "Please enter your password",
+  "please_enter_valid_domain": "Please enter a valid domain",
   "Please_fill_a_label": "Please fill a label",
   "Please_fill_a_name": "Please fill a name",
   "Please_fill_a_username": "Please fill a username",
@@ -1044,6 +1074,8 @@
   "quote": "quote",
   "Quote": "Quote",
   "Random": "Random",
+  "React_when_read_only": "Allow Reacting",
+  "React_when_read_only_changed_successfully": "Allow reacting when read only changed successfully",
   "Reacted_with": "Reacted with",
   "Reactions": "Reactions",
   "Read_only": "Read Only",
@@ -1052,6 +1084,7 @@
   "Read_only_group": "Read Only Group",
   "Record": "Record",
   "Redirect_URI": "Redirect URI",
+  "Refresh_oauth_services": "Refresh OAuth Services",
   "Refresh_keys": "Refresh keys",
   "Refresh_your_page_after_install_to_enable_screen_sharing": "Refresh your page after install to enable screen sharing",
   "Register": "Register a new account",
@@ -1074,6 +1107,7 @@
   "Require_password_change": "Require password change",
   "Resend_verification_email": "Resend verification email",
   "Reset": "Reset",
+  "Reset_section_settings": "Reset section settings",
   "Reset_password": "Reset password",
   "Restart": "Restart",
   "Restart_the_server": "Restart the server",
@@ -1090,7 +1124,10 @@
   "room_changed_topic": "Room topic changed to: <em>__room_topic__</em> by <em>__user_by__</em>",
   "Room_description_changed_successfully": "Room description changed successfully",
   "Room_has_been_deleted": "Room has been deleted",
+  "Room_has_been_archived": "Room has been archived",
+  "Room_has_been_unarchived": "Room has been unarchived",
   "Room_Info": "Room Info",
+  "room_is_blocked": "This room is blocked",
   "room_is_read_only": "This room is read only",
   "room_name": "room name",
   "Room_name_changed": "Room name changed to: <em>__room_name__</em> by <em>__user_by__</em>",
@@ -1108,8 +1145,11 @@
   "SAML_Custom_Cert": "Custom Certificate",
   "SAML_Custom_Entry_point": "Custom Entry Point",
   "SAML_Custom_Generate_Username": "Generate Username",
+  "SAML_Custom_IDP_SLO_Redirect_URL": "IDP SLO Redirect URL",
   "SAML_Custom_Issuer": "Custom Issuer",
   "SAML_Custom_Provider": "Custom Provider",
+  "SAML_Custom_Public_Cert": "Public cert contents",
+  "SAML_Custom_Private_Key": "Private key contents",
   "Sandstorm_Powerbox_Share": "Share a Sandstorm grain",
   "Saturday": "Saturday",
   "Save": "Save",
@@ -1123,8 +1163,6 @@
   "Script_Enabled": "Script Enabled",
   "Search": "Search",
   "Search_by_username": "Search by username",
-  "Search_Channels": "Search Channels",
-  "Search_Direct_Messages": "Search Direct Messages",
   "Search_Messages": "Search Messages",
   "Search_Private_Groups": "Search Private Groups",
   "seconds": "seconds",
@@ -1167,6 +1205,7 @@
   "Show_all": "Show all",
   "Show_more": "Show more",
   "show_offline_users": "show offline users",
+  "Show_on_registration_page": "Show on registration page",
   "Show_only_online": "Show only online",
   "Show_preregistration_form": "Show pre-registration form",
   "Show_queue_list_to_all_agents": "Show queue list to all agents",
@@ -1278,6 +1317,7 @@
   "theme-color-transparent-dark": "Transparent Dark",
   "theme-color-transparent-light": "Transparent Light",
   "theme-color-transparent-lighter": "Transparent Lighter",
+  "theme-color-transparent-lightest": "Transparent Lightest",
   "theme-color-content-background-color": "Content Background Color",
   "theme-color-primary-background-color": "Primary Background Color",
   "theme-color-primary-font-color": "Primary Font Color",
@@ -1339,6 +1379,7 @@
   "UI_Merge_Channels_Groups": "Merge private groups with channels",
   "UI_Use_Name_Avatar": "Use name for default user avatar",
   "Unarchive": "Unarchive",
+  "Unblock_User": "Unblock User",
   "Unmute_someone_in_room": "Unmute someone in the room",
   "Unmute_user": "Unmute user",
   "Unnamed": "Unnamed",
@@ -1347,10 +1388,13 @@
   "Unread_Rooms": "Unread Rooms",
   "Unread_Rooms_Mode": "Unread Rooms Mode",
   "Unstar_Message": "Remove Star",
+  "Upload_file_description": "File description",
+  "Upload_file_name": "File name",
   "Upload_file_question": "Upload file?",
   "Uploading_file": "Uploading file...",
   "Uptime": "Uptime",
   "URL": "URL",
+  "URL_room_prefix": "URL room prefix",
   "Use_account_preference": "Use account preference",
   "Use_Emojis": "Use Emojis",
   "Use_Global_Settings": "Use Global Settings",
@@ -1374,8 +1418,10 @@
   "User_has_been_muted_in_s": "User has been muted in %s",
   "User_has_been_removed_from_s": "User has been removed from %s",
   "User_Info": "User Info",
+  "User_is_blocked": "User is blocked",
   "User_is_no_longer_an_admin": "User is no longer an admin",
   "User_is_now_an_admin": "User is now an admin",
+  "User_is_unblocked": "User is unblocked",
   "User_joined_channel": "Has joined the channel.",
   "User_joined_channel_female": "Has joined the channel.",
   "User_joined_channel_male": "Has joined the channel.",
@@ -1413,10 +1459,12 @@
   "UTF8_Names_Slugify": "UTF8 Names Slugify",
   "UTF8_Names_Validation": "UTF8 Names Validation",
   "UTF8_Names_Validation_Description": "RegExp that will be used to validate usernames and channel names",
+  "Validate_email_address": "Validate email address",
   "Verification_email_sent": "Verification email sent",
   "Verified": "Verified",
   "Version": "Version",
   "Video_Chat_Window": "Video Chat",
+  "Video_Conference": "Video Conference",
   "Videocall_declined": "Videocall declined.",
   "Videocall_enabled": "Videocall enabled",
   "View_All": "View All",
@@ -1450,6 +1498,8 @@
   "will_be_able_to": "will be able to",
   "Would_you_like_to_return_the_inquiry": "Would you like to return the inquiry?",
   "Yes": "Yes",
+  "Yes_archive_it": "Yes, archive it!",
+  "Yes_unarchive_it": "Yes, unarchive it!",
   "Yes_clear_all": "Yes, clear all!",
   "Yes_delete_it": "Yes, delete it!",
   "Yes_hide_it": "Yes, hide it!",
diff --git a/packages/rocketchat-i18n/i18n/es.i18n.json b/packages/rocketchat-i18n/i18n/es.i18n.json
index fa8a8eab08f27805fd0c12e57d19b98ef7805f1b..1c10333a76fc922f2aa85725ef16dba01c23a750 100644
--- a/packages/rocketchat-i18n/i18n/es.i18n.json
+++ b/packages/rocketchat-i18n/i18n/es.i18n.json
@@ -466,10 +466,8 @@
   "Give_a_unique_name_for_the_custom_oauth": "Establezca un nombre único para el oauth personalizado",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Dar a la aplicación un nombre. Esto será visto por los usuarios.",
   "Global": "Global",
-  "GoogleSiteVerification_id": "Verificación de la identificación del sitio de Google",
   "GoogleTagManager_id": "Id Google Administrador de etiquetas",
   "Guest_Pool": "Pool de invitados",
-  "Has_more": "Tiene mas",
   "Hash": "Picadillo",
   "Header": "Encabezamiento",
   "Hidden": "Oculto",
@@ -740,7 +738,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "Robots",
   "minutes": "minutos",
-  "Mobile_push": "Push Mobile",
   "Monitor_history_for_changes_on": "Monitoriza el historial de cambios en",
   "More_channels": "Más canales",
   "More_direct_messages": "Más mensajes directos",
@@ -974,8 +971,6 @@
   "Script_Enabled": "Guión Habilitado",
   "Search": "Buscar",
   "Search_by_username": "Búsqueda por nombre de usuario",
-  "Search_Channels": "Canales de búsqueda",
-  "Search_Direct_Messages": "Buscar mensajes directos",
   "Search_Messages": "Buscar Mensajes",
   "Search_Private_Groups": "Grupos privados",
   "seconds": "segundos",
diff --git a/packages/rocketchat-i18n/i18n/fa.i18n.json b/packages/rocketchat-i18n/i18n/fa.i18n.json
index 4178483bac02a2b4811f45df0a23d0aaabda8d1d..040e0fbb69747d11d8bfcd8d881e95de77358d57 100644
--- a/packages/rocketchat-i18n/i18n/fa.i18n.json
+++ b/packages/rocketchat-i18n/i18n/fa.i18n.json
@@ -446,9 +446,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "یک نام منحصر به فرد برای OAuth حفظ سفارشی",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "به نرم افزار یک نام. این خواهد بود که توسط کاربران شما دیده می شود.",
   "Global": "جهانی",
-  "GoogleSiteVerification_id": "سایت ID تأیید گوگل",
   "GoogleTagManager_id": "گوگل ID مدیر برچسب",
-  "Has_more": "بیشتر داشتن",
   "Hash": "مخلوط",
   "Header": "سربرگ",
   "Hidden": "پنهان",
@@ -706,7 +704,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "روبات",
   "minutes": "دقایق",
-  "Mobile_push": "فشار های تلفن همراه",
   "More_channels": "کانال های بیشتر",
   "More_direct_messages": "پیام های مستقیم بیشتر",
   "More_groups": "گروه بیشتر خصوصی",
@@ -923,8 +920,6 @@
   "Script_Enabled": "اسکریپت فعال",
   "Search": "جستجو کردن",
   "Search_by_username": "جستجو بر اساس نام کاربری",
-  "Search_Channels": "کانال های جستجو",
-  "Search_Direct_Messages": "جستجو پیام های مستقیم",
   "Search_Messages": "پیام های جستجو",
   "Search_Private_Groups": "جستجوی گروه ها شخصی",
   "seconds": "ثانیه",
diff --git a/packages/rocketchat-i18n/i18n/fi.i18n.json b/packages/rocketchat-i18n/i18n/fi.i18n.json
index 605f60c127df0a1942844c82ead76e9efe73f124..2b0f459d43b82c879e547fefa8c6e6f5106fbb9b 100644
--- a/packages/rocketchat-i18n/i18n/fi.i18n.json
+++ b/packages/rocketchat-i18n/i18n/fi.i18n.json
@@ -466,10 +466,8 @@
   "Give_a_unique_name_for_the_custom_oauth": "Anna yksilöllinen nimi mukautettua oauth varten",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Anna sovelluksen nimi. Käyttäjät näkevät tämän.",
   "Global": "Yleinen",
-  "GoogleSiteVerification_id": "Google Site Verification Id",
   "GoogleTagManager_id": "Google Tag Manager Id",
   "Guest_Pool": "Vieraspooli",
-  "Has_more": "Löytyy lisää",
   "Hash": "Hash",
   "Header": "Ylätunniste",
   "Hidden": "Piilotettu",
@@ -741,7 +739,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "Hakurobotit",
   "minutes": "minuuttia",
-  "Mobile_push": "Puhelimen push-ilmoitukset",
   "Monitor_history_for_changes_on": "Tarkastele muutoshistoriaa koskien",
   "More_channels": "Lisää kanavia",
   "More_direct_messages": "Lisää yksityisviestejä",
@@ -972,8 +969,6 @@
   "Script_Enabled": "Skripti käytössä",
   "Search": "Hae",
   "Search_by_username": "Hae käyttäjätunnuksella",
-  "Search_Channels": "Hae kanavia",
-  "Search_Direct_Messages": "Hae yksityisviestejä",
   "Search_Messages": "Hae viestejä",
   "Search_Private_Groups": "Hae yksityisryhmiä",
   "seconds": "sekuntia",
diff --git a/packages/rocketchat-i18n/i18n/fr.i18n.json b/packages/rocketchat-i18n/i18n/fr.i18n.json
index e2c53d0395497a0b0d1ce7475efda18c1b98eae7..b06fe3d961ca62d95f9e57200e5b01b582c8b29a 100644
--- a/packages/rocketchat-i18n/i18n/fr.i18n.json
+++ b/packages/rocketchat-i18n/i18n/fr.i18n.json
@@ -491,10 +491,8 @@
   "Give_a_unique_name_for_the_custom_oauth": "Indiquez un nom unique pour l'OAuth personnalisé",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Donnez un nom à l'application. Il sera visible par les utilisateurs.",
   "Global": "Global",
-  "GoogleSiteVerification_id": "Google Site Vérification Id",
   "GoogleTagManager_id": "Google Tag Manager ID",
   "Guest_Pool": "Invités en attente",
-  "Has_more": "a plus de",
   "Hash": "Hachage",
   "Header": "En-tête",
   "Hidden": "Caché",
@@ -785,7 +783,6 @@
   "Meta_robots": "Robots",
   "Min_length_is": "La longueur minimale est %s",
   "minutes": "minutes",
-  "Mobile_push": "Notifications push sur mobile",
   "Monday": "Lundi",
   "Monitor_history_for_changes_on": "Surveiller l'historique des changements sur",
   "More_channels": "Plus de canaux",
@@ -1026,8 +1023,6 @@
   "Script_Enabled": "Script activé",
   "Search": "Recherche",
   "Search_by_username": "Rechercher par nom d'utilisateur",
-  "Search_Channels": "Recherche de canaux",
-  "Search_Direct_Messages": "Rechercher dans les Messages Privés",
   "Search_Messages": "Rechercher dans les messages",
   "Search_Private_Groups": "Rechercher dans les Groupes Privés",
   "seconds": "secondes",
diff --git a/packages/rocketchat-i18n/i18n/he.i18n.json b/packages/rocketchat-i18n/i18n/he.i18n.json
index 2e1a16486ca12df2110228bcf7e74660b7928234..459b1008f5f8bfc46174c6b47d8b9809a0a9b2e6 100644
--- a/packages/rocketchat-i18n/i18n/he.i18n.json
+++ b/packages/rocketchat-i18n/i18n/he.i18n.json
@@ -1,5 +1,5 @@
 {
-  "0_Errors_Only": "0 - שגיאות רק",
+  "0_Errors_Only": "0 - שגיאות בלבד",
   "1_Errors_and_Information": "1 - טעויות ומידע",
   "2_Erros_Information_and_Debug": "2 - erros, מידע Debug",
   "403": "אסור",
@@ -73,8 +73,8 @@
   "Accounts_OAuth_Google_secret": "סוד גוגל",
   "Accounts_OAuth_Linkedin": "כניסה ל־LinkedIn",
   "Accounts_OAuth_Linkedin_callback_url": "כתובת האתר Callback Linkedin",
-  "Accounts_OAuth_Linkedin_id": "מזהה LinkedIn",
-  "Accounts_OAuth_Linkedin_secret": "סוד LinkedIn",
+  "Accounts_OAuth_Linkedin_id": "מזהה LinkedIn",
+  "Accounts_OAuth_Linkedin_secret": "סוד LinkedIn",
   "Accounts_OAuth_Meteor": "התחברות עם Meteor",
   "Accounts_OAuth_Meteor_callback_url": "כתובת האתר Callback מטאור",
   "Accounts_OAuth_Meteor_id": "מזהה Meteor",
@@ -178,7 +178,7 @@
   "AutoLinker_Urls_www": "כתובות 'www' AutoLinker",
   "AutoLinker_UrlsRegExp": "ביטוי AutoLinker URL רגיל",
   "Available": "זמין",
-  "Available_agents": "סוכני זמין",
+  "Available_agents": "סוכנים זמינים",
   "Avatar": "תמונת פרופיל",
   "Avatar_changed_successfully": "התמונה הוחלפה בהצלחה",
   "Avatar_URL": "כתובת אתר אישי",
@@ -206,7 +206,7 @@
   "by": "על ידי",
   "Cancel": "ביטול",
   "Cancel_message_input": "ביטול",
-  "Cannot_invite_users_to_direct_rooms": "אין אפשרות להזמין משתמשים לכוון חדרים",
+  "Cannot_invite_users_to_direct_rooms": "אין אפשרות להזמין משתמשים לחדרים ישירים",
   "CDN_PREFIX": "תחילית CDN",
   "Certificates_and_Keys": "תעודות ומפתחות",
   "Changing_email": "דוא\"ל שינוי",
@@ -214,7 +214,7 @@
   "Channel_already_exist": "ערוץ '#% s' כבר קיים.",
   "Channel_already_Unarchived": "ערוץ עם השם `#% s` הוא כבר במצב הוצא מהארכיון",
   "Channel_Archived": "ערוץ עם השם `#% s` כבר בארכיון בהצלחה",
-  "Channel_doesnt_exist": "הערוץ `#%s` לא קיים.",
+  "Channel_doesnt_exist": "הערוץ `#%s` לא קיים.",
   "Channel_Unarchived": "ערוץ עם השם `#% s` הוסר מארכיון בהצלחה",
   "Channels": "ערוצים",
   "Channels_list": "רשימת ערוצים ציבוריים",
@@ -267,21 +267,21 @@
   "Date": "תאריך",
   "days": "ימים",
   "DB_Migration": "הגירת מסד נתונים",
-  "DB_Migration_Date": "תאריך הגירה מסד",
+  "DB_Migration_Date": "תאריך הגירת מסד",
   "Deactivate": "הושבת",
   "Default": "בְּרִירַת מֶחדָל",
   "Delete": "מחיקה",
   "Delete_message": "מחיקת הודעה",
   "Delete_my_account": "מחק את חשבוני",
-  "Delete_Room_Warning": "מחיקת חדר יגרום למחיקת כל ההודעות שפורסמו בחדר. פעולה זו מוחלטת.",
-  "Delete_User_Warning": "מחיקת משתמש תמחק את כל הודעותיו, פעולה זו בלתי הפיכה.",
+  "Delete_Room_Warning": "מחיקת חדר יגרום למחיקת כל ההודעות שפורסמו בחדר. פעולה זו בלתי הפיכה.",
+  "Delete_User_Warning": "מחיקת משתמש תמחק את כל הודעותיו. פעולה זו בלתי הפיכה.",
   "Deleted": "נמחק!",
   "Department_removed": "המחלקה הוסרה",
   "Departments": "מחלקות",
   "Deployment_ID": "מזהה פריסה",
   "Description": "תיאור",
   "Desktop": "שולחן עבודה",
-  "Desktop_Notification_Test": "מבחן הודעה Desktop",
+  "Desktop_Notification_Test": "בדיקת הודעה שולחן עבודה",
   "Desktop_Notifications": "התראות בשולחן העבודה",
   "Desktop_Notifications_Disabled": "הודעות עבור שולחן עבודה אינן משופעלות. שנה את הגדרות הדפדפן שלך אם אתה רוצה לשפעל הודעות עבור שולחן עבודה.",
   "Desktop_Notifications_Duration": "משך הודעות",
@@ -300,13 +300,13 @@
   "Duplicate_archived_channel_name": "עם שם ערוץ בארכיון ' %s' קיימת",
   "Duplicate_archived_private_group_name": "קבוצה פרטית בארכיון עם השם ' %s' קיימת",
   "Duplicate_channel_name": "ערוץ עם השם '% s' קיים",
-  "Duplicate_private_group_name": "כבר קיימת קבוצה פרטית בשם ‚%s‘",
+  "Duplicate_private_group_name": "כבר קיימת קבוצה פרטית בשם ‚%s‘",
   "Edit": "עריכה",
-  "Edit_Custom_Field": "שדה מותאם אישית ערוך",
+  "Edit_Custom_Field": "ערוך שדה מותאם אישית",
   "Edit_Department": "עריכת מחלקה",
   "edited": "נערך",
   "Editing_room": "עריכת חדר",
-  "Editing_user": "המשתמש עריכה",
+  "Editing_user": "עריכת משתמש",
   "Email": "דוא״ל",
   "Email_address_to_send_offline_messages": "כתובת דוא\"ל לשלוח הודעות מחוברות",
   "Email_already_exists": "כתובת הדוא״ל כבר קיימת",
@@ -335,11 +335,11 @@
   "Enter_to": "היכנס ל",
   "Error": "שגיאה",
   "error-action-not-allowed": "__action__ אסור",
-  "error-application-not-found": "אפליקציה לא נמצא",
+  "error-application-not-found": "אפליקציה לא נמצאה",
   "error-archived-duplicate-name": "יש ערוץ בארכיון עם השם '__room_name__'",
   "error-avatar-invalid-url": "כתובת אתר אישי לא חוקי: __url__",
   "error-avatar-url-handling": "שגיאה בעת טיפול הגדרה אישית מכתובת URL (__url__) עבור __שם משתמש__",
-  "error-cant-invite-for-direct-room": "לא ניתן להזמין את משתמש לחדרים ישירים",
+  "error-cant-invite-for-direct-room": "לא ניתן להזמין משתמש לחדרים ישירים",
   "error-could-not-change-email": "לא ניתן לשנות את כתובת הדוא\"ל",
   "error-could-not-change-name": "לא ניתן לשנות את השם",
   "error-could-not-change-username": "לא ניתן לשנות את שם המשתמש",
@@ -357,7 +357,7 @@
   "error-invalid-channel": "ערוץ לא חוקי.",
   "error-invalid-channel-start-with-chars": "ערוץ שגוי. יש להתחיל בסימנים @ או #",
   "error-invalid-custom-field": "שדה מותאם אישית לא חוקי",
-  "error-invalid-custom-field-name": "שם שדה מותאם אישית לא חוקי. השתמש רק אותיות, מספרים, מקפים וקווים תחתונים.",
+  "error-invalid-custom-field-name": "שם שדה מותאם אישית לא חוקי. השתמש רק באותיות, מספרים, מקפים וקווים תחתונים.",
   "error-invalid-description": "תיאור שגוי",
   "error-invalid-domain": "תחום לא חוקי",
   "error-invalid-email": "__email__ דוא\"ל לא חוקי",
@@ -370,7 +370,7 @@
   "error-invalid-method": "שיטה שגויה",
   "error-invalid-name": "שם שגוי",
   "error-invalid-password": "סיסמה שגויה",
-  "error-invalid-redirectUri": "חוקי redirectUri",
+  "error-invalid-redirectUri": "לא חוקי redirectUri",
   "error-invalid-role": "תפקיד שגוי",
   "error-invalid-room": "חדר לא חוקי",
   "error-invalid-room-name": "<strong> %s</strong> אינו שם חדר חוקי, <br/> להשתמש אותיות, מספרים, מקפים וקווים תחתונים בלבד",
@@ -400,7 +400,7 @@
   "error-user-not-in-room": "המשתמש אינו בחדר הזה",
   "error-user-registration-disabled": "רישום משתמש מושבת",
   "error-user-registration-secret": "רישום משתמש מותר רק באמצעות כתובת אתר סודית",
-  "error-you-are-last-owner": "אתה הבעלים האחרון. אנא הגדר בעלים חדשים לפני שעזבתי את החדר.",
+  "error-you-are-last-owner": "אתה הבעלים האחרון. אנא הגדר בעלים חדשים לפני שתעזוב את החדר.",
   "Error_changing_password": "הססמה הוחלפה",
   "Esc_to": "צא ל",
   "Example_s": "לדוגמה: <code class=\"inline\">%s</code>",
@@ -410,7 +410,7 @@
   "Features_Enabled": "תכונות מופעלות",
   "Field": "שדה",
   "Field_removed": "שדה הוסר",
-  "File_exceeds_allowed_size_of_bytes": "קובץ עולה על גודל מוותר של בתי __size__",
+  "File_exceeds_allowed_size_of_bytes": "קובץ עולה על גודל מותר של בתים __size__",
   "FileUpload": "העלאת קובץ",
   "FileUpload_Enabled": "העלאת קבצים משופעלת",
   "FileUpload_File_Empty": "קובץ ריק",
@@ -420,7 +420,7 @@
   "FileUpload_MediaTypeWhiteList": "סוגי מדיה מאופשרים",
   "FileUpload_MediaTypeWhiteListDescription": "רשימת סוגי מדיה מופרדים בפסיק. השאר ריק לקבל את כלל סוגי המדיה.",
   "FileUpload_ProtectFiles": "הגנה על קבצים שהועלו",
-  "FileUpload_ProtectFilesDescription": "רק משתמשים מאומתים תהיה גישה",
+  "FileUpload_ProtectFilesDescription": "רק למשתמשים מאומתים תהיה גישה",
   "FileUpload_S3_Acl": "ACL Amazon S3",
   "FileUpload_S3_AWSAccessKeyId": "Amazon S3 AWSAccessKeyId",
   "FileUpload_S3_AWSSecretAccessKey": "Amazon S3 AWSSecretAccessKey",
@@ -444,18 +444,18 @@
   "General": "כללי",
   "github_no_public_email": "אין לך אף כתובת דוא״ל פומבית בחשבון ה־GitHub שלך",
   "Give_a_unique_name_for_the_custom_oauth": "תן שם ייחודי ב-OAuth מותאם אישית",
-  "Give_the_application_a_name_This_will_be_seen_by_your_users": "תן היישום שם. זה ייראה על ידי המשתמשים שלך.",
+  "Give_the_application_a_name_This_will_be_seen_by_your_users": "תן שם ליישום. שם זה יופיע למשתמשיך",
   "Global": "גלוֹבָּלִי",
-  "GoogleSiteVerification_id": "Google Site אימות זיהוי",
   "GoogleTagManager_id": "מנהל התגים של Google Id",
-  "Has_more": "יש עוד",
   "Hash": "בְּלִיל",
   "Header": "כּוֹתֶרֶת",
   "Hidden": "מוּסתָר",
-  "Hide_Group_Warning": "האם אתה בטוח שאתה מעוניין להסתחר את הקבוצה \"%s\"?",
+  "Hide_Avatars": "הסתרת אוואטרים",
+  "Hide_flextab": "הסתרת תפריט ימני בלחיצה",
+  "Hide_Group_Warning": "האם אתה בטוח שאתה מעוניין להסתיר את הקבוצה \"%s\"?",
   "Hide_Private_Warning": "האם אתה בטוח שאתה רוצה להסתיר את הדיון עם \" %s\"?",
   "Hide_room": "להסתיר את החדר",
-  "Hide_Room_Warning": "האם אתה בטוח שאתה רוצה להסתיר בחדר \" %s\"?",
+  "Hide_Room_Warning": "האם אתה בטוח שאתה רוצה להסתיר את חדר \" %s\"?",
   "Hide_usernames": "הסתרת שמות משתמשים",
   "Highlights": "עיקרי הדברים",
   "Highlights_How_To": "כדי לקבל הודעה כאשר מישהו מזכיר את המילה או הביטוי, להוסיף אותו כאן. ניתן להפריד מילים או ביטויים עם פסיקים. מילות דגש אינן תלויות-רישיות.",
@@ -592,13 +592,13 @@
   "LDAP_Host": "מארח",
   "LDAP_Host_Description": "המארח LDAP, למשל `ldap.example.com` או` 10.0.0.30`.",
   "LDAP_Port": "פתחה",
-  "LDAP_Port_Description": "פורט לגישת LDAP. לדוגמה: `389` או `636` עבור LDAPS.",
+  "LDAP_Port_Description": "פורט לגישת LDAP. לדוגמה: `389` או `636` עבור LDAPS.",
   "LDAP_Reject_Unauthorized": "דחית מורשה",
   "LDAP_Sync_User_Avatar": "Sync משתמש אישי",
   "LDAP_Sync_User_Data": "סנכרן מידע",
   "LDAP_Sync_User_Data_Description": "דאג למידע מסונכרן על המשתמש בהתחברות לשרת (שם, אימייל).",
   "LDAP_Sync_User_Data_FieldMap": "מיפוי שדה User Data",
-  "LDAP_Sync_User_Data_FieldMap_Description": "הגדר כיצד שדות חשבון המשתמש (כגון אימייל) ישלפו מרשומת ה-LDAP (כאשר נמצאה).<br/> לדוגמה, `{\"cn\":\"name\", \"mail\":\"email\"}` יבחרו את השם הקריא של המשתמש מהשדה cn והאימייל שלהם מהשדה mail.<br/> השדות האפשריים כוללים  `name`, ו-`email`.",
+  "LDAP_Sync_User_Data_FieldMap_Description": "הגדר כיצד שדות חשבון המשתמש (כגון אימייל) ישלפו מרשומת ה-LDAP (כאשר נמצאה).<br/> לדוגמה, `{\"cn\":\"name\", \"mail\":\"email\"}` יבחרו את השם הקריא של המשתמש מהשדה cn והאימייל שלהם מהשדה mail.<br/> השדות האפשריים כוללים  `name`, ו-`email`.",
   "LDAP_Sync_Users": "משתמשים Sync",
   "LDAP_Test_Connection": "בדיקת חיבור",
   "LDAP_Unique_Identifier_Field": "ייחודיות מזהים שדה",
@@ -635,7 +635,7 @@
   "Log_File": "צג קבצי קו",
   "Log_Level": "רמה התחבר",
   "Log_Package": "חבילת הצג",
-  "Log_View_Limit": "התחבר צפו הגבל",
+  "Log_View_Limit": "הגבלת צפיה בלוג",
   "Logged_out_of_other_clients_successfully": "הביקור האחרון מתוך לקוחות אחרים בהצלחה",
   "Login": "התחברות",
   "Login_with": "כניסה עם %s",
@@ -663,10 +663,10 @@
   "Mentions": "אזכורים",
   "Mentions_default": "אזכורים (ברירת מחדל)",
   "Message": "הודעה",
-  "Message_AllowBadWordsFilter": "אפשר מילים רעות מסר סינון",
+  "Message_AllowBadWordsFilter": "אפשר סינון מילים רעות",
   "Message_AllowDeleting": "לאפשר מחיקת הודעות",
   "Message_AllowDeleting_BlockDeleteInMinutes": "בלוק הודעה מחיק אחרי (n) פרוטוקול",
-  "Message_AllowDeleting_BlockDeleteInMinutes_Description": "זן 0 להשבית חסימה.",
+  "Message_AllowDeleting_BlockDeleteInMinutes_Description": "הזן 0 להשבית חסימה.",
   "Message_AllowEditing": "לאפשר עריכת הודעות",
   "Message_AllowEditing_BlockEditInMinutes": "נעל עריכת הודעה לאחר (n) דקות",
   "Message_AllowEditing_BlockEditInMinutesDescription": "הזן 0 לביטול נעילה.",
@@ -676,14 +676,14 @@
   "Message_AlwaysSearchRegExp": "תמיד לחפש באמצעות RegExp",
   "Message_AlwaysSearchRegExp_Description": "אנו ממליצים להגדיר TRUE אם השפה שלך אינה נתמכת על <a target=\"_blank\" href=\"https://docs.mongodb.org/manual/reference/text-search-languages/#text-search-languages\">חיפוש טקסט MongoDB</a> .",
   "Message_AudioRecorderEnabled": "מקליט אודיו משופעל",
-  "Message_AudioRecorderEnabledDescription": "דורש שקבצי 'audio/wav' יתקבלו בסוגי מדיה בהגדרות 'File Upload'.  ",
+  "Message_AudioRecorderEnabledDescription": "דורש שקבצי 'audio/wav' יתקבלו בסוגי מדיה בהגדרות 'File Upload'.  ",
   "Message_BadWordsFilterList": "להוסיף מילים רעות לרשימה השחורה",
   "Message_BadWordsFilterListDescription": "להוסיף רשימה של רשימה מופרדת בפסיקים של מילים רעות לסנן",
   "Message_DateFormat": "תבנית תאריך",
   "Message_DateFormat_Description": "לעיון נוסף: <a href=\"http://momentjs.com/docs/#/displaying/format/\" target=\"momemt\">Moment.js</a>",
   "Message_deleting_blocked": "הודעה זו לא ניתן למחוק עוד",
   "Message_editing": "עריכת הודעות",
-  "Message_GroupingPeriod": "הקבצה תקופה (בשניות)",
+  "Message_GroupingPeriod": "משך הקבצת הודעה (בשניות)",
   "Message_GroupingPeriodDescription": "הודעות תקובצנה עם הודעה קודמת אם שניהם מאותו משתמש ואת הזמן שהחלף היה פחות הזמן המושכל בשניות.",
   "Message_KeepHistory": "שמירה על היסטוריית הודעות",
   "Message_MaxAll": "ALL גודל ערוץ מקסימאלי עבור הודעה",
@@ -706,7 +706,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "רובוטים",
   "minutes": "דקות",
-  "Mobile_push": "דחיפה ניידת",
   "More_channels": "עוד ערוצים",
   "More_direct_messages": "עוד הודעות ישירות",
   "More_groups": "קבוצות פרטיות נוספות",
@@ -725,42 +724,46 @@
   "Name_optional": "שם (אופציונאלי)",
   "Navigation_History": "ניווט ההיסטוריה",
   "New_Application": "יישום חדש",
-  "New_Custom_Field": "חדש בשדה מותאם אישית",
+  "New_Custom_Field": "שדה מותאם אישית חדש",
   "New_Department": "מחלקה חדשה",
   "New_integration": "שילוב חדש",
   "New_logs": "יומנים חדשים",
-  "New_Message_Notification": "הודעת הודעה חדשה",
+  "New_Message_Notification": "התרעת הודעה חדשה",
   "New_messages": "הודעות חדשות",
   "New_password": "ססמה חדשה",
   "New_role": "תפקיד חדש",
   "New_Room_Notification": "הודעת חדר חדשה",
-  "No_channel_with_name_%s_was_found": "לא נמצא ערוץ עם השם <strong>\"%s\"</strong>!",
+  "No_channel_with_name_%s_was_found": "לא נמצא ערוץ עם השם <strong>\"%s\"</strong>!",
   "No_channels_yet": "אינך חבר באף ערוץ עד כה.",
   "No_direct_messages_yet": "לא התחלת אף שיחה עד כה.",
   "No_Encryption": "ללא הצפנה",
-  "No_group_with_name_%s_was_found": "לא נמצאה קבוצה פרטית עם השם <strong>\"%s\"</strong>!",
+  "No_group_with_name_%s_was_found": "לא נמצאה קבוצה פרטית עם השם <strong>\"%s\"</strong>!",
   "No_groups_yet": "לא קיימות לך קבוצות פרטיות.",
   "No_livechats": "אין לך אף Livechats.",
   "No_mentions_found": "לא נמצאו אזכורים",
   "No_pinned_messages": "אין הודעות מוצמדות",
   "No_results_found": "לא נמצאו תוצאות",
   "No_starred_messages": "אין הודעות מועדפות",
-  "No_user_with_username_%s_was_found": "לא נמצא המשתמש <strong>\"%s\"</strong>!",
+  "No_user_with_username_%s_was_found": "לא נמצא המשתמש <strong>\"%s\"</strong>!",
   "Node_version": "גרסת Node",
+  "Normal": "נורמלי",
   "Not_authorized": "לא מאומת",
   "Not_Available": "לא זמין",
   "Not_found_or_not_allowed": "לא נמצא או שאין לך הרשאה",
   "Nothing": "שום דבר",
   "Nothing_found": "אין תוצאות",
+  "Notification_Duration": "משך התרעה",
   "Notifications": "התרעות",
   "Notify_all_in_this_room": "להודיע לכל מי שבחדר",
+  "Notify_active_in_this_room": "להודיע לכל המחוברים שבחדר",
   "Num_Agents": "סוכני #",
   "Number_of_messages": "מספר הודעות",
   "OAuth_Application": "יישום OAuth",
   "OAuth_Applications": "יישומי OAuth",
   "Objects": "אובייקטים",
-  "Off_the_record_conversation": "Off-the-שיא השיחה",
-  "Off_the_record_conversation_is_not_available_for_your_browser_or_device": "Off-the-שיא השיחה אינה זמינה בדפדפן או במכשיר שלך.",
+  "Off": "לא פועל",
+  "Off_the_record_conversation": "שיחה לא לציטוט",
+  "Off_the_record_conversation_is_not_available_for_your_browser_or_device": "שיחה לא לציטוט אינה זמינה בדפדפן או במכשיר שלך.",
   "Offline": "מנותק",
   "Offline_DM_Email": "קבלת הודעות במשך ישיר על ידי __user__",
   "Offline_form": "טופס מנותק",
@@ -769,6 +772,7 @@
   "Offline_message": "הודעה מנותקת",
   "Offline_success_message": "הודעת הצלחה מנותקת",
   "Offline_unavailable": "זמין מנותק",
+  "On": "פועל",
   "Online": "מחובר",
   "Only_you_can_see_this_message": "רק אתה יכול לראות הודעה זו",
   "Oops!": "אופס",
@@ -820,7 +824,7 @@
   "Please_wait_while_OTR_is_being_established": "אנא המתן בזמן OTR ומוקם",
   "Please_wait_while_your_account_is_being_deleted": "אנא המתן בזמן חשבונך מתבצע מחיקה ...",
   "Please_wait_while_your_profile_is_being_saved": "אנא המתן כאשר הפרופיל שלך חוזר לקדמותו ...",
-  "Port": "פתחה",
+  "Port": "פורט",
   "Post_as": "פרסום בשם",
   "Post_to_Channel": "פרסום לערוץ",
   "Post_to_s_as_s": "פרסום אל <strong>%s</strong> בשם <strong>%s</strong>",
@@ -858,16 +862,19 @@
   "Random": "אקראי",
   "Reacted_with": "הגיבו",
   "Reactions": "תגובות",
+  "Read_only": "קריאה בלבד",
+  "Read_only_changed_successfully": "קריאה בלבד השתנה בהצלחה",
+  "Read_only_channel": "חדר קריאה בלבד",
   "Record": "הקלט",
   "Redirect_URI": "הפניה URI",
-  "Refresh_keys": "מפתחות רעננים",
-  "Refresh_your_page_after_install_to_enable_screen_sharing": "רענן את הדף לאחר להתקין כדי לאפשר שיתוף מסך",
+  "Refresh_keys": "רענן מפתחות",
+  "Refresh_your_page_after_install_to_enable_screen_sharing": "רענן את הדף לאחר התקנה כדי לאפשר שיתוף מסך",
   "Register": "הרשמה עם חשבון חדש",
   "Registration_Succeeded": "הרשמה הצליחה",
   "Release": "מהדורה",
   "Remove": "מחיקה",
   "Remove_Admin": "הסר אדמין",
-  "Remove_as_moderator": "הסר כמו מנחה",
+  "Remove_as_moderator": "הסר כמנחה",
   "Remove_as_owner": "הסר כבעלים",
   "Remove_custom_oauth": "הסר הזדהות OAuth מותאם אישית",
   "Remove_from_room": "הסר מחדר",
@@ -878,18 +885,18 @@
   "Report_sent": "הדוח נשלח",
   "Report_this_message_question_mark": "דווח על הודעה זו?",
   "Require_password_change": "דרוש שינוי סיסמה",
-  "Resend_verification_email": "לשלוח דוא\"ל לאימות",
+  "Resend_verification_email": "לשלוח שוב דוא\"ל לאימות",
   "Reset": "איפוס",
   "Reset_password": "איפוס ססמה",
   "Restart": "הפעלה מחדש",
-  "Restart_the_server": "איפוס השרת",
+  "Restart_the_server": "אתחול השרת",
   "Role": "תפקיד",
   "Role_Editing": "עריכת תפקידים",
   "Role_removed": "התפקיד הוסר",
   "Room": "חדר",
-  "Room_archivation_state": "מְדִינָה",
+  "Room_archivation_state": "מצב",
   "Room_archivation_state_false": "פָּעִיל",
-  "Room_archivation_state_true": "לארכיון",
+  "Room_archivation_state_true": "בארכיון",
   "Room_archived": "חדר בארכיון",
   "room_changed_privacy": "סוג החדר השנה ל:<em>__room_type__</em> ע\"י <em>__user_by__</em>",
   "room_changed_topic": "נושא החדר שונה ל:<em>__room_topic__</em> ע\"י <em>__user_by__</em>",
@@ -923,8 +930,6 @@
   "Script_Enabled": "מאופשר סקריפט",
   "Search": "חיפוש",
   "Search_by_username": "חיפוש לפי שם משתמש",
-  "Search_Channels": "ערוצי חיפוש",
-  "Search_Direct_Messages": "חפש בהודעות ישירות",
   "Search_Messages": "חיפוש בהודעות",
   "Search_Private_Groups": "חיפוש בקבוצות פרטיות",
   "seconds": "שניות",
@@ -948,21 +953,21 @@
   "Send_invitation_email_info": "ניתן לשלוח הזמנות מרובות באימייל בפעם אחת",
   "Send_invitation_email_success": "שלחת בהצלחה הזמנה באמצעות אימייל לכתובות הבאות:",
   "Send_request_on_chat_close": "לפנות לסוכן על קרוב צ'אט",
-  "Send_request_on_offline_messages": "לפנות לסוכן על הודעות מחוברות",
+  "Send_request_on_offline_messages": "לפנות לסוכן על הודעות לא מחוברות",
   "Send_Test": "שלח מבחן",
   "Send_welcome_email": "שליחת דוא״ל קבלת פנים",
   "Send_your_JSON_payloads_to_this_URL": "שלח מטעני JSON שלך לכתובת אתר זו.",
   "Sending": "שְׁלִיחָה...",
   "Service": "שירות",
-  "Set_as_moderator": "Set as מנחה",
-  "Set_as_owner": "גדר כבעלים",
+  "Set_as_moderator": "הגדר כמנחה",
+  "Set_as_owner": "הגדר כבעלים",
   "Settings": "הגדרות",
   "Settings_updated": "ההגדרות עודכנו",
   "Should_be_a_URL_of_an_image": "צריך להיות כתובת אתר של תמונה.",
   "Should_exists_a_user_with_this_username": "המשתמש חייב להיות קיים.",
   "Show_all": "הצג הכול",
   "Show_more": "הראה עוד",
-  "Show_only_online": "הצג רק באינטרנט",
+  "Show_only_online": "הצג רק מחוברים",
   "Show_preregistration_form": "צג טופס הרשמה מראש",
   "Showing_archived_results": "<p style=\";text-align:right;direction:rtl\"> מציג תוצאות <b>בארכיון %s</b> </p>",
   "Showing_online_users": "מציג <b>__total_showing__</b> מתוך __total__ משתמשים",
@@ -982,9 +987,9 @@
   "Smileys_and_People": "סמיילים & אנשים",
   "SMS_Enabled": "SMS מופעל",
   "SMTP": "SMTP",
-  "SMTP_Host": "מארח ",
+  "SMTP_Host": "מארח ",
   "SMTP_Password": "ססמה ל־",
-  "SMTP_Port": "פתחת SMTP",
+  "SMTP_Port": "פורט SMTP",
   "SMTP_Test_Button": "הגדרות SMTP מבחן",
   "SMTP_Username": "שם משתמש ב־SMTP",
   "Sound": "שמע",
@@ -1028,7 +1033,7 @@
   "Sync_Users": "משתמשים Sync",
   "Tag": "תָג",
   "Test_Connection": "בדיקת חיבור",
-  "Test_Desktop_Notifications": "הודעות בשולחן העבודה מבחן",
+  "Test_Desktop_Notifications": "בדיקת הודעות בשולחן עבודה",
   "Thank_you_exclamation_mark": "תודה רבה!",
   "Thank_you_for_your_feedback": "תודה לך על המשוב",
   "The_application_name_is_required": "שם האפליקציה נדרש",
@@ -1037,7 +1042,7 @@
   "The_field_is_required": "השדה %s הוא חובה.",
   "The_image_resize_will_not_work_because_we_can_not_detect_ImageMagick_or_GraphicsMagick_installed_in_your_server": "שינוי גודל התמונה לא יעבוד כי אנחנו לא יכולים לזהות ImageMagick או GraphicsMagick מותקן על השרת שלך.",
   "The_redirectUri_is_required": "RedirectUri נדרש",
-  "The_server_will_restart_in_s_seconds": "השרת יפעיל את עצמו מחדש בעוד ",
+  "The_server_will_restart_in_s_seconds": "השרת יפעיל את עצמו מחדש בעוד ",
   "The_setting_s_is_configured_to_s_and_you_are_accessing_from_s": "ה- <strong>S הגדרת%</strong> <strong>מוגדר %s</strong> ואתה ניגש <strong>מ %s!</strong>",
   "The_user_will_be_removed_from_s": "המשתמש יוסר %s",
   "The_user_wont_be_able_to_type_in_s": "המשתמש לא יוכל להקליד %s",
@@ -1047,7 +1052,7 @@
   "theme-color-primary-font-color": "צבע פונט ראשי",
   "theme-color-secondary-background-color": "צבע רקע משני",
   "theme-color-secondary-font-color": "צבע פונט משני",
-  "theme-color-tertiary-background-color": "צבע סטטוס ",
+  "theme-color-tertiary-background-color": "צבע סטטוס ",
   "theme-color-tertiary-font-color": "צבע פונט שלישי",
   "theme-color-link-font-color": "צבע פונט של לינק",
   "theme-color-info-font-color": "צבע של פונט Info",
@@ -1058,10 +1063,10 @@
   "theme-color-status-online": "צבע סטטוס זמין",
   "theme-color-unread-notification-color": "צבע הודעות שלא נקראו",
   "theme-custom-css": "CSS בהתאמה אישית",
-  "There_are_no_agents_added_to_this_department_yet": "אין סוכנים הוסיף למחלקה זו עדיין.",
+  "There_are_no_agents_added_to_this_department_yet": "אין סוכנים שנוספו למחלקה זו עדיין.",
   "There_are_no_integrations": "אין ואינטגרציות",
   "There_are_no_users_in_this_role": "אין משתמשים בתפקיד זה.",
-  "This_email_has_already_been_used_and_has_not_been_verified__Please_change_your_password": "דוא\"ל זה כבר נעשה שימוש ולא אומת. שנה את הסיסמה שלך.",
+  "This_email_has_already_been_used_and_has_not_been_verified__Please_change_your_password": "בדוא\"ל זה כבר נעשה שימוש והוא לא אומת. שנה את הסיסמה שלך.",
   "This_is_a_desktop_notification": "זוהי הודעת שולחן עבודה",
   "This_is_a_push_test_messsage": "זוהי הודעת בדיקה של ה-push",
   "This_room_has_been_archived_by__username_": "חדר זה כבר בארכיון ידי __שם משתמש__",
@@ -1088,10 +1093,11 @@
   "UI_DisplayRoles": "תפקידי תצוגה",
   "UI_Merge_Channels_Groups": "מיזוג קבוצות פרטיות עם ערוצים",
   "Unarchive": "הוצאה מארכיון",
-  "Unmute_someone_in_room": "מישהו לבטל את ההשתקה בחדר",
-  "Unmute_user": "המשתמש לבטל את ההשתקה",
+  "Unmute_someone_in_room": "ביטול השתקה עבור מישהו בחדר",
+  "Unmute_user": "בטל השתקת משתמש",
   "Unnamed": "ללא שם",
   "Unpin_Message": "שחרור הודעה",
+  "Unread_Alert": "התרעה על לא נקרא",
   "Unread_Rooms": "חדרים שלא נקראו",
   "Unread_Rooms_Mode": "מצב חדרים שלא נקראו",
   "Unstar_Message": "הסר ממועדפים",
@@ -1099,13 +1105,15 @@
   "Uploading_file": "מעלה קובץ...",
   "Uptime": "uptime",
   "URL": "כתובת האתר",
-  "Use_account_preference": "השתמש העדפת חשבון",
+  "Use_account_preference": "השתמש בהעדפת חשבון",
   "Use_Emojis": "שימוש באימוג׳י",
+  "Use_Global_Settings": "השתמש בהגדרות ברירת מחדל",
   "Use_initials_avatar": "שימוש בראשי התיבות של שם המשתמש שלך",
   "Use_service_avatar": "שימוש בתמונה מ־%s",
   "Use_this_username": "יש להשתמש בשם המשתמש הזה",
   "Use_uploaded_avatar": "שימוש בתמונה שהועלתה",
   "Use_url_for_avatar": "השתמש ב-url עבור תמונת הפרופיל",
+  "Use_User_Preferences_or_Global_Settings": "השתמש בהגדרות משתמש או הגדרות ברירת מחדל",
   "User__username__is_now_a_moderator_of__room_name_": "__שם משתמש__ המשתמש עכשיו מנחה של __room_name__",
   "User__username__is_now_a_owner_of__room_name_": "__שם משתמש__ המשתמש עכשיו בעלים של __room_name__",
   "User__username__removed_from__room_name__moderators": "__שם משתמש__ המשתמש הוסר ממפקחי __room_name__",
@@ -1113,7 +1121,7 @@
   "User_added": "המשתמש נוסף.",
   "User_added_by": "המשתמש <em>__user_added__</em> נוסף על ידי <em>__user_by__</em>",
   "User_added_successfully": "משתמש נוסף בהצלחה",
-  "User_doesnt_exist": "אף משתמש לא קיים בשם `@%s`.",
+  "User_doesnt_exist": "אף משתמש לא קיים בשם `@%s`.",
   "User_has_been_activated": "המשתמש הופעל",
   "User_has_been_deactivated": "המשתמש נוטרל",
   "User_has_been_deleted": "המשתמש הוסר",
@@ -1141,7 +1149,7 @@
   "User_unmuted_in_room": "משתמש ההשתקה בחדר",
   "User_updated_successfully": "המשתמש עודכן בהצלחה",
   "Username": "שם משתמש",
-  "Username_and_message_must_not_be_empty": "שם משתמש הודעה לא יכולים להיות ריקים.",
+  "Username_and_message_must_not_be_empty": "שם משתמש והודעה לא יכולים להיות ריקים.",
   "Username_cant_be_empty": "יש להזין שם משתמש",
   "Username_Change_Disabled": "מנהל המערכת שלך ביטל את האפשרות לשנות שמות משתמשים",
   "Username_denied_the_OTR_session": "__שם משתמש__ הכחיש את הפגישה OTR",
@@ -1190,11 +1198,11 @@
   "Why_do_you_want_to_report_question_mark": "מדוע ברצונך לדווח?",
   "will_be_able_to": "תוכל",
   "Yes": "כן",
-  "Yes_clear_all": "כן, הכל נוקה!",
+  "Yes_clear_all": "כן, נקה הכל!",
   "Yes_delete_it": "כן, למחוק אותה!",
   "Yes_hide_it": "כן, להסתיר את זה!",
   "Yes_leave_it": "כן, להשאיר אותו!",
-  "Yes_mute_user": "כן, המשתמש אילם!",
+  "Yes_mute_user": "כן, השתק משתמש!",
   "Yes_remove_user": "כן, להסיר את המשתמש!",
   "You": "אתה",
   "you_are_in_preview_mode_of": "You are in preview mode of channel #<strong>__room_name__</strong>",
@@ -1206,20 +1214,20 @@
   "You_can_use_webhooks_to_easily_integrate_livechat_with_your_CRM": "אתה יכול להשתמש webhooks לשלב LiveChat בקלות עם CRM שלך.",
   "You_cant_leave_a_livechat_room_Please_use_the_close_button": "אתה לא יכול להשאיר בחדר LiveChat. אנא, השתמש בלחצן הסגירה.",
   "You_have_been_muted": "אתה הושתקת ולא יכול לדבר בחדר הזה",
-  "You_have_not_verified_your_email": "לא אימת הדוא\"ל שלך.",
+  "You_have_not_verified_your_email": "לא אימתת הדוא\"ל שלך.",
   "You_have_successfully_unsubscribed": "הוסרת מרשימת התפוצה בהצלחה.",
   "You_need_confirm_email": "עליך לאמת את כתובת הדוא״ל על מנת להתחבר!",
   "You_need_install_an_extension_to_allow_screen_sharing": "צריך להתקין הרחבה כדי לאפשר שיתוף מסך",
   "You_need_to_change_your_password": "אתה צריך לשנות את הסיסמא שלך",
   "You_need_to_type_in_your_password_in_order_to_do_this": "אתה צריך להקליד את הסיסמה שלך על מנת לעשות זאת!",
   "You_need_to_type_in_your_username_in_order_to_do_this": "אתה צריך להקליד את שם המשתמש שלך כדי לעשות את זה!",
-  "You_need_to_verifiy_your_email_address_to_get_notications": "אתה צריך verifiy כתובת הדוא\"ל שלך כדי לקבל הודעות",
+  "You_need_to_verifiy_your_email_address_to_get_notications": "אתה צריך לאמת את כתובת הדוא\"ל שלך כדי לקבל הודעות",
   "You_need_to_write_something": "עליך לכתוב משהו!",
   "You_should_inform_one_url_at_least": "עליך להגדיר כתובת אחת לפחות.",
   "You_should_name_it_to_easily_manage_your_integrations": "אתה צריך שם את זה כדי לנהל ואינטגרציות שלך בקלות.",
   "You_will_not_be_able_to_recover": "לא תהיה לך אפשרות לשחזר את ההודעה הזו!",
   "You_will_not_be_able_to_recover_file": "אתה לא תוכל לשחזר קובץ זה!",
-  "You_wont_receive_email_notifications_because_you_have_not_verified_your_email": "לא תקבל הודעות דוא\"ל, כי אתה לא מאומת הדוא\"ל שלך.",
+  "You_wont_receive_email_notifications_because_you_have_not_verified_your_email": "לא תקבל הודעות דוא\"ל, כי לא אימתת הדוא\"ל שלך.",
   "Your_email_has_been_queued_for_sending": "הדוא\"ל שלך נוסף לתור לשליחה",
   "Your_entry_has_been_deleted": "הרשומה שלך נמחקה",
   "Your_file_has_been_deleted": "הקובץ שלך נמחק.",
diff --git a/packages/rocketchat-i18n/i18n/hr.i18n.json b/packages/rocketchat-i18n/i18n/hr.i18n.json
index f83f6ffdc93a060b40f72dcb97af6e925b6be2ce..36e241e06ed8797e492c1681e8fa1b2442553457 100644
--- a/packages/rocketchat-i18n/i18n/hr.i18n.json
+++ b/packages/rocketchat-i18n/i18n/hr.i18n.json
@@ -41,6 +41,7 @@
   "Accounts_Enrollment_Email_Default": "<h2> Dobrodošli u </h2><h1> [Site_Name] </h1><p> Idite na [Site_URL] i pokušajte najbolje open source chat rješenje danas! </p>",
   "Accounts_Enrollment_Email_Description": "Možete koristiti sljedeće oznake: <br/><ul><li>[name], [fname], [lname] za korisničko ime, ime te prezime.</li><li>[email] za korisnikov email.</li><li>[Site_Name] i [Site_URL] za naziv aplikacije i URL.\n</li></ul> ",
   "Accounts_Enrollment_Email_Subject_Default": "Dobro došli na [Site_Name]",
+  "Accounts_ForgetUserSessionOnWindowClose": "Zaboravi korisnikovu prijavu pri zatvaranju prozora",
   "Accounts_Iframe_api_method": "API metoda",
   "Accounts_Iframe_api_url": "Api Url",
   "Accounts_iframe_enabled": "Omogućeno",
@@ -55,10 +56,12 @@
   "Accounts_OAuth_Custom_id": "Id",
   "Accounts_OAuth_Custom_Identity_Path": "Put identiteta",
   "Accounts_OAuth_Custom_Login_Style": "Stil Prijave",
+  "Accounts_OAuth_Custom_Merge_Users": "Spoji korisnike",
   "Accounts_OAuth_Custom_Scope": "Å irina zahtjeva",
   "Accounts_OAuth_Custom_Secret": "Tajna",
   "Accounts_OAuth_Custom_Token_Path": "Putanja Tokena",
   "Accounts_OAuth_Custom_Token_Sent_Via": "Token poslan putem",
+  "Accounts_OAuth_Custom_Username_Field": "Polje korisničkog imena",
   "Accounts_OAuth_Facebook": "Facebook prijava",
   "Accounts_OAuth_Facebook_callback_url": "URL povratnog poziva Facebook",
   "Accounts_OAuth_Facebook_id": "ID aplikacije Facebook",
@@ -106,6 +109,8 @@
   "Accounts_RegistrationForm_SecretURL_Description": "Morate navesti nasumični niz znakova koji će biti dodan u vašu registracijski URL. Na primjer: https://demo.rocket.chat/register/[secret_hash]",
   "Accounts_RequireNameForSignUp": "Zahtijevaj ime pri prijavi",
   "Accounts_RequirePasswordConfirmation": "Zahtjevaj potvrdu lozinke",
+  "Accounts_SetDefaultAvatar": "Namjesti zadani Avatar",
+  "Accounts_SetDefaultAvatar_Description": "Pokušava odrediti zadani avatar prema OAuth računu ili Gravataru",
   "Accounts_ShowFormLogin": "Prikaži obrazac za prijavu",
   "Accounts_UseDefaultBlockedDomainsList": "Koristi zadanu listu blokiranih domena",
   "Accounts_UseDNSDomainCheck": "Koristi DNS provjeru domena",
@@ -141,6 +146,7 @@
   "All_messages": "Sve poruke",
   "Allow_Invalid_SelfSigned_Certs": "Dopusti neispravne samopotpisane certifikate",
   "Allow_Invalid_SelfSigned_Certs_Description": "Dopusti nevažeće i samopotpisane SSL certifikate za poveznicu validacije i pretpregleda.",
+  "Always_open_in_new_window": "Uvijek otvori u novom prozoru",
   "Analytics_features_enabled": "Omogućene značajke",
   "Analytics_features_messages_Description": "Prati prilagođene događaje vezane za postupke korisnika na porukama.",
   "Analytics_features_rooms_Description": "Prati prilagođene događanja vezana za aktivnosti u sobu ili grupi (stvaranje, napuštanje, brisanje).",
@@ -211,6 +217,7 @@
   "Back_to_integrations": "Povratak na integracije",
   "Back_to_login": "Natrag na prijavu",
   "Back_to_permissions": "Povratak na dozvole",
+  "Block_User": "Blokiraj korisnika",
   "Body": "Tijelo",
   "bold": "podebljaj",
   "bot_request": "Bot zahtjev",
@@ -224,9 +231,11 @@
   "busy_male": "zauzet",
   "Busy_male": "Zauzet",
   "by": "od",
+  "cache_cleared": "Predmemorija očišćena",
   "Cancel": "Otkaži",
   "Cancel_message_input": "Otkaži",
   "Cannot_invite_users_to_direct_rooms": "Ne mogu pozvati korisnike da izravne sobe",
+  "CAS_autoclose": "Automatski zatvori prijavni prozor",
   "CAS_button_color": "Pozadinska boja gumba za prijavu",
   "CAS_button_label_color": "Boja teksta gumba za prijavu",
   "CAS_enabled": "Omogućeno",
@@ -253,6 +262,8 @@
   "Choose_messages": "Odaberite poruke",
   "Choose_the_alias_that_will_appear_before_the_username_in_messages": "Odaberite pseudonim koji će se pojaviti pred korisničko ime u porukama.",
   "Choose_the_username_that_this_integration_will_post_as": "Odaberite korisničko ime za koje će ova integracija objavljivati.",
+  "clear": "Očisti",
+  "clear_cache_now": "Očisti sada predmemoriju",
   "Clear_all_unreads_question": "Očisti sve nepročitane?",
   "Click_here": "Kliknite ovdje",
   "Client_ID": "ID klijenta",
@@ -303,6 +314,8 @@
   "Custom_Translations_Description": "Treba biti ispravan JSON gdje su ključevi jezici koji zadrže riječnik ključeva i prijevoda. Npr: \n <code>{\n \"en\": {\n  \"key\": \"translation\"\n },\n \"pt\": {\n  \"key\": \"tradução\"\n }\n}</code>",
   "Dashboard": "Kontrolna ploča",
   "Date": "Datum",
+  "Date_From": "Od",
+  "Date_to": "za",
   "days": "dana",
   "DB_Migration": "Baza podataka migracija",
   "DB_Migration_Date": "Datum migracije baze",
@@ -334,6 +347,7 @@
   "Do_you_want_to_change_to_s_question": "Želite li promijeniti na <strong> %s?</strong>",
   "Domain": "Domena",
   "Domains": "Domene",
+  "Download_Snippet": "Preuzmi",
   "Drop_to_upload_file": "Ispusti datoteku kako bi ju prenio",
   "Dry_run": "Testno pokretanje",
   "Dry_run_description": "Poslat ćemo samo jedan email, istoj adresi koja je u Od polju. Email mora pripadati postojećem korisniku.",
@@ -401,11 +415,13 @@
   "error-invalid-channel-start-with-chars": "Nevažeća soba. Počnite s @ ili #",
   "error-invalid-custom-field": "Nevažeće prilagođeno polje",
   "error-invalid-custom-field-name": "Neispravan naziv prilagođenog polje. Koristite samo slova, brojeve, crtice i podvlake.",
+  "error-invalid-date": "Pogrešan datum.",
   "error-invalid-description": "Nevažeći opis",
   "error-invalid-domain": "Domena nije valjana",
   "error-invalid-email": "Pogrešan __email__ email",
   "error-invalid-file-height": "Neispravna visina datoteke",
   "error-invalid-file-type": "Pogrešna vrsta datoteke",
+  "error-direct-message-file-upload-not-allowed": "Dijeljenje datoteka nije dozvoljeno u direktnim porukama",
   "error-invalid-file-width": "Pogrešna širina datoteke",
   "error-invalid-from-address": "Unijeta je kriva OD adresa",
   "error-invalid-integration": "Pogrešna integracija",
@@ -460,9 +476,12 @@
   "Field_removed": "Polje je uklonjeno",
   "Field_required": "Polje je obavezno",
   "File_exceeds_allowed_size_of_bytes": "Datoteka premašuje dopuštenu veličinu __size__.",
+  "File_not_allowed_direct_messages": "Dijeljenje datoteka nije dozvoljeno u direktnim porukama",
   "File_type_is_not_accepted": "Tip datoteke nije prihvaćen",
   "FileUpload": "Prijenos datoteke",
   "FileUpload_Enabled": "Prijenos Datoteka Omogućeno",
+  "FileUpload_Disabled": "Prijenosi datoteka su onemogućeni",
+  "FileUpload_Enabled_Direct": "Prijenos datoteka u direktnim porukama",
   "FileUpload_File_Empty": "Prazna datoteka",
   "FileUpload_FileSystemPath": "Odredište u sustavu",
   "FileUpload_MaxFileSize": "Maksimalna  Veličina Prenijete Datoteke (u bajtovima)",
@@ -503,10 +522,8 @@
   "Give_a_unique_name_for_the_custom_oauth": "Daj jedinstveno ime prilagođenom OAuth",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Dajte ime aplikaciji. To će korisnici vidjeti.",
   "Global": "Globalno",
-  "GoogleSiteVerification_id": "Google Site verifikacijski Id",
   "GoogleTagManager_id": "Google Tag Manager Id",
   "Guest_Pool": "Popis gostiju",
-  "Has_more": "Ima više",
   "Hash": "Hash",
   "Header": "Zaglavlje",
   "Hidden": "Skriveno",
@@ -543,7 +560,7 @@
   "Importer_Archived": "Arhivirano",
   "Importer_done": "Uvoz dovršen!",
   "Importer_finishing": "Završavanje uvoza.",
-  "Importer_From_Description": "Uvozi __from __  podatke u Rocket.Chat.",
+  "Importer_From_Description": "Uvezi __from __  podatke u Rocket.Chat.",
   "Importer_import_cancelled": "Uvoz je otkazan.",
   "Importer_import_failed": "Došlo je do pogreške pri izvršavanju uvoza.",
   "Importer_importing_channels": "Prebacivanje kanala.",
@@ -798,7 +815,6 @@
   "Meta_robots": "Roboti",
   "Min_length_is": "Minimalna dužina je %s",
   "minutes": "minuta",
-  "Mobile_push": "Mobilne push obavijesti",
   "Monday": "Ponedjeljak",
   "Monitor_history_for_changes_on": "Prati povijest za promjena na",
   "More_channels": "Više kanala",
@@ -1045,8 +1061,6 @@
   "Script_Enabled": "Skripta Omogućena",
   "Search": "Traži",
   "Search_by_username": "Pretraživanje po korisničkom imenu",
-  "Search_Channels": "Pretraži Kanale",
-  "Search_Direct_Messages": "Traži izravne poruke",
   "Search_Messages": "Pretraži poruke",
   "Search_Private_Groups": "Traži privatne grupe",
   "seconds": "sekunde",
@@ -1303,7 +1317,7 @@
   "Users_in_role": "Korisnici u ulozi",
   "UTF8_Names_Slugify": "UTF8 Imena Slugify",
   "UTF8_Names_Validation": "UTF8 Provjera Imena",
-  "UTF8_Names_Validation_Description": "Nemojte dopustiti posebne znakove i razmake. Možete koristiti - _ i . ali ne i na kraju imena",
+  "UTF8_Names_Validation_Description": "RegExp koji će biti korišten za provjeru korisničkih imena i imena soba",
   "Verification_email_sent": "Provjera e-maila poslana",
   "Verified": "Ovjeren",
   "Version": "Verzija",
diff --git a/packages/rocketchat-i18n/i18n/hu.i18n.json b/packages/rocketchat-i18n/i18n/hu.i18n.json
index c3add36993c39ae2f9dd47d9b8e41f088fb9e0ce..9a1c4837bac65be04174fff7daca8f0bb54e6c2f 100644
--- a/packages/rocketchat-i18n/i18n/hu.i18n.json
+++ b/packages/rocketchat-i18n/i18n/hu.i18n.json
@@ -447,9 +447,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "Adj egy egyedi nevet az egyéni OAuth",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Adjon az alkalmazás nevét. Ez látható lesz az Ön számára.",
   "Global": "Globális",
-  "GoogleSiteVerification_id": "Google Webhelyellenőrző Id",
   "GoogleTagManager_id": "Google Címkekezelő Id",
-  "Has_more": "több",
   "Hash": "hash",
   "Header": "Fejléc",
   "Hidden": "Rejtett",
@@ -707,7 +705,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "robotok",
   "minutes": "percek",
-  "Mobile_push": "Mobile push-",
   "More_channels": "Még több csatorna",
   "More_direct_messages": "Több közvetlen üzenetek",
   "More_groups": "Több privát csoport",
@@ -924,8 +921,6 @@
   "Script_Enabled": "Script engedélyezve",
   "Search": "Keresés",
   "Search_by_username": "Keresés felhasználónév",
-  "Search_Channels": "Keresés Csatornák",
-  "Search_Direct_Messages": "Keresés közvetlen üzenetek",
   "Search_Messages": "Üzenetek keresése",
   "Search_Private_Groups": "Keresés Privát Csoportok",
   "seconds": "másodperc",
diff --git a/packages/rocketchat-i18n/i18n/id.i18n.json b/packages/rocketchat-i18n/i18n/id.i18n.json
index 27e5cd281bbe92219f570b4def2ef4fbc164b209..c41f59d8ca82474050b926e05feea905f019c271 100644
--- a/packages/rocketchat-i18n/i18n/id.i18n.json
+++ b/packages/rocketchat-i18n/i18n/id.i18n.json
@@ -446,9 +446,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "Berikan nama unik untuk kustom oauth",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Memberikan aplikasi nama. Ini akan terlihat oleh pengguna Anda.",
   "Global": "Global",
-  "GoogleSiteVerification_id": "Situs Verifikasi Id Google",
   "GoogleTagManager_id": "Google Id Pengelola Tag",
-  "Has_more": "Ada lebih lanjut",
   "Hash": "hash",
   "Header": "Header",
   "Hidden": "Tersembunyi",
@@ -706,7 +704,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "Robots",
   "minutes": "menit",
-  "Mobile_push": "mobile push",
   "More_channels": "Lebih lanjut channel",
   "More_direct_messages": "pesan lebih langsung",
   "More_groups": "Grup Privat lebih lanjut",
@@ -923,8 +920,6 @@
   "Script_Enabled": "Script Diaktifkan",
   "Search": "Pencarian",
   "Search_by_username": "Cari berdasarkan nama",
-  "Search_Channels": "Cari Saluran",
-  "Search_Direct_Messages": "Cari Pesan Langsung",
   "Search_Messages": "Pencarian di Pesan",
   "Search_Private_Groups": "Cari Grup Swasta",
   "seconds": "detik",
diff --git a/packages/rocketchat-i18n/i18n/it.i18n.json b/packages/rocketchat-i18n/i18n/it.i18n.json
index 8d01c5dbb8d9d460c69e3463d5093b49345f7291..9771a6653c974ab6a7d17d0636a86e93d2816b00 100644
--- a/packages/rocketchat-i18n/i18n/it.i18n.json
+++ b/packages/rocketchat-i18n/i18n/it.i18n.json
@@ -500,10 +500,8 @@
   "Give_a_unique_name_for_the_custom_oauth": "Dai un nome univoco per OAuth personalizzato",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Dai un nome all'applicazione. Sarà visibile agli utenti.",
   "Global": "Globale",
-  "GoogleSiteVerification_id": "Google Site Verification Id",
   "GoogleTagManager_id": "Google Tag Manager Id",
   "Guest_Pool": "Stanza ospiti",
-  "Has_more": "Ha di più",
   "Hash": "Hash",
   "Header": "Header",
   "Hidden": "Nascosto",
@@ -813,7 +811,6 @@
   "Meta_robots": "Robots",
   "Min_length_is": "nghezza minima é %s",
   "minutes": "minuti",
-  "Mobile_push": "Notifiche Push",
   "Monday": "Lunedì",
   "Monitor_history_for_changes_on": "Osserva lo storico per le modifiche su",
   "More_channels": "Piu canali",
@@ -1062,8 +1059,6 @@
   "Script_Enabled": "Abilita Script ",
   "Search": "Cerca",
   "Search_by_username": "Cerca per nome utente",
-  "Search_Channels": "Ricerca Canali",
-  "Search_Direct_Messages": "Cerca messaggi diretti",
   "Search_Messages": "Cerca Messaggi",
   "Search_Private_Groups": "Ricerca gruppi privati",
   "seconds": "secondi",
diff --git a/packages/rocketchat-i18n/i18n/ja.i18n.json b/packages/rocketchat-i18n/i18n/ja.i18n.json
index 8d474fe708a8fd833d6acf2625699cff923476e0..8cc4b4e22f4ef63c61d1718ad5446aeb098db92c 100644
--- a/packages/rocketchat-i18n/i18n/ja.i18n.json
+++ b/packages/rocketchat-i18n/i18n/ja.i18n.json
@@ -449,9 +449,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "カスタム OAuth の一意な名前を入力してください",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "アプリケーション名を入力してください。この名前はユーザーに表示されます。",
   "Global": "グローバル",
-  "GoogleSiteVerification_id": "Googleサイトの確認同上",
   "GoogleTagManager_id": "Google タグマネージャー ID",
-  "Has_more": "さらにあります",
   "Hash": "ハッシュ",
   "Header": "ヘッダ",
   "Hidden": "非表示中",
@@ -713,7 +711,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "robots属性",
   "minutes": "分",
-  "Mobile_push": "モバイルプッシュ通知",
   "Monitor_history_for_changes_on": "履歴の変更を監視する",
   "More_channels": "その他のチャンネル",
   "More_direct_messages": "その他のダイレクトメッセージ",
@@ -939,8 +936,6 @@
   "Script_Enabled": "スクリプトを有効にする",
   "Search": "検索",
   "Search_by_username": "ユーザー名で検索",
-  "Search_Channels": "チャンネルを検索",
-  "Search_Direct_Messages": "ダイレクトメッセージを検索",
   "Search_Messages": "メッセージを検索",
   "Search_Private_Groups": "プライベートグループを検索",
   "seconds": "ç§’",
diff --git a/packages/rocketchat-i18n/i18n/km.i18n.json b/packages/rocketchat-i18n/i18n/km.i18n.json
index 0f15b6e2c59d5cbe6f844813c15f990161941906..2374ff4d1139cf1e90478811edd9482b0af74c8c 100644
--- a/packages/rocketchat-i18n/i18n/km.i18n.json
+++ b/packages/rocketchat-i18n/i18n/km.i18n.json
@@ -446,9 +446,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "ផ្តល់​ឱ្យ​ឈ្មោះ​តែ​មួយ​គត់​សម្រាប់ oauth ផ្ទាល់​ខ្លួន",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "ផ្តល់ឱ្យកម្មវិធីនេះមានឈ្មោះមួយ។ នេះនឹងត្រូវបានគេមើលឃើញដោយអ្នកប្រើរបស់អ្នក។",
   "Global": "សកល",
-  "GoogleSiteVerification_id": "ការផ្ទៀងផ្ទាត់លេខសម្គាល់របស់ Google តំបន់បណ្តាញ",
   "GoogleTagManager_id": "ការគ្រប់គ្រងស្លាកលេខសម្គាល់របស់ Google",
-  "Has_more": "សញ្ញា Has ច្រើនទៀត",
   "Hash": "ហាស់",
   "Header": "បឋមកថា",
   "Hidden": "លាក់",
@@ -706,7 +704,6 @@
   "Meta_msvalidate01": "កូដ MSValidate.01",
   "Meta_robots": "មនុស្ស​យន្ត",
   "minutes": "នាទី",
-  "Mobile_push": "ការជំរុញទូរស័ព្ទដៃ",
   "More_channels": "ប៉ុស្តិ៍​ច្រើន​ទៀត",
   "More_direct_messages": "សារដោយផ្ទាល់",
   "More_groups": "ក្រុមឯកជនច្រើនទៀត",
@@ -923,8 +920,6 @@
   "Script_Enabled": "ស្គ្រីបបានអនុញ្ញាត",
   "Search": "ស្វែង​រក",
   "Search_by_username": "ការស្វែងរកដោយប្រើឈ្មោះអ្នកប្រើ",
-  "Search_Channels": "ស្វែងរកឆានែល",
-  "Search_Direct_Messages": "ស្វែងរកសារដោយផ្ទាល់",
   "Search_Messages": "ស្វែងរក​សារ",
   "Search_Private_Groups": "ស្វែងរកឯកជនក្រុម",
   "seconds": "វិនាទ",
diff --git a/packages/rocketchat-i18n/i18n/ko.i18n.json b/packages/rocketchat-i18n/i18n/ko.i18n.json
index d20ba06d7c7368f0926e44de2a96202dd1636897..a8349ea92fd3eaf998eaeaed550423e5186a15dc 100644
--- a/packages/rocketchat-i18n/i18n/ko.i18n.json
+++ b/packages/rocketchat-i18n/i18n/ko.i18n.json
@@ -451,9 +451,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "사용자 정의 OAuth에 대한 고유 이름 지정",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "응용 프로그램 이름을 지정합니다. 이렇게하면 사용자가 볼 수 있습니다.",
   "Global": "글로벌",
-  "GoogleSiteVerification_id": "Google 사이트 인증 이드",
   "GoogleTagManager_id": "Google 태그 관리자 아이디",
-  "Has_more": "더 많이",
   "Hash": "해시시",
   "Header": "머리글",
   "Hidden": "숨겨진",
@@ -711,7 +709,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "로봇",
   "minutes": "ë¶„",
-  "Mobile_push": "모바일 푸시",
   "More_channels": "추가 채널",
   "More_direct_messages": "보다 직접적인 메시지",
   "More_groups": "비밀 그룹 더보기",
@@ -928,8 +925,6 @@
   "Script_Enabled": "스크립트 사용",
   "Search": "검색",
   "Search_by_username": "이름으로 검색",
-  "Search_Channels": "검색 채널",
-  "Search_Direct_Messages": "직접 메시지를 검색",
   "Search_Messages": "메시지 찾기",
   "Search_Private_Groups": "개인 그룹 검색",
   "seconds": "ì´ˆ",
diff --git a/packages/rocketchat-i18n/i18n/ku.i18n.json b/packages/rocketchat-i18n/i18n/ku.i18n.json
index 9a75d94ecb1df41f8d9668c065581a8a548a14e4..ac6d31aede773be005f66283da2d496aff55d2d0 100644
--- a/packages/rocketchat-i18n/i18n/ku.i18n.json
+++ b/packages/rocketchat-i18n/i18n/ku.i18n.json
@@ -446,9 +446,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "Give a bi navê yekta ji bo OAuth custom li",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Bide ku sepan a name. Ev jî dê ji aliyê bikarhênerên xwe dît.",
   "Global": "Cîhane",
-  "GoogleSiteVerification_id": "Site Id Verification Google",
   "GoogleTagManager_id": "Google Id Manager Tag",
-  "Has_more": "bêtir",
   "Hash": "Hash",
   "Header": "header",
   "Hidden": "veşartî",
@@ -706,7 +704,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "Qûna",
   "minutes": "minutes",
-  "Mobile_push": "push Mobile",
   "More_channels": "کەناڵی تر",
   "More_direct_messages": "mesajên direct More",
   "More_groups": "komên More taybet",
@@ -923,8 +920,6 @@
   "Script_Enabled": "script çalake",
   "Search": "گەڕان",
   "Search_by_username": "Search ji aliyê bikarhêner",
-  "Search_Channels": "Channels Search",
-  "Search_Direct_Messages": "Search Messages Direct",
   "Search_Messages": "Messages Search",
   "Search_Private_Groups": "Search komên taybet",
   "seconds": "seconds",
diff --git a/packages/rocketchat-i18n/i18n/lo.i18n.json b/packages/rocketchat-i18n/i18n/lo.i18n.json
index b9eb0394e5a3be4d6e8921ee27ef7cbb33c8d205..6c71bb90512df3662e92222303c815f20ad083bc 100644
--- a/packages/rocketchat-i18n/i18n/lo.i18n.json
+++ b/packages/rocketchat-i18n/i18n/lo.i18n.json
@@ -446,9 +446,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "ໃຫ້ຊື່ເປັນເອກະລັກສໍາລັບການ OAuth ທີ່ກໍາຫນົດເອງ",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "ໃຫ້ຄໍາຮ້ອງສະຫມັກຂອງຊື່. ນີ້ຈະໄດ້ຮັບການເຫັນໂດຍຜູ້ໃຊ້ຂອງທ່ານ.",
   "Global": "Global",
-  "GoogleSiteVerification_id": "Id ກວດສອບເວັບໄຊກູໂກ",
   "GoogleTagManager_id": "Id Tag Manager ກູໂກ",
-  "Has_more": "ມີຫຼາຍ",
   "Hash": "hash",
   "Header": "Header",
   "Hidden": "ເຊື່ອງໄວ້",
@@ -706,7 +704,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "ຫຸ່ນຍົນ",
   "minutes": "ນາທີ",
-  "Mobile_push": "ຊຸກຍູ້ການໂທລະສັບມືຖື",
   "More_channels": "ຊ່ອງທາງເພີ່ມເຕີມ",
   "More_direct_messages": "ຂໍ້ຄວາມໂດຍກົງ",
   "More_groups": "ກຸ່ມເອກະຊົນຫຼາຍ",
@@ -923,8 +920,6 @@
   "Script_Enabled": "script ເປີດໃຊ້ວຽກ",
   "Search": "ຄົ້ນຫາ",
   "Search_by_username": "ຄົ້ນຫາໂດຍຊື່ຜູ້ໃຊ້",
-  "Search_Channels": "ຊ່ອງຄົ້ນຫາ",
-  "Search_Direct_Messages": "ຄົ້ນຫາຂໍ້ຄວາມໂດຍກົງ",
   "Search_Messages": "ການຄົ້ນຫາ",
   "Search_Private_Groups": "ຄົ້ນຫາກຸ່ມເອກກະຊົນ",
   "seconds": "ວິນາທີ",
diff --git a/packages/rocketchat-i18n/i18n/ms-MY.i18n.json b/packages/rocketchat-i18n/i18n/ms-MY.i18n.json
index 2a9b8237bd5c03003db8c92734520b3b8296b571..dfb52d0a5e78631caffe7fa26d69c0f2d155e307 100644
--- a/packages/rocketchat-i18n/i18n/ms-MY.i18n.json
+++ b/packages/rocketchat-i18n/i18n/ms-MY.i18n.json
@@ -446,9 +446,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "Beri nama unik untuk OAuth adat",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Beri permohonan itu nama. Ini akan dapat dilihat oleh pengguna-pengguna anda.",
   "Global": "global",
-  "GoogleSiteVerification_id": "Id Pengesahan laman Google",
   "GoogleTagManager_id": "Id Pengurus Teg Google",
-  "Has_more": "Ada lagi",
   "Hash": "hash",
   "Header": "Kepala",
   "Hidden": "tersembunyi",
@@ -706,7 +704,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "Robot",
   "minutes": "minit",
-  "Mobile_push": "Mobile push",
   "More_channels": "Lagi saluran",
   "More_direct_messages": "Lebih mesej langsung",
   "More_groups": "Lagi kumpulan persendirian",
@@ -923,8 +920,6 @@
   "Script_Enabled": "Script Didayakan",
   "Search": "Cari",
   "Search_by_username": "Cari dengan nama pengguna",
-  "Search_Channels": "Cari Saluran",
-  "Search_Direct_Messages": "Mencari Mesej Langsung",
   "Search_Messages": "Cari Mesej",
   "Search_Private_Groups": "Cari Kumpulan Swasta",
   "seconds": "saat",
diff --git a/packages/rocketchat-i18n/i18n/nl.i18n.json b/packages/rocketchat-i18n/i18n/nl.i18n.json
index da8ace640ff1c1038596cc6fe7d783fd50fa5fb6..a175e83d61644546329dd248ec9dab136479aa53 100644
--- a/packages/rocketchat-i18n/i18n/nl.i18n.json
+++ b/packages/rocketchat-i18n/i18n/nl.i18n.json
@@ -446,9 +446,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "Geef een unieke naam voor de aangepaste OAuth",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Geef de toepassing een naam. Dit zal worden gezien door de gebruiker.",
   "Global": "Globaal",
-  "GoogleSiteVerification_id": "Google Site Verificatie Id",
   "GoogleTagManager_id": "Google Tag Manager Id",
-  "Has_more": "Heeft meer",
   "Hash": "hachee",
   "Header": "hoofd",
   "Hidden": "Verborgen",
@@ -706,7 +704,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "Robots",
   "minutes": "minuten",
-  "Mobile_push": "Mobile push",
   "More_channels": "Meer kanalen",
   "More_direct_messages": "Meer directe berichten",
   "More_groups": "Meer privé-berichten",
@@ -923,8 +920,6 @@
   "Script_Enabled": "script Ingeschakeld",
   "Search": "Zoeken",
   "Search_by_username": "Zoek op gebruikersnaam",
-  "Search_Channels": "Zoek kanalen",
-  "Search_Direct_Messages": "Zoeken Direct Messages",
   "Search_Messages": "Berichten zoeken",
   "Search_Private_Groups": "Zoeken Private Groepen",
   "seconds": "seconden",
diff --git a/packages/rocketchat-i18n/i18n/pl.i18n.json b/packages/rocketchat-i18n/i18n/pl.i18n.json
index 631a7427bf44fba8d29ae79fa708d7d8b28d3317..85a9d5cfc41444c0819f1c94eee910ffe715e7db 100644
--- a/packages/rocketchat-i18n/i18n/pl.i18n.json
+++ b/packages/rocketchat-i18n/i18n/pl.i18n.json
@@ -504,9 +504,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "Podaj unikalną nazwę dla własnego serwisu OAuth",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Nadaj aplikacji nazwę. Będzie ona widoczna dla użytkowników.",
   "Global": "Åšwiatowy",
-  "GoogleSiteVerification_id": "Google Site Weryfikacja Id",
   "GoogleTagManager_id": "Menedżer tagów Google Id",
-  "Has_more": "Jest więcej",
   "Hash": "Hash",
   "Header": "Nagłówek",
   "Hidden": "Ukryty",
@@ -783,7 +781,6 @@
   "Meta_robots": "Roboty",
   "Min_length_is": "Minimalna długość to %s",
   "minutes": "minut",
-  "Mobile_push": "Mobile push",
   "Monday": "Poniedziałek",
   "Monitor_history_for_changes_on": "Sprawdź historię zmian na",
   "More_channels": "Więcej kanałów",
@@ -1021,8 +1018,6 @@
   "Script_Enabled": "Skrypt włączony",
   "Search": "Szukaj",
   "Search_by_username": "Szukaj według nazwy użytkownika",
-  "Search_Channels": "Szukaj kanałów",
-  "Search_Direct_Messages": "Wyszukaj wiadomości bezpośrednie",
   "Search_Messages": "Przeszukaj wiadomości",
   "Search_Private_Groups": "Wyszukaj prywatne grupy",
   "seconds": "sekund",
diff --git a/packages/rocketchat-i18n/i18n/pt.i18n.json b/packages/rocketchat-i18n/i18n/pt.i18n.json
index cbea202314d5da03953f6fd473c6de8ee185e587..c67621277c14c45f732fafaa8b543f5d58c3e722 100644
--- a/packages/rocketchat-i18n/i18n/pt.i18n.json
+++ b/packages/rocketchat-i18n/i18n/pt.i18n.json
@@ -307,6 +307,8 @@
   "Custom_Script_Logged_Out": "Script Personalizado para usuários não logados",
   "Dashboard": "Dashboard",
   "Date": "Data",
+  "Date_From": "De",
+  "Date_to": "até",
   "days": "dias",
   "DB_Migration": "Migração de banco de dados",
   "DB_Migration_Date": "Data da migração do banco de dados",
@@ -349,6 +351,7 @@
   "Edit": "Editar",
   "Edit_Custom_Field": "Editar Campo Personalizado",
   "Edit_Department": "Editar Departamento",
+  "Edit_Trigger": "Editar Gatilho",
   "edited": "editado",
   "Editing_room": "Edição de sala",
   "Editing_user": "Edição de usuário",
@@ -407,6 +410,7 @@
   "error-invalid-description": "Descrição inválida",
   "error-invalid-domain": "Domínio inválido",
   "error-invalid-email": "__email__ não é um e-mail válido",
+  "error-invalid-email-address": "Endereço de e-mail inválido",
   "error-invalid-file-height": "Altura de arquivo inválida",
   "error-invalid-file-type": "Tipo de arquivo inválido",
   "error-invalid-file-width": "Altura de arquivo inválida",
@@ -497,9 +501,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "Dê um nome exclusivo para o oauth customizado",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Dê um nome à aplicação. Isso será visto por seus usuários.",
   "Global": "Global",
-  "GoogleSiteVerification_id": "ID de verificação do Google Sites",
   "GoogleTagManager_id": "Google Tag Manager Id",
-  "Has_more": "Há mais",
   "Hash": "Hash",
   "Header": "Cabeçalho",
   "Hidden": "Escondido",
@@ -765,7 +767,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "Robots",
   "minutes": "minutos",
-  "Mobile_push": "Notificação por celular",
   "Monitor_history_for_changes_on": "Monitorar mudanças de histórico para",
   "More_channels": "Mais canais",
   "More_direct_messages": "Mais mensagens diretas",
@@ -795,6 +796,7 @@
   "New_role": "Novo papel",
   "New_Room_Notification": "Notificação de nova sala",
   "New_videocall_request": "Nova requisição de chamada de vídeo",
+  "New_Trigger": "Novo Gatilho",
   "No_available_agents_to_transfer": "Nenhum agente disponível para transferir",
   "No_channel_with_name_%s_was_found": "Nenhum canal com nome <strong>\"%s\"</strong> foi encontrado!",
   "No_channels_yet": "Você não faz parte de nenhum canal ainda.",
@@ -838,6 +840,7 @@
   "Oops!": "Ops",
   "Open": "Aberto",
   "Opened": "Aberto",
+  "Opened_in_a_new_window": "Aberto em nova janela.",
   "Opens_a_channel_group_or_direct_message": "Abre um canal, grupo ou mensagem direta",
   "optional": "opcional",
   "or": "ou",
@@ -993,8 +996,6 @@
   "Script_Enabled": "Script Ativado",
   "Search": "Pesquisar",
   "Search_by_username": "Busca por nome de usuário",
-  "Search_Channels": "Pesquisar Canais",
-  "Search_Direct_Messages": "Pesquisar Mensagens Diretas",
   "Search_Messages": "Pesquisar Mensagens",
   "Search_Private_Groups": "Pesquisar Grupos Privados",
   "seconds": "segundos",
@@ -1175,6 +1176,7 @@
   "Uploading_file": "Subindo arquivo...",
   "Uptime": "Tempo online",
   "URL": "URL",
+  "URL_room_prefix": "Prefixo da URL da sala",
   "Use_account_preference": "Use preferências da conta",
   "Use_Emojis": "Usar Emojis",
   "Use_initials_avatar": "Usar as iniciais do seu nome de usuário",
@@ -1201,9 +1203,9 @@
   "User_joined_channel": "Entrou no canal.",
   "User_joined_channel_female": "Entrou no canal.",
   "User_joined_channel_male": "Entrou no canal.",
-  "User_left": "Usuário <em>__user_left__</em> deixou a conversa.",
-  "User_left_female": "Usuário <em>__user_left__</em> deixou a conversa.",
-  "User_left_male": "Usuário <em>__user_left__</em> deixou a conversa.",
+  "User_left": "Saiu da conversa.",
+  "User_left_female": "Saiu da conversa.",
+  "User_left_male": "Saiu da conversa.",
   "User_logged_out": "Usuário não logado",
   "User_management": "Gerenciamento de usuários",
   "User_muted_by": "Usuário <em>__user_muted__</em> silenciado por <em>__user_by__</em>.",
@@ -1234,10 +1236,12 @@
   "UTF8_Names_Slugify": "Slugify Nomes UTF8 ",
   "UTF8_Names_Validation": "Validação de Nomes UTF8",
   "UTF8_Names_Validation_Description": "Não permitir caracteres especiais e espaços. Você pode usar - _ e. mas não no final do nome",
+  "Validate_email_address": "Validar endereço de e-mail",
   "Verification_email_sent": "E-mail de verificação enviado",
   "Verified": "Verificado",
   "Version": "Versão",
   "Video_Chat_Window": "Vídeo Chat",
+  "Video_Conference": "Vídeo Conferência",
   "Videocall_declined": "Chamada de vídeo negada.",
   "Videocall_enabled": "Vídeoconferência habilitada",
   "View_All": "Ver Todos",
diff --git a/packages/rocketchat-i18n/i18n/ro.i18n.json b/packages/rocketchat-i18n/i18n/ro.i18n.json
index b7a13c78cd39a7872631d0d686670142c4a2d386..94f08574b0e6f9ddc176f2af419f3e4d8ff620b3 100644
--- a/packages/rocketchat-i18n/i18n/ro.i18n.json
+++ b/packages/rocketchat-i18n/i18n/ro.i18n.json
@@ -446,9 +446,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "Alegeți un nume unic pentru OAuth personalizat",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Da aplicației un nume. Acest lucru va fi văzut de utilizatori.",
   "Global": "Global",
-  "GoogleSiteVerification_id": "Id-ul Google de verificare site-ului",
   "GoogleTagManager_id": "ID Google Manager de etichete",
-  "Has_more": "Are mai multe",
   "Hash": "hașiș",
   "Header": "Antet",
   "Hidden": "Ascuns",
@@ -706,7 +704,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "Roboți",
   "minutes": "minute",
-  "Mobile_push": "împinge mobil",
   "More_channels": "Mai multe canale",
   "More_direct_messages": "Mai multe mesaje directe",
   "More_groups": "Mai multe grupuri private",
@@ -923,8 +920,6 @@
   "Script_Enabled": "script-ul activat",
   "Search": "Căutare",
   "Search_by_username": "Căutare după nume de utilizator",
-  "Search_Channels": "canale de căutare",
-  "Search_Direct_Messages": "Căutare mesaje directe",
   "Search_Messages": "Căutare mesaje",
   "Search_Private_Groups": "Căutare Grupuri private",
   "seconds": "secunde",
diff --git a/packages/rocketchat-i18n/i18n/ru.i18n.json b/packages/rocketchat-i18n/i18n/ru.i18n.json
index eef65c1bbc25bfc7957a4694d6dfa593e97304c7..d2bd983890313c3b2ba516f9c113a4e37d431c98 100644
--- a/packages/rocketchat-i18n/i18n/ru.i18n.json
+++ b/packages/rocketchat-i18n/i18n/ru.i18n.json
@@ -448,9 +448,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "Задайте уникальное имя для пользовательского OAuth",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Задайте приложению имя. Оно будет видно всем пользователям.",
   "Global": "Общие",
-  "GoogleSiteVerification_id": "Идентификатор Google Site Verification",
   "GoogleTagManager_id": "Google Tag Manager Id",
-  "Has_more": "Еще",
   "Hash": "Хэш",
   "Header": "Заголовок",
   "Hidden": "Скрытый",
@@ -710,7 +708,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "Боты",
   "minutes": "минут(ы)",
-  "Mobile_push": "Push уведомления",
   "More_channels": "Другие чаты",
   "More_direct_messages": "Больше личных сообщений",
   "More_groups": "Больше приватных чатов",
@@ -930,8 +927,6 @@
   "Script_Enabled": "Сценарий включен",
   "Search": "Поиск",
   "Search_by_username": "Поиск по имени пользователя",
-  "Search_Channels": "Поиск каналов",
-  "Search_Direct_Messages": "Поиск личных сообщений",
   "Search_Messages": "Поиск сообщений",
   "Search_Private_Groups": "Поиск приватных чатов",
   "seconds": "секунд(ы)",
diff --git a/packages/rocketchat-i18n/i18n/sq.i18n.json b/packages/rocketchat-i18n/i18n/sq.i18n.json
index 3d19d80484e517a4aa363e5ebebe040ced7b9486..2789b1173d7f2293b71cfb758cf3bacaa4acc3d2 100644
--- a/packages/rocketchat-i18n/i18n/sq.i18n.json
+++ b/packages/rocketchat-i18n/i18n/sq.i18n.json
@@ -446,9 +446,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "Jepni një emër të veçantë për OAuth porosi",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Jepni aplikacionin një emër. Kjo do të shihet nga përdoruesit e juaj.",
   "Global": "global",
-  "GoogleSiteVerification_id": "Site Verifikimi Id Google",
   "GoogleTagManager_id": "Google Tag Menaxheri Id",
-  "Has_more": "Ka më shumë",
   "Hash": "hashish",
   "Header": "arkitra",
   "Hidden": "I fshehur",
@@ -706,7 +704,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "Robots",
   "minutes": "minuta",
-  "Mobile_push": "shtytje Mobile",
   "More_channels": "Më shumë kanale",
   "More_direct_messages": "Më shumë mesazhe të drejtpërdrejta",
   "More_groups": "Më shumë grupe private",
@@ -923,8 +920,6 @@
   "Script_Enabled": "script aktivizuar",
   "Search": "Kërko",
   "Search_by_username": "Kërko sipas emrin",
-  "Search_Channels": "Kërko Kanalet",
-  "Search_Direct_Messages": "Kërko mesazhe të drejtpërdrejta",
   "Search_Messages": "Kërko mesazhet",
   "Search_Private_Groups": "Kërko Grupe private",
   "seconds": "sekonda",
diff --git a/packages/rocketchat-i18n/i18n/sr.i18n.json b/packages/rocketchat-i18n/i18n/sr.i18n.json
index cb960fcff2b6dce30c49683f6aceb87acb851109..86b6a9570fcb433f27aae3558d0b21b705bfc065 100644
--- a/packages/rocketchat-i18n/i18n/sr.i18n.json
+++ b/packages/rocketchat-i18n/i18n/sr.i18n.json
@@ -446,9 +446,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "Дати јединствено име за прилагођени ОАутх",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Дајте Апликација име. Ово ће бити виђена од својих корисника.",
   "Global": "глобалан",
-  "GoogleSiteVerification_id": "Верификација ИД Гоогле сајт",
   "GoogleTagManager_id": "Гоогле ИД менаџер ознака",
-  "Has_more": "има више",
   "Hash": "хасх",
   "Header": "хеадер",
   "Hidden": "Сакривен",
@@ -706,7 +704,6 @@
   "Meta_msvalidate01": "МСВалидате.01",
   "Meta_robots": "Роботи",
   "minutes": "минута",
-  "Mobile_push": "мобиле Пусх",
   "More_channels": "Више канала",
   "More_direct_messages": "Више директне поруке",
   "More_groups": "Више приватне групе",
@@ -923,8 +920,6 @@
   "Script_Enabled": "сцрипт Омогућено",
   "Search": "Претрага",
   "Search_by_username": "Претрага по корисничком имену",
-  "Search_Channels": "Сеарцх Цханнелс",
-  "Search_Direct_Messages": "Тражи директне поруке",
   "Search_Messages": "Сеарцх Мессагес",
   "Search_Private_Groups": "Тражи приватних група",
   "seconds": "секунде",
diff --git a/packages/rocketchat-i18n/i18n/sv.i18n.json b/packages/rocketchat-i18n/i18n/sv.i18n.json
index ba7f8e7cbded27c2a867edfebd10c40e5b097fd8..04158212186557ce94b2055bda251d15e735dff0 100644
--- a/packages/rocketchat-i18n/i18n/sv.i18n.json
+++ b/packages/rocketchat-i18n/i18n/sv.i18n.json
@@ -6,6 +6,7 @@
   "500": "internt serverfel",
   "__username__is_no_longer__role__defined_by__user_by_": "__username__ är inte längre __role__, genom __user_by__",
   "__username__was_set__role__by__user_by_": "__username__ sattes __role__ genom __user_by__",
+  "Accept": "Acceptera",
   "Access_not_authorized": "Tillgång som inte godkänts",
   "Access_Token_URL": "Tillgång Token URL",
   "Accessing_permissions": "Åtkomstbehörigheter",
@@ -134,7 +135,7 @@
   "Analytics_features_users_Description": "Spår anpassade händelser i samband med åtgärder som rör användare (lösenordsåterställning gånger, profilbild förändring, etc).",
   "and": "och",
   "And_more": "Och mer __length __",
-  "Animals_and_Nature": "Djur & natur",
+  "Animals_and_Nature": "Djur & Natur",
   "API": "API",
   "API_Analytics": "Analytics",
   "API_Embed": "Inbäddad",
@@ -259,6 +260,7 @@
   "Created_at_s_by_s": "Skapad vid <strong>%s</strong> av <strong>%s</strong>",
   "Current_Chats": "nuvarande Chatt",
   "Custom": "Beställnings",
+  "Custom_Emoji_Add": "Lägg till ny emoji",
   "Custom_Fields": "Anpassade fält",
   "Custom_oauth_helper": "När du ställer in din OAuth leverantör, måste du informera en återuppringning webbadress. Användning <pre> %s </pre> .",
   "Custom_oauth_unique_name": "Anpassad oauth unikt namn",
@@ -430,7 +432,7 @@
   "FileUpload_S3_CDN": "CDN domän för nedladdningar",
   "FileUpload_S3_Region": "Område",
   "FileUpload_Storage_Type": "lagring Typ",
-  "Flags": "flags",
+  "Flags": "Flaggor",
   "Follow_social_profiles": "Följ våra sociala mediakonton, forka oss på github och dela med dig av dina tankar om rocket.chatt på vår trello.",
   "Food_and_Drink": "Mat & Dryck",
   "Footer": "footer",
@@ -438,7 +440,7 @@
   "Force_SSL": "force SSL",
   "Force_SSL_Description": "* OBS! * _Force SSL_ ska aldrig användas med reverse proxy. Om du har en omvänd proxy, bör du göra omdirigeringen DET. Det här alternativet finns för installationer som Heroku, som inte tillåter konfiguration omdirigeringen på den omvända proxyservern.",
   "Forgot_password": "Glömt ditt lösenord?",
-  "Frequently_Used": "Vanliga Används",
+  "Frequently_Used": "Ofta använd",
   "From": "Från",
   "From_Email": "Från e-postadress",
   "From_email_warning": "<b>Varning:</b> Fältet <b>Från</b> är föremål för e-postserverinställningar.",
@@ -447,9 +449,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "Ge ett unikt namn för den anpassade oauth",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Ge applikationen ett namn. Detta kommer att ses av dina användare.",
   "Global": "Global",
-  "GoogleSiteVerification_id": "Google Site Verifiering Id",
   "GoogleTagManager_id": "Google Tagghanteraren Id",
-  "Has_more": "har mer",
   "Hash": "Hash",
   "Header": "Rubrik",
   "Hidden": "Dolda",
@@ -708,7 +708,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "Robots",
   "minutes": "minuter",
-  "Mobile_push": "Mobila notifieringar",
   "More_channels": "Fler kanaler",
   "More_direct_messages": "Fler direktmeddelanden",
   "More_groups": "Fler privata grupper",
@@ -925,8 +924,6 @@
   "Script_Enabled": "script Enabled",
   "Search": "Sök",
   "Search_by_username": "Sök på användarnamn",
-  "Search_Channels": "Sök kanaler",
-  "Search_Direct_Messages": "Sök bland direktmeddelanden ",
   "Search_Messages": "Sök meddelanden",
   "Search_Private_Groups": "Sök i privata grupper",
   "seconds": "sekunder",
@@ -1025,7 +1022,7 @@
   "Success_message": "framgång meddelande",
   "Survey": "Enkät",
   "Survey_instructions": "Betygsätt varje fråga efter hur nöjd du är, 1 betyder att du inte alls är nöjd och 5 betyder att du är helt nöjd.\n",
-  "Symbols": "symboler",
+  "Symbols": "Symboler",
   "Sync_success": "synk framgång",
   "Sync_Users": "Synkronisera Användare",
   "Tag": "Märka",
@@ -1077,7 +1074,7 @@
   "to_see_more_details_on_how_to_integrate": "att se mer information om hur man kan integrera.",
   "To_users": "Till användare",
   "Topic": "Ämne",
-  "Travel_and_Places": "Travel & Places",
+  "Travel_and_Places": "Fordon & Platser",
   "Trigger_removed": "trigger avlägsnades",
   "Trigger_Words": "trigger ord",
   "Triggers": "triggers",
diff --git a/packages/rocketchat-i18n/i18n/ta-IN.i18n.json b/packages/rocketchat-i18n/i18n/ta-IN.i18n.json
index 16a29858df0cbae540596cc7681142c91d353e7b..58ea59cd2b62ad74ed4278c0b26ac508d1a0c786 100644
--- a/packages/rocketchat-i18n/i18n/ta-IN.i18n.json
+++ b/packages/rocketchat-i18n/i18n/ta-IN.i18n.json
@@ -446,9 +446,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "விருப்ப OAuth ஒரு தனிப்பட்ட பெயரை கொடுங்கள்",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "விண்ணப்ப ஒரு பெயர் கொடுக்க. இது உங்கள் பயனர் பார்க்க வேண்டும்.",
   "Global": "குளோபல்",
-  "GoogleSiteVerification_id": "Google தள சரிபார்ப்பு அடையாளம்",
   "GoogleTagManager_id": "Google குறி மேலாளர் ஐடி",
-  "Has_more": "இன்னும் உள்ளது",
   "Hash": "புல",
   "Header": "தலைப்பு",
   "Hidden": "மறைக்கப்பட்ட",
@@ -706,7 +704,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "ரோபோக்கள்",
   "minutes": "நிமிடங்கள்",
-  "Mobile_push": "மொபைல் மிகுதி",
   "More_channels": "மேலும் பொது குழுக்கள்",
   "More_direct_messages": "மேலும் நேரடி செய்திகளை",
   "More_groups": "மேலும் தனியார் குழுக்கள்",
@@ -923,8 +920,6 @@
   "Script_Enabled": "ஸ்கிரிப்ட்",
   "Search": "தேடு",
   "Search_by_username": "பயனர் பெயர் மூலம் தேடல்",
-  "Search_Channels": "தேடல் சேனல்கள்",
-  "Search_Direct_Messages": "நேரடி செய்திகள் தேடல்",
   "Search_Messages": "தேடல் செய்திகள்",
   "Search_Private_Groups": "தனியார் குழுக்கள் தேடல்",
   "seconds": "விநாடிகள்",
diff --git a/packages/rocketchat-i18n/i18n/tr.i18n.json b/packages/rocketchat-i18n/i18n/tr.i18n.json
index eafe8ef785909d8b4fe5db53274105646055a646..210bb755effaadec508c060822d28197a8b48b92 100644
--- a/packages/rocketchat-i18n/i18n/tr.i18n.json
+++ b/packages/rocketchat-i18n/i18n/tr.i18n.json
@@ -489,10 +489,8 @@
   "Give_a_unique_name_for_the_custom_oauth": "Özel OAuth için benzersiz bir ad verin",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Uygulamayı bir ad verin. Bu kullanıcılar tarafından görülecektir.",
   "Global": "global",
-  "GoogleSiteVerification_id": "Google Site DoÄŸrulama KimliÄŸi",
   "GoogleTagManager_id": "Google Etiket Yöneticisi Kimliği",
   "Guest_Pool": "Misafir Havuzu",
-  "Has_more": "Daha fazla var",
   "Hash": "esrar",
   "Header": "üstbilgi",
   "Hidden": "Gizli",
@@ -759,7 +757,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "Robotlar",
   "minutes": "dakika",
-  "Mobile_push": "Mobil itme",
   "More_channels": "Daha fazla",
   "More_direct_messages": "Daha direkt mesajlar",
   "More_groups": "Daha fazla özel grup",
@@ -976,8 +973,6 @@
   "Script_Enabled": "Senaryo Etkin",
   "Search": "Ara",
   "Search_by_username": "Kullanıcı adına göre ara",
-  "Search_Channels": "Kanal Arama",
-  "Search_Direct_Messages": "DoÄŸrudan Mesajlar Arama",
   "Search_Messages": "Mesajlarda ara",
   "Search_Private_Groups": "Özel Gruplar Arama",
   "seconds": "saniye",
diff --git a/packages/rocketchat-i18n/i18n/ug.i18n.json b/packages/rocketchat-i18n/i18n/ug.i18n.json
index e4081486dd3f578bab89380a30437294b8645a98..d3a1dc7c7cfadcc4cc4fd52166b46a0a840d5c8f 100644
--- a/packages/rocketchat-i18n/i18n/ug.i18n.json
+++ b/packages/rocketchat-i18n/i18n/ug.i18n.json
@@ -446,9 +446,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "بىردىنبىر ئىسىم بېكىتىڭ OAuth ئۆزى بېكىتىش",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "ئەپكە بىر ئىسىم قويۇڭ . بۇ ئىسىمنى سىزنىڭ ئەزايىڭىز كۆرەلەيدۇ.",
   "Global": "ئومۇمىي ئەھۋال",
-  "GoogleSiteVerification_id": "ID Google تورى دەلىللەش",
   "GoogleTagManager_id": "IDئىز قوغلاش كودنى باشقۇرغۇچى Google",
-  "Has_more": "تېخىمۇ كۆپ بار",
   "Hash": "خاش قىممىتى",
   "Header": "باش",
   "Hidden": "يوشۇرۇلغان",
@@ -706,7 +704,6 @@
   "Meta_msvalidate01": "تورى تەكشۈرۈپ ئىسپاتلاشMicrosoft",
   "Meta_robots": "ماشىنا ئادەم",
   "minutes": "مىنۇت",
-  "Mobile_push": "كۆچمە تېرمىنال ئىتتىرىش",
   "More_channels": "تېخىمۇ كۆپ قانال",
   "More_direct_messages": "تېخىمۇ كۆپ سۆھبەتلىشىش",
   "More_groups": "تېخىمۇ كۆپ شەخسىي گۇرپپا",
@@ -923,8 +920,6 @@
   "Script_Enabled": "ئىسكرپت قوزغىتىلدى",
   "Search": "ئىزدەش",
   "Search_by_username": "ئەزا نامىغا ئاساسەن ئىزدەش",
-  "Search_Channels": "قانالنى ئىزدەش",
-  "Search_Direct_Messages": "بىۋاسىتە دىيالوگنى ئىزدەش",
   "Search_Messages": "ئۇچۇر ئىزدەش",
   "Search_Private_Groups": "شەخسىي گۇرۇپپىنى ئىزدەش",
   "seconds": "سېكۇنت",
diff --git a/packages/rocketchat-i18n/i18n/uk.i18n.json b/packages/rocketchat-i18n/i18n/uk.i18n.json
index 12c213e00b66d86e049f1058240e63a3e3de387d..51d83c1911d66c86607057823edb5b6150aa15a7 100644
--- a/packages/rocketchat-i18n/i18n/uk.i18n.json
+++ b/packages/rocketchat-i18n/i18n/uk.i18n.json
@@ -446,9 +446,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "Дайте унікальне ім'я для призначеного для користувача OAuth",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "Дайте додатком ім'я. Це буде видно ваших користувачів.",
   "Global": "глобальної",
-  "GoogleSiteVerification_id": "Ідентифікатор Google Site Verification",
   "GoogleTagManager_id": "Google Id Диспетчер тегів",
-  "Has_more": "має більш",
   "Hash": "мішанина",
   "Header": "заголовок",
   "Hidden": "прихований",
@@ -706,7 +704,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "роботи",
   "minutes": "хвилин",
-  "Mobile_push": "мобільний поштовх",
   "More_channels": "Більше каналів",
   "More_direct_messages": "Інші прямі повідомлення",
   "More_groups": "Більш приватні групи",
@@ -923,8 +920,6 @@
   "Script_Enabled": "сценарій Включено",
   "Search": "Пошук",
   "Search_by_username": "Пошук по імені користувача",
-  "Search_Channels": "Пошук каналів",
-  "Search_Direct_Messages": "Пошук прямих повідомлень",
   "Search_Messages": "Пошук повідомлень",
   "Search_Private_Groups": "Пошук приватних груп",
   "seconds": "секунд",
diff --git a/packages/rocketchat-i18n/i18n/zh-HK.i18n.json b/packages/rocketchat-i18n/i18n/zh-HK.i18n.json
index a93c8660a4de4f2631b00b899182f7e3e9914a79..a9a19981f020ff7310241c657f1ab46fe5ce84dd 100644
--- a/packages/rocketchat-i18n/i18n/zh-HK.i18n.json
+++ b/packages/rocketchat-i18n/i18n/zh-HK.i18n.json
@@ -71,7 +71,6 @@
   "From_Email": "从电子邮件",
   "General": "通用",
   "github_no_public_email": "在您的GitHub上帐户中,您没有设置任何电子邮件作为公共电子邮件地址。",
-  "Has_more": "有更多",
   "Hide_room": "隐藏聊天室",
   "History": "历史",
   "hours": "小时",
diff --git a/packages/rocketchat-i18n/i18n/zh-TW.i18n.json b/packages/rocketchat-i18n/i18n/zh-TW.i18n.json
index 96f284bdbbbaa142162e81557041cf56d8080021..e9a057f6d62628bf87e65b770e67124e7ebb6452 100644
--- a/packages/rocketchat-i18n/i18n/zh-TW.i18n.json
+++ b/packages/rocketchat-i18n/i18n/zh-TW.i18n.json
@@ -446,9 +446,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "為自訂 OAuth 設定一個獨一無二的名稱",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "給應用程序的名稱。這將被用戶看到。",
   "Global": "全球",
-  "GoogleSiteVerification_id": "谷歌網站驗證標識",
   "GoogleTagManager_id": "谷歌代碼管理標識",
-  "Has_more": "有更多",
   "Hash": "哈希",
   "Header": "é ­",
   "Hidden": "隱藏",
@@ -706,7 +704,6 @@
   "Meta_msvalidate01": "MSValidate.01",
   "Meta_robots": "機器人",
   "minutes": "分鐘",
-  "Mobile_push": "移動推送",
   "More_channels": "更多頻道",
   "More_direct_messages": "更直接的訊息",
   "More_groups": "更多私有群組",
@@ -923,8 +920,6 @@
   "Script_Enabled": "腳本已啟用",
   "Search": "搜尋",
   "Search_by_username": "通過用戶名搜尋",
-  "Search_Channels": "搜尋頻道",
-  "Search_Direct_Messages": "搜索私聊訊息",
   "Search_Messages": "搜尋訊息",
   "Search_Private_Groups": "搜尋私人群組",
   "seconds": "ç§’",
diff --git a/packages/rocketchat-i18n/i18n/zh.i18n.json b/packages/rocketchat-i18n/i18n/zh.i18n.json
index f5f72e2b3a2e59c63e4e6557fd3e78d078036499..145471928d184643744794769a3c1c84d555767b 100644
--- a/packages/rocketchat-i18n/i18n/zh.i18n.json
+++ b/packages/rocketchat-i18n/i18n/zh.i18n.json
@@ -456,9 +456,7 @@
   "Give_a_unique_name_for_the_custom_oauth": "请给自定义 OAuth 设置一个唯一的名称",
   "Give_the_application_a_name_This_will_be_seen_by_your_users": "给该应用设置一个名称。该名称将被您的用户看到。",
   "Global": "全局",
-  "GoogleSiteVerification_id": "谷歌网站验证ID",
   "GoogleTagManager_id": "谷歌跟踪代码管理器 ID",
-  "Has_more": "有更多",
   "Hash": "哈希值",
   "Header": "头",
   "Hidden": "已隐藏",
@@ -721,7 +719,6 @@
   "Meta_msvalidate01": "微软网站验证",
   "Meta_robots": "机器人",
   "minutes": "分钟",
-  "Mobile_push": "移动端推送",
   "More_channels": "更多频道",
   "More_direct_messages": "更多对话",
   "More_groups": "更多私有组",
@@ -952,8 +949,6 @@
   "Script_Enabled": "脚本已启用",
   "Search": "搜索",
   "Search_by_username": "根据用户名搜索",
-  "Search_Channels": "搜索频道",
-  "Search_Direct_Messages": "搜索直接对话",
   "Search_Messages": "搜索消息",
   "Search_Private_Groups": "搜索私有组",
   "seconds": "ç§’",
diff --git a/packages/rocketchat-importer-csv/main.js b/packages/rocketchat-importer-csv/main.js
index 578d360c247079056e4b977e8e439df92d57cb39..cea869b960b37ca7529ce8f73dc2d53777d9ecd7 100644
--- a/packages/rocketchat-importer-csv/main.js
+++ b/packages/rocketchat-importer-csv/main.js
@@ -6,5 +6,5 @@ Importer.addImporter('csv', Importer.CSV, {
 		text: 'Importer_CSV_Information',
 		href: 'https://rocket.chat/docs/administrator-guides/import/csv/'
 	}],
-	fileTypeRegex: new RegExp('application\/.*?zip')
+	mimeType: 'application/zip'
 });
diff --git a/packages/rocketchat-importer-csv/server.js b/packages/rocketchat-importer-csv/server.js
index 9358d9f0df6f652252e21420ff4e845d9de0bea5..98eec8ea44e1cd55710cd7494c0a600392d5a6d8 100644
--- a/packages/rocketchat-importer-csv/server.js
+++ b/packages/rocketchat-importer-csv/server.js
@@ -1,8 +1,8 @@
 /* globals Importer */
 
 Importer.CSV = class ImporterCSV extends Importer.Base {
-	constructor(name, descriptionI18N, fileTypeRegex) {
-		super(name, descriptionI18N, fileTypeRegex);
+	constructor(name, descriptionI18N, mimeType) {
+		super(name, descriptionI18N, mimeType);
 		this.logger.debug('Constructed a new CSV Importer.');
 
 		this.csvParser = Npm.require('csv-parse/lib/sync');
@@ -184,8 +184,7 @@ Importer.CSV = class ImporterCSV extends Importer.Base {
 					} else {
 						const userId = Accounts.createUser({ email: u.email, password: Date.now() + u.name + u.email.toUpperCase() });
 						Meteor.runAsUser(userId, () => {
-							Meteor.call('setUsername', u.username);
-							Meteor.call('joinDefaultChannels', true);
+							Meteor.call('setUsername', u.username, {joinDefaultChannelsSilenced: true});
 							RocketChat.models.Users.setName(userId, u.name);
 							RocketChat.models.Users.update({ _id: userId }, { $addToSet: { importIds: u.id } });
 							u.rocketId = userId;
diff --git a/packages/rocketchat-importer-hipchat-enterprise/.npm/package/.gitignore b/packages/rocketchat-importer-hipchat-enterprise/.npm/package/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..3c3629e647f5ddf82548912e337bea9826b434af
--- /dev/null
+++ b/packages/rocketchat-importer-hipchat-enterprise/.npm/package/.gitignore
@@ -0,0 +1 @@
+node_modules
diff --git a/packages/rocketchat-importer-hipchat-enterprise/.npm/package/README b/packages/rocketchat-importer-hipchat-enterprise/.npm/package/README
new file mode 100644
index 0000000000000000000000000000000000000000..3d492553a438e46facd411cd3e206a648395a38c
--- /dev/null
+++ b/packages/rocketchat-importer-hipchat-enterprise/.npm/package/README
@@ -0,0 +1,7 @@
+This directory and the files immediately inside it are automatically generated
+when you change this package's NPM dependencies. Commit the files in this
+directory (npm-shrinkwrap.json, .gitignore, and this README) to source control
+so that others run the same versions of sub-dependencies.
+
+You should NOT check in the node_modules directory that Meteor automatically
+creates; if you are using git, the .gitignore file tells git to ignore it.
diff --git a/packages/rocketchat-importer-hipchat-enterprise/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-importer-hipchat-enterprise/.npm/package/npm-shrinkwrap.json
new file mode 100644
index 0000000000000000000000000000000000000000..c064b4aa3200b8f6023bf91ad49ca8c93936315e
--- /dev/null
+++ b/packages/rocketchat-importer-hipchat-enterprise/.npm/package/npm-shrinkwrap.json
@@ -0,0 +1,81 @@
+{
+  "dependencies": {
+    "bl": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz",
+      "from": "bl@>=1.0.0 <2.0.0",
+      "dependencies": {
+        "readable-stream": {
+          "version": "2.0.6",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
+          "from": "readable-stream@>=2.0.5 <2.1.0"
+        }
+      }
+    },
+    "buffer-shims": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz",
+      "from": "buffer-shims@>=1.0.0 <2.0.0"
+    },
+    "core-util-is": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+      "from": "core-util-is@>=1.0.0 <1.1.0"
+    },
+    "end-of-stream": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.1.0.tgz",
+      "from": "end-of-stream@>=1.0.0 <2.0.0"
+    },
+    "inherits": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+      "from": "inherits@>=2.0.1 <2.1.0"
+    },
+    "isarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+      "from": "isarray@>=1.0.0 <1.1.0"
+    },
+    "once": {
+      "version": "1.3.3",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz",
+      "from": "once@>=1.3.0 <1.4.0"
+    },
+    "process-nextick-args": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+      "from": "process-nextick-args@>=1.0.6 <1.1.0"
+    },
+    "readable-stream": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.2.tgz",
+      "from": "readable-stream@>=2.0.0 <3.0.0"
+    },
+    "string_decoder": {
+      "version": "0.10.31",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+      "from": "string_decoder@>=0.10.0 <0.11.0"
+    },
+    "tar-stream": {
+      "version": "1.5.2",
+      "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.2.tgz",
+      "from": "tar-stream@1.5.2"
+    },
+    "util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "from": "util-deprecate@>=1.0.1 <1.1.0"
+    },
+    "wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "from": "wrappy@>=1.0.0 <2.0.0"
+    },
+    "xtend": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
+      "from": "xtend@>=4.0.0 <5.0.0"
+    }
+  }
+}
diff --git a/packages/rocketchat-importer-hipchat-enterprise/main.js b/packages/rocketchat-importer-hipchat-enterprise/main.js
new file mode 100644
index 0000000000000000000000000000000000000000..69dfcb1f778a10e18e4a9e59afd70af8fcc5c76a
--- /dev/null
+++ b/packages/rocketchat-importer-hipchat-enterprise/main.js
@@ -0,0 +1,15 @@
+/* globals Importer */
+
+Importer.addImporter('hipchatenterprise', Importer.HipChatEnterprise, {
+	name: 'HipChat Enterprise',
+	warnings: [
+		{
+			text: 'Importer_HipChatEnterprise_Information',
+			href: 'https://rocket.chat/docs/administrator-guides/import/hipchat/enterprise/'
+		}, {
+			text: 'Importer_HipChatEnterprise_BetaWarning',
+			href: 'https://github.com/RocketChat/Rocket.Chat/issues/new'
+		}
+	],
+	mimeType: 'application/gzip'
+});
diff --git a/packages/rocketchat-importer-hipchat-enterprise/package.js b/packages/rocketchat-importer-hipchat-enterprise/package.js
new file mode 100644
index 0000000000000000000000000000000000000000..76844dae9fa622e23c6a5f9dd6419967b056f7f3
--- /dev/null
+++ b/packages/rocketchat-importer-hipchat-enterprise/package.js
@@ -0,0 +1,22 @@
+Package.describe({
+	name: 'rocketchat:importer-hipchat-enterprise',
+	version: '1.0.0',
+	summary: 'Importer for Hipchat Importer Files',
+	git: ''
+});
+
+Package.onUse(function(api) {
+	api.use([
+		'ecmascript',
+		'rocketchat:lib',
+		'rocketchat:importer'
+	]);
+
+	api.use('rocketchat:logger', 'server');
+	api.addFiles('server.js', 'server');
+	api.addFiles('main.js', ['client', 'server']);
+});
+
+Npm.depends({
+	'tar-stream': '1.5.2'
+});
diff --git a/packages/rocketchat-importer-hipchat-enterprise/server.js b/packages/rocketchat-importer-hipchat-enterprise/server.js
new file mode 100644
index 0000000000000000000000000000000000000000..42e007012eb59cff36204189a03ffa18b66a231e
--- /dev/null
+++ b/packages/rocketchat-importer-hipchat-enterprise/server.js
@@ -0,0 +1,461 @@
+/* globals Importer */
+
+Importer.HipChatEnterprise = class ImporterHipChatEnterprise extends Importer.Base {
+	constructor(name, descriptionI18N, mimeType) {
+		super(name, descriptionI18N, mimeType);
+		this.logger.debug('Constructed a new HipChat Enterprise Importer.');
+
+		this.Readable = require('stream').Readable;
+		this.zlib = require('zlib');
+		this.tarStream = Npm.require('tar-stream');
+		this.extract = this.tarStream.extract();
+		this.path = require('path');
+		this.messages = new Map();
+		this.directMessages = new Map();
+	}
+
+	prepare(dataURI, sentContentType, fileName) {
+		super.prepare(dataURI, sentContentType, fileName);
+
+		const tempUsers = [];
+		const tempRooms = [];
+		const tempMessages = new Map();
+		const tempDirectMessages = new Map();
+		const promise = new Promise((resolve, reject) => {
+			this.extract.on('entry', Meteor.bindEnvironment((header, stream, next) => {
+				if (header.name.indexOf('.json') !== -1) {
+					const info = this.path.parse(header.name);
+
+					stream.on('data', Meteor.bindEnvironment((chunk) => {
+						this.logger.debug(`Processing the file: ${header.name}`);
+						const file = JSON.parse(chunk);
+
+						if (info.base === 'users.json') {
+							super.updateProgress(Importer.ProgressStep.PREPARING_USERS);
+							for (let u of file) {
+								tempUsers.push({
+									id: u.User.id,
+									email: u.User.email,
+									name: u.User.name,
+									username: u.User.mention_name,
+									avatar: u.User.avatar.replace(/\n/g, ''),
+									timezone: u.User.timezone,
+									isDeleted: u.User.is_deleted
+								});
+							}
+						} else if (info.base === 'rooms.json') {
+							super.updateProgress(Importer.ProgressStep.PREPARING_CHANNELS);
+							for (let r of file) {
+								tempRooms.push({
+									id: r.Room.id,
+									creator: r.Room.owner,
+									created: new Date(r.Room.created),
+									name: r.Room.name.replace(/ /g, '_').toLowerCase(),
+									isPrivate: r.Room.privacy === 'private',
+									isArchived: r.Room.is_archived,
+									topic: r.Room.topic
+								});
+							}
+						} else if (info.base === 'history.json') {
+							const dirSplit = info.dir.split('/'); //['.', 'users', '1']
+							const roomIdentifier = `${dirSplit[1]}/${dirSplit[2]}`;
+
+							if (dirSplit[1] === 'users') {
+								const msgs = [];
+								for (let m of file) {
+									if (m.PrivateUserMessage) {
+										msgs.push({
+											type: 'user',
+											id: `hipchatenterprise-${m.PrivateUserMessage.id}`,
+											senderId: m.PrivateUserMessage.sender.id,
+											receiverId: m.PrivateUserMessage.receiver.id,
+											text: m.PrivateUserMessage.message.indexOf('/me ') === -1 ? m.PrivateUserMessage.message : `${m.PrivateUserMessage.message.replace(/\/me /, '_')}_`,
+											ts: new Date(m.PrivateUserMessage.timestamp.split(' ')[0])
+										});
+									}
+								}
+								tempDirectMessages.set(roomIdentifier, msgs);
+							} else if (dirSplit[1] === 'rooms') {
+								const roomMsgs = [];
+
+								for (let m of file) {
+									if (m.UserMessage) {
+										roomMsgs.push({
+											type: 'user',
+											id: `hipchatenterprise-${dirSplit[2]}-${m.UserMessage.id}`,
+											userId: m.UserMessage.sender.id,
+											text: m.UserMessage.message.indexOf('/me ') === -1 ? m.UserMessage.message : `${m.UserMessage.message.replace(/\/me /, '_')}_`,
+											ts: new Date(m.UserMessage.timestamp.split(' ')[0])
+										});
+									} else if (m.TopicRoomMessage) {
+										roomMsgs.push({
+											type: 'topic',
+											id: `hipchatenterprise-${dirSplit[2]}-${m.TopicRoomMessage.id}`,
+											userId: m.TopicRoomMessage.sender.id,
+											ts: new Date(m.TopicRoomMessage.timestamp.split(' ')[0]),
+											text: m.TopicRoomMessage.message
+										});
+									} else {
+										this.logger.warn('HipChat Enterprise importer isn\'t configured to handle this message:', m);
+									}
+								}
+								tempMessages.set(roomIdentifier, roomMsgs);
+							} else {
+								this.logger.warn(`HipChat Enterprise importer isn't configured to handle "${dirSplit[1]}" files.`);
+							}
+						} else {
+							//What are these files!?
+							this.logger.warn(`HipChat Enterprise importer doesn't know what to do with the file "${header.name}" :o`, info);
+						}
+					}));
+
+					stream.on('end', () => next());
+					stream.on('error', () => next());
+				} else {
+					next();
+				}
+			}));
+
+			this.extract.on('error', (err) => {
+				this.logger.warn('extract error:', err);
+				reject();
+			});
+
+			this.extract.on('finish', Meteor.bindEnvironment(() => {
+				// Insert the users record, eventually this might have to be split into several ones as well
+				// if someone tries to import a several thousands users instance
+				const usersId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'users', 'users': tempUsers });
+				this.users = this.collection.findOne(usersId);
+				super.updateRecord({ 'count.users': tempUsers.length });
+				super.addCountToTotal(tempUsers.length);
+
+				// Insert the channels records.
+				const channelsId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'channels', 'channels': tempRooms });
+				this.channels = this.collection.findOne(channelsId);
+				super.updateRecord({ 'count.channels': tempRooms.length });
+				super.addCountToTotal(tempRooms.length);
+
+				// Save the messages records to the import record for `startImport` usage
+				super.updateProgress(Importer.ProgressStep.PREPARING_MESSAGES);
+				let messagesCount = 0;
+				for (let [channel, msgs] of tempMessages.entries()) {
+					if (!this.messages.get(channel)) {
+						this.messages.set(channel, new Map());
+					}
+
+					messagesCount += msgs.length;
+					super.updateRecord({ 'messagesstatus': channel });
+
+					if (Importer.Base.getBSONSize(msgs) > Importer.Base.MaxBSONSize) {
+						Importer.Base.getBSONSafeArraysFromAnArray(msgs).forEach((splitMsg, i) => {
+							const messagesId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'messages', 'name': `${channel}/${i}`, 'messages': splitMsg });
+							this.messages.get(channel).set(`${channel}.${i}`, this.collection.findOne(messagesId));
+						});
+					} else {
+						const messagesId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'messages', 'name': `${channel}`, 'messages': msgs });
+						this.messages.get(channel).set(channel, this.collection.findOne(messagesId));
+					}
+				}
+
+				for (let [directMsgUser, msgs] of tempDirectMessages.entries()) {
+					this.logger.debug(`Preparing the direct messages for: ${directMsgUser}`);
+					if (!this.directMessages.get(directMsgUser)) {
+						this.directMessages.set(directMsgUser, new Map());
+					}
+
+					messagesCount += msgs.length;
+					super.updateRecord({ 'messagesstatus': directMsgUser });
+
+					if (Importer.Base.getBSONSize(msgs) > Importer.Base.MaxBSONSize) {
+						Importer.Base.getBSONSafeArraysFromAnArray(msgs).forEach((splitMsg, i) => {
+							const messagesId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'directMessages', 'name': `${directMsgUser}/${i}`, 'messages': splitMsg });
+							this.directMessages.get(directMsgUser).set(`${directMsgUser}.${i}`, this.collection.findOne(messagesId));
+						});
+					} else {
+						const messagesId = this.collection.insert({ 'import': this.importRecord._id, 'importer': this.name, 'type': 'directMessages', 'name': `${directMsgUser}`, 'messages': msgs });
+						this.directMessages.get(directMsgUser).set(directMsgUser, this.collection.findOne(messagesId));
+					}
+				}
+
+				super.updateRecord({ 'count.messages': messagesCount, 'messagesstatus': null });
+				super.addCountToTotal(messagesCount);
+
+				//Ensure we have some users, channels, and messages
+				if (tempUsers.length === 0 || tempRooms.length === 0 || messagesCount === 0) {
+					this.logger.warn(`The loaded users count ${tempUsers.length}, the loaded rooms ${tempRooms.length}, and the loaded messages ${messagesCount}`);
+					super.updateProgress(Importer.ProgressStep.ERROR);
+					reject();
+					return;
+				}
+
+				const selectionUsers = tempUsers.map((u) => new Importer.SelectionUser(u.id, u.username, u.email, u.isDeleted, false, true));
+				const selectionChannels = tempRooms.map((r) => new Importer.SelectionChannel(r.id, r.name, r.isArchived, true, r.isPrivate));
+
+				super.updateProgress(Importer.ProgressStep.USER_SELECTION);
+
+				resolve(new Importer.Selection(this.name, selectionUsers, selectionChannels));
+			}));
+
+			//Wish I could make this cleaner :(
+			const split = dataURI.split(',');
+			const s = new this.Readable;
+			s.push(new Buffer(split[split.length - 1], 'base64'));
+			s.push(null);
+			s.pipe(this.zlib.createGunzip()).pipe(this.extract);
+		});
+
+		return promise;
+	}
+
+	startImport(importSelection) {
+		super.startImport(importSelection);
+		const started = Date.now();
+
+		//Ensure we're only going to import the users that the user has selected
+		for (let user of importSelection.users) {
+			for (let u of this.users.users) {
+				if (u.id === user.user_id) {
+					u.do_import = user.do_import;
+				}
+			}
+		}
+		this.collection.update({ _id: this.users._id }, { $set: { 'users': this.users.users }});
+
+		//Ensure we're only importing the channels the user has selected.
+		for (let channel of importSelection.channels) {
+			for (let c of this.channels.channels) {
+				if (c.id === channel.channel_id) {
+					c.do_import = channel.do_import;
+				}
+			}
+		}
+		this.collection.update({ _id: this.channels._id }, { $set: { 'channels': this.channels.channels }});
+
+		const startedByUserId = Meteor.userId();
+		Meteor.defer(() => {
+			super.updateProgress(Importer.ProgressStep.IMPORTING_USERS);
+			//Import the users
+			for (let u of this.users.users) {
+				this.logger.debug(`Starting the user import: ${u.username} and are we importing them? ${u.do_import}`);
+				if (!u.do_import) {
+					continue;
+				}
+
+				Meteor.runAsUser(startedByUserId, () => {
+					let existantUser = RocketChat.models.Users.findOneByEmailAddress(u.email);
+
+					//If we couldn't find one by their email address, try to find an existing user by their username
+					if (!existantUser) {
+						existantUser = RocketChat.models.Users.findOneByUsername(u.username);
+					}
+
+					if (existantUser) {
+						//since we have an existing user, let's try a few things
+						u.rocketId = existantUser._id;
+						RocketChat.models.Users.update({ _id: u.rocketId }, { $addToSet: { importIds: u.id } });
+					} else {
+						const userId = Accounts.createUser({ email: u.email, password: Date.now() + u.name + u.email.toUpperCase() });
+						Meteor.runAsUser(userId, () => {
+							Meteor.call('setUsername', u.username, {joinDefaultChannelsSilenced: true});
+							//TODO: Use moment timezone to calc the time offset - Meteor.call 'userSetUtcOffset', user.tz_offset / 3600
+							RocketChat.models.Users.setName(userId, u.name);
+							//TODO: Think about using a custom field for the users "title" field
+
+							if (u.avatar) {
+								Meteor.call('setAvatarFromService', `data:image/png;base64,${u.avatar}`);
+							}
+
+							//Deleted users are 'inactive' users in Rocket.Chat
+							if (u.deleted) {
+								Meteor.call('setUserActiveStatus', userId, false);
+							}
+
+							RocketChat.models.Users.update({ _id: userId }, { $addToSet: { importIds: u.id } });
+							u.rocketId = userId;
+						});
+					}
+
+					super.addCountCompleted(1);
+				});
+			}
+			this.collection.update({ _id: this.users._id }, { $set: { 'users': this.users.users }});
+
+			//Import the channels
+			super.updateProgress(Importer.ProgressStep.IMPORTING_CHANNELS);
+			for (let c of this.channels.channels) {
+				if (!c.do_import) {
+					continue;
+				}
+
+				Meteor.runAsUser(startedByUserId, () => {
+					let existantRoom = RocketChat.models.Rooms.findOneByName(c.name);
+					//If the room exists or the name of it is 'general', then we don't need to create it again
+					if (existantRoom || c.name.toUpperCase() === 'GENERAL') {
+						c.rocketId = c.name.toUpperCase() === 'GENERAL' ? 'GENERAL' : existantRoom._id;
+						RocketChat.models.Rooms.update({ _id: c.rocketId }, { $addToSet: { importIds: c.id } });
+					} else {
+						//Find the rocketchatId of the user who created this channel
+						let creatorId = startedByUserId;
+						for (let u of this.users.users) {
+							if (u.id === c.creator && u.do_import) {
+								creatorId = u.rocketId;
+							}
+						}
+
+						//Create the channel
+						Meteor.runAsUser(creatorId, () => {
+							const roomInfo = Meteor.call(c.isPrivate ? 'createPrivateGroup' : 'createChannel', c.name, []);
+							c.rocketId = roomInfo.rid;
+						});
+
+						RocketChat.models.Rooms.update({ _id: c.rocketId }, { $set: { ts: c.created, topic: c.topic }, $addToSet: { importIds: c.id } });
+					}
+
+					super.addCountCompleted(1);
+				});
+			}
+			this.collection.update({ _id: this.channels._id }, { $set: { 'channels': this.channels.channels }});
+
+			//Import the Messages
+			super.updateProgress(Importer.ProgressStep.IMPORTING_MESSAGES);
+			for (let [ch, messagesMap] of this.messages.entries()) {
+				const hipChannel = this.getChannelFromRoomIdentifier(ch);
+				if (!hipChannel.do_import) {
+					continue;
+				}
+
+				const room = RocketChat.models.Rooms.findOneById(hipChannel.rocketId, { fields: { usernames: 1, t: 1, name: 1 } });
+				Meteor.runAsUser(startedByUserId, () => {
+					for (let [msgGroupData, msgs] of messagesMap.entries()) {
+						super.updateRecord({ 'messagesstatus': `${ch}/${msgGroupData}.${msgs.messages.length}` });
+						for (let msg of msgs.messages) {
+							if (isNaN(msg.ts)) {
+								this.logger.warn(`Timestamp on a message in ${ch}/${msgGroupData} is invalid`);
+								super.addCountCompleted(1);
+								continue;
+							}
+
+							const creator = this.getRocketUserFromUserId(msg.userId);
+							if (creator) {
+								switch (msg.type) {
+									case 'user':
+										RocketChat.sendMessage(creator, {
+											_id: msg.id,
+											ts: msg.ts,
+											msg: msg.text,
+											rid: room._id,
+											u: {
+												_id: creator._id,
+												username: creator.username
+											}
+										}, room, true);
+										break;
+									case 'topic':
+										RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser('room_changed_topic', room._id, msg.text, creator, { _id: msg.id, ts: msg.ts });
+										break;
+								}
+							}
+
+							super.addCountCompleted(1);
+						}
+					}
+				});
+			}
+
+			//Import the Direct Messages
+			for (let [directMsgRoom, directMessagesMap] of this.directMessages.entries()) {
+				const hipUser = this.getUserFromDirectMessageIdentifier(directMsgRoom);
+				if (!hipUser.do_import) {
+					continue;
+				}
+
+				//Verify this direct message user's room is valid (confusing but idk how else to explain it)
+				if (!this.getRocketUserFromUserId(hipUser.id)) {
+					continue;
+				}
+
+				for (let [msgGroupData, msgs] of directMessagesMap.entries()) {
+					super.updateRecord({ 'messagesstatus': `${directMsgRoom}/${msgGroupData}.${msgs.messages.length}` });
+					for (let msg of msgs.messages) {
+						if (isNaN(msg.ts)) {
+							this.logger.warn(`Timestamp on a message in ${directMsgRoom}/${msgGroupData} is invalid`);
+							super.addCountCompleted(1);
+							continue;
+						}
+
+						//make sure the message sender is a valid user inside rocket.chat
+						const sender = this.getRocketUserFromUserId(msg.senderId);
+						if (!sender) {
+							continue;
+						}
+
+						//make sure the receiver of the message is a valid rocket.chat user
+						const receiver = this.getRocketUserFromUserId(msg.receiverId);
+						if (!receiver) {
+							continue;
+						}
+
+						let room = RocketChat.models.Rooms.findOneById([receiver._id, sender._id].sort().join(''));
+						if (!room) {
+							Meteor.runAsUser(sender._id, () => {
+								const roomInfo = Meteor.call('createDirectMessage', receiver.username);
+								room = RocketChat.models.Rooms.findOneById(roomInfo.rid);
+							});
+						}
+
+						Meteor.runAsUser(sender._id, () => {
+							RocketChat.sendMessage(sender, {
+								_id: msg.id,
+								ts: msg.ts,
+								msg: msg.text,
+								rid: room._id,
+								u: {
+									_id: sender._id,
+									username: sender.username
+								}
+							}, room, true);
+						});
+					}
+				}
+			}
+
+			super.updateProgress(Importer.ProgressStep.FINISHING);
+			super.updateProgress(Importer.ProgressStep.DONE);
+			const timeTook = Date.now() - started;
+			this.logger.log(`HipChat Enterprise Import took ${timeTook} milliseconds.`);
+		});
+
+		return super.getProgress();
+	}
+
+	getSelection() {
+		const selectionUsers = this.users.users.map((u) => new Importer.SelectionUser(u.id, u.username, u.email, false, false, true));
+		const selectionChannels = this.channels.channels.map((c) => new Importer.SelectionChannel(c.id, c.name, false, true, c.isPrivate));
+
+		return new Importer.Selection(this.name, selectionUsers, selectionChannels);
+	}
+
+	getChannelFromRoomIdentifier(roomIdentifier) {
+		for (let ch of this.channels.channels) {
+			if (`rooms/${ch.id}` === roomIdentifier) {
+				return ch;
+			}
+		}
+	}
+
+	getUserFromDirectMessageIdentifier(directIdentifier) {
+		for (let u of this.users.users) {
+			if (`users/${u.id}` === directIdentifier) {
+				return u;
+			}
+		}
+	}
+
+	getRocketUserFromUserId(userId) {
+		for (let u of this.users.users) {
+			if (u.id === userId) {
+				return RocketChat.models.Users.findOneById(u.rocketId, { fields: { username: 1 }});
+			}
+		}
+	}
+};
diff --git a/packages/rocketchat-importer-hipchat/main.coffee b/packages/rocketchat-importer-hipchat/main.coffee
index 441aa85e0b9f1f9d38a213afce3d6465ffb90cd0..1198383d75c6a801856f1fd8f6b44f93e3731d0e 100644
--- a/packages/rocketchat-importer-hipchat/main.coffee
+++ b/packages/rocketchat-importer-hipchat/main.coffee
@@ -1,3 +1,3 @@
 Importer.addImporter 'hipchat', Importer.HipChat,
 	name: 'HipChat'
-	fileTypeRegex: new RegExp 'application\/.*?zip'
+	mimeType: 'application/zip'
diff --git a/packages/rocketchat-importer-hipchat/server.coffee b/packages/rocketchat-importer-hipchat/server.coffee
index 80f79a5b41c333e6e7e256a68430f28976ec7fb7..c84a6413b8f1fae11bcd5e4134d335ec16b70932 100644
--- a/packages/rocketchat-importer-hipchat/server.coffee
+++ b/packages/rocketchat-importer-hipchat/server.coffee
@@ -5,8 +5,8 @@ Importer.HipChat = class Importer.HipChat extends Importer.Base
 	@RoomPrefix = 'hipchat_export/rooms/'
 	@UsersPrefix = 'hipchat_export/users/'
 
-	constructor: (name, descriptionI18N, fileTypeRegex) ->
-		super(name, descriptionI18N, fileTypeRegex)
+	constructor: (name, descriptionI18N, mimeType) ->
+		super(name, descriptionI18N, mimeType)
 		@logger.debug('Constructed a new Slack Importer.')
 		@userTags = []
 
@@ -135,8 +135,7 @@ Importer.HipChat = class Importer.HipChat extends Importer.Base
 								hipchat: "@#{user.mention_name}"
 								rocket: "@#{user.mention_name}"
 							Meteor.runAsUser userId, () =>
-								Meteor.call 'setUsername', user.mention_name
-								Meteor.call 'joinDefaultChannels', true
+								Meteor.call 'setUsername', user.mention_name, {joinDefaultChannelsSilenced: true}
 								Meteor.call 'setAvatarFromService', user.photo_url, undefined, 'url'
 								Meteor.call 'userSetUtcOffset', parseInt moment().tz(user.timezone).format('Z').toString().split(':')[0]
 
diff --git a/packages/rocketchat-importer-slack/main.coffee b/packages/rocketchat-importer-slack/main.coffee
index 62e470ded88e2e99ab70f156df1b8a26aa7a2836..da0518e538746aec7087d8489e95646a4ad79a8a 100644
--- a/packages/rocketchat-importer-slack/main.coffee
+++ b/packages/rocketchat-importer-slack/main.coffee
@@ -1,3 +1,3 @@
 Importer.addImporter 'slack', Importer.Slack,
 	name: 'Slack'
-	fileTypeRegex: new RegExp 'application\/.*?zip'
+	mimeType: 'application/zip'
diff --git a/packages/rocketchat-importer-slack/server.coffee b/packages/rocketchat-importer-slack/server.coffee
index 85813b34d6e234b0551e4af2209e4d2b075bc214..ccd1975175cc941fcdecc8a5272b13c64c2f6857 100644
--- a/packages/rocketchat-importer-slack/server.coffee
+++ b/packages/rocketchat-importer-slack/server.coffee
@@ -1,6 +1,6 @@
 Importer.Slack = class Importer.Slack extends Importer.Base
-	constructor: (name, descriptionI18N, fileTypeRegex) ->
-		super(name, descriptionI18N, fileTypeRegex)
+	constructor: (name, descriptionI18N, mimeType) ->
+		super(name, descriptionI18N, mimeType)
 		@userTags = []
 		@bots = {}
 		@logger.debug('Constructed a new Slack Importer.')
@@ -126,10 +126,9 @@ Importer.Slack = class Importer.Slack extends Importer.Base
 							if user.profile.email
 								userId = Accounts.createUser { email: user.profile.email, password: Date.now() + user.name + user.profile.email.toUpperCase() }
 							else
-								userId = Accounts.createUser { username: user.name, password: Date.now() + user.name }
+								userId = Accounts.createUser { username: user.name, password: Date.now() + user.name, joinDefaultChannelsSilenced: true }
 							Meteor.runAsUser userId, () =>
-								Meteor.call 'setUsername', user.name
-								Meteor.call 'joinDefaultChannels', true
+								Meteor.call 'setUsername', user.name, {joinDefaultChannelsSilenced: true}
 								url = null
 								if user.profile.image_original
 									url = user.profile.image_original
diff --git a/packages/rocketchat-importer/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-importer/.npm/package/npm-shrinkwrap.json
index 4fb75e8129e6a98c1a9a020fbdf16a0850365369..238dae99d6986a1bec8c53c14bf877b752638f43 100644
--- a/packages/rocketchat-importer/.npm/package/npm-shrinkwrap.json
+++ b/packages/rocketchat-importer/.npm/package/npm-shrinkwrap.json
@@ -9,6 +9,11 @@
       "version": "0.5.5",
       "resolved": "https://registry.npmjs.org/bson/-/bson-0.5.5.tgz",
       "from": "bson@0.5.5"
+    },
+    "file-type": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.0.0.tgz",
+      "from": "file-type@4.0.0"
     }
   }
 }
diff --git a/packages/rocketchat-importer/client/admin/adminImport.html b/packages/rocketchat-importer/client/admin/adminImport.html
index 03a7a274faa02cfe55978b7b1d6d024d867fd296..3e22cbcbc29dbafba76c20ac61bf869d207f0d1d 100644
--- a/packages/rocketchat-importer/client/admin/adminImport.html
+++ b/packages/rocketchat-importer/client/admin/adminImport.html
@@ -1,6 +1,6 @@
 <template name="adminImport">
 	<section class="page-container page-home page-static page-settings">
-		<header class="fixed-title">
+		<header class="fixed-title border-component-color">
 			{{> burger}}
 			<h2>
 				<span class="room-title">Import</span>
diff --git a/packages/rocketchat-importer/client/admin/adminImportPrepare.coffee b/packages/rocketchat-importer/client/admin/adminImportPrepare.coffee
index b246e4ffaf516b2faaab144aff5dec813d438931..823418efed047b62b312260eda1f49f4610f2274 100644
--- a/packages/rocketchat-importer/client/admin/adminImportPrepare.coffee
+++ b/packages/rocketchat-importer/client/admin/adminImportPrepare.coffee
@@ -23,6 +23,8 @@ Template.adminImportPrepare.helpers
 Template.adminImportPrepare.events
 	'change .import-file-input': (event, template) ->
 		importer = @
+		return if not importer.key
+
 		e = event.originalEvent or event
 		files = e.target.files
 		if not files or files.length is 0
@@ -30,18 +32,14 @@ Template.adminImportPrepare.events
 
 		for blob in files
 			template.preparing.set true
-			if not importer.fileTypeRegex.test blob.type
-				toastr.error t('Invalid_Import_File_Type')
-				template.preparing.set false
-				return
 
 			reader = new FileReader()
 			reader.readAsDataURL(blob)
 			reader.onloadend = ->
 				Meteor.call 'prepareImport', importer.key, reader.result, blob.type, blob.name, (error, data) ->
 					if error
-						console.warn 'Errored out preparing the import:', error
-						handleError(error)
+						toastr.error t('Invalid_Import_File_Type')
+						template.preparing.set false
 						return
 
 					if !data
@@ -51,7 +49,7 @@ Template.adminImportPrepare.events
 						return
 
 					if data.step
-						console.warn 'Invalid file.'
+						console.warn 'Invalid file, contains `data.step`.', data
 						toastr.error t('Invalid_Export_File', importer.key)
 						template.preparing.set false
 						return
@@ -131,21 +129,24 @@ Template.adminImportPrepare.onCreated ->
 			console.warn 'Invalid progress information.', progress
 
 	# Load the initial progress to determine what we need to do
-	Meteor.call 'getImportProgress', FlowRouter.getParam('importer'), (error, progress) ->
-		if error
-			console.warn 'Error while getting the import progress:', error
-			handleError error
-			return
-
-		# if the progress isnt defined, that means there currently isn't an instance
-		# of the importer, so we need to create it
-		if progress is undefined
-			Meteor.call 'setupImporter', FlowRouter.getParam('importer'), (err, data) ->
-				if err
-					handleError(err)
-				instance.preparing.set false
-				loadSelection(data)
-		else
-			# Otherwise, we might need to do something based upon the current step
-			# of the import
-			loadSelection(progress)
+	if FlowRouter.getParam('importer')
+		Meteor.call 'getImportProgress', FlowRouter.getParam('importer'), (error, progress) ->
+			if error
+				console.warn 'Error while getting the import progress:', error
+				handleError error
+				return
+
+			# if the progress isnt defined, that means there currently isn't an instance
+			# of the importer, so we need to create it
+			if progress is undefined
+				Meteor.call 'setupImporter', FlowRouter.getParam('importer'), (err, data) ->
+					if err
+						handleError(err)
+					instance.preparing.set false
+					loadSelection(data)
+			else
+				# Otherwise, we might need to do something based upon the current step
+				# of the import
+				loadSelection(progress)
+	else
+		FlowRouter.go '/admin/import'
diff --git a/packages/rocketchat-importer/client/admin/adminImportPrepare.html b/packages/rocketchat-importer/client/admin/adminImportPrepare.html
index 5c0504c70f467a3abac04e8e533854ca22a26fd0..cac461eb89e7b7c7002d66a9a5f598eb0e06f62c 100644
--- a/packages/rocketchat-importer/client/admin/adminImportPrepare.html
+++ b/packages/rocketchat-importer/client/admin/adminImportPrepare.html
@@ -1,7 +1,7 @@
 <template name="adminImportPrepare">
 	<section class="page-container page-home page-static page-settings">
 		{{#with importer}}
-			<header class="fixed-title">
+			<header class="fixed-title border-component-color">
 				{{> burger}}
 				<h2>
 					<span class="room-title">{{name}}</span>
@@ -70,7 +70,7 @@
 									<div class="section">
 										<h1>{{_ "Importer_Source_File"}}</h1>
 										<div class="section-content">
-											<input type="file" class="import-file-input" accept="{{ fileType }}">
+											<input type="file" class="import-file-input">
 										</div>
 									</div>
 								{{/if}}
diff --git a/packages/rocketchat-importer/client/admin/adminImportProgress.html b/packages/rocketchat-importer/client/admin/adminImportProgress.html
index 1ff4725ffc5e2dedd64ea18c0c19a50c8e1b2730..6f8d95c00e66192f4c28bbac9bc7ce8017827c30 100644
--- a/packages/rocketchat-importer/client/admin/adminImportProgress.html
+++ b/packages/rocketchat-importer/client/admin/adminImportProgress.html
@@ -1,28 +1,5 @@
 <template name="adminImportProgress">
-	<svg class="rocket-loader" version="1.1" x="0px" y="0px" width="200" height="275" viewBox="0 0 200 275" enable-background="new 0 0 200 275" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
-		<g>
-			<g>
-				<path class="outer" fill="#CC3333" d="m188.146,99.881c0,-8.852 -2.647,-17.341 -7.873,-25.23199c-4.69098,-7.083 -11.263,-13.354 -19.53299,
-					-18.637c-15.96701,-10.199 -36.953,-15.817 -59.089,-15.817c-7.395,0 -14.68201,0.625 -21.75102,1.863c-4.38699,-4.105 -9.521,-7.798 -14.953,
-					-10.72c-29.024,-14.066 -53.09401,-0.331 -53.09401,-0.331s22.379,18.383 18.739,34.499c-10.012,9.931 -15.438,21.90601 -15.438,34.375c0,
-					0.04 0.002,0.08 0.003,0.119c-0.001,0.04 -0.003,0.08 -0.003,0.119c0,12.46899 5.426,24.44299 15.438,34.37499c3.64,16.11401 -18.739,
-					34.498 -18.739,34.498s24.069,13.735 53.09401,-0.33c5.433,-2.922 10.566,-6.61501 14.953,-10.72101c7.06902,1.239 14.356,1.86302 21.75102,
-					1.86302c22.13599,0 43.12199,-5.617 59.089,-15.81599c8.27098,-5.28201 14.84201,-11.554 19.53299,-18.63701c5.226,-7.89201 7.873,-16.38 7.873,
-					-25.23201c0,-0.04 -0.002,-0.08 -0.002,-0.119s0.002,-0.07999 0.002,-0.119l0,-0.00002l0,0.00001l0,0.00001z" />
-				<path class="inner" fill="#FFFFFF" d="m101.686,51.726c41.84301,0 75.76501,21.667 75.76501,48.395c0,26.728 -33.922,48.396 -75.76501,48.396c-9.31699,
-					0 -18.239,-1.076 -26.48299,-3.04199c-8.37801,10.07999 -26.809,24.09201 -44.713,19.562c5.823,-6.25499 14.452,-16.825 12.604,-34.23299c-10.731,
-					-8.35101 -17.173,-19.03699 -17.173,-30.68301c0,-26.728 33.921,-48.395 75.76499,-48.395" />
-				<g>
-					<circle fill="#CC3333" cx="136.68" cy="100.121" r="10.063" />
-					<circle fill="#CC3333" cx="101.685" cy="100.121" r="10.064" />
-					<circle fill="#CC3333" cx="66.691" cy="100.121" r="10.064" />
-				</g>
-				<path class="inner" fill="#CCCCCC" d="m101.686,142.149c-9.31699,0 -18.239,-0.933 -26.48299,-2.636c-7.397,7.713 -22.634,18.08099 -38.425,
-					17.69901c-2.079,3.153 -4.34,5.73199 -6.288,7.82399c17.904,4.53 36.335,-9.481 44.713,-19.562c8.244,1.966 17.166,3.04201 26.48299,
-					3.04201c41.507,0 75.214,-21.32401 75.75201,-47.755c-0.53899,22.909 -34.24599,41.38801 -75.75201,41.38801l0,-0.00002z" />
-			</g>
-			<text xml:space="preserve" text-anchor="middle" font-family="serif" font-size="24" y="245" x="100" stroke-width="0" stroke="#000000" fill="#044974">{{step}}</text>
-			<text fill="#044974" stroke="#000000" stroke-width="0" x="100.01563" y="270" font-size="24" font-family="serif" text-anchor="middle" xml:space="preserve">{{completed}} / {{total}}</text>
-		</g>
-	</svg>
+	{{> loading}}
+	<p>{{step}}</p>
+	<p>{{completed}} / {{total}}</p>
 </template>
diff --git a/packages/rocketchat-importer/lib/importTool.coffee b/packages/rocketchat-importer/lib/importTool.coffee
index 861b7ce8af55dc6a2e347b6faa7f97cc39df5144..99514e045e9a059092fd7e887da717a296eb65e8 100644
--- a/packages/rocketchat-importer/lib/importTool.coffee
+++ b/packages/rocketchat-importer/lib/importTool.coffee
@@ -5,5 +5,5 @@ Importer.addImporter = (name, importer, options) ->
 		Importer.Importers[name] =
 			name: options.name
 			importer: importer
-			fileTypeRegex: options.fileTypeRegex
+			mimeType: options.mimeType
 			warnings: options.warnings
diff --git a/packages/rocketchat-importer/package.js b/packages/rocketchat-importer/package.js
index bb33f0da6125e1cc5fd096a0b22e9760fa29ad5d..5820b21e2ac7b13a34e21357e2a19518f824cb23 100644
--- a/packages/rocketchat-importer/package.js
+++ b/packages/rocketchat-importer/package.js
@@ -34,7 +34,7 @@ Package.onUse(function(api) {
 	//Server methods
 	api.addFiles('server/methods/getImportProgress.coffee', 'server');
 	api.addFiles('server/methods/getSelectionData.coffee', 'server');
-	api.addFiles('server/methods/prepareImport.coffee', 'server');
+	api.addFiles('server/methods/prepareImport.js', 'server');
 	api.addFiles('server/methods/restartImport.coffee', 'server');
 	api.addFiles('server/methods/setupImporter.coffee', 'server');
 	api.addFiles('server/methods/startImport.coffee', 'server');
diff --git a/packages/rocketchat-importer/server/classes/ImporterBase.coffee b/packages/rocketchat-importer/server/classes/ImporterBase.coffee
index 2e1a3771dd97eb751f8576f36aa09bf5bc184f5a..197e76d48ee86a6b76bdd5a7c22ba17bb3b1bf26 100644
--- a/packages/rocketchat-importer/server/classes/ImporterBase.coffee
+++ b/packages/rocketchat-importer/server/classes/ImporterBase.coffee
@@ -38,13 +38,14 @@ Importer.Base = class Importer.Base
 	#
 	# @param [String] name the name of the Importer
 	# @param [String] description the i18n string which describes the importer
-	# @param [RegExp] fileTypeRegex the regexp to validate the uploaded file type against
+	# @param [String] mimeType the of the expected file type
 	#
-	constructor: (@name, @description, @fileTypeRegex) ->
+	constructor: (@name, @description, @mimeType) ->
 		@logger = new Logger("#{@name} Importer", {});
 		@progress = new Importer.Progress @name
 		@collection = Importer.RawImports
 		@AdmZip = Npm.require 'adm-zip'
+		@getFileType = Npm.require 'file-type'
 		importId = Importer.Imports.insert { 'type': @name, 'ts': Date.now(), 'status': @progress.step, 'valid': true, 'user': Meteor.user()._id }
 		@importRecord = Importer.Imports.findOne importId
 		@users = {}
@@ -60,8 +61,13 @@ Importer.Base = class Importer.Base
 	# @return [Importer.Selection] Contains two properties which are arrays of objects, `channels` and `users`.
 	#
 	prepare: (dataURI, sentContentType, fileName) =>
-		if not @fileTypeRegex.test sentContentType
-			throw new Error "Invalid file uploaded to import #{@name} data from." #TODO: Make translatable
+		fileType = @getFileType(new Buffer(dataURI.split(',')[1], 'base64'))
+		@logger.debug 'Uploaded file information is:', fileType
+		@logger.debug 'Expected file type is:', @mimeType
+
+		if not fileType or fileType.mime isnt @mimeType
+			@logger.warn "Invalid file uploaded for the #{@name} importer."
+			throw new Meteor.Error('error-invalid-file-uploaded', "Invalid file uploaded to import #{@name} data from.", { step: 'prepare' })
 
 		@updateProgress Importer.ProgressStep.PREPARING_STARTED
 		@updateRecord { 'file': fileName }
diff --git a/packages/rocketchat-importer/server/methods/prepareImport.coffee b/packages/rocketchat-importer/server/methods/prepareImport.coffee
deleted file mode 100644
index a1bab14a5fa096f3728b8f4ebfe7399db075db02..0000000000000000000000000000000000000000
--- a/packages/rocketchat-importer/server/methods/prepareImport.coffee
+++ /dev/null
@@ -1,9 +0,0 @@
-Meteor.methods
-	prepareImport: (name, dataURI, contentType, fileName) ->
-		if not Meteor.userId()
-			throw new Meteor.Error 'error-invalid-user', 'Invalid user', { method: 'prepareImport' }
-
-		if Importer.Importers[name]?.importerInstance?
-			Importer.Importers[name].importerInstance.prepare dataURI, contentType, fileName
-		else
-			throw new Meteor.Error 'error-importer-not-defined', 'The importer was not defined correctly, it is missing the Import class.', { method: 'prepareImport' }
diff --git a/packages/rocketchat-importer/server/methods/prepareImport.js b/packages/rocketchat-importer/server/methods/prepareImport.js
new file mode 100644
index 0000000000000000000000000000000000000000..88b5ded9a7b4353d3e1e41c6f9ec103e07288287
--- /dev/null
+++ b/packages/rocketchat-importer/server/methods/prepareImport.js
@@ -0,0 +1,29 @@
+/* globals Importer */
+
+Meteor.methods({
+	prepareImport(name, dataURI, contentType, fileName) {
+		if (!Meteor.userId()) {
+			throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'prepareImport' });
+		}
+
+		check(name, String);
+		check(dataURI, String);
+		check(fileName, String);
+
+		if (name && Importer.Importers[name] && Importer.Importers[name].importerInstance) {
+			const results = Importer.Importers[name].importerInstance.prepare(dataURI, contentType, fileName);
+
+			if (typeof results === 'object') {
+				if (results instanceof Promise) {
+					return results.catch(e => { throw new Meteor.Error(e); });
+				} else {
+					return results;
+				}
+			}
+		} else if (!name) {
+			throw new Meteor.Error('error-importer-not-defined', `No Importer Found: "${name}"`, { method: 'prepareImport' });
+		} else {
+			throw new Meteor.Error('error-importer-not-defined', `The importer, "${name}", was not defined correctly, it is missing the Import class.`, { method: 'prepareImport' });
+		}
+	}
+});
diff --git a/packages/rocketchat-importer/server/methods/restartImport.coffee b/packages/rocketchat-importer/server/methods/restartImport.coffee
index 97b14c33e4b1bf116b4db96527f8c71603706deb..7df99cb95fee582ce0c1ce0249060937b6c5c18b 100644
--- a/packages/rocketchat-importer/server/methods/restartImport.coffee
+++ b/packages/rocketchat-importer/server/methods/restartImport.coffee
@@ -8,7 +8,7 @@ Meteor.methods
 			importer.importerInstance.updateProgress Importer.ProgressStep.CANCELLED
 			importer.importerInstance.updateRecord { valid: false }
 			importer.importerInstance = undefined
-			importer.importerInstance = new importer.importer importer.name, importer.description, importer.fileTypeRegex
+			importer.importerInstance = new importer.importer importer.name, importer.description, importer.mimeType
 			return importer.importerInstance.getProgress()
 		else
 			throw new Meteor.Error 'error-importer-not-defined', 'The importer was not defined correctly, it is missing the Import class.', { method: 'restartImport' }
diff --git a/packages/rocketchat-importer/server/methods/setupImporter.coffee b/packages/rocketchat-importer/server/methods/setupImporter.coffee
index b74f2f34c485c94f731c6c02c2761c1234d771cd..7e9e89e353a16e1342987419707da9a48c8a3561 100644
--- a/packages/rocketchat-importer/server/methods/setupImporter.coffee
+++ b/packages/rocketchat-importer/server/methods/setupImporter.coffee
@@ -9,7 +9,7 @@ Meteor.methods
 			if importer.importerInstance
 				return importer.importerInstance.getProgress()
 			else
-				importer.importerInstance = new importer.importer importer.name, importer.description, importer.fileTypeRegex
+				importer.importerInstance = new importer.importer importer.name, importer.description, importer.mimeType
 				return importer.importerInstance.getProgress()
 		else
 			console.warn "Tried to setup #{name} as an importer."
diff --git a/packages/rocketchat-integrations/client/stylesheets/integrations.less b/packages/rocketchat-integrations/client/stylesheets/integrations.less
index 04e51fba4147ca476d46d19543868a8f8c117399..d2a41bc010071cd5dc066b1d077be690fc631be6 100644
--- a/packages/rocketchat-integrations/client/stylesheets/integrations.less
+++ b/packages/rocketchat-integrations/client/stylesheets/integrations.less
@@ -3,17 +3,17 @@
 		display: flex;
 		align-items: center;
 		padding: 20px 10px;
-		color: #444;
-		border-bottom: 1px solid #ddd;
+		color: #444444;
+		border-bottom: 1px solid #dddddd;
 		cursor: pointer;
 
 		&:hover {
 			background-color: #fafafa;
 		}
 
-		>i {
+		> i {
 			font-size: 2rem;
-			color: #aaa;
+			color: #aaaaaa;
 		}
 
 		.admin-integrations-new-item-body {
@@ -32,7 +32,7 @@
 		.admin-integrations-new-item-description {
 			font-size: 1rem;
 			line-height: 1.5rem;
-			color: #aaa;
+			color: #aaaaaa;
 		}
 	}
 
diff --git a/packages/rocketchat-integrations/client/stylesheets/load.coffee b/packages/rocketchat-integrations/client/stylesheets/load.coffee
deleted file mode 100644
index 88d4bb35ad139307960ae22ec551881e3ae329ff..0000000000000000000000000000000000000000
--- a/packages/rocketchat-integrations/client/stylesheets/load.coffee
+++ /dev/null
@@ -1,2 +0,0 @@
-RocketChat.theme.addPackageAsset ->
-	return Assets.getText 'client/stylesheets/integrations.less'
diff --git a/packages/rocketchat-integrations/client/views/integrationsIncoming.coffee b/packages/rocketchat-integrations/client/views/integrationsIncoming.coffee
index 68f912fc07eeb80d7dd6571569e1ea230e9708af..06655c651879466940003bf2422c6e50e1f7085f 100644
--- a/packages/rocketchat-integrations/client/views/integrationsIncoming.coffee
+++ b/packages/rocketchat-integrations/client/views/integrationsIncoming.coffee
@@ -154,12 +154,12 @@ Template.integrationsIncoming.events
 
 	"click .button-fullscreen": ->
 		codeMirrorBox = $('.code-mirror-box')
-		codeMirrorBox.addClass('code-mirror-box-fullscreen')
+		codeMirrorBox.addClass('code-mirror-box-fullscreen content-background-color')
 		codeMirrorBox.find('.CodeMirror')[0].CodeMirror.refresh()
 
 	"click .button-restore": ->
 		codeMirrorBox = $('.code-mirror-box')
-		codeMirrorBox.removeClass('code-mirror-box-fullscreen')
+		codeMirrorBox.removeClass('code-mirror-box-fullscreen content-background-color')
 		codeMirrorBox.find('.CodeMirror')[0].CodeMirror.refresh()
 
 	"click .submit > .save": ->
diff --git a/packages/rocketchat-integrations/client/views/integrationsIncoming.html b/packages/rocketchat-integrations/client/views/integrationsIncoming.html
index 51f2ec9d52a8f3a93dec0011b8dfb5298f635ac3..68955e653b5d4bb836e8350e1762d611f79de1eb 100644
--- a/packages/rocketchat-integrations/client/views/integrationsIncoming.html
+++ b/packages/rocketchat-integrations/client/views/integrationsIncoming.html
@@ -16,15 +16,15 @@
 							<label>{{_ "Name"}} ({{_ "optional"}})</label>
 							<div>
 								<input type="text" name="name" value="{{data.name}}" placeholder="{{_ 'Optional'}}" />
-								<div class="settings-description">{{_ "You_should_name_it_to_easily_manage_your_integrations"}}</div>
+								<div class="settings-description secondary-font-color">{{_ "You_should_name_it_to_easily_manage_your_integrations"}}</div>
 							</div>
 						</div>
 						<div class="input-line double-col">
 							<label>{{_ "Post_to_Channel"}}</label>
 							<div>
 								<input type="text" name="channel" value="{{data.channel}}" placeholder="{{_ 'User_or_channel_name'}}" />
-								<div class="settings-description">{{_ "Messages_that_are_sent_to_the_Incoming_WebHook_will_be_posted_here"}}</div>
-								<div class="settings-description">{{{_ "Start_with_s_for_user_or_s_for_channel_Eg_s_or_s" "@" "#" "@john" "#general"}}}</div>
+								<div class="settings-description secondary-font-color">{{_ "Messages_that_are_sent_to_the_Incoming_WebHook_will_be_posted_here"}}</div>
+								<div class="settings-description secondary-font-color">{{{_ "Start_with_s_for_user_or_s_for_channel_Eg_s_or_s" "@" "#" "@john" "#general"}}}</div>
 							</div>
 						</div>
 						<div class="input-line double-col">
@@ -35,31 +35,31 @@
 								{{else}}
 									<input type="text" name="username" value="{{data.username}}" />
 								{{/if}}
-								<div class="settings-description">{{_ "Choose_the_username_that_this_integration_will_post_as"}}</div>
-								<div class="settings-description">{{_ "Should_exists_a_user_with_this_username"}}</div>
+								<div class="settings-description secondary-font-color">{{_ "Choose_the_username_that_this_integration_will_post_as"}}</div>
+								<div class="settings-description secondary-font-color">{{_ "Should_exists_a_user_with_this_username"}}</div>
 							</div>
 						</div>
 						<div class="input-line double-col">
 							<label>{{_ "Alias"}} ({{_ "optional"}})</label>
 							<div>
 								<input type="text" name="alias" value="{{data.alias}}" placeholder="{{_ 'Optional'}}" />
-								<div class="settings-description">{{_ "Choose_the_alias_that_will_appear_before_the_username_in_messages"}}</div>
+								<div class="settings-description secondary-font-color">{{_ "Choose_the_alias_that_will_appear_before_the_username_in_messages"}}</div>
 							</div>
 						</div>
 						<div class="input-line double-col">
 							<label>{{_ "Avatar_URL"}} ({{_ "optional"}})</label>
 							<div>
 								<input type="url" name="avatar" value="{{data.avatar}}" placeholder="{{_ 'Optional'}}" />
-								<div class="settings-description">{{_ "You_can_change_a_different_avatar_too"}}</div>
-								<div class="settings-description">{{_ "Should_be_a_URL_of_an_image"}}</div>
+								<div class="settings-description secondary-font-color">{{_ "You_can_change_a_different_avatar_too"}}</div>
+								<div class="settings-description secondary-font-color">{{_ "Should_be_a_URL_of_an_image"}}</div>
 							</div>
 						</div>
 						<div class="input-line double-col">
 							<label>{{_ "Emoji"}} ({{_ "optional"}})</label>
 							<div>
 								<input type="text" name="emoji" value="{{data.emoji}}" placeholder="{{_ 'Optional'}}" />
-								<div class="settings-description">{{_ "You_can_use_an_emoji_as_avatar"}}</div>
-								<div class="settings-description">{{{_ "Example_s" ":ghost:"}}}</div>
+								<div class="settings-description secondary-font-color">{{_ "You_can_use_an_emoji_as_avatar"}}</div>
+								<div class="settings-description secondary-font-color">{{{_ "Example_s" ":ghost:"}}}</div>
 							</div>
 						</div>
 						<div class="input-line double-col">
@@ -84,10 +84,10 @@
 								</div>
 								{{#if data.scriptError}}
 									<div class="code-error-box">
-										<div class="title">
+										<div class="title color-content-background-color background-error-color">
 											{{data.scriptError.name}}
 										</div>
-										<pre>{{data.scriptError.message}}</pre>
+										<pre class="script-error background-transparent-lightest error-color error-border">{{data.scriptError.message}}</pre>
 									</div>
 								{{/if}}
 							</div>
@@ -97,25 +97,25 @@
 								<label>Webhook URL</label>
 								<div>
 									<input type="text" name="webhookurl" value="{{data.url}}" readonly="readonly" />
-									<div class="settings-description">{{_ "Send_your_JSON_payloads_to_this_URL"}}</div>
-									<div class="settings-description"><button class="clipboard" data-clipboard-target="[name=webhookurl]">{{_ "COPY_TO_CLIPBOARD"}}</button></div>
+									<div class="settings-description secondary-font-color">{{_ "Send_your_JSON_payloads_to_this_URL"}}</div>
+									<div class="settings-description secondary-font-color"><button class="clipboard" data-clipboard-target="[name=webhookurl]">{{_ "COPY_TO_CLIPBOARD"}}</button></div>
 								</div>
 							</div>
 							<div class="input-line double-col">
 								<label>Token</label>
 								<div>
 									<input type="text" name="completeToken" value="{{data.completeToken}}" readonly="readonly" />
-									<div class="settings-description"><button class="clipboard" data-clipboard-target="[name=completeToken]">{{_ "COPY_TO_CLIPBOARD"}}</button></div>
+									<div class="settings-description secondary-font-color"><button class="clipboard" data-clipboard-target="[name=completeToken]">{{_ "COPY_TO_CLIPBOARD"}}</button></div>
 								</div>
 							</div>
 						{{/if}}
 						<div class="input-line double-col">
 							<label>{{_ "Example"}}</label>
 							<div>
-								<pre><code class="hljs json json-example">{{{exampleJson}}}</code></pre>
+								<pre><code class="code-colors hljs json json-example">{{{exampleJson}}}</code></pre>
 								{{#if curl}}
 									<input type="text" name="curl" value="{{curl}}" readonly="readonly" />
-									<div class="settings-description"><button class="clipboard" data-clipboard-target="[name=curl]">{{_ "COPY_TO_CLIPBOARD"}}</button></div>
+									<div class="settings-description secondary-font-color"><button class="clipboard" data-clipboard-target="[name=curl]">{{_ "COPY_TO_CLIPBOARD"}}</button></div>
 								{{/if}}
 							</div>
 						</div>
diff --git a/packages/rocketchat-integrations/client/views/integrationsOutgoing.coffee b/packages/rocketchat-integrations/client/views/integrationsOutgoing.coffee
index 7b78f0cc0e7d6eb59eb4f8cafb0c8c8124b84417..bb13783bfefd7502c88bf76ca8b0e581f1d306ad 100644
--- a/packages/rocketchat-integrations/client/views/integrationsOutgoing.coffee
+++ b/packages/rocketchat-integrations/client/views/integrationsOutgoing.coffee
@@ -136,11 +136,11 @@ Template.integrationsOutgoing.events
 					FlowRouter.go "admin-integrations"
 
 	"click .button-fullscreen": ->
-		$('.code-mirror-box').addClass('code-mirror-box-fullscreen');
+		$('.code-mirror-box').addClass('code-mirror-box-fullscreen content-background-color');
 		$('.CodeMirror')[0].CodeMirror.refresh()
 
 	"click .button-restore": ->
-		$('.code-mirror-box').removeClass('code-mirror-box-fullscreen');
+		$('.code-mirror-box').removeClass('code-mirror-box-fullscreen content-background-color');
 		$('.CodeMirror')[0].CodeMirror.refresh()
 
 	"click .submit > .save": ->
diff --git a/packages/rocketchat-integrations/client/views/integrationsOutgoing.html b/packages/rocketchat-integrations/client/views/integrationsOutgoing.html
index ef06ec00ecef62be459b92c92a66d6003b849979..ed690600e5e0c78a3f694885ba17c817f780d03d 100644
--- a/packages/rocketchat-integrations/client/views/integrationsOutgoing.html
+++ b/packages/rocketchat-integrations/client/views/integrationsOutgoing.html
@@ -110,10 +110,10 @@
 								</div>
 								{{#if data.scriptError}}
 									<div class="code-error-box">
-										<div class="title">
+										<div class="title color-content-background-color background-error-color">
 											{{data.scriptError.name}}
 										</div>
-										<pre>{{data.scriptError.message}}</pre>
+										<pre class="script-error background-transparent-lightest error-color error-border">{{data.scriptError.message}}</pre>
 									</div>
 								{{/if}}
 							</div>
@@ -122,7 +122,7 @@
 							<label>{{_ "Responding"}}</label>
 							<div>
 								<div class="settings-description">{{{_ "If the handler wishes to post a response back into the channel, the following JSON should be returned as the body of the response:"}}}</div>
-								<pre><code class="hljs json json-example">{{{exampleJson}}}</code></pre>
+								<pre><code class="code-colors hljs json json-example">{{{exampleJson}}}</code></pre>
 								<div class="settings-description">{{{_ "Empty bodies or bodies with an empty text property will simply be ignored. Non-200 responses will be retried a reasonable number of times. A response will be posted using the alias and avatar specified above. You can override these informations as in the example above."}}}</div>
 							</div>
 						</div>
diff --git a/packages/rocketchat-integrations/package.js b/packages/rocketchat-integrations/package.js
index eee59622436d549c17a82c331d680c989c58f984..d339476abdc5d1b5ccc0f5ef19da29c49e4e4e62 100644
--- a/packages/rocketchat-integrations/package.js
+++ b/packages/rocketchat-integrations/package.js
@@ -17,6 +17,7 @@ Package.onUse(function(api) {
 	api.use('rocketchat:api');
 	api.use('rocketchat:theme');
 	api.use('rocketchat:logger');
+	api.use('less');
 
 	api.use('kadira:flow-router', 'client');
 	api.use('templating', 'client');
@@ -37,8 +38,7 @@ Package.onUse(function(api) {
 	api.addFiles('client/views/integrationsOutgoing.coffee', 'client');
 
 	// stylesheets
-	api.addAssets('client/stylesheets/integrations.less', 'server');
-	api.addFiles('client/stylesheets/load.coffee', 'server');
+	api.addFiles('client/stylesheets/integrations.less', 'client');
 
 	api.addFiles('server/logger.js', 'server');
 	api.addFiles('server/lib/validation.coffee', 'server');
diff --git a/packages/rocketchat-integrations/server/api/api.coffee b/packages/rocketchat-integrations/server/api/api.coffee
index 1786e0ce2fe348f1167090bbd600bce3a1f4bb45..ff2a99e96da47912e779a152a81bf6c243d4f9bb 100644
--- a/packages/rocketchat-integrations/server/api/api.coffee
+++ b/packages/rocketchat-integrations/server/api/api.coffee
@@ -50,7 +50,10 @@ Api = new Restivus
 	apiPath: 'hooks/'
 	auth:
 		user: ->
-			if @bodyParams?.payload?
+			payloadKeys = Object.keys @bodyParams
+			payloadIsWrapped = @bodyParams?.payload? and payloadKeys.length == 1
+
+			if payloadIsWrapped and @request.headers['content-type'] is 'application/x-www-form-urlencoded'
 				@bodyParams = JSON.parse @bodyParams.payload
 
 			@integration = RocketChat.models.Integrations.findOne
@@ -237,17 +240,6 @@ integrationInfoRest = ->
 		body:
 			success: true
 
-
-RocketChat.API.v1.addRoute 'integrations.create', authRequired: true,
-	post: ->
-		return createIntegration @bodyParams, @user
-
-
-RocketChat.API.v1.addRoute 'integrations.remove', authRequired: true,
-	post: ->
-		return removeIntegration @bodyParams, @user
-
-
 Api.addRoute ':integrationId/:userId/:token', authRequired: true, {post: executeIntegrationRest, get: executeIntegrationRest}
 Api.addRoute ':integrationId/:token', authRequired: true, {post: executeIntegrationRest, get: executeIntegrationRest}
 
diff --git a/packages/rocketchat-integrations/server/methods/incoming/addIncomingIntegration.coffee b/packages/rocketchat-integrations/server/methods/incoming/addIncomingIntegration.coffee
index bcf6823ba0824df5d3f5a1090d02b85bc420c797..66335efef3e46405c5ed5b310d7810729cafaabb 100644
--- a/packages/rocketchat-integrations/server/methods/incoming/addIncomingIntegration.coffee
+++ b/packages/rocketchat-integrations/server/methods/incoming/addIncomingIntegration.coffee
@@ -69,6 +69,7 @@ Meteor.methods
 
 		integration.type = 'webhook-incoming'
 		integration.token = token
+		integration.channel = channels
 		integration.userId = user._id
 		integration._createdAt = new Date
 		integration._createdBy = RocketChat.models.Users.findOne @userId, {fields: {username: 1}}
diff --git a/packages/rocketchat-integrations/server/processWebhookMessage.js b/packages/rocketchat-integrations/server/processWebhookMessage.js
index 56730a50d55c120b9163b3333c3855a51a167b94..ad4e301bf674d07f19939aed88de06a418e4c78c 100644
--- a/packages/rocketchat-integrations/server/processWebhookMessage.js
+++ b/packages/rocketchat-integrations/server/processWebhookMessage.js
@@ -1,5 +1,48 @@
+function retrieveRoomInfo({ currentUserId, channel, ignoreEmpty=false }) {
+	const room = RocketChat.models.Rooms.findOneByIdOrName(channel);
+	if (!_.isObject(room) && !ignoreEmpty) {
+		throw new Meteor.Error('invalid-channel');
+	}
+
+	if (room && room.t === 'c') {
+		Meteor.runAsUser(currentUserId, function() {
+			return Meteor.call('joinRoom', room._id);
+		});
+	}
+
+	return room;
+}
+
+function retrieveDirectMessageInfo({ currentUserId, channel, findByUserIdOnly=false }) {
+	let roomUser = undefined;
+
+	if (findByUserIdOnly) {
+		roomUser = RocketChat.models.Users.findOneById(channel);
+	} else {
+		roomUser = RocketChat.models.Users.findOne({
+			$or: [{ _id: channel }, { username: channel }]
+		});
+	}
+
+	if (!_.isObject(roomUser)) {
+		throw new Meteor.Error('invalid-channel');
+	}
+
+	const rid = [currentUserId, roomUser._id].sort().join('');
+	let room = RocketChat.models.Rooms.findOneById({ $in: [rid, channel] });
+
+	if (!room) {
+		Meteor.runAsUser(currentUserId, function() {
+			Meteor.call('createDirectMessage', roomUser.username);
+			room = RocketChat.models.Rooms.findOneById(rid);
+		});
+	}
+
+	return room;
+}
+
 this.processWebhookMessage = function(messageObj, user, defaultValues) {
-	var attachment, channel, channels, channelType, i, len, message, ref, rid, room, roomUser, ret;
+	var attachment, channel, channels, channelType, i, len, message, ref, room, ret;
 	ret = [];
 
 	if (!defaultValues) {
@@ -11,7 +54,7 @@ this.processWebhookMessage = function(messageObj, user, defaultValues) {
 		};
 	}
 
-	channel = messageObj.channel || defaultValues.channel;
+	channel = messageObj.channel || messageObj.roomId || defaultValues.channel;
 
 	channels = [].concat(channel);
 
@@ -22,41 +65,26 @@ this.processWebhookMessage = function(messageObj, user, defaultValues) {
 
 		switch (channelType) {
 			case '#':
-				room = RocketChat.models.Rooms.findOneByIdOrName(channel);
-				if (!_.isObject(room)) {
-					throw new Meteor.Error('invalid-channel');
-				}
-				rid = room._id;
-				if (room.t === 'c') {
-					Meteor.runAsUser(user._id, function() {
-						return Meteor.call('joinRoom', room._id);
-					});
-				}
+				room = retrieveRoomInfo({ currentUserId: user._id, channel });
 				break;
 			case '@':
-				roomUser = RocketChat.models.Users.findOne({
-					$or: [
-						{
-							_id: channel
-						}, {
-							username: channel
-						}
-					]
-				}) || {};
-				rid = [user._id, roomUser._id].sort().join('');
-				room = RocketChat.models.Rooms.findOneById({$in: [rid, channel]});
-				if (!_.isObject(roomUser) && !_.isObject(room)) {
-					throw new Meteor.Error('invalid-channel');
-				}
-				if (!room) {
-					Meteor.runAsUser(user._id, function() {
-						Meteor.call('createDirectMessage', roomUser.username);
-						room = RocketChat.models.Rooms.findOneById(rid);
-					});
-				}
+				room = retrieveDirectMessageInfo({ currentUserId: user._id, channel });
 				break;
 			default:
-				throw new Meteor.Error('invalid-channel-type');
+				//Try to find the room by id or name if they didn't include the prefix.
+				room = retrieveRoomInfo({ currentUserId: user._id, channel: channelType + channel, ignoreEmpty: true });
+				if (room) {
+					break;
+				}
+
+				//We didn't get a room, let's try finding direct messages
+				room = retrieveDirectMessageInfo({ currentUserId: user._id, channel: channelType + channel, findByUserIdOnly: true });
+				if (room) {
+					break;
+				}
+
+				//No room, so throw an error
+				throw new Meteor.Error('invalid-channel');
 		}
 
 		if (messageObj.attachments && !_.isArray(messageObj.attachments)) {
diff --git a/packages/rocketchat-integrations/server/triggers.coffee b/packages/rocketchat-integrations/server/triggers.coffee
index 324f4040eb56b48d36b5d4bd841890c1a6073627..3835d5de61f9ce8ceaa480b2cf1be6545563ad29 100644
--- a/packages/rocketchat-integrations/server/triggers.coffee
+++ b/packages/rocketchat-integrations/server/triggers.coffee
@@ -132,6 +132,7 @@ ExecuteTriggerUrl = (url, trigger, message, room, tries=0) ->
 			return
 
 	data =
+		message_id: message._id
 		token: trigger.token
 		channel_id: room._id
 		channel_name: room.name
diff --git a/packages/rocketchat-irc/server/server.coffee b/packages/rocketchat-irc/server/server.coffee
index 032635abd7fba691effb395ad1dc30fa27d1f70b..4f753e1683eb1e101e5192f5d8ca3ce911aa436c 100644
--- a/packages/rocketchat-irc/server/server.coffee
+++ b/packages/rocketchat-irc/server/server.coffee
@@ -1,6 +1,6 @@
 # # #
 # Assign values
-# 
+#
 
 # Package availability
 IRC_AVAILABILITY = RocketChat.settings.get('IRC_Enabled');
@@ -19,7 +19,7 @@ IRC_HOST = RocketChat.settings.get('IRC_Host');
 ircClientMap = {}
 
 
-# # # 
+# # #
 # Core functionality
 #
 
@@ -237,7 +237,7 @@ class IrcClient
 		@sendRawMessage msg
 
 	initRoomList: ->
-		roomsCursor = RocketChat.models.Rooms.findByTypeContainigUsername 'c', @user.username,
+		roomsCursor = RocketChat.models.Rooms.findByTypeContainingUsername 'c', @user.username,
 			fields:
 				name: 1
 				t: 1
@@ -396,7 +396,7 @@ class IrcLogoutCleanUper
 
 
 # # #
-# Make magic happen 
+# Make magic happen
 #
 
 # Only proceed if the package has been enabled
diff --git a/packages/rocketchat-katex/katex.coffee b/packages/rocketchat-katex/katex.coffee
index 6b07134a39ca99b51f095d47020c259e7338d05a..f108ab9b6ea4972bee05aa0f0c043dd8b29ebc64 100644
--- a/packages/rocketchat-katex/katex.coffee
+++ b/packages/rocketchat-katex/katex.coffee
@@ -2,6 +2,9 @@
 # KaTeX is a fast, easy-to-use JavaScript library for TeX math rendering on the web.
 # https://github.com/Khan/KaTeX
 ###
+
+import katex from './client/katex/katex.min.js'
+
 class Katex
 	constructor: ->
 		@delimiters_map = [
diff --git a/packages/rocketchat-katex/package.js b/packages/rocketchat-katex/package.js
index c7f561b190deb26fc646353f0d1beeab2491ab13..300f7f86b12a7786a2d1eb064f918efc9062d464 100644
--- a/packages/rocketchat-katex/package.js
+++ b/packages/rocketchat-katex/package.js
@@ -15,7 +15,6 @@ Package.onUse(function(api) {
 
 	api.addFiles('settings.coffee', 'server');
 	api.addFiles('katex.coffee');
-	api.addFiles('client/katex/katex.min.js', 'client');
 	api.addFiles('client/katex/katex.min.css', 'client');
 	api.addFiles('client/style.css', 'client');
 
diff --git a/packages/rocketchat-ldap/server/loginHandler.js b/packages/rocketchat-ldap/server/loginHandler.js
index 9c396c2eae638a793d8612b2a9c51f4c59b7b032..b142dfd2c49df155b682c7999ea3bf58c1751436 100644
--- a/packages/rocketchat-ldap/server/loginHandler.js
+++ b/packages/rocketchat-ldap/server/loginHandler.js
@@ -12,7 +12,7 @@ function fallbackDefaultAccountSystem(bind, username, password) {
 		}
 	}
 
-	logger.info('Fallback to default account systen', username);
+	logger.info('Fallback to default account system', username);
 
 	const loginRequest = {
 		user: username,
diff --git a/packages/rocketchat-ldap/server/sync.js b/packages/rocketchat-ldap/server/sync.js
index bce6c278f7ac4ddf43e08ae0c35a683d5037eb90..d235b7cc49daadf7f9f93325a4c792295a830368 100644
--- a/packages/rocketchat-ldap/server/sync.js
+++ b/packages/rocketchat-ldap/server/sync.js
@@ -187,11 +187,6 @@ addLdapUser = function addLdapUser(ldapUser, username, password) {
 
 	syncUserData(userObject, ldapUser);
 
-	logger.info('Joining user to default channels');
-	Meteor.runAsUser(userObject._id, function() {
-		Meteor.call('joinDefaultChannels');
-	});
-
 	return {
 		userId: userObject._id
 	};
@@ -226,6 +221,8 @@ sync = function sync() {
 
 				if (!user) {
 					addLdapUser(ldapUser, username);
+				} else if (user.ldap !== true && RocketChat.settings.get('LDAP_Merge_Existing_Users') === true) {
+					syncUserData(user, ldapUser);
 				}
 			});
 		}
diff --git a/packages/rocketchat-lib/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-lib/.npm/package/npm-shrinkwrap.json
index d31e308b77e624019bc0e7abeed7883ae3230348..d2ac7e3c6b8c266d560b99c4069a68147fded02c 100644
--- a/packages/rocketchat-lib/.npm/package/npm-shrinkwrap.json
+++ b/packages/rocketchat-lib/.npm/package/npm-shrinkwrap.json
@@ -324,6 +324,11 @@
       "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.4.2.tgz",
       "from": "localforage@1.4.2"
     },
+    "lokijs": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/lokijs/-/lokijs-1.4.1.tgz",
+      "from": "lokijs@1.4.1"
+    },
     "mime-db": {
       "version": "1.24.0",
       "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.24.0.tgz",
@@ -354,6 +359,11 @@
       "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz",
       "from": "object-keys@>=1.0.6 <2.0.0"
     },
+    "object-path": {
+      "version": "0.9.2",
+      "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.9.2.tgz",
+      "from": "object-path@0.9.2"
+    },
     "pinkie": {
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
diff --git a/packages/rocketchat-lib/client/MessageAction.coffee b/packages/rocketchat-lib/client/MessageAction.coffee
index 5f066302dd271f5b2fe4ea8b8c7be993febb602e..80837c3a0bebe9e4dd587f2dcc35e2d4d9b1251c 100644
--- a/packages/rocketchat-lib/client/MessageAction.coffee
+++ b/packages/rocketchat-lib/client/MessageAction.coffee
@@ -183,8 +183,12 @@ Meteor.startup ->
 		]
 		action: (event, instance) ->
 			message = @_arguments[1]
+			permalink = RocketChat.MessageAction.getPermaLink(message._id)
 			RocketChat.MessageAction.hideDropDown()
-			$(event.currentTarget).attr('data-clipboard-text', RocketChat.MessageAction.getPermaLink(message._id));
+			if Meteor.isCordova
+				cordova.plugins.clipboard.copy(permalink);
+			else
+				$(event.currentTarget).attr('data-clipboard-text', permalink);
 			toastr.success(TAPi18n.__('Copied'))
 		validation: (message) ->
 			if not RocketChat.models.Subscriptions.findOne({ rid: message.rid })?
@@ -205,7 +209,10 @@ Meteor.startup ->
 		action: (event, instance) ->
 			message = @_arguments[1].msg
 			RocketChat.MessageAction.hideDropDown()
-			$(event.currentTarget).attr('data-clipboard-text', message)
+			if Meteor.isCordova
+				cordova.plugins.clipboard.copy(message);
+			else
+				$(event.currentTarget).attr('data-clipboard-text', message)
 			toastr.success(TAPi18n.__('Copied'))
 		validation: (message) ->
 			if not RocketChat.models.Subscriptions.findOne({ rid: message.rid })?
diff --git a/packages/rocketchat-lib/client/TabBar.coffee b/packages/rocketchat-lib/client/TabBar.coffee
index db93cc82c402eba586a7783442dcd26a63dd55d0..0a3fd17b37ddd4aab3436bed9f95c2fc426e5e1f 100644
--- a/packages/rocketchat-lib/client/TabBar.coffee
+++ b/packages/rocketchat-lib/client/TabBar.coffee
@@ -12,6 +12,9 @@ RocketChat.TabBar = new class
 
 	visibleGroup = new ReactiveVar ''
 
+	_setTemplate = (t) ->
+		template.set t
+
 	setTemplate = (t, callback) ->
 		template.set t
 		openFlex(callback)
@@ -110,6 +113,8 @@ RocketChat.TabBar = new class
 				extraGroups[id] ?= []
 				extraGroups[id] = _.union extraGroups[id], groups
 
+	_setTemplate: _setTemplate
+
 	removeGroup = (id, groups) ->
 		Tracker.nonreactive ->
 			btns = buttons.get()
diff --git a/packages/rocketchat-lib/client/lib/cachedCollection.js b/packages/rocketchat-lib/client/lib/cachedCollection.js
index 175725ed775210f0603c88f22eca357862e860fd..d5c54a69e14828d9fb29d8b8fc1db32a3f02010b 100644
--- a/packages/rocketchat-lib/client/lib/cachedCollection.js
+++ b/packages/rocketchat-lib/client/lib/cachedCollection.js
@@ -98,7 +98,7 @@ class CachedCollection {
 		useSync = true,
 		useCache = true,
 		debug = true,
-		version = 3,
+		version = 5,
 		maxCacheTime = 60*60*24*30
 	}) {
 		this.collection = collection || new Meteor.Collection(null);
@@ -195,6 +195,7 @@ class CachedCollection {
 		Meteor.call(this.methodName, (error, data) => {
 			this.log(`${data.length} records loaded from server`);
 			data.forEach((record) => {
+				delete record.$loki;
 				this.collection.upsert({ _id: record._id }, _.omit(record, '_id'));
 
 				if (record._updatedAt && record._updatedAt > this.updatedAt) {
@@ -310,9 +311,10 @@ class CachedCollection {
 	setupListener(eventType, eventName) {
 		RocketChat.Notifications[eventType || this.eventType](eventName || this.eventName, (t, record) => {
 			this.log('record received', t, record);
-			if (t === 'remove') {
+			if (t === 'removed') {
 				this.collection.remove(record._id);
 			} else {
+				delete record.$loki;
 				this.collection.upsert({ _id: record._id }, _.omit(record, '_id'));
 			}
 
diff --git a/packages/rocketchat-lib/client/lib/openRoom.coffee b/packages/rocketchat-lib/client/lib/openRoom.coffee
index 0734abde72e7562357e59834e0b7953e4f164539..ecb6e411c98585e827e53b1a4980571863f9ed9a 100644
--- a/packages/rocketchat-lib/client/lib/openRoom.coffee
+++ b/packages/rocketchat-lib/client/lib/openRoom.coffee
@@ -28,11 +28,18 @@ currentTracker = undefined
 							BlazeLayout.render 'main', {center: 'roomNotFound'}
 							return
 				else
-					Session.set 'roomNotFound', {type: type, name: name}
-					BlazeLayout.render 'main', {center: 'roomNotFound'}
+					Meteor.call 'getRoomByTypeAndName', type, name, (err, record) ->
+						if err?
+							Session.set 'roomNotFound', {type: type, name: name}
+							BlazeLayout.render 'main', {center: 'roomNotFound'}
+						else
+							delete record.$loki
+							RocketChat.models.Rooms.upsert({ _id: record._id }, _.omit(record, '_id'))
+							RoomManager.close(type + name)
+							openRoom(type, name)
+
 				return
 
-			$('.rocket-loader').remove();
 			mainNode = document.querySelector('.main-content')
 			if mainNode?
 				for child in mainNode.children
diff --git a/packages/rocketchat-lib/client/lib/roomTypes.coffee b/packages/rocketchat-lib/client/lib/roomTypes.coffee
index d77a095640dc56d51454a10008d53e15b0cc8d2d..53689c00fff491978a1bc403c4927ab429b825e7 100644
--- a/packages/rocketchat-lib/client/lib/roomTypes.coffee
+++ b/packages/rocketchat-lib/client/lib/roomTypes.coffee
@@ -21,6 +21,9 @@ RocketChat.roomTypes = new class roomTypesClient extends roomTypesCommon
 		list = _.reject @roomTypesOrder, (t) -> return except.indexOf(t.identifier) isnt -1
 		return _.map list, (t) -> return t.identifier
 
+	getUserStatus: (roomType, roomId) ->
+		return @roomTypes[roomType]?.getUserStatus?(roomId)
+
 	findRoom: (roomType, identifier, user) ->
 		return @roomTypes[roomType]?.findRoom identifier, user
 
diff --git a/packages/rocketchat-lib/client/views/customFieldsForm.html b/packages/rocketchat-lib/client/views/customFieldsForm.html
new file mode 100644
index 0000000000000000000000000000000000000000..5b067a372a0727d57db98835796110d29b8c50ac
--- /dev/null
+++ b/packages/rocketchat-lib/client/views/customFieldsForm.html
@@ -0,0 +1,26 @@
+<template name="customFieldsForm">
+	{{#each customFields}}
+		{{#if $eq field.type 'select'}}
+			<div class="input-line">
+				<label for="{{fieldName}}">{{_ fieldName}}</label>
+				<div>
+					<select name="{{fieldName}}" data-customfield="true">
+						{{#each field.options}}
+							<option value="{{.}}" selected="{{selectedField . ..}}">{{_ .}}</option>
+						{{/each}}
+					</select>
+					<div class="input-error"></div>
+				</div>
+			</div>
+		{{/if}}
+		{{#if $eq field.type 'text'}}
+			<div class="input-line">
+				<label for="{{fieldName}}">{{_ fieldName}}</label>
+				<div>
+					<input type="text" name="{{fieldName}}" id="{{fieldName}}" data-customfield="true" value="{{fieldValue}}" maxlength="{{field.maxLength}}" />
+					<div class="input-error"></div>
+				</div>
+			</div>
+		{{/if}}
+	{{/each}}
+</template>
diff --git a/packages/rocketchat-lib/client/views/customFieldsForm.js b/packages/rocketchat-lib/client/views/customFieldsForm.js
new file mode 100644
index 0000000000000000000000000000000000000000..56d5ae7e22724347515afaf6971c255fd461f877
--- /dev/null
+++ b/packages/rocketchat-lib/client/views/customFieldsForm.js
@@ -0,0 +1,59 @@
+Template.customFieldsForm.helpers({
+	customFields() {
+		const customFields = Template.instance().customFields.get();
+
+		if (!customFields) {
+			return [];
+		}
+
+		const customFieldsArray = [];
+
+		Object.keys(customFields).forEach((key) => {
+			const value = customFields[key];
+			if (value.hideFromForm === true && Template.instance().hideFromForm === true) {
+				return;
+			}
+			customFieldsArray.push({
+				fieldName: key,
+				field: value
+			});
+		});
+
+		return customFieldsArray;
+	},
+	selectedField(current, field) {
+		const formData = Template.instance().formData;
+
+		if (typeof formData[field.fieldName] !== 'undefined') {
+			return formData[field.fieldName] === current;
+		} else if (typeof field.defaultValue !== 'undefined') {
+			return field.defaultValue === current;
+		}
+	},
+	fieldValue() {
+		const formData = Template.instance().formData;
+
+		return formData[this.fieldName];
+	}
+});
+
+Template.customFieldsForm.onCreated(function() {
+	this.customFields = new ReactiveVar();
+
+	const currentData = Template.currentData();
+	this.hideFromForm = currentData && currentData.hideFromForm;
+	this.formData = (currentData && currentData.formData) || {};
+
+	Tracker.autorun(() => {
+		const Accounts_CustomFields = RocketChat.settings.get('Accounts_CustomFields');
+		if (typeof Accounts_CustomFields === 'string' && Accounts_CustomFields.trim() !== '') {
+			try {
+				this.customFields.set(JSON.parse(RocketChat.settings.get('Accounts_CustomFields')));
+			} catch (e) {
+				console.error('Invalid JSON for Accounts_CustomFields');
+			}
+		} else {
+			this.customFields.set(undefined);
+		}
+	});
+});
diff --git a/packages/rocketchat-lib/lib/roomTypesCommon.coffee b/packages/rocketchat-lib/lib/roomTypesCommon.coffee
index f18efd87c7783189958dda0a88bb4718e745731b..a351dc258922d7c20994afec0a29b84a833b54a4 100644
--- a/packages/rocketchat-lib/lib/roomTypesCommon.coffee
+++ b/packages/rocketchat-lib/lib/roomTypesCommon.coffee
@@ -60,3 +60,16 @@ class @roomTypesCommon
 
 		return FlowRouter.path @roomTypes[roomType].route.name, routeData
 
+	openRouteLink: (roomType, subData, queryParams) ->
+		unless @roomTypes[roomType]?
+			return false
+
+		routeData = {}
+
+		if @roomTypes[roomType]?.route?.link?
+			routeData = @roomTypes[roomType].route.link(subData)
+		else if subData?.name?
+			routeData = { name: subData.name }
+
+		return FlowRouter.go @roomTypes[roomType].route.name, routeData, queryParams
+
diff --git a/packages/rocketchat-lib/package.js b/packages/rocketchat-lib/package.js
index b5ca3dfe3e2ed6465f363b79ecbe2fb6221f20ad..3b0612fabb9c560fd0437ea58b7bc67a4ee324e1 100644
--- a/packages/rocketchat-lib/package.js
+++ b/packages/rocketchat-lib/package.js
@@ -7,8 +7,10 @@ Package.describe({
 
 Npm.depends({
 	'bad-words': '1.3.1',
+	'object-path': '0.9.2',
 	'node-dogstatsd': '0.0.6',
 	'localforage': '1.4.2',
+	'lokijs': '1.4.1',
 	'bugsnag': '1.8.0'
 });
 
@@ -63,6 +65,7 @@ Package.onUse(function(api) {
 	api.addFiles('server/lib/RateLimiter.coffee', 'server');
 
 	// SERVER FUNCTIONS
+	api.addFiles('server/functions/isDocker.js', 'server');
 	api.addFiles('server/functions/addUserToDefaultChannels.js', 'server');
 	api.addFiles('server/functions/addUserToRoom.js', 'server');
 	api.addFiles('server/functions/archiveRoom.js', 'server');
@@ -71,6 +74,7 @@ Package.onUse(function(api) {
 	api.addFiles('server/functions/createRoom.js', 'server');
 	api.addFiles('server/functions/deleteMessage.js', 'server');
 	api.addFiles('server/functions/deleteUser.js', 'server');
+	api.addFiles('server/functions/getFullUserData.js', 'server');
 	api.addFiles('server/functions/removeUserFromRoom.js', 'server');
 	api.addFiles('server/functions/saveUser.js', 'server');
 	api.addFiles('server/functions/saveCustomFields.js', 'server');
@@ -103,19 +107,26 @@ Package.onUse(function(api) {
 
 	api.addFiles('server/startup/statsTracker.js', 'server');
 
+	// CACHE
+	api.addFiles('server/startup/cache/CacheLoad.js', 'server');
+
 	// SERVER PUBLICATIONS
 	api.addFiles('server/publications/settings.coffee', 'server');
 
 	// SERVER METHODS
 	api.addFiles('server/methods/addOAuthService.coffee', 'server');
+	api.addFiles('server/methods/refreshOAuthService.js', 'server');
 	api.addFiles('server/methods/addUserToRoom.coffee', 'server');
 	api.addFiles('server/methods/archiveRoom.coffee', 'server');
+	api.addFiles('server/methods/blockUser.js', 'server');
 	api.addFiles('server/methods/checkRegistrationSecretURL.coffee', 'server');
 	api.addFiles('server/methods/createChannel.coffee', 'server');
 	api.addFiles('server/methods/createPrivateGroup.coffee', 'server');
 	api.addFiles('server/methods/deleteMessage.coffee', 'server');
 	api.addFiles('server/methods/deleteUserOwnAccount.js', 'server');
+	api.addFiles('server/methods/getFullUserData.js', 'server');
 	api.addFiles('server/methods/getRoomRoles.js', 'server');
+	api.addFiles('server/methods/getServerInfo.js', 'server');
 	api.addFiles('server/methods/getUserRoles.js', 'server');
 	api.addFiles('server/methods/joinRoom.coffee', 'server');
 	api.addFiles('server/methods/joinDefaultChannels.coffee', 'server');
@@ -133,9 +144,12 @@ Package.onUse(function(api) {
 	api.addFiles('server/methods/setEmail.js', 'server');
 	api.addFiles('server/methods/restartServer.coffee', 'server');
 	api.addFiles('server/methods/unarchiveRoom.coffee', 'server');
+	api.addFiles('server/methods/unblockUser.js', 'server');
 	api.addFiles('server/methods/updateMessage.coffee', 'server');
 	api.addFiles('server/methods/filterBadWords.js', ['server']);
 	api.addFiles('server/methods/filterATAllTag.js', 'server');
+	api.addFiles('server/methods/getChannelHistory.js', 'server');
+	api.addFiles('server/methods/cleanChannelHistory.js', 'server');
 
 	// SERVER STARTUP
 	api.addFiles('server/startup/settingsOnLoadCdnPrefix.coffee', 'server');
@@ -169,6 +183,10 @@ Package.onUse(function(api) {
 	api.addFiles('client/models/_Base.coffee', 'client');
 	api.addFiles('client/models/Uploads.coffee', 'client');
 
+	// CLIENT VIEWS
+	api.addFiles('client/views/customFieldsForm.html', 'client');
+	api.addFiles('client/views/customFieldsForm.js', 'client');
+
 	api.addFiles('startup/defaultRoomTypes.coffee');
 
 	// VERSION
diff --git a/packages/rocketchat-lib/rocketchat.info b/packages/rocketchat-lib/rocketchat.info
index e56b5d6f0a09a3c0f1c200bcff514da1b80c6d6c..b276990b92a8de47ed536c9895c39f37e4aaf44a 100644
--- a/packages/rocketchat-lib/rocketchat.info
+++ b/packages/rocketchat-lib/rocketchat.info
@@ -1,3 +1,3 @@
 {
-	"version": "0.47.0-develop"
+	"version": "0.50.0-develop"
 }
diff --git a/packages/rocketchat-lib/server/functions/Notifications.coffee b/packages/rocketchat-lib/server/functions/Notifications.coffee
index b8c76b744c471142bdbb25233ad4afd5a207c19c..fc81ede6be950cf1059054165a80e8e84d9f005c 100644
--- a/packages/rocketchat-lib/server/functions/Notifications.coffee
+++ b/packages/rocketchat-lib/server/functions/Notifications.coffee
@@ -33,7 +33,11 @@ RocketChat.Notifications = new class
 			roomId = eventName.split('/')[0]
 
 			user = Meteor.users.findOne @userId, {fields: {username: 1}}
-			return RocketChat.models.Rooms.findOneByIdContainigUsername(roomId, user.username, {fields: {_id: 1}})?
+			room = RocketChat.models.Rooms.findOneById(roomId)
+			if room.t is 'l' and room.v._id is user._id
+				return true
+
+			return room.usernames.indexOf(user.username) > -1
 
 		@streamRoomUsers.allowRead('none');
 
diff --git a/packages/rocketchat-lib/server/functions/createRoom.js b/packages/rocketchat-lib/server/functions/createRoom.js
index e2f325eda6ee2fbd874e2787d110e333e9f58693..bb86253791b0cdddd638635422cd71f02c340368 100644
--- a/packages/rocketchat-lib/server/functions/createRoom.js
+++ b/packages/rocketchat-lib/server/functions/createRoom.js
@@ -54,7 +54,7 @@ RocketChat.createRoom = function(type, name, owner, members, readOnly) {
 		});
 	}
 
-	room = RocketChat.models.Rooms.createWithTypeNameUserAndUsernames(type, name, owner.username, members, {
+	room = RocketChat.models.Rooms.createWithTypeNameUserAndUsernames(type, name, owner, members, {
 		ts: now,
 		ro: readOnly === true,
 		sysMes: readOnly !== true
diff --git a/packages/rocketchat-lib/server/functions/deleteMessage.js b/packages/rocketchat-lib/server/functions/deleteMessage.js
index 54ac4dd917589bf9965905af321a6570f103ee27..a193308fb2ebb80da91d1a9c793f283e85e7b05d 100644
--- a/packages/rocketchat-lib/server/functions/deleteMessage.js
+++ b/packages/rocketchat-lib/server/functions/deleteMessage.js
@@ -2,6 +2,7 @@
 RocketChat.deleteMessage = function(message, user) {
 	let keepHistory = RocketChat.settings.get('Message_KeepHistory');
 	let showDeletedStatus = RocketChat.settings.get('Message_ShowDeletedStatus');
+	let deletedMsg;
 
 	if (keepHistory) {
 		if (showDeletedStatus) {
@@ -15,12 +16,17 @@ RocketChat.deleteMessage = function(message, user) {
 		}
 	} else {
 		if (!showDeletedStatus) {
+			deletedMsg = RocketChat.models.Messages.findOneById(message._id);
 			RocketChat.models.Messages.removeById(message._id);
 		}
 
 		if (message.file && message.file._id) {
 			FileUpload.delete(message.file._id);
 		}
+
+		Meteor.defer(function() {
+			RocketChat.callbacks.run('afterDeleteMessage', deletedMsg);
+		});
 	}
 
 	if (showDeletedStatus) {
diff --git a/packages/rocketchat-lib/server/functions/getFullUserData.js b/packages/rocketchat-lib/server/functions/getFullUserData.js
new file mode 100644
index 0000000000000000000000000000000000000000..7e77af13e3603047d7877b279b79d92b432df18f
--- /dev/null
+++ b/packages/rocketchat-lib/server/functions/getFullUserData.js
@@ -0,0 +1,51 @@
+/* globals RocketChat */
+RocketChat.getFullUserData = function({userId, filter, limit}) {
+	let fields = {
+		name: 1,
+		username: 1,
+		status: 1,
+		utcOffset: 1,
+		type: 1,
+		active: 1
+	};
+
+	if (RocketChat.authz.hasPermission(userId, 'view-full-other-user-info')) {
+		fields = _.extend(fields, {
+			emails: 1,
+			phone: 1,
+			statusConnection: 1,
+			createdAt: 1,
+			lastLogin: 1,
+			services: 1,
+			requirePasswordChange: 1,
+			requirePasswordChangeReason: 1,
+			roles: 1,
+			customFields: 1
+		});
+	} else if (limit !== 0) {
+		limit = 1;
+	}
+
+	filter = s.trim(filter);
+
+	if (!filter && limit === 1) {
+		return undefined;
+	}
+
+	const options = {
+		fields: fields,
+		limit: limit,
+		sort: { username: 1 }
+	};
+
+	if (filter) {
+		if (limit === 1) {
+			return RocketChat.models.Users.findByUsername(filter, options);
+		} else {
+			const filterReg = new RegExp(s.escapeRegExp(filter), 'i');
+			return RocketChat.models.Users.findByUsernameNameOrEmailAddress(filterReg, options);
+		}
+	}
+
+	return RocketChat.models.Users.find({}, options);
+};
diff --git a/packages/rocketchat-lib/server/functions/isDocker.js b/packages/rocketchat-lib/server/functions/isDocker.js
new file mode 100644
index 0000000000000000000000000000000000000000..3ec908de64e9c0a41856ab5cc5ddeda51bc8c0ce
--- /dev/null
+++ b/packages/rocketchat-lib/server/functions/isDocker.js
@@ -0,0 +1,31 @@
+import fs from 'fs';
+
+function hasDockerEnv() {
+	try {
+		fs.statSync('/.dockerenv');
+		return true;
+	} catch (err) {
+		return false;
+	}
+}
+
+function hasDockerCGroup() {
+	try {
+		return fs.readFileSync('/proc/self/cgroup', 'utf8').indexOf('docker') !== -1;
+	} catch (err) {
+		return false;
+	}
+}
+
+function check() {
+	return hasDockerEnv() || hasDockerCGroup();
+}
+
+let isDocker;
+RocketChat.isDocker = function() {
+	if (isDocker === undefined) {
+		isDocker = check();
+	}
+
+	return isDocker;
+};
diff --git a/packages/rocketchat-lib/server/functions/saveUser.js b/packages/rocketchat-lib/server/functions/saveUser.js
index 4ba9882871e9ae0c9e65d6f387f0355ab545bbe9..ac322efd231045752e76d253c1176101bcd490f1 100644
--- a/packages/rocketchat-lib/server/functions/saveUser.js
+++ b/packages/rocketchat-lib/server/functions/saveUser.js
@@ -1,5 +1,7 @@
+/* globals Gravatar */
 RocketChat.saveUser = function(userId, userData) {
 	const user = RocketChat.models.Users.findOneById(userId);
+	let existingRoles = _.pluck(RocketChat.authz.getRoles(), '_id');
 
 	if (userData._id && userId !== userData._id && !RocketChat.authz.hasPermission(userId, 'edit-other-user-info')) {
 		throw new Meteor.Error('error-action-not-allowed', 'Editing user is not allowed', { method: 'insertOrUpdateUser', action: 'Editing_user' });
@@ -9,7 +11,11 @@ RocketChat.saveUser = function(userId, userData) {
 		throw new Meteor.Error('error-action-not-allowed', 'Adding user is not allowed', { method: 'insertOrUpdateUser', action: 'Adding_user' });
 	}
 
-	if (userData.role === 'admin' && !RocketChat.authz.hasPermission(userId, 'assign-admin-role')) {
+	if (userData.roles && _.difference(userData.roles, existingRoles).length > 0) {
+		throw new Meteor.Error('error-action-not-allowed', 'The field Roles consist invalid role name', { method: 'insertOrUpdateUser', action: 'Assign_role' });
+	}
+
+	if (userData.roles && _.indexOf(userData.roles, 'admin') >= 0 && !RocketChat.authz.hasPermission(userId, 'assign-admin-role')) {
 		throw new Meteor.Error('error-action-not-allowed', 'Assigning admin is not allowed', { method: 'insertOrUpdateUser', action: 'Assign_admin' });
 	}
 
@@ -51,7 +57,8 @@ RocketChat.saveUser = function(userId, userData) {
 		// insert user
 		const createUser = {
 			username: userData.username,
-			password: userData.password
+			password: userData.password,
+			joinDefaultChannels: userData.joinDefaultChannels
 		};
 		if (userData.email) {
 			createUser.email = userData.email;
@@ -62,7 +69,7 @@ RocketChat.saveUser = function(userId, userData) {
 		const updateUser = {
 			$set: {
 				name: userData.name,
-				roles: [ (userData.role || 'user') ]
+				roles: userData.roles || ['user']
 			}
 		};
 
@@ -76,12 +83,6 @@ RocketChat.saveUser = function(userId, userData) {
 
 		Meteor.users.update({ _id: _id }, updateUser);
 
-		if (userData.joinDefaultChannels) {
-			Meteor.runAsUser(_id, () => {
-				Meteor.call('joinDefaultChannels');
-			});
-		}
-
 		if (userData.sendWelcomeEmail) {
 			const header = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Header') || '');
 			const footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || '');
@@ -119,9 +120,33 @@ RocketChat.saveUser = function(userId, userData) {
 			});
 		}
 
+		userData._id = _id;
+
+		if (RocketChat.settings.get('Accounts_SetDefaultAvatar') === true && userData.email) {
+			let gravatarUrl = Gravatar.imageUrl(userData.email, {default: '404', size: 200, secure: true});
+
+			try {
+				RocketChat.setUserAvatar(userData, gravatarUrl, '', 'url');
+			} catch (e) {
+				//Ignore this error for now, as it not being successful isn't bad
+			}
+		}
+
 		return _id;
 	} else {
 		// update user
+		if (userData.username) {
+			RocketChat.setUsername(userData._id, userData.username);
+		}
+
+		if (userData.email) {
+			RocketChat.setEmail(userData._id, userData.email);
+		}
+
+		if (userData.password && userData.password.trim() && RocketChat.authz.hasPermission(userId, 'edit-other-user-password')) {
+			Accounts.setPassword(userData._id, userData.password.trim());
+		}
+
 		const updateUser = {
 			$set: {}
 		};
@@ -130,30 +155,20 @@ RocketChat.saveUser = function(userId, userData) {
 			updateUser.$set.name = userData.name;
 		}
 
+		if (userData.roles) {
+			updateUser.$set.roles = userData.roles;
+		}
+
 		if (userData.requirePasswordChange) {
 			updateUser.$set.requirePasswordChange = userData.requirePasswordChange;
 		}
 
 		if (userData.verified) {
-			updateUser.$set['emails.0.verified'] = true;
-		} else {
-			updateUser.$set['emails.0.verified'] = false;
+			updateUser.$set['emails.0.verified'] = userData.verified;
 		}
 
 		Meteor.users.update({ _id: userData._id }, updateUser);
 
-		if (userData.username) {
-			RocketChat.setUsername(userData._id, userData.username);
-		}
-
-		if (userData.email) {
-			RocketChat.setEmail(userData._id, userData.email);
-		}
-
-		if (userData.password && userData.password.trim() && RocketChat.authz.hasPermission(userId, 'edit-other-user-password')) {
-			Accounts.setPassword(userData._id, userData.password.trim());
-		}
-
 		return true;
 	}
 };
diff --git a/packages/rocketchat-lib/server/functions/sendMessage.coffee b/packages/rocketchat-lib/server/functions/sendMessage.coffee
index 4532d965983013a390e5a3b76d2f253d88d4c48f..bdce87faba4d40f69610db48e1f17fe269834568 100644
--- a/packages/rocketchat-lib/server/functions/sendMessage.coffee
+++ b/packages/rocketchat-lib/server/functions/sendMessage.coffee
@@ -13,7 +13,11 @@ RocketChat.sendMessage = (user, message, room, upsert = false) ->
 	message.rid = room._id
 
 	if not room.usernames? || room.usernames.length is 0
-		room = RocketChat.models.Rooms.findOneById(room._id)
+		updated_room = RocketChat.models.Rooms.findOneById(room._id)
+		if updated_room?
+			room = updated_room
+		else
+			room.usernames = []
 
 	if message.parseUrls isnt false
 		if urls = message.msg.match /([A-Za-z]{3,9}):\/\/([-;:&=\+\$,\w]+@{1})?([-A-Za-z0-9\.]+)+:?(\d+)?((\/[-\+=!:~%\/\.@\,\w]*)?\??([-\+=&!:;%@\/\.\,\w]+)?(?:#([^\s\)]+))?)?/g
diff --git a/packages/rocketchat-lib/server/functions/setUsername.coffee b/packages/rocketchat-lib/server/functions/setUsername.coffee
index 3d38c88edbf1a9b9d15feadbe454ca7f1e6521f2..66163088f331feffe3ba814cbb7895782dbee0b3 100644
--- a/packages/rocketchat-lib/server/functions/setUsername.coffee
+++ b/packages/rocketchat-lib/server/functions/setUsername.coffee
@@ -24,14 +24,27 @@ RocketChat._setUsername = (userId, username) ->
 		unless RocketChat.checkUsernameAvailability username
 			return false
 
-
-
 	# If first time setting username, send Enrollment Email
 	try
 		if not previousUsername and user.emails?.length > 0 and RocketChat.settings.get 'Accounts_Enrollment_Email'
 			Accounts.sendEnrollmentEmail(user._id)
 	catch error
 
+	user.username = username
+
+	# If first time setting username, check if should set default avatar
+	if not previousUsername and RocketChat.settings.get('Accounts_SetDefaultAvatar') is true
+		avatarSuggestions = getAvatarSuggestionForUser user
+		for service, avatarData of avatarSuggestions
+			if service isnt 'gravatar'
+				RocketChat.setUserAvatar(user, avatarData.blob, avatarData.contentType, service)
+				gravatar = null
+				break
+			else
+				gravatar = avatarData
+		if gravatar?
+			RocketChat.setUserAvatar(user, gravatar.blob, gravatar.contentType, 'gravatar')
+
 	# Username is available; if coming from old username, update all references
 	if previousUsername
 		RocketChat.models.Messages.updateAllUsernamesByUserId user._id, username
@@ -58,7 +71,6 @@ RocketChat._setUsername = (userId, username) ->
 
 	# Set new username
 	RocketChat.models.Users.setUsername user._id, username
-	user.username = username
 	return user
 
 RocketChat.setUsername = RocketChat.RateLimiter.limitFunction RocketChat._setUsername, 1, 60000,
diff --git a/packages/rocketchat-lib/server/functions/settings.coffee b/packages/rocketchat-lib/server/functions/settings.coffee
index e5197b6f20f446bf521ec152f215e0125108d497..f8348261c5f009408eba5a9077d1b8c4e8b45dc1 100644
--- a/packages/rocketchat-lib/server/functions/settings.coffee
+++ b/packages/rocketchat-lib/server/functions/settings.coffee
@@ -92,9 +92,16 @@ RocketChat.settings.add = (_id, value, options = {}) ->
 		updateOperations.$unset = { section: 1 }
 		query.section = { $exists: false }
 
-	if not RocketChat.models.Settings.findOne(query)?
+	existantSetting = RocketChat.models.Settings.db.findOne(query)
+
+	if existantSetting?
+		if not existantSetting.editor? and updateOperations.$setOnInsert.editor?
+			updateOperations.$set.editor = updateOperations.$setOnInsert.editor
+			delete updateOperations.$setOnInsert.editor
+	else
 		updateOperations.$set.ts = new Date
-		return RocketChat.models.Settings.upsert { _id: _id }, updateOperations
+
+	return RocketChat.models.Settings.upsert { _id: _id }, updateOperations
 
 
 
diff --git a/packages/rocketchat-lib/server/lib/bugsnag.js b/packages/rocketchat-lib/server/lib/bugsnag.js
index d250eacedddd2340bc3066cb84767e9f9cde0b7a..cfe1fa9853be56b6b611a7a7296996e1f81d28d4 100644
--- a/packages/rocketchat-lib/server/lib/bugsnag.js
+++ b/packages/rocketchat-lib/server/lib/bugsnag.js
@@ -12,7 +12,10 @@ const notify = function(message, stack) {
 	if (typeof stack === 'string') {
 		message += ' ' + stack;
 	}
-	const options = { app: { version: RocketChat.Info.version, info: RocketChat.Info } };
+	let options = {};
+	if (RocketChat.Info) {
+		options = { app: { version: RocketChat.Info.version, info: RocketChat.Info } };
+	}
 	const error = new Error(message);
 	error.stack = stack;
 	RocketChat.bugsnag.notify(error, options);
@@ -20,6 +23,7 @@ const notify = function(message, stack) {
 
 process.on('uncaughtException', Meteor.bindEnvironment((error) => {
 	notify(error.message, error.stack);
+	throw error;
 }));
 
 let originalMeteorDebug = Meteor._debug;
diff --git a/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js b/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js
index d2500c4ef0159ca87e4a743759c03518a7bb16b8..714d96d9262469bb98aa3604787f5b7a8360d765 100644
--- a/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js
+++ b/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js
@@ -74,7 +74,9 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) {
 	settings.alwaysNotifyMobileUsers = [];
 	settings.dontNotifyMobileUsers = [];
 	settings.desktopNotificationDurations = {};
-	RocketChat.models.Subscriptions.findNotificationPreferencesByRoom(room._id).forEach(function(subscription) {
+
+	const notificationPreferencesByRoom = RocketChat.models.Subscriptions.findNotificationPreferencesByRoom(room._id);
+	notificationPreferencesByRoom.forEach(function(subscription) {
 		if (subscription.desktopNotifications === 'all') {
 			settings.alwaysNotifyDesktopUsers.push(subscription.u._id);
 		} else if (subscription.desktopNotifications === 'nothing') {
@@ -91,10 +93,11 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) {
 	userIdsToNotify = [];
 	userIdsToPushNotify = [];
 	usersWithHighlights = [];
+
 	highlights = RocketChat.models.Users.findUsersByUsernamesWithHighlights(room.usernames, { fields: { '_id': 1, 'settings.preferences.highlights': 1 }}).fetch();
 
 	highlights.forEach(function(user) {
-		if (user && user.settings && user.settings.preferences && messageContainsHighlight(message, user.settings.preferences.highlights)) {
+		if (messageContainsHighlight(message, user.settings.preferences.highlights)) {
 			usersWithHighlights.push(user);
 		}
 	});
@@ -148,6 +151,7 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) {
 				}
 			});
 		}
+
 		if ((userOfMention != null) && canBeNotified(userOfMentionId, 'desktop')) {
 			if (Push.enabled === true && userOfMention.statusConnection !== 'online') {
 				Push.send({
@@ -174,6 +178,7 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) {
 				return message;
 			}
 		}
+
 	} else {
 		mentionIds = [];
 		if ((ref = message.mentions) != null) {
diff --git a/packages/rocketchat-lib/server/methods/addOAuthService.coffee b/packages/rocketchat-lib/server/methods/addOAuthService.coffee
index b3ff589bc14a925714f18e5b3376cb6709b43267..1fcd37b69729e2bc3dd0b13fcbf86fa2acd34d1e 100644
--- a/packages/rocketchat-lib/server/methods/addOAuthService.coffee
+++ b/packages/rocketchat-lib/server/methods/addOAuthService.coffee
@@ -9,18 +9,20 @@ Meteor.methods
 		unless RocketChat.authz.hasPermission( Meteor.userId(), 'add-oauth-service') is true
 			throw new Meteor.Error 'error-action-not-allowed', 'Adding OAuth Services is not allowed', { method: 'addOAuthService', action: 'Adding_OAuth_Services' }
 
-		name = name.toLowerCase().replace(/[^a-z0-9]/g, '')
+		name = name.toLowerCase().replace(/[^a-z0-9_]/g, '')
 		name = s.capitalize(name)
-		RocketChat.settings.add "Accounts_OAuth_Custom_#{name}"                           , false             , { type: 'boolean', group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_Enable', persistent: true }
-		RocketChat.settings.add "Accounts_OAuth_Custom_#{name}_url"                       , ''                , { type: 'string' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'URL', persistent: true }
-		RocketChat.settings.add "Accounts_OAuth_Custom_#{name}_token_path"                , '/oauth/token'    , { type: 'string' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_Token_Path', persistent: true }
-		RocketChat.settings.add "Accounts_OAuth_Custom_#{name}_identity_path"             , '/me'             , { type: 'string' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_Identity_Path', persistent: true }
-		RocketChat.settings.add "Accounts_OAuth_Custom_#{name}_authorize_path"            , '/oauth/authorize', { type: 'string' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_Authorize_Path', persistent: true }
-		RocketChat.settings.add "Accounts_OAuth_Custom_#{name}_scope"                     , 'openid'          , { type: 'string' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_Scope', persistent: true }
-		RocketChat.settings.add "Accounts_OAuth_Custom_#{name}_token_sent_via"            , 'payload'         , { type: 'select' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_Token_Sent_Via', persistent: true, values: [ { key: 'header', i18nLabel: 'Header' }, { key: 'payload', i18nLabel: 'Payload' } ] }
-		RocketChat.settings.add "Accounts_OAuth_Custom_#{name}_id"                        , ''                , { type: 'string' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_id', persistent: true }
-		RocketChat.settings.add "Accounts_OAuth_Custom_#{name}_secret"                    , ''                , { type: 'string' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_Secret', persistent: true }
-		RocketChat.settings.add "Accounts_OAuth_Custom_#{name}_login_style"               , 'popup'           , { type: 'select' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_Login_Style', persistent: true, values: [ { key: 'redirect', i18nLabel: 'Redirect' }, { key: 'popup', i18nLabel: 'Popup' }, { key: '', i18nLabel: 'Default' } ] }
-		RocketChat.settings.add "Accounts_OAuth_Custom_#{name}_button_label_text"         , ''                , { type: 'string' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_Button_Label_Text', persistent: true }
-		RocketChat.settings.add "Accounts_OAuth_Custom_#{name}_button_label_color"        , '#FFFFFF'         , { type: 'string' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_Button_Label_Color', persistent: true }
-		RocketChat.settings.add "Accounts_OAuth_Custom_#{name}_button_color"              , '#13679A'         , { type: 'string' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_Button_Color', persistent: true }
+		RocketChat.settings.add "Accounts_OAuth_Custom-#{name}"                           , false             , { type: 'boolean', group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_Enable', persistent: true }
+		RocketChat.settings.add "Accounts_OAuth_Custom-#{name}-url"                       , ''                , { type: 'string' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'URL', persistent: true }
+		RocketChat.settings.add "Accounts_OAuth_Custom-#{name}-token_path"                , '/oauth/token'    , { type: 'string' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_Token_Path', persistent: true }
+		RocketChat.settings.add "Accounts_OAuth_Custom-#{name}-identity_path"             , '/me'             , { type: 'string' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_Identity_Path', persistent: true }
+		RocketChat.settings.add "Accounts_OAuth_Custom-#{name}-authorize_path"            , '/oauth/authorize', { type: 'string' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_Authorize_Path', persistent: true }
+		RocketChat.settings.add "Accounts_OAuth_Custom-#{name}-scope"                     , 'openid'          , { type: 'string' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_Scope', persistent: true }
+		RocketChat.settings.add "Accounts_OAuth_Custom-#{name}-token_sent_via"            , 'payload'         , { type: 'select' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_Token_Sent_Via', persistent: true, values: [ { key: 'header', i18nLabel: 'Header' }, { key: 'payload', i18nLabel: 'Payload' } ] }
+		RocketChat.settings.add "Accounts_OAuth_Custom-#{name}-id"                        , ''                , { type: 'string' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_id', persistent: true }
+		RocketChat.settings.add "Accounts_OAuth_Custom-#{name}-secret"                    , ''                , { type: 'string' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_Secret', persistent: true }
+		RocketChat.settings.add "Accounts_OAuth_Custom-#{name}-login_style"               , 'popup'           , { type: 'select' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_Login_Style', persistent: true, values: [ { key: 'redirect', i18nLabel: 'Redirect' }, { key: 'popup', i18nLabel: 'Popup' }, { key: '', i18nLabel: 'Default' } ] }
+		RocketChat.settings.add "Accounts_OAuth_Custom-#{name}-button_label_text"         , ''                , { type: 'string' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_Button_Label_Text', persistent: true }
+		RocketChat.settings.add "Accounts_OAuth_Custom-#{name}-button_label_color"        , '#FFFFFF'         , { type: 'string' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_Button_Label_Color', persistent: true }
+		RocketChat.settings.add "Accounts_OAuth_Custom-#{name}-button_color"              , '#13679A'         , { type: 'string' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_Button_Color', persistent: true }
+		RocketChat.settings.add "Accounts_OAuth_Custom-#{name}-username_field"            , ''                , { type: 'string' , group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_Username_Field', persistent: true }
+		RocketChat.settings.add "Accounts_OAuth_Custom-#{name}-merge_users"               , false             , { type: 'boolean', group: 'OAuth', section: "Custom OAuth: #{name}", i18nLabel: 'Accounts_OAuth_Custom_Merge_Users', persistent: true }
diff --git a/packages/rocketchat-lib/server/methods/blockUser.js b/packages/rocketchat-lib/server/methods/blockUser.js
new file mode 100644
index 0000000000000000000000000000000000000000..27d2a8d65912dbf3a9004b82616589001b9ccc25
--- /dev/null
+++ b/packages/rocketchat-lib/server/methods/blockUser.js
@@ -0,0 +1,22 @@
+Meteor.methods({
+	blockUser({rid, blocked}) {
+
+		check(rid, String);
+		check(blocked, String);
+
+		if (!Meteor.userId()) {
+			throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'blockUser' });
+		}
+
+		const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(rid, Meteor.userId());
+		const subscription2 = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(rid, blocked);
+
+		if (!subscription || !subscription2) {
+			throw new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'blockUser' });
+		}
+
+		RocketChat.models.Subscriptions.setBlockedByRoomId(rid, blocked, Meteor.userId());
+
+		return true;
+	}
+});
diff --git a/packages/rocketchat-lib/server/methods/cleanChannelHistory.js b/packages/rocketchat-lib/server/methods/cleanChannelHistory.js
new file mode 100644
index 0000000000000000000000000000000000000000..8c96388c7fb481de602de4fcaeae302735e66def
--- /dev/null
+++ b/packages/rocketchat-lib/server/methods/cleanChannelHistory.js
@@ -0,0 +1,34 @@
+Meteor.methods({
+	cleanChannelHistory({roomId, latest, oldest, inclusive}) {
+		check(roomId, String);
+		check(latest, Date);
+		check(oldest, Date);
+		check(inclusive, Boolean);
+
+		if (!Meteor.userId()) {
+			throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'cleanChannelHistory' });
+		}
+
+		if (!RocketChat.authz.hasPermission(Meteor.userId(), 'clean-channel-history')) {
+			throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'cleanChannelHistory' });
+		}
+
+		if (inclusive) {
+			RocketChat.models.Messages.remove({
+				rid: roomId,
+				ts: {
+					$gte: oldest,
+					$lte: latest
+				}
+			});
+		} else {
+			RocketChat.models.Messages.remove({
+				rid: roomId,
+				ts: {
+					$gt: oldest,
+					$lt: latest
+				}
+			});
+		}
+	}
+});
diff --git a/packages/rocketchat-lib/server/methods/getChannelHistory.js b/packages/rocketchat-lib/server/methods/getChannelHistory.js
new file mode 100644
index 0000000000000000000000000000000000000000..03958a40fae564bf82c8a748e241ef713ab78039
--- /dev/null
+++ b/packages/rocketchat-lib/server/methods/getChannelHistory.js
@@ -0,0 +1,81 @@
+Meteor.methods({
+	getChannelHistory({rid, latest, oldest, inclusive, count = 20, unreads}) {
+		check(rid, String);
+
+		if (!Meteor.userId()) {
+			throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getChannelHistory' });
+		}
+
+		const fromUserId = Meteor.userId();
+		const room = Meteor.call('canAccessRoom', rid, fromUserId);
+		if (!room) {
+			return false;
+		}
+
+		//Make sure they can access the room
+		if (room.t === 'c' && !RocketChat.authz.hasPermission(fromUserId, 'preview-c-room') && room.usernames.indexOf(room.username) === -1) {
+			return false;
+		}
+
+		//Ensure latest is always defined.
+		if (_.isUndefined(latest)) {
+			latest = new Date();
+		}
+
+		//Verify oldest is a date if it exists
+		if (!_.isUndefined(oldest) && !_.isDate(oldest)) {
+			throw new Meteor.Error('error-invalid-date', 'Invalid date', { method: 'getChannelHistory' });
+		}
+
+		const options = {
+			sort: {
+				ts: -1
+			},
+			limit: count
+		};
+
+		if (!RocketChat.settings.get('Message_ShowEditedStatus')) {
+			options.fields = { 'editedAt': 0 };
+		}
+
+		let records = [];
+		if (_.isUndefined(oldest) && inclusive) {
+			records = RocketChat.models.Messages.findVisibleByRoomIdBeforeTimestampInclusive(rid, latest, options).fetch();
+		} else if (_.isUndefined(oldest) && !inclusive) {
+			records = RocketChat.models.Messages.findVisibleByRoomIdBeforeTimestamp(rid, latest, options).fetch();
+		} else if (!_.isUndefined(oldest) && inclusive) {
+			records = RocketChat.models.Messages.findVisibleByRoomIdBetweenTimestampsInclusive(rid, oldest, latest, options).fetch();
+		} else {
+			records = RocketChat.models.Messages.findVisibleByRoomIdBetweenTimestamps(rid, oldest, latest, options).fetch();
+		}
+
+		const messages = _.map(records, (message) => {
+			message.starred = _.findWhere(message.starred, { _id: fromUserId });
+			return message;
+		});
+
+		if (unreads) {
+			let unreadNotLoaded = 0;
+			let firstUnread = undefined;
+
+			if (!_.isUndefined(oldest)) {
+				const firstMsg = messages[messages.length - 1];
+				if (!_.isUndefined(firstMsg) && firstMsg.ts > oldest) {
+					const unreadMessages = RocketChat.models.Messages.findVisibleByRoomIdBetweenTimestamps(rid, oldest, firstMsg.ts, { limit: 1, sort: { ts: 1 } });
+					firstUnread = unreadMessages.fetch()[0];
+					unreadNotLoaded = unreadMessages.count();
+				}
+			}
+
+			return {
+				messages,
+				firstUnread,
+				unreadNotLoaded
+			};
+		}
+
+		return {
+			messages
+		};
+	}
+});
diff --git a/packages/rocketchat-lib/server/methods/getFullUserData.js b/packages/rocketchat-lib/server/methods/getFullUserData.js
new file mode 100644
index 0000000000000000000000000000000000000000..f9caf8b23d771ed83e6e5aae5da384b6af0d7f1e
--- /dev/null
+++ b/packages/rocketchat-lib/server/methods/getFullUserData.js
@@ -0,0 +1,11 @@
+Meteor.methods({
+	getFullUserData({ filter = '', limit }) {
+		const result = RocketChat.getFullUserData({ userId: Meteor.userId(), filter, limit });
+
+		if (!result) {
+			return result;
+		}
+
+		return result.fetch();
+	}
+});
diff --git a/packages/rocketchat-lib/server/methods/getServerInfo.js b/packages/rocketchat-lib/server/methods/getServerInfo.js
new file mode 100644
index 0000000000000000000000000000000000000000..8db017a1528f86176404133ff13803bac7540d17
--- /dev/null
+++ b/packages/rocketchat-lib/server/methods/getServerInfo.js
@@ -0,0 +1,5 @@
+Meteor.methods({
+	getServerInfo() {
+		return RocketChat.Info;
+	}
+});
diff --git a/packages/rocketchat-lib/server/methods/leaveRoom.coffee b/packages/rocketchat-lib/server/methods/leaveRoom.coffee
index 7e66f405bc2348dc676ca84695ebad25243b5857..462b10cb715cb7d7c758f3a766aa49009b50e49f 100644
--- a/packages/rocketchat-lib/server/methods/leaveRoom.coffee
+++ b/packages/rocketchat-lib/server/methods/leaveRoom.coffee
@@ -11,9 +11,12 @@ Meteor.methods
 		fromId = Meteor.userId()
 		room = RocketChat.models.Rooms.findOneById rid
 		user = Meteor.user()
-		
+
 		if room.t is 'd'
-			throw new Meteor.Error 'error-not-allowed', 'Not allowed', { method: 'leaveRoom' } 
+			throw new Meteor.Error 'error-not-allowed', 'Not allowed', { method: 'leaveRoom' }
+
+		if user.username not in (room?.usernames or [])
+			throw new Meteor.Error 'error-user-not-in-room', 'You are not in this room', { method: 'leaveRoom' }
 
 		# If user is room owner, check if there are other owners. If there isn't anyone else, warn user to set a new owner.
 		if RocketChat.authz.hasRole(user._id, 'owner', room._id)
diff --git a/packages/rocketchat-lib/server/methods/refreshOAuthService.js b/packages/rocketchat-lib/server/methods/refreshOAuthService.js
new file mode 100644
index 0000000000000000000000000000000000000000..513090b6ecd6a59d46163c34f61a1f6706eb2f67
--- /dev/null
+++ b/packages/rocketchat-lib/server/methods/refreshOAuthService.js
@@ -0,0 +1,15 @@
+Meteor.methods({
+	refreshOAuthService() {
+		if (!Meteor.userId()) {
+			throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'refreshOAuthService' });
+		}
+
+		if (RocketChat.authz.hasPermission(Meteor.userId(), 'add-oauth-service') !== true) {
+			throw new Meteor.Error('error-action-not-allowed', 'Refresh OAuth Services is not allowed', { method: 'refreshOAuthService', action: 'Refreshing_OAuth_Services' });
+		}
+
+		ServiceConfiguration.configurations.remove({});
+
+		RocketChat.models.Settings.update({_id: /^Accounts_OAuth_.+/}, {$set: {_updatedAt: new Date}}, {multi: true});
+	}
+});
diff --git a/packages/rocketchat-lib/server/methods/removeOAuthService.coffee b/packages/rocketchat-lib/server/methods/removeOAuthService.coffee
index 689609246ecfd52809a0220f3ad14755b9de0a92..13ba3a2afb81d114707fc819453d46c173efdf45 100644
--- a/packages/rocketchat-lib/server/methods/removeOAuthService.coffee
+++ b/packages/rocketchat-lib/server/methods/removeOAuthService.coffee
@@ -9,18 +9,20 @@ Meteor.methods
 		unless RocketChat.authz.hasPermission( Meteor.userId(), 'add-oauth-service') is true
 			throw new Meteor.Error 'error-not-allowed', 'Not allowed', { method: 'removeOAuthService' }
 
-		name = name.toLowerCase().replace(/[^a-z0-9]/g, '')
+		name = name.toLowerCase().replace(/[^a-z0-9_]/g, '')
 		name = s.capitalize(name)
-		RocketChat.settings.removeById "Accounts_OAuth_Custom_#{name}"
-		RocketChat.settings.removeById "Accounts_OAuth_Custom_#{name}_url"
-		RocketChat.settings.removeById "Accounts_OAuth_Custom_#{name}_token_path"
-		RocketChat.settings.removeById "Accounts_OAuth_Custom_#{name}_identity_path"
-		RocketChat.settings.removeById "Accounts_OAuth_Custom_#{name}_authorize_path"
-		RocketChat.settings.removeById "Accounts_OAuth_Custom_#{name}_scope"
-		RocketChat.settings.removeById "Accounts_OAuth_Custom_#{name}_token_sent_via"
-		RocketChat.settings.removeById "Accounts_OAuth_Custom_#{name}_id"
-		RocketChat.settings.removeById "Accounts_OAuth_Custom_#{name}_secret"
-		RocketChat.settings.removeById "Accounts_OAuth_Custom_#{name}_button_label_text"
-		RocketChat.settings.removeById "Accounts_OAuth_Custom_#{name}_button_label_color"
-		RocketChat.settings.removeById "Accounts_OAuth_Custom_#{name}_button_color"
-		RocketChat.settings.removeById "Accounts_OAuth_Custom_#{name}_login_style"
+		RocketChat.settings.removeById "Accounts_OAuth_Custom-#{name}"
+		RocketChat.settings.removeById "Accounts_OAuth_Custom-#{name}-url"
+		RocketChat.settings.removeById "Accounts_OAuth_Custom-#{name}-token_path"
+		RocketChat.settings.removeById "Accounts_OAuth_Custom-#{name}-identity_path"
+		RocketChat.settings.removeById "Accounts_OAuth_Custom-#{name}-authorize_path"
+		RocketChat.settings.removeById "Accounts_OAuth_Custom-#{name}-scope"
+		RocketChat.settings.removeById "Accounts_OAuth_Custom-#{name}-token_sent_via"
+		RocketChat.settings.removeById "Accounts_OAuth_Custom-#{name}-id"
+		RocketChat.settings.removeById "Accounts_OAuth_Custom-#{name}-secret"
+		RocketChat.settings.removeById "Accounts_OAuth_Custom-#{name}-button_label_text"
+		RocketChat.settings.removeById "Accounts_OAuth_Custom-#{name}-button_label_color"
+		RocketChat.settings.removeById "Accounts_OAuth_Custom-#{name}-button_color"
+		RocketChat.settings.removeById "Accounts_OAuth_Custom-#{name}-login_style"
+		RocketChat.settings.removeById "Accounts_OAuth_Custom-#{name}-username_field"
+		RocketChat.settings.removeById "Accounts_OAuth_Custom-#{name}-merge_users"
diff --git a/packages/rocketchat-lib/server/methods/saveSetting.js b/packages/rocketchat-lib/server/methods/saveSetting.js
index 029732e9909a6554fe0151cba0bccbb31a5f5aab..f9380922607016de99567a9c3c741d34046b37c8 100644
--- a/packages/rocketchat-lib/server/methods/saveSetting.js
+++ b/packages/rocketchat-lib/server/methods/saveSetting.js
@@ -15,7 +15,7 @@ Meteor.methods({
 		//Verify the _id passed in is a string.
 		check(_id, String);
 
-		const setting = RocketChat.models.Settings.findOneById(_id);
+		const setting = RocketChat.models.Settings.db.findOneById(_id);
 
 		//Verify the value is what it should be
 		switch (setting.type) {
diff --git a/packages/rocketchat-lib/server/methods/sendMessage.coffee b/packages/rocketchat-lib/server/methods/sendMessage.coffee
index c787be5f359ad82a407124ad0dbaa7272f884b42..e8defe8ed2e8e1fdc0436ba02f10459927932e2d 100644
--- a/packages/rocketchat-lib/server/methods/sendMessage.coffee
+++ b/packages/rocketchat-lib/server/methods/sendMessage.coffee
@@ -5,6 +5,9 @@ Meteor.methods
 
 		check message, Object
 
+		if not Meteor.userId()
+			throw new Meteor.Error('error-invalid-user', "Invalid user", { method: 'sendMessage' })
+
 		if message.ts
 			tsDiff = Math.abs(moment(message.ts).diff())
 			if tsDiff > 60000
@@ -17,9 +20,6 @@ Meteor.methods
 		if message.msg?.length > RocketChat.settings.get('Message_MaxAllowedSize')
 			throw new Meteor.Error('error-message-size-exceeded', 'Message size exceeds Message_MaxAllowedSize', { method: 'sendMessage' })
 
-		if not Meteor.userId()
-			throw new Meteor.Error('error-invalid-user', "Invalid user", { method: 'sendMessage' })
-
 		user = RocketChat.models.Users.findOneById Meteor.userId(), fields: username: 1, name: 1
 
 		room = Meteor.call 'canAccessRoom', message.rid, user._id
@@ -27,6 +27,16 @@ Meteor.methods
 		if not room
 			return false
 
+		subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(message.rid, Meteor.userId());
+		if subscription and (subscription.blocked or subscription.blocker)
+			RocketChat.Notifications.notifyUser Meteor.userId(), 'message', {
+				_id: Random.id()
+				rid: room._id
+				ts: new Date
+				msg: TAPi18n.__('room_is_blocked', {}, user.language)
+			}
+			return false
+
 		if user.username in (room.muted or [])
 			RocketChat.Notifications.notifyUser Meteor.userId(), 'message', {
 				_id: Random.id()
@@ -42,10 +52,12 @@ Meteor.methods
 
 		RocketChat.sendMessage user, message, room
 
-# Limit a user to sending 5 msgs/second
+# Limit a user, who does not have the "bot" role, to sending 5 msgs/second
 DDPRateLimiter.addRule
 	type: 'method'
 	name: 'sendMessage'
 	userId: (userId) ->
-		return RocketChat.models.Users.findOneById(userId)?.username isnt RocketChat.settings.get('InternalHubot_Username')
+		user = RocketChat.models.Users.findOneById(userId)
+		return true if not user?.roles
+		return 'bot' not in user.roles
 , 5, 1000
diff --git a/packages/rocketchat-lib/server/methods/setUsername.coffee b/packages/rocketchat-lib/server/methods/setUsername.coffee
index 3438c74b2f1506e10af61997d18fe56eaff176d9..af260d1eac33930c9b3df8624f9d0f7d482074e4 100644
--- a/packages/rocketchat-lib/server/methods/setUsername.coffee
+++ b/packages/rocketchat-lib/server/methods/setUsername.coffee
@@ -1,5 +1,5 @@
 Meteor.methods
-	setUsername: (username) ->
+	setUsername: (username, {joinDefaultChannelsSilenced}={}) ->
 
 		check username, String
 
@@ -33,6 +33,10 @@ Meteor.methods
 		unless RocketChat.setUsername user._id, username
 			throw new Meteor.Error 'error-could-not-change-username', "Could not change username", { method: 'setUsername' }
 
+		if not user.username?
+			Meteor.runAsUser user._id, ->
+				Meteor.call('joinDefaultChannels', joinDefaultChannelsSilenced)
+
 		return username
 
 RocketChat.RateLimiter.limitMethod 'setUsername', 1, 1000,
diff --git a/packages/rocketchat-lib/server/methods/unblockUser.js b/packages/rocketchat-lib/server/methods/unblockUser.js
new file mode 100644
index 0000000000000000000000000000000000000000..d91d2f3780c6a6c363e8fd8a95f008f55e86ba12
--- /dev/null
+++ b/packages/rocketchat-lib/server/methods/unblockUser.js
@@ -0,0 +1,22 @@
+Meteor.methods({
+	unblockUser({rid, blocked}) {
+
+		check(rid, String);
+		check(blocked, String);
+
+		if (!Meteor.userId()) {
+			throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'blockUser' });
+		}
+
+		const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(rid, Meteor.userId());
+		const subscription2 = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(rid, blocked);
+
+		if (!subscription || !subscription2) {
+			throw new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'blockUser' });
+		}
+
+		RocketChat.models.Subscriptions.unsetBlockedByRoomId(rid, blocked, Meteor.userId());
+
+		return true;
+	}
+});
diff --git a/packages/rocketchat-lib/server/models/Messages.coffee b/packages/rocketchat-lib/server/models/Messages.coffee
index 02cc0f77e56dc4849771d6ed1d6f5d8f1db53d9f..dbaee48242a5759fdfb08514f6564c92fbbca40c 100644
--- a/packages/rocketchat-lib/server/models/Messages.coffee
+++ b/packages/rocketchat-lib/server/models/Messages.coffee
@@ -89,6 +89,16 @@ RocketChat.models.Messages = new class extends RocketChat.models._Base
 
 		return @find query, options
 
+	findVisibleByRoomIdBeforeTimestampInclusive: (roomId, timestamp, options) ->
+		query =
+			_hidden:
+				$ne: true
+			rid: roomId
+			ts:
+				$lte: timestamp
+
+		return @find query, options
+
 	findVisibleByRoomIdBetweenTimestamps: (roomId, afterTimestamp, beforeTimestamp, options) ->
 		query =
 			_hidden:
@@ -100,6 +110,17 @@ RocketChat.models.Messages = new class extends RocketChat.models._Base
 
 		return @find query, options
 
+	findVisibleByRoomIdBetweenTimestampsInclusive: (roomId, afterTimestamp, beforeTimestamp, options) ->
+		query =
+			_hidden:
+				$ne: true
+			rid: roomId
+			ts:
+				$gte: afterTimestamp
+				$lte: beforeTimestamp
+
+		return @find query, options
+
 	findVisibleByRoomIdBeforeTimestampNotContainingTypes: (roomId, timestamp, types, options) ->
 		query =
 			_hidden:
@@ -189,6 +210,12 @@ RocketChat.models.Messages = new class extends RocketChat.models._Base
 
 		return @findOne query
 
+	findOneBySlackTs: (slackTs) ->
+		query =
+			slackTs: slackTs
+
+		return @findOne query
+
 	cloneAndSaveAsHistoryById: (_id) ->
 		me = RocketChat.models.Users.findOneById Meteor.userId()
 		record = @findOneById _id
@@ -223,6 +250,7 @@ RocketChat.models.Messages = new class extends RocketChat.models._Base
 				urls: []
 				mentions: []
 				attachments: []
+				reactions: []
 				editedAt: new Date()
 				editedBy:
 					_id: user._id
diff --git a/packages/rocketchat-lib/server/models/Rooms.coffee b/packages/rocketchat-lib/server/models/Rooms.coffee
index 415a6b3850d6cd17b9fdfb39f8921aa89d3a810b..32707524b6734b1a1f18e170b8a127d44a40a385 100644
--- a/packages/rocketchat-lib/server/models/Rooms.coffee
+++ b/packages/rocketchat-lib/server/models/Rooms.coffee
@@ -8,8 +8,15 @@ class ModelRooms extends RocketChat.models._Base
 		@tryEnsureIndex { 't': 1 }
 		@tryEnsureIndex { 'u._id': 1 }
 
+		this.cache.ignoreUpdatedFields.push('msgs', 'lm')
+		this.cache.ensureIndex(['t', 'name'], 'unique')
+		this.cache.options = {fields: {usernames: 0}}
+
 	# FIND ONE
 	findOneById: (_id, options) ->
+		if this.useCache
+			return this.cache.findByIndex('_id', _id, options).fetch()
+
 		query =
 			_id: _id
 
@@ -45,14 +52,14 @@ class ModelRooms extends RocketChat.models._Base
 
 		return @findOne query, options
 
-	findOneByIdContainigUsername: (_id, username, options) ->
+	findOneByIdContainingUsername: (_id, username, options) ->
 		query =
 			_id: _id
 			usernames: username
 
 		return @findOne query, options
 
-	findOneByNameAndTypeNotContainigUsername: (name, type, username, options) ->
+	findOneByNameAndTypeNotContainingUsername: (name, type, username, options) ->
 		query =
 			name: name
 			t: type
@@ -89,6 +96,47 @@ class ModelRooms extends RocketChat.models._Base
 
 		return @find query, options
 
+	findBySubscriptionUserId: (userId, options) ->
+		if this.useCache
+			data = RocketChat.models.Subscriptions.findByUserId(userId).fetch()
+			data = data.map (item) ->
+				if item._room
+					return item._room
+				console.log('Empty Room for Subscription', item);
+				return {}
+			return this.arrayToCursor this.processQueryOptionsOnResult(data, options)
+
+		data = RocketChat.models.Subscriptions.findByUserId(userId, {fields: {rid: 1}}).fetch()
+		data = data.map (item) -> item.rid
+
+		query =
+			_id:
+				$in: data
+
+		this.find query, options
+
+	findBySubscriptionUserIdUpdatedAfter: (userId, _updatedAt, options) ->
+		if this.useCache
+			data = RocketChat.models.Subscriptions.findByUserId(userId).fetch()
+			data = data.map (item) ->
+				if item._room
+					return item._room
+				console.log('Empty Room for Subscription', item);
+				return {}
+			data = data.filter (item) -> item._updatedAt > _updatedAt
+			return this.arrayToCursor this.processQueryOptionsOnResult(data, options)
+
+		ids = RocketChat.models.Subscriptions.findByUserId(userId, {fields: {rid: 1}}).fetch()
+		ids = ids.map (item) -> item.rid
+
+		query =
+			_id:
+				$in: ids
+			_updatedAt:
+				$gt: _updatedAt
+
+		this.find query, options
+
 	findByNameContaining: (name, options) ->
 		nameRegex = new RegExp s.trim(s.escapeRegExp(name)), "i"
 
@@ -182,14 +230,14 @@ class ModelRooms extends RocketChat.models._Base
 
 		return @find query, options
 
-	findByTypeContainigUsername: (type, username, options) ->
+	findByTypeContainingUsername: (type, username, options) ->
 		query =
 			t: type
 			usernames: username
 
 		return @find query, options
 
-	findByTypeContainigUsernames: (type, username, options) ->
+	findByTypeContainingUsernames: (type, username, options) ->
 		query =
 			t: type
 			usernames: { $all: [].concat(username) }
@@ -206,13 +254,16 @@ class ModelRooms extends RocketChat.models._Base
 
 		return @find query, options
 
-	findByContainigUsername: (username, options) ->
+	findByContainingUsername: (username, options) ->
 		query =
 			usernames: username
 
 		return @find query, options
 
 	findByTypeAndName: (type, name, options) ->
+		if this.useCache
+			return this.cache.findByIndex('t,name', [type, name], options)
+
 		query =
 			name: name
 			t: type
@@ -549,4 +600,4 @@ class ModelRooms extends RocketChat.models._Base
 
 		return @remove query
 
-RocketChat.models.Rooms = new ModelRooms('room')
+RocketChat.models.Rooms = new ModelRooms('room', true)
diff --git a/packages/rocketchat-lib/server/models/Settings.coffee b/packages/rocketchat-lib/server/models/Settings.coffee
index eb2769bc65c2236a54998f2e4eca3d0b1185b55a..05cb9946db279a04c463e68475d6108f37db4dd9 100644
--- a/packages/rocketchat-lib/server/models/Settings.coffee
+++ b/packages/rocketchat-lib/server/models/Settings.coffee
@@ -148,4 +148,4 @@ class ModelSettings extends RocketChat.models._Base
 
 		return @remove query
 
-RocketChat.models.Settings = new ModelSettings('settings')
+RocketChat.models.Settings = new ModelSettings('settings', true)
diff --git a/packages/rocketchat-lib/server/models/Subscriptions.coffee b/packages/rocketchat-lib/server/models/Subscriptions.coffee
index df71930731c3ed6120a0e65f3ccd9551b437ea6b..ddeb5e4e357a46fe49543aa908c822a69245325e 100644
--- a/packages/rocketchat-lib/server/models/Subscriptions.coffee
+++ b/packages/rocketchat-lib/server/models/Subscriptions.coffee
@@ -16,8 +16,16 @@ class ModelSubscriptions extends RocketChat.models._Base
 		@tryEnsureIndex { 'mobilePushNotifications': 1 }, { sparse: 1 }
 		@tryEnsureIndex { 'emailNotifications': 1 }, { sparse: 1 }
 
+		this.cache.ensureIndex('rid', 'array')
+		this.cache.ensureIndex('u._id', 'array')
+		this.cache.ensureIndex(['rid', 'u._id'], 'unique')
+
+
 	# FIND ONE
 	findOneByRoomIdAndUserId: (roomId, userId) ->
+		if this.useCache
+			return this.cache.findByIndex('rid,u._id', [roomId, userId]).fetch()
+
 		query =
 			rid: roomId
 			"u._id": userId
@@ -26,6 +34,9 @@ class ModelSubscriptions extends RocketChat.models._Base
 
 	# FIND
 	findByUserId: (userId, options) ->
+		if this.useCache
+			return this.cache.findByIndex('u._id', userId, options)
+
 		query =
 			"u._id": userId
 
@@ -71,6 +82,9 @@ class ModelSubscriptions extends RocketChat.models._Base
 		return @find query, options
 
 	findByRoomId: (roomId, options) ->
+		if this.useCache
+			return this.cache.findByIndex('rid', roomId, options)
+
 		query =
 			rid: roomId
 
@@ -290,6 +304,44 @@ class ModelSubscriptions extends RocketChat.models._Base
 
 		return @update query, update, { multi: true }
 
+	setBlockedByRoomId: (rid, blocked, blocker) ->
+		query =
+			rid: rid
+			'u._id': blocked
+
+		update =
+			$set:
+				blocked: true
+
+		query2 =
+			rid: rid
+			'u._id': blocker
+
+		update2 =
+			$set:
+				blocker: true
+
+		return @update(query, update) and @update(query2, update2)
+
+	unsetBlockedByRoomId: (rid, blocked, blocker) ->
+		query =
+			rid: rid
+			'u._id': blocked
+
+		update =
+			$unset:
+				blocked: 1
+
+		query2 =
+			rid: rid
+			'u._id': blocker
+
+		update2 =
+			$unset:
+				blocker: 1
+
+		return @update(query, update) and @update(query2, update2)
+
 	updateTypeByRoomId: (roomId, type) ->
 		query =
 			rid: roomId
@@ -370,4 +422,4 @@ class ModelSubscriptions extends RocketChat.models._Base
 
 		return @remove query
 
-RocketChat.models.Subscriptions = new ModelSubscriptions('subscription')
+RocketChat.models.Subscriptions = new ModelSubscriptions('subscription', true)
diff --git a/packages/rocketchat-lib/server/models/Uploads.coffee b/packages/rocketchat-lib/server/models/Uploads.coffee
index 01cbeedf3d2ca2e7f68831b2011db1cb81696817..dc41e6939cdd42cc58015b97dd53bf30411e74d8 100644
--- a/packages/rocketchat-lib/server/models/Uploads.coffee
+++ b/packages/rocketchat-lib/server/models/Uploads.coffee
@@ -25,6 +25,7 @@ RocketChat.models.Uploads = new class extends RocketChat.models._Base
 				userId: 1
 				rid: 1
 				name: 1
+				description: 1
 				type: 1
 				url: 1
 				uploadedAt: 1
diff --git a/packages/rocketchat-lib/server/models/Users.coffee b/packages/rocketchat-lib/server/models/Users.coffee
index 3e343b39b325242ddc528eed8e374dde522255ba..6c4df1f5212acc80116a072fad672f1e6007f34a 100644
--- a/packages/rocketchat-lib/server/models/Users.coffee
+++ b/packages/rocketchat-lib/server/models/Users.coffee
@@ -68,6 +68,17 @@ class ModelUsers extends RocketChat.models._Base
 		return @find query, options
 
 	findUsersByUsernamesWithHighlights: (usernames, options) ->
+		if this.useCache
+			result =
+				fetch: () ->
+					return RocketChat.models.Users.getDynamicView('highlights').data().filter (record) ->
+						return usernames.indexOf(record.username) > -1
+				count: () ->
+					return result.fetch().length
+				forEach: (fn) ->
+					return result.fetch().forEach(fn)
+			return result
+
 		query =
 			username: { $in: usernames }
 			'settings.preferences.highlights.0':
@@ -353,7 +364,7 @@ class ModelUsers extends RocketChat.models._Base
 					address: s.trim(data.email)
 				]
 			else
-				unsetData.name = 1
+				unsetData.emails = 1
 
 		if data.phone?
 			if not _.isEmpty(s.trim(data.phone))
@@ -410,4 +421,4 @@ class ModelUsers extends RocketChat.models._Base
 
 		return @find query, { fields: { name: 1, username: 1, emails: 1, 'settings.preferences.emailNotificationMode': 1 } }
 
-RocketChat.models.Users = new ModelUsers(Meteor.users)
+RocketChat.models.Users = new ModelUsers(Meteor.users, true)
diff --git a/packages/rocketchat-lib/server/models/_Base.js b/packages/rocketchat-lib/server/models/_Base.js
index d2ac1f12a4fdfe5d4574a5c68b0407f7d2835245..940b98d9c4690eade7eae177d95860970606f1a1 100644
--- a/packages/rocketchat-lib/server/models/_Base.js
+++ b/packages/rocketchat-lib/server/models/_Base.js
@@ -1,252 +1,168 @@
-const {EventEmitter} = Npm.require('events');
+import ModelsBaseDb from './_BaseDb';
+import ModelsBaseCache from './_BaseCache';
 
-const baseName = 'rocketchat_';
+RocketChat.models._CacheControl = new Meteor.EnvironmentVariable();
 
-const trash = new Mongo.Collection(baseName + '_trash');
-try {
-	trash._ensureIndex({ collection: 1 });
-	trash._ensureIndex({ _deletedAt: 1 }, { expireAfterSeconds: 60 * 60 * 24 * 30 });
-} catch (e) {
-	console.log(e);
-}
+class ModelsBase {
+	constructor(nameOrModel, useCache) {
+		this._db = new ModelsBaseDb(nameOrModel, this);
+		this.model = this._db.model;
+		this.collectionName = this._db.collectionName;
+		this.name = this._db.name;
 
-class ModelsBase extends EventEmitter {
-	constructor(model) {
-		super();
-
-		if (Match.test(model, String)) {
-			this.name = model;
-			this.collectionName = this.baseName + this.name;
-			this.model = new Mongo.Collection(this.collectionName);
-		} else {
-			this.name = model._name;
-			this.collectionName = this.name;
-			this.model = model;
-		}
+		this._useCache = useCache === true;
 
-		this.tryEnsureIndex({ '_updatedAt': 1 });
-	}
+		this.cache = new ModelsBaseCache(this);
+		// TODO_CACHE: remove
+		this.on = this.cache.on.bind(this.cache);
+		this.emit = this.cache.emit.bind(this.cache);
+		this.getDynamicView = this.cache.getDynamicView.bind(this.cache);
+		this.processQueryOptionsOnResult = this.cache.processQueryOptionsOnResult.bind(this.cache);
+		// END_TODO_CACHE
 
-	get baseName() {
-		return baseName;
-	}
+		this.db = this;
 
-	setUpdatedAt(record = {}, checkQuery = false, query) {
-		if (checkQuery === true) {
-			if (!query || Object.keys(query).length === 0) {
-				throw new Meteor.Error('Models._Base: Empty query');
-			}
+		if (this._useCache) {
+			this.db = new this.constructor(this.model, false);
 		}
+	}
 
-		if (/(^|,)\$/.test(Object.keys(record).join(','))) {
-			record.$set = record.$set || {};
-			record.$set._updatedAt = new Date;
-		} else {
-			record._updatedAt = new Date;
+	get useCache() {
+		if (RocketChat.models._CacheControl.get() === false) {
+			return false;
 		}
 
-		return record;
+		return this._useCache;
 	}
 
-	find() {
-		return this.model.find(...arguments);
+	get origin() {
+		return this.useCache === true ? 'cache' : '_db';
 	}
 
-	findOne() {
-		return this.model.findOne(...arguments);
+	arrayToCursor(data) {
+		return {
+			fetch() {
+				return data;
+			},
+			count() {
+				return data.length;
+			},
+			forEach(fn) {
+				return data.forEach(fn);
+			}
+		};
 	}
 
-	insert(record) {
-		this.setUpdatedAt(record);
-
-		const result = this.model.insert(...arguments);
-		record._id = result;
-		this.emit('insert', record);
-		this.emit('change', 'insert', record);
-		return result;
+	setUpdatedAt(/*record, checkQuery, query*/) {
+		return this._db.setUpdatedAt(...arguments);
 	}
 
-	update(query, update, options = {}) {
-		this.setUpdatedAt(update, true, query);
-
-		if (options.upsert) {
-			return this.upsert(query, update);
-		}
-
-		let ids = [];
-		if (options.multi === true) {
-			const updated = this.model.find(query, { fields: { _id: 1 } }).fetch();
-			if (updated) {
-				ids = ids.concat(updated);
-			}
-		} else {
-			const updated = this.model.findOne(query, { fields: { _id: 1 } });
-			if (updated) {
-				ids.push(updated);
-			}
+	find() {
+		try {
+			return this[this.origin].find(...arguments);
+		} catch (e) {
+			console.error('Exception on find', e, ...arguments);
 		}
-
-		const result = this.model.update(query, update, options);
-		const idQuery = { _id: { $in: _.pluck(ids, '_id') } };
-		this.emit('update', idQuery, update);
-		this.emit('change', 'update', idQuery, update);
-		return result;
 	}
 
-	upsert(query, update) {
-		this.setUpdatedAt(update, true, query);
-
-		const id = this.model.findOne(query, { fields: { _id: 1 } });
-		const result = this.model.upsert(...arguments);
-
-		let record = id;
-		if (result.insertedId) {
-			record = { _id: result.insertedId };
+	findOne() {
+		try {
+			return this[this.origin].findOne(...arguments);
+		} catch (e) {
+			console.error('Exception on find', e, ...arguments);
 		}
-
-		this.emit('update', record);
-		this.emit('change', 'update', record);
-		return result;
 	}
 
-	remove(query) {
-		const records = this.model.find(query).fetch();
-
-		const ids = [];
-		for (const record of records) {
-			ids.push(record._id);
-
-			record._deletedAt = new Date;
-			record.__collection__ = this.name;
-
-			trash.upsert({_id: record._id}, _.omit(record, '_id'));
-		}
+	insert(/*record*/) {
+		return this._db.insert(...arguments);
+	}
 
-		query = { _id: { $in: ids } };
+	update(/*query, update, options*/) {
+		return this._db.update(...arguments);
+	}
 
-		this.emit('remove', records);
-		this.emit('change', 'remove', records);
-		return this.model.remove(query);
+	upsert(/*query, update*/) {
+		return this._db.upsert(...arguments);
 	}
 
-	insertOrUpsert(...args) {
-		if (args[0] && args[0]._id) {
-			const _id = args[0]._id;
-			delete args[0]._id;
-			args.unshift({
-				_id: _id
-			});
+	remove(/*query*/) {
+		return this._db.remove(...arguments);
+	}
 
-			this.upsert(...args);
-			return _id;
-		} else {
-			return this.insert(...args);
-		}
+	insertOrUpsert() {
+		return this._db.insertOrUpsert(...arguments);
 	}
 
 	allow() {
-		return this.model.allow(...arguments);
+		return this._db.allow(...arguments);
 	}
 
 	deny() {
-		return this.model.deny(...arguments);
+		return this._db.deny(...arguments);
 	}
 
 	ensureIndex() {
-		return this.model._ensureIndex(...arguments);
+		return this._db.ensureIndex(...arguments);
 	}
 
 	dropIndex() {
-		return this.model._dropIndex(...arguments);
+		return this._db.dropIndex(...arguments);
 	}
 
 	tryEnsureIndex() {
-		try {
-			return this.ensureIndex(...arguments);
-		} catch (e) {
-			console.log(e);
-		}
+		return this._db.tryEnsureIndex(...arguments);
 	}
 
 	tryDropIndex() {
-		try {
-			return this.dropIndex(...arguments);
-		} catch (e) {
-			console.log(e);
-		}
+		return this._db.tryDropIndex(...arguments);
 	}
 
-	getChangedRecords(type, recordOrQuery, fields) {
-		if (type === 'insert') {
-			return [recordOrQuery];
-		}
-
-		if (type === 'remove') {
-			return recordOrQuery;
-		}
-
-		if (type === 'update') {
-			const options = {};
-			if (fields) {
-				options.fields = fields;
-			}
-			return this.find(recordOrQuery, options).fetch();
-		}
+	trashFind(/*query, options*/) {
+		return this._db.trashFind(...arguments);
 	}
 
-	trashFind(query, options) {
-		query.__collection__ = this.name;
-
-		return trash.find(query, options);
+	trashFindDeletedAfter(/*deletedAt, query, options*/) {
+		return this._db.trashFindDeletedAfter(...arguments);
 	}
 
-	trashFindDeletedAfter(deletedAt, query = {}, options) {
-		query.__collection__ = this.name;
-		query._deletedAt = {
-			$gt: deletedAt
-		};
+	// dinamicTrashFindAfter(method, deletedAt, ...args) {
+	// 	const scope = {
+	// 		find: (query={}) => {
+	// 			return this.trashFindDeletedAfter(deletedAt, query, { fields: {_id: 1, _deletedAt: 1} });
+	// 		}
+	// 	};
 
-		return trash.find(query, options);
-	}
+	// 	scope.model = {
+	// 		find: scope.find
+	// 	};
 
-	dinamicTrashFindAfter(method, deletedAt, ...args) {
-		const scope = {
-			find: (query={}) => {
-				return this.trashFindDeletedAfter(deletedAt, query, { fields: {_id: 1, _deletedAt: 1} });
-			}
-		};
+	// 	return this[method].apply(scope, args);
+	// }
 
-		scope.model = {
-			find: scope.find
-		};
+	// dinamicFindAfter(method, updatedAt, ...args) {
+	// 	const scope = {
+	// 		find: (query={}, options) => {
+	// 			query._updatedAt = {
+	// 				$gt: updatedAt
+	// 			};
 
-		return this[method].apply(scope, args);
-	}
+	// 			return this.find(query, options);
+	// 		}
+	// 	};
 
-	dinamicFindAfter(method, updatedAt, ...args) {
-		const scope = {
-			find: (query={}, options) => {
-				query._updatedAt = {
-					$gt: updatedAt
-				};
+	// 	scope.model = {
+	// 		find: scope.find
+	// 	};
 
-				return this.find(query, options);
-			}
-		};
+	// 	return this[method].apply(scope, args);
+	// }
 
-		scope.model = {
-			find: scope.find
-		};
-
-		return this[method].apply(scope, args);
-	}
-
-	dinamicFindChangesAfter(method, updatedAt, ...args) {
-		return {
-			update: this.dinamicFindAfter(method, updatedAt, ...args).fetch(),
-			remove: this.dinamicTrashFindAfter(method, updatedAt, ...args).fetch()
-		};
-	}
+	// dinamicFindChangesAfter(method, updatedAt, ...args) {
+	// 	return {
+	// 		update: this.dinamicFindAfter(method, updatedAt, ...args).fetch(),
+	// 		remove: this.dinamicTrashFindAfter(method, updatedAt, ...args).fetch()
+	// 	};
+	// }
 
 }
 
diff --git a/packages/rocketchat-lib/server/models/_BaseCache.js b/packages/rocketchat-lib/server/models/_BaseCache.js
new file mode 100644
index 0000000000000000000000000000000000000000..0e2aaab6299755368d670c4d60270e69e744d8de
--- /dev/null
+++ b/packages/rocketchat-lib/server/models/_BaseCache.js
@@ -0,0 +1,892 @@
+/* eslint new-cap: 0 */
+
+import loki from 'lokijs';
+import {EventEmitter} from 'events';
+import objectPath from 'object-path';
+
+const logger = new Logger('BaseCache');
+
+const lokiEq = loki.LokiOps.$eq;
+
+loki.LokiOps.$eq = function(a, b) {
+	if (Array.isArray(a)) {
+		return loki.LokiOps.$containsAny(a, b);
+	}
+	return lokiEq(a, b);
+};
+
+loki.LokiOps.$in = loki.LokiOps.$containsAny;
+loki.LokiOps.$nin = loki.LokiOps.$containsNone;
+
+loki.LokiOps.$exists = function(a, b) {
+	if (b) {
+		return loki.LokiOps.$ne(a, undefined);
+	}
+
+	return loki.LokiOps.$eq(a, undefined);
+};
+
+
+const ignore = [
+	'emit',
+	'load',
+	'on',
+	'addToAllIndexes'
+];
+
+function traceMethodCalls(target) {
+	target._stats = {};
+
+	for (const property in target) {
+		if (typeof target[property] === 'function' && ignore.indexOf(property) === -1) {
+			target._stats[property] = {
+				calls: 0,
+				time: 0,
+				avg: 0
+			};
+			const origMethod = target[property];
+			target[property] = function(...args) {
+
+				if (target.loaded !== true) {
+					return origMethod.apply(target, args);
+				}
+
+				const startTime = RocketChat.statsTracker.now();
+				const result = origMethod.apply(target, args);
+				const time = Math.round(RocketChat.statsTracker.now() - startTime) / 1000;
+				target._stats[property].time += time;
+				target._stats[property].calls++;
+				target._stats[property].avg = target._stats[property].time / target._stats[property].calls;
+
+				return result;
+			};
+		}
+	}
+
+	setInterval(function() {
+		for (const property in target._stats) {
+			if (target._stats.hasOwnProperty(property) && target._stats[property].time > 0) {
+				const tags = [`property:${property}`, `collection:${target.collectionName}`];
+				RocketChat.statsTracker.timing('cache.methods.time', target._stats[property].avg, tags);
+				RocketChat.statsTracker.increment('cache.methods.totalTime', target._stats[property].time, tags);
+				RocketChat.statsTracker.increment('cache.methods.count', target._stats[property].calls, tags);
+				target._stats[property].avg = 0;
+				target._stats[property].time = 0;
+				target._stats[property].calls = 0;
+			}
+		}
+	}, 10000);
+
+	target._getStatsAvg = function() {
+		const stats = [];
+		for (const property in target._stats) {
+			if (target._stats.hasOwnProperty(property)) {
+				stats.push([Math.round(target._stats[property].avg*100)/100, property]);
+			}
+		}
+		return _.sortBy(stats, function(record) {
+			return record[0];
+		});
+	};
+}
+
+class Adapter {
+	loadDatabase(/*dbname, callback*/) {}
+	saveDatabase(/*dbname, dbstring, callback*/) {}
+	deleteDatabase(/*dbname, callback*/) {}
+}
+
+const db = new loki('rocket.chat.json', {adapter: Adapter});
+
+class ModelsBaseCache extends EventEmitter {
+	constructor(model) {
+		super();
+
+		traceMethodCalls(this);
+
+		this.indexes = {};
+		this.ignoreUpdatedFields = ['_updatedAt'];
+
+		this.query = {};
+		this.options = {};
+
+		this.ensureIndex('_id', 'unique');
+
+		this.joins = {};
+
+		this.on('inserted', (...args) => { this.emit('changed', 'inserted', ...args); });
+		this.on('removed', (...args) => { this.emit('changed', 'removed', ...args); });
+		this.on('updated', (...args) => { this.emit('changed', 'updated', ...args); });
+
+		this.on('beforeinsert', (...args) => { this.emit('beforechange', 'inserted', ...args); });
+		this.on('beforeremove', (...args) => { this.emit('beforechange', 'removed', ...args); });
+		this.on('beforeupdate', (...args) => { this.emit('beforechange', 'updated', ...args); });
+
+		this.on('inserted', (...args) => { this.emit('sync', 'inserted', ...args); });
+		this.on('updated', (...args) => { this.emit('sync', 'updated', ...args); });
+		this.on('beforeremove', (...args) => { this.emit('sync', 'removed', ...args); });
+
+		this.db = db;
+
+		this.model = model;
+
+		this.collectionName = this.model._db.collectionName;
+		this.collection = this.db.addCollection(this.collectionName);
+	}
+
+	hasOne(join, {field, link}) {
+		this.join({join, field, link, multi: false});
+	}
+
+	hasMany(join, {field, link}) {
+		this.join({join, field, link, multi: true});
+	}
+
+	join({join, field, link, multi}) {
+		if (!RocketChat.models[join]) {
+			console.log(`Invalid cache model ${join}`);
+			return;
+		}
+
+		RocketChat.models[join].cache.on('inserted', (record) => {
+			this.processRemoteJoinInserted({join, field, link, multi, record: record});
+		});
+
+		RocketChat.models[join].cache.on('beforeupdate', (record, diff) => {
+			if (diff[link.remote]) {
+				this.processRemoteJoinRemoved({join, field, link, multi, record: record});
+			}
+		});
+
+		RocketChat.models[join].cache.on('updated', (record, diff) => {
+			if (diff[link.remote]) {
+				this.processRemoteJoinInserted({join, field, link, multi, record: record});
+			}
+		});
+
+		RocketChat.models[join].cache.on('removed', (record) => {
+			this.processRemoteJoinRemoved({join, field, link, multi, record: record});
+		});
+
+		this.on('inserted', (localRecord) => {
+			this.processLocalJoinInserted({join, field, link, multi, localRecord: localRecord});
+		});
+
+		this.on('beforeupdate', (localRecord, diff) => {
+			if (diff[link.local]) {
+				if (multi === true) {
+					localRecord[field] = [];
+				} else {
+					localRecord[field] = undefined;
+				}
+			}
+		});
+
+		this.on('updated', (localRecord, diff) => {
+			if (diff[link.local]) {
+				this.processLocalJoinInserted({join, field, link, multi, localRecord: localRecord});
+			}
+		});
+	}
+
+	processRemoteJoinInserted({field, link, multi, record}) {
+		let localRecords = this._findByIndex(link.local, objectPath.get(record, link.remote));
+
+		if (!localRecords) {
+			return;
+		}
+
+		if (!Array.isArray(localRecords)) {
+			localRecords = [localRecords];
+		}
+
+		for (var i = 0; i < localRecords.length; i++) {
+			const localRecord = localRecords[i];
+			if (multi === true && !localRecord[field]) {
+				localRecord[field] = [];
+			}
+
+			if (typeof link.transform === 'function') {
+				record = link.transform(localRecord, record);
+			}
+
+			if (multi === true) {
+				localRecord[field].push(record);
+			} else {
+				localRecord[field] = record;
+			}
+
+			this.emit(`join:${field}:inserted`, localRecord, record);
+			this.emit(`join:${field}:changed`, 'inserted', localRecord, record);
+		}
+	}
+
+	processLocalJoinInserted({join, field, link, multi, localRecord}) {
+		let records = RocketChat.models[join].cache._findByIndex(link.remote, objectPath.get(localRecord, link.local));
+
+		if (!Array.isArray(records)) {
+			records = [records];
+		}
+
+		for (let i = 0; i < records.length; i++) {
+			let record = records[i];
+
+			if (typeof link.transform === 'function') {
+				record = link.transform(localRecord, record);
+			}
+
+			if (multi === true) {
+				localRecord[field].push(record);
+			} else {
+				localRecord[field] = record;
+			}
+
+			this.emit(`join:${field}:inserted`, localRecord, record);
+			this.emit(`join:${field}:changed`, 'inserted', localRecord, record);
+		}
+	}
+
+	processRemoteJoinRemoved({field, link, multi, record}) {
+		let localRecords = this._findByIndex(link.local, objectPath.get(record, link.remote));
+
+		if (!localRecords) {
+			return;
+		}
+
+		if (!Array.isArray(localRecords)) {
+			localRecords = [localRecords];
+		}
+
+		for (var i = 0; i < localRecords.length; i++) {
+			const localRecord = localRecords[i];
+
+			if (multi === true) {
+				if (Array.isArray(localRecord[field])) {
+					if (typeof link.remove === 'function') {
+						link.remove(localRecord[field], record);
+					} else if (localRecord[field].indexOf(record) > -1) {
+						localRecord[field].splice(localRecord[field].indexOf(record), 1);
+					}
+				}
+			} else {
+				localRecord[field] = undefined;
+			}
+
+			this.emit(`join:${field}:removed`, localRecord, record);
+			this.emit(`join:${field}:changed`, 'removed', localRecord, record);
+		}
+	}
+
+	ensureIndex(fields, type='array') {
+		if (!Array.isArray(fields)) {
+			fields = [fields];
+		}
+
+		this.indexes[fields.join(',')] = {
+			type: type,
+			fields: fields,
+			data: {}
+		};
+	}
+
+	addToAllIndexes(record) {
+		for (const indexName in this.indexes) {
+			if (this.indexes.hasOwnProperty(indexName)) {
+				this.addToIndex(indexName, record);
+			}
+		}
+	}
+
+	addToIndex(indexName, record) {
+		const index = this.indexes[indexName];
+		if (!index) {
+			console.error(`Index not defined ${indexName}`);
+			return;
+		}
+
+		const keys = [];
+		for (const field of index.fields) {
+			keys.push(objectPath.get(record, field));
+		}
+		const key = keys.join('|');
+
+		if (index.type === 'unique') {
+			index.data[key] = record;
+			return;
+		}
+
+		if (index.type === 'array') {
+			if (!index.data[key]) {
+				index.data[key] = [];
+			}
+			index.data[key].push(record);
+			return;
+		}
+	}
+
+	removeFromAllIndexes(record) {
+		for (const indexName in this.indexes) {
+			if (this.indexes.hasOwnProperty(indexName)) {
+				this.removeFromIndex(indexName, record);
+			}
+		}
+	}
+
+	removeFromIndex(indexName, record) {
+		const index = this.indexes[indexName];
+		if (!this.indexes[indexName]) {
+			console.error(`Index not defined ${indexName}`);
+			return;
+		}
+
+		if (!index.data) {
+			return;
+		}
+
+		let key = [];
+		for (const field of index.fields) {
+			key.push(objectPath.get(record, field));
+		}
+		key = key.join('|');
+
+		if (index.type === 'unique') {
+			index.data[key] = undefined;
+			return;
+		}
+
+		if (index.type === 'array') {
+			if (!index.data[key]) {
+				return;
+			}
+			const i = index.data[key].indexOf(record);
+			if (i > -1) {
+				index.data[key].splice(i, 1);
+			}
+			return;
+		}
+	}
+
+	_findByIndex(index, keys) {
+		const key = [].concat(keys).join('|');
+		if (!this.indexes[index]) {
+			return;
+		}
+
+		if (this.indexes[index].data) {
+			const result = this.indexes[index].data[key];
+			if (result) {
+				return result;
+			}
+		}
+
+		if (this.indexes[index].type === 'array') {
+			return [];
+		}
+	}
+
+	findByIndex(index, keys, options={}) {
+		return {
+			fetch: () => {
+				return this.processQueryOptionsOnResult(this._findByIndex(index, keys), options);
+			},
+
+			count: () => {
+				const records = this.findByIndex(index, keys, options).fetch();
+				if (Array.isArray(records)) {
+					return records.length;
+				}
+				return !records ? 0 : 1;
+			},
+
+			forEach: (fn) => {
+				const records = this.findByIndex(index, keys, options).fetch();
+				if (Array.isArray(records)) {
+					return records.forEach(fn);
+				}
+				if (records) {
+					return fn(records);
+				}
+			}
+		};
+	}
+
+	load() {
+		if (this.model._useCache === false) {
+			return;
+		}
+
+		console.log('Will load cache for', this.collectionName);
+		this.emit('beforeload');
+		this.loaded = false;
+		const time = RocketChat.statsTracker.now();
+		const data = this.model.db.find(this.query, this.options).fetch();
+		for (let i=0; i < data.length; i++) {
+			this.insert(data[i]);
+		}
+		console.log(String(data.length), 'records load from', this.collectionName);
+		RocketChat.statsTracker.timing('cache.load', RocketChat.statsTracker.now() - time, [`collection:${this.collectionName}`]);
+
+		this.startSync();
+		this.loaded = true;
+		this.emit('afterload');
+	}
+
+	startSync() {
+		if (this.model._useCache === false) {
+			return;
+		}
+
+		this.model._db.on('change', ({action, id, data/*, oplog*/}) => {
+			switch (action) {
+				case 'insert':
+					data._id = id;
+					this.insert(data);
+					break;
+
+				case 'remove':
+					this.removeById(id);
+					break;
+
+				case 'update:record':
+					this.updateDiffById(id, data);
+					break;
+
+				case 'update:diff':
+					this.updateDiffById(id, data);
+					break;
+
+				case 'update:query':
+					this.update(data.query, data.update, data.options);
+					break;
+			}
+		});
+	}
+
+	processQueryOptionsOnResult(result, options={}) {
+		if (result === undefined || result === null) {
+			return undefined;
+		}
+
+		if (Array.isArray(result)) {
+			if (options.sort) {
+				result = result.sort((a, b) => {
+					let r = 0;
+					for (const field in options.sort) {
+						if (options.sort.hasOwnProperty(field)) {
+							const direction = options.sort[field];
+							let valueA;
+							let valueB;
+							if (field.indexOf('.') > -1) {
+								valueA = objectPath.get(a, field);
+								valueB = objectPath.get(b, field);
+							} else {
+								valueA = a[field];
+								valueB = b[field];
+							}
+							if (valueA > valueB) {
+								r = direction;
+								break;
+							}
+							if (valueA < valueB) {
+								r = -direction;
+								break;
+							}
+						}
+					}
+					return r;
+				});
+			}
+
+			if (typeof options.skip === 'number') {
+				result.splice(0, options.skip);
+			}
+
+			if (typeof options.limit === 'number' && options.limit !== 0) {
+				result.splice(options.limit);
+			}
+		}
+
+		if (!options.fields) {
+			options.fields = {};
+		}
+
+		const fieldsToRemove = [];
+		const fieldsToGet = [];
+
+		for (const field in options.fields) {
+			if (options.fields.hasOwnProperty(field)) {
+				if (options.fields[field] === 0) {
+					fieldsToRemove.push(field);
+				} else if (options.fields[field] === 1) {
+					fieldsToGet.push(field);
+				}
+			}
+		}
+
+		if (fieldsToRemove.length > 0 && fieldsToGet.length > 0) {
+			console.warn('Can\'t mix remove and get fields');
+			fieldsToRemove.splice(0, fieldsToRemove.length);
+		}
+
+		if (fieldsToGet.length > 0 && fieldsToGet.indexOf('_id') === -1) {
+			fieldsToGet.push('_id');
+		}
+
+		let pickFields = (obj, fields) => {
+			let picked = {};
+			fields.forEach((field) => {
+				if (field.indexOf('.') !== -1) {
+					objectPath.set(picked, field, objectPath.get(obj, field));
+				} else {
+					picked[field] = obj[field];
+				}
+			});
+			return picked;
+		};
+
+		if (fieldsToRemove.length > 0 || fieldsToGet.length > 0) {
+			if (Array.isArray(result)) {
+				result = result.map((record) => {
+					if (fieldsToRemove.length > 0) {
+						return _.omit(record, ...fieldsToRemove);
+					}
+
+					if (fieldsToGet.length > 0) {
+						return pickFields(record, fieldsToGet);
+					}
+				});
+			} else {
+				if (fieldsToRemove.length > 0) {
+					return _.omit(result, ...fieldsToRemove);
+				}
+
+				if (fieldsToGet.length > 0) {
+					return pickFields(result, fieldsToGet);
+				}
+			}
+		}
+
+		return result;
+	}
+
+	processQuery(query) {
+		if (!query) {
+			return query;
+		}
+
+		if (Match.test(query, String)) {
+			return {
+				_id: query
+			};
+		}
+
+		if (Object.keys(query).length > 1) {
+			const and = [];
+			for (const field in query) {
+				if (query.hasOwnProperty(field)) {
+					and.push({
+						[field]: query[field]
+					});
+				}
+			}
+			query = {$and: and};
+		}
+
+		for (const field in query) {
+			if (query.hasOwnProperty(field)) {
+				const value = query[field];
+				if (value instanceof RegExp && field !== '$regex') {
+					query[field] = {
+						$regex: value
+					};
+				}
+
+				if (field === '$and' || field === '$or') {
+					query[field] = value.map((subValue) => {
+						return this.processQuery(subValue);
+					});
+				}
+
+				if (Match.test(value, Object) && Object.keys(value).length > 0) {
+					query[field] = this.processQuery(value);
+				}
+			}
+		}
+
+		return query;
+	}
+
+	find(query, options={}) {
+		return {
+			fetch: () => {
+				try {
+					query = this.processQuery(query);
+					return this.processQueryOptionsOnResult(this.collection.find(query), options);
+				} catch (e) {
+					console.error('Exception on cache find for', this.collectionName, ...arguments);
+					console.error(e.stack);
+				}
+			},
+
+			count: () => {
+				try {
+					query = this.processQuery(query);
+					const { limit, skip } = options;
+					return this.processQueryOptionsOnResult(this.collection.find(query), { limit, skip }).length;
+				} catch (e) {
+					console.error('Exception on cache find for', this.collectionName, ...arguments);
+					console.error(e.stack);
+				}
+			},
+
+			forEach: (fn) => {
+				return this.find(query, options).fetch().forEach(fn);
+			},
+
+			observe: (obj) => {
+				logger.debug(this.collectionName, 'Falling back observe to model with query:', query);
+				return this.model.db.find(...arguments).observe(obj);
+			},
+
+			observeChanges: (obj) => {
+				logger.debug(this.collectionName, 'Falling back observeChanges to model with query:', query);
+				return this.model.db.find(...arguments).observeChanges(obj);
+			},
+
+			_publishCursor: (cursor, sub, collection) => {
+				logger.debug(this.collectionName, 'Falling back _publishCursor to model with query:', query);
+				return this.model.db.find(...arguments)._publishCursor(cursor, sub, collection);
+			}
+		};
+	}
+
+	findOne(query, options) {
+		query = this.processQuery(query);
+		return this.processQueryOptionsOnResult(this.collection.findOne(query), options);
+	}
+
+	findOneById(_id, options) {
+		return this.findByIndex('_id', _id, options).fetch();
+	}
+
+	findWhere(query, options) {
+		query = this.processQuery(query);
+		return this.processQueryOptionsOnResult(this.collection.findWhere(query), options);
+	}
+
+	addDynamicView() {
+		return this.collection.addDynamicView(...arguments);
+	}
+
+	getDynamicView() {
+		return this.collection.getDynamicView(...arguments);
+	}
+
+	insert(record) {
+		if (Array.isArray(record)) {
+			for (const item of record) {
+				this.insert(item);
+			}
+		} else {
+			// TODO remove - ignore updates in room.usernames
+			if (this.collectionName === 'rocketchat_room' && record.usernames) {
+				delete record.usernames;
+			}
+			this.emit('beforeinsert', record);
+			this.addToAllIndexes(record);
+			this.collection.insert(record);
+			this.emit('inserted', record);
+		}
+	}
+
+	updateDiffById(id, diff) {
+		// TODO remove - ignore updates in room.usernames
+		if (this.collectionName === 'rocketchat_room' && diff.usernames) {
+			delete diff.usernames;
+		}
+
+		const record = this._findByIndex('_id', id);
+		if (!record) {
+			console.error('Cache.updateDiffById: No record', this.collectionName, id, diff);
+			return;
+		}
+
+		const updatedFields = _.without(Object.keys(diff), ...this.ignoreUpdatedFields);
+
+		if (updatedFields.length > 0) {
+			this.emit('beforeupdate', record, diff);
+		}
+
+		for (let key in diff) {
+			if (diff.hasOwnProperty(key)) {
+				objectPath.set(record, key, diff[key]);
+			}
+		}
+
+		this.collection.update(record);
+
+		if (updatedFields.length > 0) {
+			this.emit('updated', record, diff);
+		}
+	}
+
+	updateRecord(record, update) {
+		// TODO remove - ignore updates in room.usernames
+		if (this.collectionName === 'rocketchat_room' && (record.usernames || (record.$set && record.$set.usernames))) {
+			delete record.usernames;
+			if (record.$set && record.$set.usernames) {
+				delete record.$set.usernames;
+			}
+		}
+
+		const topLevelFields = Object.keys(update).map(field => field.split('.')[0]);
+		const updatedFields = _.without(topLevelFields, ...this.ignoreUpdatedFields);
+
+		if (updatedFields.length > 0) {
+			this.emit('beforeupdate', record, record);
+		}
+
+		if (update.$set) {
+			_.each(update.$set, (value, field) => {
+				objectPath.set(record, field, value);
+			});
+		}
+
+		if (update.$unset) {
+			_.each(update.$unset, (value, field) => {
+				objectPath.del(record, field);
+			});
+		}
+
+		if (update.$min) {
+			_.each(update.$min, (value, field) => {
+				let curValue = objectPath.get(record, field);
+				if (curValue === undefined || value < curValue) {
+					objectPath.set(record, field, value);
+				}
+			});
+		}
+
+		if (update.$max) {
+			_.each(update.$max, (value, field) => {
+				let curValue = objectPath.get(record, field);
+				if (curValue === undefined || value > curValue) {
+					objectPath.set(record, field, value);
+				}
+			});
+		}
+
+		if (update.$inc) {
+			_.each(update.$inc, (value, field) => {
+				let curValue = objectPath.get(record, field);
+				if (curValue === undefined) {
+					curValue = value;
+				} else {
+					curValue += value;
+				}
+				objectPath.set(record, field, curValue);
+			});
+		}
+
+		if (update.$mul) {
+			_.each(update.$mul, (value, field) => {
+				let curValue = objectPath.get(record, field);
+				if (curValue === undefined) {
+					curValue = 0;
+				} else {
+					curValue *= value;
+				}
+				objectPath.set(record, field, curValue);
+			});
+		}
+
+		if (update.$rename) {
+			_.each(update.$rename, (value, field) => {
+				let curValue = objectPath.get(record, field);
+				if (curValue !== undefined) {
+					objectPath.set(record, value, curValue);
+					objectPath.del(record, field);
+				}
+			});
+		}
+
+		if (update.$pullAll) {
+			_.each(update.$pullAll, (value, field) => {
+				let curValue = objectPath.get(record, field);
+				if (Array.isArray(curValue)) {
+					curValue = _.difference(curValue, value);
+					objectPath.set(record, field, curValue);
+				}
+			});
+		}
+
+		if (update.$pop) {
+			_.each(update.$pop, (value, field) => {
+				let curValue = objectPath.get(record, field);
+				if (Array.isArray(curValue)) {
+					if (value === -1) {
+						curValue.shift();
+					} else {
+						curValue.pop();
+					}
+					objectPath.set(record, field, curValue);
+				}
+			});
+		}
+
+		if (update.$addToSet) {
+			_.each(update.$addToSet, (value, field) => {
+				let curValue = objectPath.get(record, field);
+				if (curValue === undefined) {
+					curValue = [];
+				}
+				if (Array.isArray(curValue)) {
+					const length = curValue.length;
+
+					if (value && value.$each && Array.isArray(value.$each)) {
+						for (const valueItem of value.$each) {
+							if (curValue.indexOf(valueItem) === -1) {
+								curValue.push(valueItem);
+							}
+						}
+					} else if (curValue.indexOf(value) === -1) {
+						curValue.push(value);
+					}
+
+					if (curValue.length > length) {
+						objectPath.set(record, field, curValue);
+					}
+				}
+			});
+		}
+
+		this.collection.update(record);
+
+		if (updatedFields.length > 0) {
+			this.emit('updated', record, record);
+		}
+	}
+
+	update(query, update, options = {}) {
+		let records = options.multi ? this.find(query).fetch() : this.findOne(query) || [];
+		if (!Array.isArray(records)) {
+			records = [records];
+		}
+
+		for (const record of records) {
+			this.updateRecord(record, update);
+		}
+	}
+
+	removeById(id) {
+		const record = this._findByIndex('_id', id);
+		if (record) {
+			this.emit('beforeremove', record);
+			this.collection.removeWhere({_id: id});
+			this.removeFromAllIndexes(record);
+			this.emit('removed', record);
+		}
+	}
+}
+
+export default ModelsBaseCache;
diff --git a/packages/rocketchat-lib/server/models/_BaseDb.js b/packages/rocketchat-lib/server/models/_BaseDb.js
new file mode 100644
index 0000000000000000000000000000000000000000..a13c595032d3a3fb25e7875d2ad43c3ff8145153
--- /dev/null
+++ b/packages/rocketchat-lib/server/models/_BaseDb.js
@@ -0,0 +1,402 @@
+/* globals MongoInternals */
+
+const baseName = 'rocketchat_';
+import {EventEmitter} from 'events';
+
+const trash = new Mongo.Collection(baseName + '_trash');
+try {
+	trash._ensureIndex({ collection: 1 });
+	trash._ensureIndex({ _deletedAt: 1 }, { expireAfterSeconds: 60 * 60 * 24 * 30 });
+} catch (e) {
+	console.log(e);
+}
+
+let isOplogAvailable = MongoInternals.defaultRemoteCollectionDriver().mongo._oplogHandle && !!MongoInternals.defaultRemoteCollectionDriver().mongo._oplogHandle.onOplogEntry;
+let isOplogEnabled = isOplogAvailable;
+RocketChat.settings.get('Force_Disable_OpLog_For_Cache', (key, value) => {
+	isOplogEnabled = isOplogAvailable && value === false;
+});
+
+class ModelsBaseDb extends EventEmitter {
+	constructor(model, baseModel) {
+		super();
+
+		if (Match.test(model, String)) {
+			this.name = model;
+			this.collectionName = this.baseName + this.name;
+			this.model = new Mongo.Collection(this.collectionName);
+		} else {
+			this.name = model._name;
+			this.collectionName = this.name;
+			this.model = model;
+		}
+
+		this.baseModel = baseModel;
+
+		this.wrapModel();
+
+		// When someone start listening for changes we start oplog if available
+		this.once('newListener', (event/*, listener*/) => {
+			if (event === 'change') {
+				if (isOplogEnabled) {
+					const query = {
+						collection: this.collectionName
+					};
+
+					MongoInternals.defaultRemoteCollectionDriver().mongo._oplogHandle.onOplogEntry(query, this.processOplogRecord.bind(this));
+					MongoInternals.defaultRemoteCollectionDriver().mongo._oplogHandle._defineTooFarBehind(Number.MAX_SAFE_INTEGER);
+				}
+			}
+		});
+
+		this.tryEnsureIndex({ '_updatedAt': 1 });
+	}
+
+	get baseName() {
+		return baseName;
+	}
+
+	setUpdatedAt(record = {}, checkQuery = false, query) {
+		if (checkQuery === true) {
+			if (!query || Object.keys(query).length === 0) {
+				throw new Meteor.Error('Models._Base: Empty query');
+			}
+		}
+
+		if (/(^|,)\$/.test(Object.keys(record).join(','))) {
+			record.$set = record.$set || {};
+			record.$set._updatedAt = new Date;
+		} else {
+			record._updatedAt = new Date;
+		}
+
+		return record;
+	}
+
+	wrapModel() {
+		this.originals = {
+			insert: this.model.insert.bind(this.model),
+			update: this.model.update.bind(this.model),
+			remove: this.model.remove.bind(this.model)
+		};
+		const self = this;
+
+		this.model.insert = function() {
+			return self.insert(...arguments);
+		};
+
+		this.model.update = function() {
+			return self.update(...arguments);
+		};
+
+		this.model.remove = function() {
+			return self.remove(...arguments);
+		};
+	}
+
+	find() {
+		return this.model.find(...arguments);
+	}
+
+	findOne() {
+		return this.model.findOne(...arguments);
+	}
+
+	defineSyncStrategy(query, modifier, options) {
+		if (this.baseModel.useCache === false) {
+			return 'db';
+		}
+
+		if (options.upsert === true) {
+			return 'db';
+		}
+
+		// const dbModifiers = [
+		// 	'$currentDate',
+		// 	'$bit',
+		// 	'$pull',
+		// 	'$pushAll',
+		// 	'$push',
+		// 	'$setOnInsert'
+		// ];
+
+		const cacheAllowedModifiers = [
+			'$set',
+			'$unset',
+			'$min',
+			'$max',
+			'$inc',
+			'$mul',
+			'$rename',
+			'$pullAll',
+			'$pop',
+			'$addToSet'
+		];
+
+		const notAllowedModifiers = Object.keys(modifier).filter(i => i.startsWith('$') && cacheAllowedModifiers.includes(i) === false);
+
+		if (notAllowedModifiers.length > 0) {
+			return 'db';
+		}
+
+		const placeholderFields = Object.keys(query).filter(item => item.indexOf('$') > -1);
+		if (placeholderFields.length > 0) {
+			return 'db';
+		}
+
+		return 'cache';
+	}
+
+	processOplogRecord(action) {
+		if (isOplogEnabled === false) {
+			return;
+		}
+
+		if (action.op.op === 'i') {
+			this.emit('change', {
+				action: 'insert',
+				id: action.op.o._id,
+				data: action.op.o,
+				oplog: true
+			});
+			return;
+		}
+
+		if (action.op.op === 'u') {
+			if (!action.op.o.$set && !action.op.o.$unset) {
+				this.emit('change', {
+					action: 'update:record',
+					id: action.id,
+					data: action.op.o,
+					oplog: true
+				});
+				return;
+			}
+
+			let diff = {};
+			if (action.op.o.$set) {
+				for (let key in action.op.o.$set) {
+					if (action.op.o.$set.hasOwnProperty(key)) {
+						diff[key] = action.op.o.$set[key];
+					}
+				}
+			}
+
+			if (action.op.o.$unset) {
+				for (let key in action.op.o.$unset) {
+					if (action.op.o.$unset.hasOwnProperty(key)) {
+						diff[key] = undefined;
+					}
+				}
+			}
+
+			this.emit('change', {
+				action: 'update:diff',
+				id: action.id,
+				data: diff,
+				oplog: true
+			});
+			return;
+		}
+
+		if (action.op.op === 'd') {
+			this.emit('change', {
+				action: 'remove',
+				id: action.id,
+				oplog: true
+			});
+			return;
+		}
+	}
+
+	insert(record) {
+		this.setUpdatedAt(record);
+
+		const result = this.originals.insert(...arguments);
+		if (!isOplogEnabled && this.listenerCount('change') > 0) {
+			this.emit('change', {
+				action: 'insert',
+				id: result,
+				data: _.extend({}, record),
+				oplog: false
+			});
+		}
+
+		record._id = result;
+
+		return result;
+	}
+
+	update(query, update, options = {}) {
+		this.setUpdatedAt(update, true, query);
+
+		let strategy = this.defineSyncStrategy(query, update, options);
+		let ids = [];
+		if (!isOplogEnabled && this.listenerCount('change') > 0 && strategy === 'db') {
+			const findOptions = {fields: {_id: 1}};
+			let records = options.multi ? this.find(query, findOptions).fetch() : this.findOne(query, findOptions) || [];
+			if (!Array.isArray(records)) {
+				records = [records];
+			}
+
+			ids = records.map(item => item._id);
+			if (options.upsert !== true) {
+				query = {
+					_id: {
+						$in: ids
+					}
+				};
+			}
+		}
+
+		const result = this.originals.update(query, update, options);
+
+		if (!isOplogEnabled && this.listenerCount('change') > 0) {
+			if (strategy === 'db') {
+				if (options.upsert === true) {
+					if (result.insertedId) {
+						this.emit('change', {
+							action: 'insert',
+							id: result.insertedId,
+							data: this.findOne({_id: result.insertedId}),
+							oplog: false
+						});
+						return;
+					}
+
+					query = {
+						_id: {
+							$in: ids
+						}
+					};
+				}
+
+				let records = options.multi ? this.find(query).fetch() : this.findOne(query) || [];
+				if (!Array.isArray(records)) {
+					records = [records];
+				}
+				for (const record of records) {
+					this.emit('change', {
+						action: 'update:record',
+						id: record._id,
+						data: record,
+						oplog: false
+					});
+				}
+			} else {
+				this.emit('change', {
+					action: 'update:query',
+					id: undefined,
+					data: {
+						query: query,
+						update: update,
+						options: options
+					},
+					oplog: false
+				});
+			}
+		}
+		return result;
+	}
+
+	upsert(query, update, options = {}) {
+		options.upsert = true;
+		options._returnObject = true;
+		return this.update(query, update, options);
+	}
+
+	remove(query) {
+		const records = this.model.find(query).fetch();
+
+		const ids = [];
+		for (const record of records) {
+			ids.push(record._id);
+
+			record._deletedAt = new Date;
+			record.__collection__ = this.name;
+
+			trash.upsert({_id: record._id}, _.omit(record, '_id'));
+		}
+
+		query = { _id: { $in: ids } };
+
+		const result = this.originals.remove(query);
+
+		if (!isOplogEnabled && this.listenerCount('change') > 0) {
+			for (const record of records) {
+				this.emit('change', {
+					action: 'remove',
+					id: record._id,
+					data: _.extend({}, record),
+					oplog: false
+				});
+			}
+		}
+
+		return result;
+	}
+
+	insertOrUpsert(...args) {
+		if (args[0] && args[0]._id) {
+			const _id = args[0]._id;
+			delete args[0]._id;
+			args.unshift({
+				_id: _id
+			});
+
+			this.upsert(...args);
+			return _id;
+		} else {
+			return this.insert(...args);
+		}
+	}
+
+	allow() {
+		return this.model.allow(...arguments);
+	}
+
+	deny() {
+		return this.model.deny(...arguments);
+	}
+
+	ensureIndex() {
+		return this.model._ensureIndex(...arguments);
+	}
+
+	dropIndex() {
+		return this.model._dropIndex(...arguments);
+	}
+
+	tryEnsureIndex() {
+		try {
+			return this.ensureIndex(...arguments);
+		} catch (e) {
+			console.error('Error creating index:', this.name, '->', ...arguments, e);
+		}
+	}
+
+	tryDropIndex() {
+		try {
+			return this.dropIndex(...arguments);
+		} catch (e) {
+			console.error('Error dropping index:', this.name, '->', ...arguments, e);
+		}
+	}
+
+	trashFind(query, options) {
+		query.__collection__ = this.name;
+
+		return trash.find(query, options);
+	}
+
+	trashFindDeletedAfter(deletedAt, query = {}, options) {
+		query.__collection__ = this.name;
+		query._deletedAt = {
+			$gt: deletedAt
+		};
+
+		return trash.find(query, options);
+	}
+}
+
+export default ModelsBaseDb;
diff --git a/packages/rocketchat-lib/server/publications/settings.coffee b/packages/rocketchat-lib/server/publications/settings.coffee
index 955b7844c9a7076c962f2bba8058d5d1e5cc4f0b..8532ae0d967954c8c22e7e3bee35060455cffb08 100644
--- a/packages/rocketchat-lib/server/publications/settings.coffee
+++ b/packages/rocketchat-lib/server/publications/settings.coffee
@@ -2,14 +2,18 @@ Meteor.methods
 	'public-settings/get': (updatedAt) ->
 		this.unblock()
 
+		records = RocketChat.models.Settings.find().fetch().filter (record) ->
+			return record.hidden isnt true and record.public is true
+
 		if updatedAt instanceof Date
 			result =
-				update: RocketChat.models.Settings.findNotHiddenPublicUpdatedAfter(updatedAt).fetch()
+				update: records.filter (record) ->
+					return record._updatedAt > updatedAt
 				remove: RocketChat.models.Settings.trashFindDeletedAfter(updatedAt, {hidden: { $ne: true }, public: true}, {fields: {_id: 1, _deletedAt: 1}}).fetch()
 
 			return result
 
-		return RocketChat.models.Settings.findNotHiddenPublic().fetch()
+		return records
 
 	'private-settings/get': (updatedAt) ->
 		unless Meteor.userId()
@@ -20,20 +24,24 @@ Meteor.methods
 		if not RocketChat.authz.hasPermission Meteor.userId(), 'view-privileged-setting'
 			return []
 
-		if updatedAt instanceof Date
-			return RocketChat.models.Settings.dinamicFindChangesAfter('findNotHidden', updatedAt);
+		records = RocketChat.models.Settings.find().fetch().filter (record) ->
+			return record.hidden isnt true
 
-		return RocketChat.models.Settings.findNotHidden().fetch()
+		if updatedAt instanceof Date
+			return {
+				update: records.filter (record) ->
+					return record._updatedAt > updatedAt
+				remove: RocketChat.models.Settings.trashFindDeletedAfter(updatedAt, {hidden: { $ne: true }}, {fields: {_id: 1, _deletedAt: 1}}).fetch()
+			}
 
+		return records
 
-RocketChat.models.Settings.on 'change', (type, args...) ->
-	records = RocketChat.models.Settings.getChangedRecords type, args[0]
 
-	for record in records
-		if record.public is true
-			RocketChat.Notifications.notifyAll 'public-settings-changed', type, _.pick(record, '_id', 'value')
+RocketChat.models.Settings.cache.on 'changed', (type, setting) ->
+	if setting.public is true
+		RocketChat.Notifications.notifyAllInThisInstance 'public-settings-changed', type, _.pick(setting, '_id', 'value')
 
-		RocketChat.Notifications.notifyAll 'private-settings-changed', type, record
+	RocketChat.Notifications.notifyAllInThisInstance 'private-settings-changed', type, setting
 
 
 RocketChat.Notifications.streamAll.allowRead 'private-settings-changed', ->
diff --git a/packages/rocketchat-lib/server/startup/cache/CacheLoad.js b/packages/rocketchat-lib/server/startup/cache/CacheLoad.js
new file mode 100644
index 0000000000000000000000000000000000000000..ac56be599002e3eb3f8d3e778e9578d1ade0e60c
--- /dev/null
+++ b/packages/rocketchat-lib/server/startup/cache/CacheLoad.js
@@ -0,0 +1,51 @@
+RocketChat.models.Rooms.cache.hasMany('Subscriptions', {
+	field: 'usernames',
+	link: {
+		local: '_id',
+		remote: 'rid',
+		transform(room, subscription) {
+			return subscription.u.username;
+		},
+		remove(arr, subscription) {
+			if (arr.indexOf(subscription.u.username) > -1) {
+				arr.splice(arr.indexOf(subscription.u.username), 1);
+			}
+		}
+	}
+});
+
+
+RocketChat.models.Subscriptions.cache.hasOne('Rooms', {
+	field: '_room',
+	link: {
+		local: 'rid',
+		remote: '_id'
+	}
+});
+
+
+RocketChat.models.Subscriptions.cache.hasOne('Users', {
+	field: '_user',
+	link: {
+		local: 'u._id',
+		remote: '_id'
+	}
+});
+
+
+RocketChat.models.Users.cache.load();
+RocketChat.models.Rooms.cache.load();
+RocketChat.models.Subscriptions.cache.load();
+RocketChat.models.Settings.cache.load();
+
+
+RocketChat.models.Users.cache.addDynamicView('highlights').applyFind({
+	'settings.preferences.highlights': {$size: {$gt: 0}}
+});
+
+RocketChat.models.Subscriptions.cache.addDynamicView('notifications').applyFind({
+	$or: [
+		{desktopNotifications: {$in: ['all', 'nothing']}},
+		{mobilePushNotifications: {$in: ['all', 'nothing']}}
+	]
+});
diff --git a/packages/rocketchat-lib/server/startup/oAuthServicesUpdate.coffee b/packages/rocketchat-lib/server/startup/oAuthServicesUpdate.coffee
index d59f2370fdd691fc566db9e3a0fe4572aa33c5c3..d5fb356dc4729a336e8c5a5f1b73ff3b16278689 100644
--- a/packages/rocketchat-lib/server/startup/oAuthServicesUpdate.coffee
+++ b/packages/rocketchat-lib/server/startup/oAuthServicesUpdate.coffee
@@ -8,7 +8,7 @@ OAuthServicesUpdate = ->
 	Meteor.clearTimeout timer if timer?
 
 	timer = Meteor.setTimeout ->
-		services = RocketChat.settings.get(/^(Accounts_OAuth_|Accounts_OAuth_Custom_)[a-z0-9_-]+$/i)
+		services = RocketChat.settings.get(/^(Accounts_OAuth_|Accounts_OAuth_Custom-)[a-z0-9_]+$/i)
 		for service in services
 			logger.oauth_updated service.key
 
@@ -16,8 +16,8 @@ OAuthServicesUpdate = ->
 			if serviceName is 'Meteor'
 				serviceName = 'meteor-developer'
 
-			if /Accounts_OAuth_Custom_/.test service.key
-				serviceName = service.key.replace('Accounts_OAuth_Custom_', '')
+			if /Accounts_OAuth_Custom-/.test service.key
+				serviceName = service.key.replace('Accounts_OAuth_Custom-', '')
 
 			if service.value is true
 				data =
@@ -25,18 +25,22 @@ OAuthServicesUpdate = ->
 					secret: RocketChat.settings.get("#{service.key}_secret")
 
 
-				if /Accounts_OAuth_Custom_/.test service.key
+				if /Accounts_OAuth_Custom-/.test service.key
 					data.custom = true
-					data.serverURL = RocketChat.settings.get("#{service.key}_url")
-					data.tokenPath = RocketChat.settings.get("#{service.key}_token_path")
-					data.identityPath = RocketChat.settings.get("#{service.key}_identity_path")
-					data.authorizePath = RocketChat.settings.get("#{service.key}_authorize_path")
-					data.scope = RocketChat.settings.get("#{service.key}_scope")
-					data.buttonLabelText = RocketChat.settings.get("#{service.key}_button_label_text")
-					data.buttonLabelColor = RocketChat.settings.get("#{service.key}_button_label_color")
-					data.loginStyle = RocketChat.settings.get("#{service.key}_login_style")
-					data.buttonColor = RocketChat.settings.get("#{service.key}_button_color")
-					data.tokenSentVia = RocketChat.settings.get("#{service.key}_token_sent_via")
+					data.clientId = RocketChat.settings.get("#{service.key}-id")
+					data.secret = RocketChat.settings.get("#{service.key}-secret")
+					data.serverURL = RocketChat.settings.get("#{service.key}-url")
+					data.tokenPath = RocketChat.settings.get("#{service.key}-token_path")
+					data.identityPath = RocketChat.settings.get("#{service.key}-identity_path")
+					data.authorizePath = RocketChat.settings.get("#{service.key}-authorize_path")
+					data.scope = RocketChat.settings.get("#{service.key}-scope")
+					data.buttonLabelText = RocketChat.settings.get("#{service.key}-button_label_text")
+					data.buttonLabelColor = RocketChat.settings.get("#{service.key}-button_label_color")
+					data.loginStyle = RocketChat.settings.get("#{service.key}-login_style")
+					data.buttonColor = RocketChat.settings.get("#{service.key}-button_color")
+					data.tokenSentVia = RocketChat.settings.get("#{service.key}-token_sent_via")
+					data.usernameField = RocketChat.settings.get("#{service.key}-username_field")
+					data.mergeUsers = RocketChat.settings.get("#{service.key}-merge_users")
 					new CustomOAuth serviceName.toLowerCase(),
 						serverURL: data.serverURL
 						tokenPath: data.tokenPath
@@ -45,6 +49,8 @@ OAuthServicesUpdate = ->
 						scope: data.scope
 						loginStyle: data.loginStyle
 						tokenSentVia: data.tokenSentVia
+						usernameField: data.usernameField
+						mergeUsers: data.mergeUsers
 
 				if serviceName is 'Facebook'
 					data.appId = data.clientId
@@ -60,13 +66,13 @@ OAuthServicesUpdate = ->
 
 
 OAuthServicesRemove = (_id) ->
-	serviceName = _id.replace('Accounts_OAuth_Custom_', '')
+	serviceName = _id.replace('Accounts_OAuth_Custom-', '')
 	ServiceConfiguration.configurations.remove {service: serviceName.toLowerCase()}
 
 
 RocketChat.settings.get /^Accounts_OAuth_.+/, (key, value) ->
 		OAuthServicesUpdate()
 
-RocketChat.settings.get /^Accounts_OAuth_Custom.+/, (key, value) ->
+RocketChat.settings.get /^Accounts_OAuth_Custom-[a-z0-9_]+/, (key, value) ->
 	if not value
 		OAuthServicesRemove key
diff --git a/packages/rocketchat-lib/server/startup/settings.coffee b/packages/rocketchat-lib/server/startup/settings.coffee
index b0044a5866701b736b2ea7e7e4ac858fe1ed6ae4..dae035b010e22b30439e6cc4ac2a0a6b1b93bfd5 100644
--- a/packages/rocketchat-lib/server/startup/settings.coffee
+++ b/packages/rocketchat-lib/server/startup/settings.coffee
@@ -41,6 +41,7 @@ RocketChat.settings.addGroup 'Accounts', ->
 		@add 'Accounts_AvatarSize', 200, { type: 'int', enableQuery: {_id: 'Accounts_AvatarResize', value: true} }
 		@add 'Accounts_AvatarStoreType', 'GridFS', { type: 'select', values: [ { key: 'GridFS', i18nLabel: 'GridFS' }, { key: 'FileSystem', i18nLabel: 'FileSystem' } ] }
 		@add 'Accounts_AvatarStorePath', '', { type: 'string', enableQuery: {_id: 'Accounts_AvatarStoreType', value: 'FileSystem'} }
+		@add 'Accounts_SetDefaultAvatar', true, { type: 'boolean' }
 
 RocketChat.settings.addGroup 'OAuth', ->
 
@@ -94,11 +95,11 @@ RocketChat.settings.addGroup 'General', ->
 	@add 'Language', '', { type: 'language', public: true }
 	@add 'Allow_Invalid_SelfSigned_Certs', false, { type: 'boolean' }
 	@add 'Favorite_Rooms', true, { type: 'boolean', public: true }
-	@add 'CDN_PREFIX', '', { type: 'string' }
+	@add 'CDN_PREFIX', '', { type: 'string', public: true }
 	@add 'Force_SSL', false, { type: 'boolean', public: true }
 	@add 'GoogleTagManager_id', '', { type: 'string', public: true }
-	@add 'GoogleSiteVerification_id', '', { type: 'string', public: false }
 	@add 'Bugsnag_api_key', '', { type: 'string', public: false }
+	@add 'Force_Disable_OpLog_For_Cache', false, { type: 'boolean', public: false }
 	@add 'Restart', 'restart_server', { type: 'action', actionText: 'Restart_the_server' }
 
 	@section 'UTF8', ->
@@ -201,9 +202,10 @@ RocketChat.settings.addGroup 'Message', ->
 RocketChat.settings.addGroup 'Meta', ->
 	@add 'Meta_language', '', { type: 'string' }
 	@add 'Meta_fb_app_id', '', { type: 'string' }
-	@add 'Meta_robots', '', { type: 'string' }
+	@add 'Meta_robots', 'INDEX,FOLLOW', { type: 'string' }
 	@add 'Meta_google-site-verification', '', { type: 'string' }
 	@add 'Meta_msvalidate01', '', { type: 'string' }
+	@add 'Meta_custom', '', { type: 'code', code: 'text/html', multiline: true }
 
 
 RocketChat.settings.addGroup 'Push', ->
diff --git a/packages/rocketchat-lib/startup/defaultRoomTypes.coffee b/packages/rocketchat-lib/startup/defaultRoomTypes.coffee
index 05be736ce9b2b442178bf274b229cff588a76e07..1056e2afb76960df8bee1cb0be2a279a2a71d18b 100644
--- a/packages/rocketchat-lib/startup/defaultRoomTypes.coffee
+++ b/packages/rocketchat-lib/startup/defaultRoomTypes.coffee
@@ -38,16 +38,26 @@ RocketChat.roomTypes.add 'd', 20,
 			RocketChat.TabBar.showGroup 'directmessage'
 		link: (sub) ->
 			return { username: sub.name }
+
 	findRoom: (identifier, user) ->
 		query =
 			t: 'd'
-			usernames:
-				$all: [identifier, user.username]
-		return ChatRoom.findOne(query)
+			name: identifier
+
+		subscription = ChatSubscription.findOne(query)
+		if subscription?.rid
+			return ChatRoom.findOne(subscription.rid)
+
 	roomName: (roomData) ->
 		return ChatSubscription.findOne({ rid: roomData._id }, { fields: { name: 1 } })?.name
+
 	condition: ->
 		return RocketChat.authz.hasAtLeastOnePermission ['view-d-room', 'view-joined-room']
+	getUserStatus: (roomId) ->
+		subscription = RocketChat.models.Subscriptions.findOne({rid: roomId});
+		return if not subscription?
+
+		return Session.get('user_' + subscription.name + '_status');
 
 RocketChat.roomTypes.add 'p', 30,
 	template: 'privateGroups'
diff --git a/packages/rocketchat-livechat/app/.meteor/versions b/packages/rocketchat-livechat/app/.meteor/versions
index a8d305f20bcf2977ecdd0d66cb74c1a63c5dfc1c..0f29e93176f00a88cd45f18668cb66bd206360dd 100644
--- a/packages/rocketchat-livechat/app/.meteor/versions
+++ b/packages/rocketchat-livechat/app/.meteor/versions
@@ -6,7 +6,7 @@ babel-compiler@6.13.0
 babel-runtime@1.0.1
 base64@1.0.10
 binary-heap@1.0.10
-blaze@2.2.0
+blaze@2.2.1
 blaze-tools@1.0.10
 boilerplate-generator@1.0.11
 caching-compiler@1.1.9
@@ -48,12 +48,12 @@ minifier-js@1.2.15
 minimongo@1.0.19
 mizzao:timesync@0.4.0
 modules@0.7.7
-modules-runtime@0.7.7
-momentjs:moment@2.16.0
+modules-runtime@0.7.8
+momentjs:moment@2.17.1
 mongo@1.1.14
 mongo-id@1.0.6
 npm-bcrypt@0.9.2
-npm-mongo@2.2.11_2
+npm-mongo@2.2.16_1
 observe-sequence@1.0.14
 ordered-dict@1.0.9
 promise@0.8.8
diff --git a/packages/rocketchat-livechat/app/client/lib/_livechat.js b/packages/rocketchat-livechat/app/client/lib/_livechat.js
index 46895402b43a8c0a9b29b63639d6ed68c0bd1988..0e84b0f7eaae5c2f9f607ec9efa180aba865ed6e 100644
--- a/packages/rocketchat-livechat/app/client/lib/_livechat.js
+++ b/packages/rocketchat-livechat/app/client/lib/_livechat.js
@@ -18,15 +18,35 @@ this.Livechat = new (class Livechat {
 		this._offlineSuccessMessage = new ReactiveVar(TAPi18n.__('Thanks_We_ll_get_back_to_you_soon'));
 		this._videoCall = new ReactiveVar(false);
 		this._transcriptMessage = new ReactiveVar('');
-
+		this._connecting = new ReactiveVar(false);
 		this._room = new ReactiveVar(null);
+		this._department = new ReactiveVar(null);
+		this._widgetOpened = new ReactiveVar(false);
+		this._ready = new ReactiveVar(false);
+		this._agent = new ReactiveVar();
+
+		this.stream = new Meteor.Streamer('livechat-room');
 
-		Tracker.autorun((c) => {
+		Tracker.autorun(() => {
 			if (this._room.get() && Meteor.userId()) {
 				RoomHistoryManager.getMoreIfIsEmpty(this._room.get());
 				visitor.subscribeToRoom(this._room.get());
 				visitor.setRoom(this._room.get());
-				c.stop();
+
+				Meteor.call('livechat:getAgentData', this._room.get(), (error, result) => {
+					if (!error) {
+						this._agent.set(result);
+					}
+				});
+				this.stream.on(this._room.get(), (eventData) => {
+					if (!eventData || !eventData.type) {
+						return;
+					}
+
+					if (eventData.type === 'agentData') {
+						this._agent.set(eventData.data);
+					}
+				});
 			}
 		});
 	}
@@ -70,6 +90,15 @@ this.Livechat = new (class Livechat {
 	get transcriptMessage() {
 		return this._transcriptMessage.get();
 	}
+	get department() {
+		return this._department.get();
+	}
+	get connecting() {
+		return this._connecting.get();
+	}
+	get agent() {
+		return this._agent.get();
+	}
 
 	set online(value) {
 		this._online.set(value);
@@ -92,7 +121,6 @@ this.Livechat = new (class Livechat {
 	set offlineSuccessMessage(value) {
 		this._offlineSuccessMessage.set(value);
 	}
-
 	set customColor(value) {
 		this._customColor.set(value);
 	}
@@ -102,7 +130,6 @@ this.Livechat = new (class Livechat {
 	set offlineColor(value) {
 		this._offlineColor.set(value);
 	}
-
 	set customFontColor(value) {
 		this._customFontColor.set(value);
 	}
@@ -118,8 +145,40 @@ this.Livechat = new (class Livechat {
 	set transcriptMessage(value) {
 		this._transcriptMessage.set(value);
 	}
-
+	set connecting(value) {
+		this._connecting.set(value);
+	}
 	set room(roomId) {
 		this._room.set(roomId);
 	}
+	set department(departmentId) {
+		const dept = Department.findOne({ _id: departmentId }) || Department.findOne({ name: departmentId });
+
+		if (dept) {
+			this._department.set(dept._id);
+		}
+	}
+	set agent(agentData) {
+		this._agent.set(agentData);
+	}
+
+	ready() {
+		this._ready.set(true);
+	}
+
+	isReady() {
+		return this._ready.get();
+	}
+
+	setWidgetOpened() {
+		return this._widgetOpened.set(true);
+	}
+
+	setWidgetClosed() {
+		return this._widgetOpened.set(false);
+	}
+
+	isWidgetOpened() {
+		return this._widgetOpened.get();
+	}
 })();
diff --git a/packages/rocketchat-livechat/app/client/lib/chatMessages.coffee b/packages/rocketchat-livechat/app/client/lib/chatMessages.coffee
index f63f91e5ce26744a49ba0228da72dd152de4c101..4b6eecccf0e3524d5babf5f4641c4be0162d03bd 100644
--- a/packages/rocketchat-livechat/app/client/lib/chatMessages.coffee
+++ b/packages/rocketchat-livechat/app/client/lib/chatMessages.coffee
@@ -76,7 +76,12 @@ class @ChatMessages
 			rid ?= visitor.getRoom(true)
 
 			sendMessage = (callback) ->
-				msgObject = { _id: Random.id(), rid: rid, msg: msg, token: visitor.getToken() }
+				msgObject = {
+					_id: Random.id(),
+					rid: rid,
+					msg: msg,
+					token: visitor.getToken()
+				}
 				MsgTyping.stop(rid)
 
 				Meteor.call 'sendMessageLivechat', msgObject, (error, result) ->
@@ -84,12 +89,20 @@ class @ChatMessages
 						ChatMessage.update msgObject._id, { $set: { error: true } }
 						showError error.reason
 
-					if result.rid? and not visitor.isSubscribed(result.rid)
+					if result?.rid? and not visitor.isSubscribed(result.rid)
+						Livechat.connecting = result.showConnecting
 						ChatMessage.update result._id, _.omit(result, '_id')
 						Livechat.room = result.rid
 
 			if not Meteor.userId()
-				Meteor.call 'livechat:registerGuest', { token: visitor.getToken() }, (error, result) ->
+				guest = {
+					token: visitor.getToken()
+				}
+
+				if Livechat.department
+					guest.department = Livechat.department
+
+				Meteor.call 'livechat:registerGuest', guest, (error, result) ->
 					if error?
 						return showError error.reason
 
diff --git a/packages/rocketchat-livechat/app/client/lib/commands.js b/packages/rocketchat-livechat/app/client/lib/commands.js
index 8c8f60bbbddf8d979ed65e626b7e27393ed698ca..52d9b8801231eeb7ebff741f11d6871fa94fbdd7 100644
--- a/packages/rocketchat-livechat/app/client/lib/commands.js
+++ b/packages/rocketchat-livechat/app/client/lib/commands.js
@@ -14,7 +14,7 @@ this.Commands = {
 	promptTranscript: function() {
 		if (Livechat.transcript) {
 			const user = Meteor.user();
-			let email = user.emails && user.emails.length > 0 ? user.emails[0].address : '';
+			let email = user.visitorEmails && user.visitorEmails.length > 0 ? user.visitorEmails[0].address : '';
 
 			swal({
 				title: t('Chat_ended'),
@@ -60,5 +60,9 @@ this.Commands = {
 				showConfirmButton: false
 			});
 		}
+	},
+
+	connected: function() {
+		Livechat.connecting = false;
 	}
 };
diff --git a/packages/rocketchat-livechat/app/client/lib/hooks.js b/packages/rocketchat-livechat/app/client/lib/hooks.js
index 4a8fa387a3f93b50984d2ae0e49d1a35e4c38f72..2739bed6f9fe4f4c6bb1326d6849e37a2d4d51e8 100644
--- a/packages/rocketchat-livechat/app/client/lib/hooks.js
+++ b/packages/rocketchat-livechat/app/client/lib/hooks.js
@@ -19,6 +19,22 @@ var api = {
 		if (theme.fontColor) {
 			Livechat.customFontColor = theme.fontColor;
 		}
+	},
+
+	setDepartment: function(department) {
+		Livechat.department = department;
+	},
+
+	clearDepartment: function() {
+		Livechat.department = null;
+	},
+
+	widgetOpened: function() {
+		Livechat.setWidgetOpened();
+	},
+
+	widgetClosed: function() {
+		Livechat.setWidgetClosed();
 	}
 };
 
@@ -33,5 +49,10 @@ window.addEventListener('message', function(msg) {
 
 // tell parent window that we are ready
 Meteor.startup(function() {
-	parentCall('ready');
+	Tracker.autorun((c) => {
+		if (Livechat.isReady()) {
+			parentCall('ready');
+			c.stop();
+		}
+	});
 });
diff --git a/packages/rocketchat-livechat/app/client/lib/msgTyping.coffee b/packages/rocketchat-livechat/app/client/lib/msgTyping.coffee
index 45c68aeb73e0ca50e455f2b50d564f4a62b633af..ac6bd5b72269e1b54a7447411c6a219795eb1343 100644
--- a/packages/rocketchat-livechat/app/client/lib/msgTyping.coffee
+++ b/packages/rocketchat-livechat/app/client/lib/msgTyping.coffee
@@ -28,7 +28,7 @@
 						dep.changed()
 
 	Tracker.autorun ->
-		if visitor.getRoom()
+		if visitor.getRoom() and Meteor.userId()
 			addStream visitor.getRoom()
 
 	start = (room) ->
diff --git a/packages/rocketchat-livechat/app/client/stylesheets/main.less b/packages/rocketchat-livechat/app/client/stylesheets/main.less
index 3f567615d832b4db59955e66b55165c1da11205b..a92b5a0a4e029167563bd60290d9d4ea20e80fae 100644
--- a/packages/rocketchat-livechat/app/client/stylesheets/main.less
+++ b/packages/rocketchat-livechat/app/client/stylesheets/main.less
@@ -1,16 +1,20 @@
-@import "_variables.less";
-@import "utils/_lesshat.import.less";
 @import "utils/_reset.import.less";
+@import "utils/_lesshat.import.less";
+@import "utils/_variables.import.less";
 @import "utils/_keyframes.import.less";
+@import "utils/_loading.import.less";
 
 * {
 	box-sizing: border-box;
 	-moz-box-sizing: border-box;
 	-webkit-box-sizing: border-box;
 }
-html, body {
+
+html,
+body {
 	height: 100%;
 }
+
 body {
 	margin: 0;
 	font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif, "Meiryo UI";
@@ -23,8 +27,6 @@ body {
 	padding: 0;
 	overflow: hidden;
 	position: relative;
-	// background-color: @primary-background-color;
-
 	border-top-right-radius: 5px;
 	border-top-left-radius: 5px;
 }
@@ -37,7 +39,7 @@ textarea {
 	line-height: inherit;
 	padding: 5px;
 	margin: 5px 0;
-	border: 1px solid #E7E7E7;
+	border: 1px solid #e7e7e7;
 	border-radius: 5px;
 	outline: none;
 }
@@ -45,7 +47,7 @@ textarea {
 button {
 	background: none;
 	border: none;
-	padding: 0px;
+	padding: 0;
 	text-align: left;
 	cursor: pointer;
 	text-transform: inherit;
@@ -72,14 +74,16 @@ input:focus {
 	border-radius: 0;
 	line-height: 16px;
 	position: relative;
-	cursor: pointer;background-color: #FFF;
+	cursor: pointer;
 	color: rgba(255, 255, 255, 0.85);
 	background-color: lighten(desaturate(@primary-background-color, 15%), 12.5%);
+
 	span {
 		position: relative;
 		z-index: 2;
 	}
-	&:before {
+
+	&::before {
 		background-color: rgba(0, 0, 0, 0.1);
 		content: " ";
 		position: absolute;
@@ -89,29 +93,36 @@ input:focus {
 		height: 100%;
 		opacity: 0;
 		z-index: 1;
-		.transition(opacity .1s ease-out);
+		transition: opacity 0.1s ease-out;
 	}
+
 	&:hover {
 		text-decoration: none;
-		color: #FFF;
-		&:before {
+		color: #ffffff;
+
+		&::before {
 			opacity: 1;
 		}
 	}
+
 	&.secondary {
 		background-color: @tertiary-background-color;
 		color: @primary-font-color;
-		&:before {
+
+		&::before {
 			background-color: rgba(0, 0, 0, 0.045);
 		}
 	}
+
 	&.clean {
 		font-size: 14px;
 		box-shadow: 0 0 3px rgba(0, 0, 0, 0.08);
+
 		&.primary {
 			font-weight: 600;
 		}
 	}
+
 	&.button-block {
 		display: block;
 		width: 100%;
@@ -126,53 +137,101 @@ input:focus {
 	display: flex;
 	flex-direction: column;
 	height: 100%;
-
 	border-top-right-radius: inherit;
 	border-top-left-radius: inherit;
 
+	&.popout {
+		border-top-right-radius: 0;
+		border-top-left-radius: 0;
+
+		.title {
+			cursor: default;
+		}
+	}
+
 	.title {
 		flex: 1 0 @header-min-height;
-
 		line-height: @header-min-height;
-
 		border-top-right-radius: inherit;
 		border-top-left-radius: inherit;
-		color: #FFF;
+		color: #ffffff;
 		z-index: 10;
 		cursor: pointer;
+		padding: 0 10px;
+
 		h1 {
 			margin: 0;
-			padding: 0 5px;
-			font-size: 9pt;
+			font-size: 10pt;
 			display: inline-block;
 		}
 
 		.toolbar {
 			display: inline-block;
 			float: right;
-			padding-right: 5px;
 
 			svg {
+				cursor: pointer;
 				fill: currentColor;
 				width: 14px;
-				margin: 0 2px;
+				margin: 0 5px;
 				vertical-align: middle;
+
+				&:last-of-type {
+					margin-right: 0;
+				}
 			}
 		}
 	}
+
+	.header {
+		flex: 1 0 60px;
+		display: flex;
+		box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.2);
+		background-color: #fcfcfc;
+		color: @secondary-font-color;
+		z-index: 2;
+
+		.picture {
+			flex: 0 1 60px;
+			padding: 5px 10px;
+
+			img {
+				width: 50px;
+				height: 50px;
+				border-radius: 6px;
+				border: 1px solid @window-border-color;
+			}
+		}
+
+		.info {
+			flex: 1;
+			padding: 5px 0;
+
+			h2 {
+				color: @primary-font-color;
+				font-size: 14px;
+			}
+
+			li {
+				font-size: 11px;
+			}
+		}
+	}
+
 	.messages {
 		flex: 1 1 100%;
-
-		background-color: #FFF;
+		background-color: #ffffff;
 		border-left: 1px solid @window-border-color;
 		border-right: 1px solid @window-border-color;
 		overflow-y: auto;
+
 		.wrapper {
 			padding-bottom: 6px;
 
 			ul {
 				list-style-type: none;
 				padding: 0;
+
 				li {
 					padding: 0;
 				}
@@ -180,19 +239,48 @@ input:focus {
 
 			.message {
 				font-size: 12px;
-				padding-left: 40px;
+				padding: 8px 10px 0;
 				position: relative;
 				line-height: 18px;
-				margin: 12px 10px 0;
 				min-height: 36px;
+
+				&::after {
+					content: '';
+					display: block;
+					clear: both;
+				}
+
+				.content {
+					width: 75%;
+					background-color: #f3f3f3;
+					border: 1px solid desaturate(darken(#f3f3f3, 10%), 40%);
+					margin-left: 38px;
+					border-radius: 6px;
+					padding: 5px;
+					float: left;
+
+					&::before {
+						border-style: solid;
+						border-color: transparent desaturate(darken(#f3f3f3, 10%), 40%) transparent transparent;
+						content: " ";
+						height: 0;
+						width: 0;
+						font-size: 0;
+						pointer-events: none;
+						border-width: 5px;
+						position: absolute;
+						left: 38px;
+					}
+				}
+
 				&:nth-child(1) {
 					margin-top: 0;
 				}
+
 				&.new-day {
 					margin-top: 60px;
-				}
-				&.new-day {
-					&:before {
+
+					&::before {
 						content: attr(data-date);
 						display: block;
 						position: absolute;
@@ -203,124 +291,150 @@ input:focus {
 						text-align: center;
 						.calc(left, ~'50% - 70px');
 						color: @secondary-font-color;
-						z-index: 10;
+						z-index: 1;
 						padding: 0 10px;
-						background-color: #FFF;
+						background-color: #ffffff;
 						min-width: 120px;
 					}
-					&:after {
-						content: " ";
-						display: block;
-						position: absolute;
-						top: -20px;
-						left: 0;
-						width: 100%;
-						border-top: 1px solid #ddd;
+
+					.content {
+						&::after {
+							content: " ";
+							display: block;
+							position: absolute;
+							top: -20px;
+							left: 0;
+							width: 100%;
+							border-top: 1px solid #dddddd;
+						}
 					}
 				}
+
 				.edit-message {
 					display: none;
 					cursor: pointer;
 				}
-				&.own:hover:not(.system) .edit-message {
-					display: inline-block;
+
+				&.own {
+					.content {
+						background-color: #feffd7;
+						border: 1px solid desaturate(darken(#feffd7, 10%), 40%);
+						float: right;
+						margin-right: 3px;
+
+						&::before {
+							border-style: solid;
+							border-color: transparent transparent transparent desaturate(darken(#feffd7, 10%), 40%);
+							content: " ";
+							height: 0;
+							width: 0;
+							font-size: 0;
+							pointer-events: none;
+							border-width: 5px;
+							position: absolute;
+							right: 3px;
+							left: inherit;
+						}
+					}
 				}
+
 				.delete-message {
 					display: none;
 					cursor: pointer;
 				}
-				&.own:hover:not(.system) .delete-message {
-					display: inline-block;
-				}
+
 				.user {
 					display: inline-block;
 					font-weight: 600;
 					color: #444444;
 					margin-right: 5px;
 					outline: none;
+
 					&:hover {
-						color: #333;
+						color: #333333;
 					}
 				}
+
 				.thumb {
 					position: absolute;
-					left: 0;
-					top: 0;
+					left: 10px;
+					top: 6px;
 					display: block;
 					width: 30px;
 					height: 30px;
 				}
+
 				.info {
-					font-size: 10px;
 					color: @info-font-color;
+					display: inline-block;
+					float: right;
+					margin: 9px -1px -5px 9px;
+					font-size: 9px;
+					text-align: right;
+					left: -10px;
+					width: 55px;
+
+					.edited {
+						display: inline-block;
+					}
+
+					.edit-message {
+						float: left;
+						margin-left: 1px;
+					}
+
+					.delete-message {
+						float: left;
+					}
 				}
+
 				&.sequential {
-					// margin-top: 5px;
-					padding-top: 5px;
-					margin-top: 0;
-					margin-bottom: 0;
+					padding-top: 2px;
 					min-height: 20px;
+
 					.user {
 						display: none;
 					}
+
 					.thumb {
 						display: none;
 					}
-					.info {
-						position: absolute;
-						text-align: right;
-						left: -20px;
-						width: 55px;
-						.time {
-							display: none;
-						}
-						.edited {
-							display: inline-block;
-						}
-						.edit-message {
-							float: left;
-							margin-left: 1px;
-						}
-						.delete-message {
-							float: left;
-						}
-					}
-					&:hover {
-						.time {
-							display: inline-block;
-						}
-						.edited {
-							display: none;
-						}
-					}
 				}
+
 				&.system {
 					.body {
 						color: @info-font-color;
 						font-style: italic;
+
 						em {
 							font-weight: 600;
 						}
 					}
 				}
+
 				.avatar-initials {
 					line-height: 40px;
 				}
+
 				a {
 					color: @link-font-color;
 					font-weight: 400;
+
 					&:hover {
 						color: darken(@link-font-color, 10%);
 						text-decoration: underline;
 					}
 				}
+
 				.body {
 					opacity: 1;
-					.transition(opacity 1s linear);
+					transition: opacity 1s linear;
 				}
+
 				&.temp .body {
-					opacity: .5;
+					opacity: 0.5;
 				}
+
 				&.msg-error .body {
 					text-decoration: line-through;
 				}
@@ -340,6 +454,7 @@ input:focus {
 				}
 			}
 		}
+
 		.new-message {
 			margin: 0 -65px;
 			position: absolute;
@@ -348,15 +463,16 @@ input:focus {
 			width: 130px;
 			height: 30px;
 			text-align: center;
-			color: #FFF;
+			color: #ffffff;
 			line-height: 30px;
 			font-size: 0.8em;
 			cursor: pointer;
 			bottom: 8px;
 			left: 50%;
 			z-index: 5;
-			.transition(transform 0.3s ease-out);
+			transition: transform 0.3s ease-out;
 			.transform(translateY(-40px));
+
 			&.not {
 				.transform(translateY(100%));
 			}
@@ -366,11 +482,10 @@ input:focus {
 			bottom: @footer-min-height;
 			position: fixed;
 			width: 100%;
-			background-color: #F7D799;
+			background-color: #f7d799;
 			padding: 5px;
 			z-index: 8;
-
-			.transition(transform 0.2s ease-out);
+			transition: transform 0.2s ease-out;
 			.transform(translateY(100%));
 
 			&.show {
@@ -378,13 +493,12 @@ input:focus {
 			}
 		}
 	}
+
 	.footer {
 		flex: 1 0 @footer-min-height;
-
 		z-index: 10;
-
-		background-color: #FCFCFC;
-		border-top: 1px solid #E7E7E7;
+		background-color: #fcfcfc;
+		border-top: 1px solid @window-border-color;
 		border-left: 1px solid @window-border-color;
 		border-right: 1px solid @window-border-color;
 
@@ -410,7 +524,7 @@ input:focus {
 					-webkit-appearance: none;
 					height: 28px;
 					line-height: normal;
-					background-color: #fff;
+					background-color: #ffffff;
 					position: relative;
 				}
 			}
@@ -418,7 +532,6 @@ input:focus {
 			.buttons {
 				color: @secondary-font-color;
 				fill: @secondary-font-color;
-
 				display: flex;
 				align-items: center;
 				padding: 0 5px;
@@ -428,7 +541,7 @@ input:focus {
 					height: 15px;
 					margin: 0 4px;
 					cursor: pointer;
-					.transition(fill .15s ease-out);
+					transition: fill 0.15s ease-out;
 
 					&:hover {
 						fill: @primary-font-color;
@@ -436,6 +549,7 @@ input:focus {
 				}
 			}
 		}
+
 		.toggle-options {
 			clear: both;
 			color: @secondary-font-color;
@@ -445,22 +559,29 @@ input:focus {
 			font-size: 0.65rem;
 		}
 
+		.typing {
+			clear: both;
+			color: @secondary-font-color;
+			margin-left: 8px;
+			outline: none;
+			margin-top: 2px;
+			font-size: 0.65rem;
+		}
+
 		.options-menu {
 			min-width: 100px;
-			// min-height: 40px;
 			bottom: 21px;
 			left: 6px;
 			border-radius: 2px;
 			padding: 6px 0;
-			background-color: #fff;
+			background-color: #ffffff;
 			color: @secondary-font-color;
-
-			box-shadow: 0px 1px 1px 0 rgba(0,0,0,0.2), 0 2px 10px 0 rgba(0,0,0,.16);
+			box-shadow:
+				0 1px 1px 0 rgba(0, 0, 0, 0.2),
+				0 2px 10px 0 rgba(0, 0, 0, 0.16);
 			position: absolute;
 			z-index: 200;
-
-			.transition(transform 0.15s ease, visibility 0.15s ease, opacity 0.15s ease);
-
+			transition: transform 0.15s ease, visibility 0.15s ease, opacity 0.15s ease;
 			.transform(translateY(30px));
 			opacity: 0;
 			visibility: hidden;
@@ -475,9 +596,11 @@ input:focus {
 			ul {
 				li {
 					padding: 0 13px 0 8px;
+
 					&:hover {
-						background-color: #EEE;
+						background-color: #eeeeee;
 					}
+
 					button {
 						display: block;
 						padding: 4px 2px;
@@ -487,6 +610,7 @@ input:focus {
 			}
 		}
 	}
+
 	.offline {
 		flex: 1 1 100%;
 		background-color: white;
@@ -503,7 +627,8 @@ input:focus {
 		}
 
 		form {
-			input, textarea {
+			input,
+			textarea {
 				display: block;
 				width: 100%;
 			}
@@ -514,7 +639,7 @@ input:focus {
 
 			.error {
 				display: none;
-				background-color: #F7D799;
+				background-color: #f7d799;
 				padding: 5px;
 
 				&.show {
@@ -528,28 +653,24 @@ input:focus {
 .livechat-form {
 	flex: 1 1 100%;
 	display: block;
-	background-color: #FFF;
+	background-color: #ffffff;
 	border-left: 1px solid @window-border-color;
 	border-right: 1px solid @window-border-color;
 	padding: 5px;
 
-	input, select {
+	input,
+	select {
 		display: block;
-		background-color: #FFF;
+		background-color: #ffffff;
 	}
 
 	.error {
 		display: none;
-		// width: 100%;
-		background-color: #F7D799;
+		background-color: #f7d799;
 		padding: 5px;
 
-		// .transition(transform 0.3s ease-out);
-		// .transform(translateY(-100%));
-
 		&.show {
 			display: block;
-			// .transform(translateY(0px));
 		}
 	}
 
@@ -557,7 +678,8 @@ input:focus {
 		padding: 0 1em;
 		text-align: center;
 
-		input, select {
+		input,
+		select {
 			width: 100%;
 		}
 	}
@@ -570,7 +692,7 @@ input:focus {
 	.overlay {
 		border-top-right-radius: inherit;
 		border-top-left-radius: inherit;
-		background-color: rgba(0,0,0,0.5);
+		background-color: rgba(0, 0, 0, 0.5);
 		position: fixed;
 		height: 100%;
 		width: 100%;
@@ -596,7 +718,6 @@ input:focus {
 			padding: 0 15px;
 			border-bottom: 1px solid rgba(0, 0, 0, 0.1);
 			line-height: 40px;
-
 			white-space: nowrap;
 			text-overflow: ellipsis;
 			overflow: hidden;
@@ -644,12 +765,11 @@ input:focus {
 	text-align: right;
 	font-size: 0.65rem;
 	height: 20px;
-	color: #666;
+	color: #666666;
 	padding: 0 1em;
 	opacity: 0.5;
 	align-self: flex-end;
-
-	.transition(opacity .15s ease-out);
+	transition: opacity 0.15s ease-out;
 
 	&:hover {
 		opacity: 1;
@@ -658,6 +778,7 @@ input:focus {
 	a {
 		text-decoration: none;
 		margin-left: 1px;
+
 		img {
 			height: 14px;
 			vertical-align: middle;
@@ -676,7 +797,7 @@ input:focus {
 	bottom: 0;
 	left: 0;
 	right: 0;
-	background-color: #000;
+	background-color: #000000;
 	z-index: 11;
 
 	.video-overlay {
@@ -695,8 +816,7 @@ input:focus {
 			opacity: 0;
 			visibility: hidden;
 			.transform(translateY(50px));
-
-			.transition(opacity 0.175s ease-out, transform 0.175s ease-out, visibility 0.175s ease-out);
+			transition: opacity 0.175s ease-out, transform 0.175s ease-out, visibility 0.175s ease-out;
 
 			&.visible {
 				opacity: 1;
@@ -731,12 +851,15 @@ input:focus {
 		.title {
 			height: 100%;
 		}
+
 		.footer {
 			display: none;
 		}
+
 		.messages {
 			display: none;
 		}
+
 		.powered-by {
 			display: none;
 		}
diff --git a/packages/rocketchat-livechat/app/client/stylesheets/utils/_keyframes.import.less b/packages/rocketchat-livechat/app/client/stylesheets/utils/_keyframes.import.less
index cf3f1ab05356d32b4b96ff8af322d199c3e8a26e..8aa3df96f1da34e7f83d2bb7a7cc7c92b7a75e19 100644
--- a/packages/rocketchat-livechat/app/client/stylesheets/utils/_keyframes.import.less
+++ b/packages/rocketchat-livechat/app/client/stylesheets/utils/_keyframes.import.less
@@ -1,30 +1,78 @@
 // keyframes
+
 @-webkit-keyframes fadeIn {
-	0%   { opacity: 0; visibility: hidden; }
-	1%   { opacity: 0; visibility: visible; }
-	100% { opacity: 1; visibility: visible; }
+	0% {
+		opacity: 0;
+		visibility: hidden;
+	}
+
+	1% {
+		opacity: 0;
+		visibility: visible;
+	}
+
+	100% {
+		opacity: 1;
+		visibility: visible;
+	}
 }
+
 @keyframes fadeIn {
-	0%   { opacity: 0; visibility: hidden; }
-	1%   { opacity: 0; visibility: visible; }
-	100% { opacity: 1; visibility: visible; }
+	0% {
+		opacity: 0;
+		visibility: hidden;
+	}
+
+	1% {
+		opacity: 0;
+		visibility: visible;
+	}
+
+	100% {
+		opacity: 1;
+		visibility: visible;
+	}
 }
 
 @-webkit-keyframes fadeOut {
-	0%   { opacity: 1; visibility: visible; }
-	99%  { opacity: 0; visibility: visible; }
-	100% { opacity: 0; visibility: hidden; }
+	0% {
+		opacity: 1;
+		visibility: visible;
+	}
+
+	99% {
+		opacity: 0;
+		visibility: visible;
+	}
+
+	100% {
+		opacity: 0;
+		visibility: hidden;
+	}
 }
+
 @keyframes fadeOut {
-	0%   { opacity: 1; visibility: visible; }
-	99%  { opacity: 0; visibility: visible; }
-	100% { opacity: 0; visibility: hidden; }
+	0% {
+		opacity: 1;
+		visibility: visible;
+	}
+
+	99% {
+		opacity: 0;
+		visibility: visible;
+	}
+
+	100% {
+		opacity: 0;
+		visibility: hidden;
+	}
 }
 
 @-webkit-keyframes highlight {
 	0% {
 		background: #ffff99;
 	}
+
 	100% {
 		background: none;
 	}
@@ -34,6 +82,7 @@
 	0% {
 		background: #ffff99;
 	}
+
 	100% {
 		background: none;
 	}
@@ -43,6 +92,7 @@
 	0% {
 		background: #ffff99;
 	}
+
 	100% {
 		background: none;
 	}
@@ -52,6 +102,7 @@
 	0% {
 		background: #ffff99;
 	}
+
 	100% {
 		background: none;
 	}
@@ -62,11 +113,13 @@
 		opacity: 0;
 		visibility: hidden;
 	}
+
 	1% {
 		opacity: 0;
 		visibility: visible;
 		.transform(translateY(-150px));
 	}
+
 	100% {
 		opacity: 1;
 		visibility: visible;
@@ -79,11 +132,13 @@
 		opacity: 0;
 		visibility: hidden;
 	}
+
 	1% {
 		opacity: 0;
 		visibility: visible;
 		-webkit-transform: translateY(-150px);
 	}
+
 	100% {
 		opacity: 1;
 		visibility: visible;
@@ -96,11 +151,13 @@
 		opacity: 1;
 		visibility: visible;
 	}
+
 	99% {
 		opacity: 0;
 		visibility: visible;
 		.transform(translateY(150px));
 	}
+
 	100% {
 		opacity: 0;
 		visibility: hidden;
@@ -112,13 +169,15 @@
 		opacity: 1;
 		visibility: visible;
 	}
+
 	99% {
 		opacity: 0;
 		visibility: visible;
 		-webkit-transform: translateY(150px);
 	}
+
 	100% {
 		opacity: 0;
 		visibility: hidden;
 	}
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-livechat/app/client/stylesheets/utils/_lesshat.import.less b/packages/rocketchat-livechat/app/client/stylesheets/utils/_lesshat.import.less
index 1ce1fc07fded5e103b603921e82f78964e9790f5..0979dd5275e4c8ca63c69433f10d0dcaa5aac34f 100644
--- a/packages/rocketchat-livechat/app/client/stylesheets/utils/_lesshat.import.less
+++ b/packages/rocketchat-livechat/app/client/stylesheets/utils/_lesshat.import.less
@@ -2,123 +2,6 @@
 //
 // version: v4.1.0 (2016-07-19)
 
-// TABLE OF MIXINS:
-	// align-content
-	// align-items
-	// align-self
-	// animation
-	// animation-delay
-	// animation-direction
-	// animation-duration
-	// animation-fill-mode
-	// animation-iteration-count
-	// animation-name
-	// animation-play-state
-	// animation-timing-function
-	// appearance
-	// backface-visibility
-	// background-clip
-	// background-image
-	// background-origin
-	// background-size
-	// blur
-	// border-bottom-left-radius
-	// border-bottom-right-radius
-	// border-image
-	// border-radius
-	// border-top-left-radius
-	// border-top-right-radius
-	// box-shadow
-	// box-sizing
-	// brightness
-	// calc
-	// column-count
-	// column-gap
-	// column-rule
-	// column-width
-	// columns
-	// contrast
-	// display
-	// drop-shadow
-	// filter
-	// flex
-	// flex-basis
-	// flex-direction
-	// flex-grow
-	// flex-shrink
-	// flex-wrap
-	// font-face
-	// grayscale
-	// hue-rotate
-	// hyphens
-	// invert
-	// justify-content
-	// keyframes
-	// opacity
-	// order
-	// perspective
-	// perspective-origin
-	// placeholder
-	// rotate
-	// rotate3d
-	// rotateX
-	// rotateY
-	// rotateZ
-	// saturate
-	// scale
-	// scale3d
-	// scaleX
-	// scaleY
-	// scaleZ
-	// selection
-	// sepia
-	// size
-	// skew
-	// skewX
-	// skewY
-	// transform
-	// transform-origin
-	// transform-style
-	// transition
-	// transition-delay
-	// transition-duration
-	// transition-property
-	// transition-timing-function
-	// translate
-	// translate3d
-	// translateX
-	// translateY
-	// translateZ
-	// user-select
-
-.align-content(...) {
-	@process: ~`(function(t){return t=t||"stretch"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_ms: ~`(function(e){return e=e||"stretch","flex-start"==e?e="start":"flex-end"==e?e="end":"space-between"==e?e="justify":"space-around"==e&&(e="distribute"),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-align-content: @process;
-	-ms-flex-line-pack: @process_ms;
-	align-content: @process;
-}
-
-.align-items(...) {
-	@process_olderwebkit: ~`(function(t){return t=t||"stretch","flex-start"==t?t="start":"flex-end"==t&&(t="end"),t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_moz: ~`(function(t){return t=t||"stretch","flex-start"==t?t="start":"flex-end"==t&&(t="end"),t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process: ~`(function(t){return t=t||"stretch"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_ms: ~`(function(t){return t=t||"stretch","flex-start"==t?t="start":"flex-end"==t&&(t="end"),t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-box-align: @process_olderwebkit;
-	-moz-box-align: @process_moz;
-	-webkit-align-items: @process;
-	-ms-flex-align: @process_ms;
-	align-items: @process;
-}
-
-.align-self(...) {
-	@process: ~`(function(n){return n=n||"auto"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_ms: ~`(function(t){return t=t||"auto","flex-start"==t?t="start":"flex-end"==t&&(t="end"),t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-align-self: @process;
-	-ms-flex-item-align: @process_ms;
-	align-self: @process;
-}
-
 .animation(...) {
 	@process: ~`(function(e){return e=e||"none",/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
 	-webkit-animation: @process;
@@ -127,178 +10,6 @@
 	animation: @process;
 }
 
-.animation-delay(...) {
-	@process: ~`(function(r){r=r||"0";var s=/(?:\d)(?:ms|s)/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return s.test(r)||"0"===r||(r=r.replace(t,function(r){return r+=parseFloat(r,10)>10?"ms":"s"})),r})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-animation-delay: @process;
-	-moz-animation-delay: @process;
-	-o-animation-delay: @process;
-	animation-delay: @process;
-}
-
-.animation-direction(...) {
-	@process: ~`(function(n){return n||"normal"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-animation-direction: @process;
-	-moz-animation-direction: @process;
-	-o-animation-direction: @process;
-	animation-direction: @process;
-}
-
-.animation-duration(...) {
-	@process: ~`(function(r){r=r||"0";var s=/ms|s/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return s.test(r)||"0"===r||(r=r.replace(t,function(r){return r+=parseFloat(r,10)>10?"ms":"s"})),r})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-animation-duration: @process;
-	-moz-animation-duration: @process;
-	-o-animation-duration: @process;
-	animation-duration: @process;
-}
-
-.animation-fill-mode(...) {
-	@process: ~`(function(n){return n||"none"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-animation-fill-mode: @process;
-	-moz-animation-fill-mode: @process;
-	-o-animation-fill-mode: @process;
-	animation-fill-mode: @process;
-}
-
-.animation-iteration-count(...) {
-	@process: ~`(function(n){return n||"0"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-animation-iteration-count: @process;
-	-moz-animation-iteration-count: @process;
-	-o-animation-iteration-count: @process;
-	animation-iteration-count: @process;
-}
-
-.animation-name(...) {
-	@process: ~`(function(n){return n||"none"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-animation-name: @process;
-	-moz-animation-name: @process;
-	-o-animation-name: @process;
-	animation-name: @process;
-}
-
-.animation-play-state(...) {
-	@process: ~`(function(n){return n||"running"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-animation-play-state: @process;
-	-moz-animation-play-state: @process;
-	-o-animation-play-state: @process;
-	animation-play-state: @process;
-}
-
-.animation-timing-function(...) {
-	@process: ~`(function(e){return e||"ease"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-animation-timing-function: @process;
-	-moz-animation-timing-function: @process;
-	-o-animation-timing-function: @process;
-	animation-timing-function: @process;
-}
-
-.appearance(...) {
-	@process: ~`(function(n){return n||"none"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-appearance: @process;
-	-moz-appearance: @process;
-	appearance: @process;
-}
-
-.backface-visibility(...) {
-	@process: ~`(function(i){return i||"visible"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-backface-visibility: @process;
-	-moz-backface-visibility: @process;
-	-ms-backface-visibility: @process;
-	-o-backface-visibility: @process;
-	backface-visibility: @process;
-}
-
-.background-clip(...) {
-	@process: ~`(function(r){return r||"border-box"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-background-clip: @process;
-	-moz-background-clip: @process;
-	background-clip: @process;
-}
-
-.background-image(...) {
-	@process_ms: ~`(function(t){function e(t){var e,r,s,a,n,i,o,c,g="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",d=0,l=0,f="",h=[];if(!t)return t;do e=t.charCodeAt(d++),r=t.charCodeAt(d++),s=t.charCodeAt(d++),c=e<<16|r<<8|s,a=c>>18&63,n=c>>12&63,i=c>>6&63,o=63&c,h[l++]=g.charAt(a)+g.charAt(n)+g.charAt(i)+g.charAt(o);while(d<t.length);f=h.join("");var u=t.length%3;return(u?f.slice(0,u-3):f)+"===".slice(u||3)}if(t=t||8121991,8121991==t)return t;var r=/linear|radial/g.test(t)&&t.split(/,(?=\s*(?:linear|radial|url))/g),s=[],a={"to bottom":'x1="0%" y1="0%" x2="0%" y2="100%"',"to left":'x1="100%" y1="0%" x2="0%" y2="0%"',"to top":'x1="0%" y1="100%" x2="0%" y2="0%"',"to right":'x1="0%" y1="0%" x2="100%" y2="0%"',get"top"(){return this["to bottom"]},get"180deg"(){return this["to bottom"]},get"right"(){return this["to left"]},get"270deg"(){return this["to left"]},get"bottom"(){return this["to top"]},get"90deg"(){return this["to right"]},get"0deg"(){return this["to top"]},get"left"(){return this["to right"]},"-45deg":'x1="0%" y1="0%" x2="100%" y2="100%"',"45deg":'x1="0%" y1="100%" x2="100%" y2="0%"',"ellipse at center":'cx="50%" cy="50%" r="75%"',get"135deg"(){return this["-45deg"]}},n={uri_data:"url(data:image/svg+xml;base64,",xml:'<?xml version="1.0" ?>',svg_start:'<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none">',linear_gradient_start:'<linearGradient id="lesshat-generated" gradientUnits="userSpaceOnUse"',radial_gradient_start:'<radialGradient id="lesshat-generated" gradientUnits="userSpaceOnUse"',linear_gradient_end:"</linearGradient>",radial_gradient_end:"</radialGradient>",rect_linear:'<rect x="0" y="0" width="1" height="1" fill="url(#lesshat-generated)" />',rect_radial:'<rect x="-50" y="-50" width="101" height="101" fill="url(#lesshat-generated)" />',svg_end:"</svg>"};if(r.length){r.forEach(function(t,e){var r={};if(Object.keys(a).some(function(e){return t.indexOf(e)>=0?(r.svg_direction=a[e],!0):void(r.svg_direction=!1)}),/linear/.test(t))r.svg_type="linear";else if(/radial/.test(t))r.svg_type="radial";else if(!/linear/.test(t)&&!/radial/.test(t))return r.url=t.trim(),r.svg_type="url",r.svg_direction=!0,s.push(r),!1;var n=t.match(/rgb|#[a-zA-Z0-9]|hsl/g).length;r.svg_stops=[],t=t.replace(/transparent/g,"rgba(0,0,0,0)"),t.match(/#[a-zA-Z0-9]/g)&&t.match(/(#[a-zA-Z0-9]+)\s*(\d+%)?/g).forEach(function(t){t=t.split(" "),r.svg_stops.push('<stop offset="'+(t[1]||!1)+'" stop-color="'+t[0]+'" stop-opacity="1"/>')}),t.match(/rgba?\(\d+,\s*\d+,\s*\d+(?:,\s*(0|1|\.\d+|0\.\d+))?\)/g)&&t.replace(/rgba?\((\d+,\s*\d+,\s*\d+)(?:,\s*(0|1|\.\d+|0\.\d+))?\)\s*(\d+%)?/g,function(t,e,s,a){r.svg_stops.push('<stop offset="'+(a||!1)+'" stop-color="rgb('+e+')" stop-opacity="'+(s||1)+'"/>')}),t.match(/hsla?\((\d+,\s*\d+%,\s*\d+%),\s*(0|1|\.\d+|0\.\d+)\)/g)&&t.replace(/hsla?\((\d+,\s*\d+%,\s*\d+%),\s*(0|1|\.\d+|0\.\d+)\)\s*(\d+%)?/g,function(t,e,s,a){r.svg_stops.push('<stop offset="'+(a||!1)+'" stop-color="hsl('+e+')" stop-opacity="'+(s||1)+'"/>')});var i=Math.floor(100/(n-1));r.svg_stops.forEach(function(t,e){/offset="false"/.test(t)&&(r.svg_stops[e]=t.replace(/offset="false"/,'offset="'+i*e+'%"'))}),r.svg_stops.sort(function(t,e){if(t=t.match(/offset="(\d+)%"/),e=e.match(/offset="(\d+)%"/),2==t.length&&2==e.length)return t[1]-e[1]}),s.push(r)});var i=[],o=s.every(function(t){for(var e in t)if(0==t[e]||0==t[e].length)return!1;return!0});if(!o)return 8121991;s.forEach(function(t,e){"linear"!=t.svg_type&&"radial"!=t.svg_type||(i[e]=n.xml+n.svg_start),"linear"==t.svg_type?(i[e]+=n.linear_gradient_start+" "+t.svg_direction+">",t.svg_stops.forEach(function(t){i[e]+=t}),i[e]+=n.linear_gradient_end,i[e]+=n.rect_linear,i[e]+=n.svg_end):"radial"==t.svg_type?(i[e]+=n.radial_gradient_start+" "+t.svg_direction+">",t.svg_stops.forEach(function(t){i[e]+=t}),i[e]+=n.radial_gradient_end,i[e]+=n.rect_radial,i[e]+=n.svg_end):"url"==t.svg_type&&(i[e]=t.url)}),i.forEach(function(t,r){/<\?xml version="1.0" \?>/g.test(t)&&(i[r]=n.uri_data+e(t)+")")}),t=i.join(",")}return t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_webkit: ~`(function(e){if(e=e||8121991,8121991==e)return e;var r={"to bottom":"top","to left":"right","to top":"bottom","to right":"left","ellipse at center":"center, ellipse cover","circle closest-side":"center center, circle contain","circle farthest-corner":"center center, circle cover","circle farthest-side":"center center, circle cover","ellipse closest-side":"center center, ellipse contain","ellipse farthest-corner":"center center, ellipse cover","ellipse farthest-side":"center center, ellipse cover"},t=/(radial-gradient\()([a-z- ]+)at\s+(\w+%?)\s*(\w*%?)/g,c=Object.keys(r);return c.some(function(c){return e.indexOf(c)>=0?(e=e.replace(new RegExp(c+"(?![ a-z0-9])","g"),r[c]),!0):void(t.test(e)&&(e=e.replace(t,function(e,r,t,c,i){return r.trim()+c.trim()+" "+i.trim()+","+t.replace(/closest-side/g,"contain").replace(/farthest-corner/g,"cover").trim()})))}),e=e.replace(/(\d+)\s*deg/g,function(e,r){return 90-r+"deg"}).replace(/(linear|radial)-gradient/g,"-webkit-$1-gradient")})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_moz: ~`(function(e){if(e=e||8121991,8121991==e)return e;var r={"to bottom":"top","to left":"right","to top":"bottom","to right":"left","ellipse at center":"center, ellipse cover","circle closest-side":"center center, circle contain","circle farthest-corner":"center center, circle cover","circle farthest-side":"center center, circle cover","ellipse closest-side":"center center, ellipse contain","ellipse farthest-corner":"center center, ellipse cover","ellipse farthest-side":"center center, ellipse cover"},t=/(radial-gradient\()([a-z- ]+)at\s+(\w+%?)\s*(\w*%?)/g,c=Object.keys(r);return c.some(function(c){return e.indexOf(c)>=0?(e=e.replace(new RegExp(c+"(?![ a-z0-9])","g"),r[c]),!0):void(t.test(e)&&(e=e.replace(t,function(e,r,t,c,n){return r.trim()+c.trim()+" "+n.trim()+","+t.replace(/closest-side/g,"contain").replace(/farthest-corner/g,"cover").trim()})))}),e=e.replace(/(\d+)\s*deg/g,function(e,r){return 90-r+"deg"}).replace(/(linear|radial)-gradient/g,"-moz-$1-gradient")})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_opera: ~`(function(e){if(e=e||8121991,8121991==e)return e;var r={"to bottom":"top","to left":"right","to top":"bottom","to right":"left","ellipse at center":"center, ellipse cover","circle closest-side":"center center, circle contain","circle farthest-corner":"center center, circle cover","circle farthest-side":"center center, circle cover","ellipse closest-side":"center center, ellipse contain","ellipse farthest-corner":"center center, ellipse cover","ellipse farthest-side":"center center, ellipse cover"},t=/(radial-gradient\()([a-z- ]+)at\s+(\w+%?)\s*(\w*%?)/g,c=Object.keys(r);return c.some(function(c){return e.indexOf(c)>=0?(e=e.replace(new RegExp(c+"(?![ a-z0-9])","g"),r[c]),!0):void(t.test(e)&&(e=e.replace(t,function(e,r,t,c,n){return r.trim()+c.trim()+" "+n.trim()+","+t.replace(/closest-side/g,"contain").replace(/farthest-corner/g,"cover").trim()})))}),e=e.replace(/(\d+)\s*deg/g,function(e,r){return 90-r+"deg"}).replace(/(linear|radial)-gradient/g,"-o-$1-gradient")})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process: ~`(function(t){if(t=t||8121991,8121991==t)return t;var e={top:"to bottom",right:"to left",bottom:"to top",left:"to right"},o=Object.keys(e);return o.some(function(o){if(t.indexOf(o)>=0&&!new RegExp("to\\s+"+o+"|at\\s+"+o,"g").test(t))return t=t.replace(new RegExp(o),e[o]),!0}),t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	background-image: @process_ms;
-	background-image: @process_webkit;
-	background-image: @process_moz;
-	background-image: @process_opera;
-	background-image: @process;
-}
-
-.background-origin(...) {
-	@process: ~`(function(n){return n||"padding-box"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-background-origin: @process;
-	-moz-background-origin: @process;
-	background-origin: @process;
-}
-
-.background-size(...) {
-	@process: ~`(function(t){t=t||"auto auto";var e=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return/^[^, ]*,/.test(t)&&(t=t.replace(/(?:,)(?![^(]*\))/g,"")),e.test(t)&&(t=t.replace(r,function(t){return 0==t&&t||t+"px"})),t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-background-size: @process;
-	-moz-background-size: @process;
-	background-size: @process;
-}
-
-.blur(...) {
-	@process: ~`(function(n){n=n||"0";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"px"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-filter: blur(@process);
-	-moz-filter: blur(@process);
-	-ms-filter: blur(@process);
-	filter: blur(@process);
-}
-
-.border-bottom-left-radius(...) {
-	@process: ~`(function(e){e=e||"0";var t=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),t.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"px"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-border-bottom-left-radius: @process; -webkit-background-clip: padding-box;
-	-moz-border-radius-bottomleft: @process; -moz-background-clip: padding;
-	border-bottom-left-radius: @process; background-clip: padding-box;
-}
-
-.border-bottom-right-radius(...) {
-	@process: ~`(function(e){e=e||"0";var t=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),t.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"px"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-border-bottom-right-radius: @process; -webkit-background-clip: padding-box;
-	-moz-border-radius-bottomright: @process; -moz-background-clip: padding;
-	border-bottom-right-radius: @process; background-clip: padding-box;
-}
-
-.border-image(...) {
-	@process: ~`(function(e){return e=e||8121991,/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-border-image: @process;
-	-moz-border-image: @process;
-	-o-border-image: @process;
-	border-image: @process;
-}
-
-.border-radius(...) {
-	@process: ~`(function(e){e=e||"0";var t=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),t.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"px"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-border-radius: @process; -webkit-background-clip: padding-box;
-	-moz-border-radius: @process; -moz-background-clip: padding;
-	border-radius: @process; background-clip: padding-box;
-}
-
-.border-top-left-radius(...) {
-	@process: ~`(function(e){e=e||"0";var t=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),t.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"px"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-border-top-left-radius: @process; -webkit-background-clip: padding-box;
-	-moz-border-radius-topleft: @process; -moz-background-clip: padding;
-	border-top-left-radius: @process; background-clip: padding-box;
-}
-
-.border-top-right-radius(...) {
-	@process: ~`(function(e){e=e||"0";var t=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),t.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"px"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-border-top-right-radius: @process; -webkit-background-clip: padding-box;
-	-moz-border-radius-topright: @process; -moz-background-clip: padding;
-	border-top-right-radius: @process; background-clip: padding-box;
-}
-
-.box-shadow(...) {
-	@process: ~`(function(e){e=e||"0";var t=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),t.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"px"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-box-shadow: @process;
-	-moz-box-shadow: @process;
-	box-shadow: @process;
-}
-
 .box-sizing(...) {
 	@process: ~`(function(n){return n=n||"content-box"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
 	-webkit-box-sizing: @process;
@@ -306,455 +17,9 @@
 	box-sizing: @process;
 }
 
-.brightness(...) {
-	@process: ~`(function(n){return n=n||"1"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-filter: brightness(@process);
-	-moz-filter: brightness(@process);
-	-ms-filter: brightness(@process);
-	filter: brightness(@process);
-}
-
 .calc(...) {
 	@process: ~`(function(a){function c(c,t){var r=");\n",s=e.split(","),l=s[0]+":"+c+"("+(s[1].trim()||0)+r;"start"==t?a="0;\n"+l:a+=l}a=a||8121991;var t="@{state}",e=a;if(8121991==a)return a;switch(t){case"1":c("-webkit-calc","start"),c("-moz-calc"),c("calc");break;case"2":c("-webkit-calc","start"),c("-moz-calc");break;case"3":c("-webkit-calc","start"),c("calc");break;case"4":c("-webkit-calc","start");break;case"5":c("-moz-calc","start"),c("calc");break;case"6":c("-moz-calc","start");break;case"7":c("calc","start")}return a=a.replace(/;$/g,"")})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
 	@state: 1; -lh-property: @process;
-
-}
-
-.column-count(...) {
-	@process: ~`(function(n){return n=n||"auto"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-column-count: @process;
-	-moz-column-count: @process;
-	column-count: @process;
-}
-
-.column-gap(...) {
-	@process: ~`(function(n){n=n||"normal";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"px"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-column-gap: @process;
-	-moz-column-gap: @process;
-	column-gap: @process;
-}
-
-.column-rule(...) {
-	@process: ~`(function(e){e=e||"medium none black";var n=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),n.test(e)&&(e=e.replace(t,function(e){return 0==e&&e||e+"px"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-column-rule: @process;
-	-moz-column-rule: @process;
-	column-rule: @process;
-}
-
-.column-width(...) {
-	@process: ~`(function(t){t=t||"auto";var n=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return n.test(t)&&(t=t.replace(r,function(t){return 0==t&&t||t+"px"})),t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-column-width: @process;
-	-moz-column-width: @process;
-	column-width: @process;
-}
-
-.columns(...) {
-	@process: ~`(function(t){t=t||"auto auto";var e=/^\d+$/;return/^[^, ]*,/.test(t)&&(t=t.replace(/(?:,)(?![^(]*\))/g,""),t=t.split(" ")),e.test(t[0])&&(t[0]=t[0]+"px"),t.join(" ")})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-columns: @process;
-	-moz-columns: @process;
-	columns: @process;
-}
-
-.contrast(...) {
-	@process: ~`(function(n){n=n||"100%";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"%"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-filter: ~"contrast(@{process})";
-	-moz-filter: ~"contrast(@{process})";
-	-ms-filter: ~"contrast(@{process})";
-	filter: ~"contrast(@{process})";
-}
-
-.display(...) {
-	@process_oldwebkit: ~`(function(e){return e="flex"==e||"inline-flex"==e?"-webkit-box":8121991})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_moz: ~`(function(n){return n="flex"==n||"inline-flex"==n?"-moz-box":8121991})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_webkit: ~`(function(e){return e="flex"==e||"inline-flex"==e?"-webkit-"+e:8121991})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_ms: ~`(function(e){return e="flex"==e?"-ms-flexbox":"inline-flex"==e?"-ms-inline-flexbox":8121991})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process: ~`(function(n){return"flex"!=n&&"inline-flex"!=n&&(n=8121991),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	display: @process_oldwebkit;
-	display: @process_moz;
-	display: @process_webkit;
-	display: @process_ms;
-	display: @process;
-}
-
-.drop-shadow(...) {
-	@process: ~`(function(e){if(e=e||8121991,8121991==e)return e;var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),r.test(e)&&(e=e.replace(t,function(e){return 0==e&&e||e+"px"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-filter: drop-shadow(@process);
-	-moz-filter: drop-shadow(@process);
-	-ms-filter: drop-shadow(@process);
-	filter: drop-shadow(@process);
-}
-
-.filter(...) {
-	@process: ~`(function(e){return e=e||"none",/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-filter: @process;
-	-moz-filter: @process;
-	-ms-filter: @process;
-	filter: @process;
-}
-
-.flex(...) {
-	@process_olderwebkit: ~`(function(t){return/^\d+/.test(t)?t=t.match(/^\d+/)[0]:""==t&&(t="0"),t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_moz: ~`(function(t){return/^\d+/.test(t)?t=t.match(/^\d+/)[0]:""==t&&(t="0"),t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process: ~`(function(t){return t=t||"0 1 auto",/^[^, ]*,/.test(t)&&(t=t.replace(/(?:,)(?![^(]*\))/g,"")),t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-box-flex: @process_olderwebkit;
-	-moz-box-flex: @process_moz;
-	-webkit-flex: @process;
-	-ms-flex: @process;
-	flex: @process;
-}
-
-.flex-basis(...) {
-	@process: ~`(function(t){t=t||"auto";var n=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return n.test(t)&&(t=t.replace(r,function(t){return 0==t&&t||t+"px"})),t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-flex-basis: @process;
-	flex-basis: @process;
-}
-
-.flex-direction(...) {
-	@process_oldestwebkit: ~`(function(r){return r="row"==r||"column"==r?"normal":"row-reverse"==r||"column-reverse"==r?"reverse":8121991})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_oldermoz: ~`(function(r){return r="row"==r||"column"==r?"normal":"row-reverse"==r||"column-reverse"==r?"reverse":8121991})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_olderwebkit: ~`(function(r){return r="row"==r||"row-reverse"==r?"horizontal":"column"==r||"column-reverse"==r?"vertical":8121991})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_moz: ~`(function(r){return r="row"==r||"row-reverse"==r?"horizontal":"column"==r||"column-reverse"==r?"vertical":8121991})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process: ~`(function(n){return n=n||"row"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-box-direction: @process_oldestwebkit;
-	-moz-box-direction: @process_oldermoz;
-	-webkit-box-orient: @process_olderwebkit;
-	-moz-box-orient: @process_moz;
-	-webkit-flex-direction: @process;
-	-ms-flex-direction: @process;
-	flex-direction: @process;
-}
-
-.flex-grow(...) {
-	@process: ~`(function(n){return n=n||"0"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-flex-grow: @process;
-	flex-grow: @process;
-}
-
-.flex-shrink(...) {
-	@process: ~`(function(n){return n=n||"1"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-flex-shrink: @process;
-	flex-shrink: @process;
-}
-
-.flex-wrap(...) {
-	@process: ~`(function(n){return n=n||"nowrap"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-flex-wrap: @process;
-	-ms-flex-wrap: @process;
-	flex-wrap: @process;
-}
-
-.font-face(@fontname, @fontfile, @fontweight:normal, @fontstyle:normal) {
-	font-family: "@{fontname}";
-	src: url("@{fontfile}.eot");
-	src: url("@{fontfile}.eot?#iefix") format("embedded-opentype"),
-			 url("@{fontfile}.woff") format("woff"),
-			 url("@{fontfile}.ttf") format("truetype"),
-			 url("@{fontfile}.svg#@{fontname}") format("svg");
-	font-weight: @fontweight;
-	font-style: @fontstyle;
-}
-
-.grayscale(...) {
-	@process: ~`(function(n){n=n||"0";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"%"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-filter: grayscale(@process);
-	-moz-filter: grayscale(@process);
-	-ms-filter: grayscale(@process);
-	filter: grayscale(@process);
-}
-
-.hue-rotate(...) {
-	@process: ~`(function(e){e=e||"0";var n=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return n.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"deg"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-filter: hue-rotate(@process);
-	-moz-filter: hue-rotate(@process);
-	-ms-filter: hue-rotate(@process);
-	filter: hue-rotate(@process);
-}
-
-.hyphens(...) {
-	@process: ~`(function(n){return n=n||"manual"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-hyphens: @process;
-	-moz-hyphens: @process;
-	-ms-hyphens: @process;
-	hyphens: @process;
-}
-
-.invert(...) {
-	@process: ~`(function(n){n=n||"100%";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"%"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-filter: invert(@process);
-	-moz-filter: invert(@process);
-	-ms-filter: invert(@process);
-	filter: invert(@process);
-}
-
-.justify-content(...) {
-	@process_oldestWebkit: ~`(function(e){return e=e||"start","flex-start"==e?e="start":"flex-end"==e?e="end":"space-between"!=e&&"space-around"!=e||(e="justify"),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_moz: ~`(function(e){return e=e||"start","flex-start"==e?e="start":"flex-end"==e?e="end":"space-between"!=e&&"space-around"!=e||(e="justify"),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_ms: ~`(function(t){return t=t||"start","flex-start"==t?t="start":"flex-end"==t?t="end":"space-between"==t?t="justify":"space-around"==t&&(t="distribute"),t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process: ~`(function(t){return t=t||"flex-start"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-box-pack: @process_oldestWebkit;
-	-moz-box-pack: @process_moz;
-	-ms-flex-pack: @process_ms;
-	-webkit-justify-content: @process;
-	justify-content: @process;
-}
-
-.keyframes(...) {
-	@process: ~`(function(e){function a(a,r,k){var n="}\n",m=t.split(/(^[a-zA-Z0-9-]+),/g),o=r+" "+m[1]+"{",f=["-webkit-","-moz-","-ms-",""];k?s.forEach(function(a,r){e.indexOf(a)!==-1&&(m[2]=m[2].replace(new RegExp(a,"g"),function(e){return k+e}))}):m[2]=m[2].replace(/{([^}]+)}/g,function(e,a){var r=a.split(";");r.forEach(function(e,a){s.forEach(function(t){e.indexOf(t)!==-1&&(r[a]="",f.forEach(function(s){r[a]+=e.trim().replace(new RegExp(t,"g"),function(e){return s+e})+";"}))})});var t=r.join(";").replace(/;;/g,";");return e.replace(a,t)}),o+=m[2]+n,"start"==a?e="0; } \n"+o:"startend"==a?e="0; } \n"+o.replace(n,""):e+="end"==a?o.replace(n,""):o}e=e||8121991;var r="@{state}",t=e;if(8121991==e)return e;var s=["animation","transform","filter"];switch(r){case"1":a("start","@-webkit-keyframes","-webkit-"),a(null,"@-moz-keyframes","-moz-"),a(null,"@-o-keyframes","-o-"),a("end","@keyframes");break;case"2":a("start","@-webkit-keyframes","-webkit-"),a(null,"@-moz-keyframes","-moz-"),a("end","@keyframes");break;case"3":a("start","@-webkit-keyframes","-webkit-"),a(null,"@-moz-keyframes","-moz-"),a("end","@-o-keyframes","-o-");break;case"4":a("start","@-webkit-keyframes","-webkit-"),a(null,"@-o-keyframes","-o-"),a("end","@keyframes");break;case"5":a("start","@-webkit-keyframes","-webkit-"),a("end","@-moz-keyframes","-moz-");break;case"6":a("start","@-webkit-keyframes","-webkit-"),a("end","@-o-keyframes","-o-");break;case"7":a("start","@-webkit-keyframes","-webkit-"),a("end","@keyframes");break;case"8":a("startend","@-webkit-keyframes","-webkit-");break;case"9":a("start","@-moz-keyframes","-moz-"),a(null,"@-o-keyframes","-o-"),a("end","@keyframes");break;case"10":a("start","@-moz-keyframes","-moz-"),a("end","@-o-keyframes","-o-");break;case"11":a("start","@-moz-keyframes","-moz-"),a("end","@keyframes");break;case"12":a("startend","@-moz-keyframes","-moz-");break;case"13":a("start","@-o-keyframes","-o-"),a("end","@keyframes");break;case"14":a("startend","@-o-keyframes","-o-");break;case"15":a("startend","@keyframes")}return e+"}\n[not-existing] {\n  zoom: 1"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@state: 1; lesshat-selector { -lh-property: @process; }
-
-
-
-}
-
-.opacity(...) {
-	@process_ms: ~`(function(a){return a=a||"filter: alpha(opacity=100)","alpha(opacity="+Math.floor(100*a)+")"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process: ~`(function(n){return n=n||"1"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	 zoom: 1; filter: @process_ms;
-	-webkit-opacity: @process;
-	-moz-opacity: @process;
-	opacity: @process;
-}
-
-.order(...) {
-	@process: ~`(function(n){return n=n||"0"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-box-ordinal-group: @process;
-	-moz-box-ordinal-group: @process;
-	-ms-flex-order: @process;
-	-webkit-order: @process;
-	order: @process;
-}
-
-.perspective(...) {
-	@process: ~`(function(n){n=n||"none";var e=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return e.test(n)&&(n=n.replace(r,function(n){return 0==n&&n||n+"px"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-perspective: @process;
-	-moz-perspective: @process;
-	perspective: @process;
-}
-
-.perspective-origin(...) {
-	@process: ~`(function(e){e=e||"50% 50%";var t=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),t.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"%"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-perspective-origin: @process;
-	-moz-perspective-origin: @process;
-	perspective-origin: @process;
-}
-
-.placeholder(@color:#aaa, @element: 08121991) {
-	.inception (@arguments) when not (@element = 08121991) {
-		@{element}::-webkit-input-placeholder {
-			 color: @color;
-		}
-		@{element}:-moz-placeholder {
-			 color: @color;
-		}
-		@{element}::-moz-placeholder {
-			 color: @color;
-		}
-		@{element}:-ms-input-placeholder {
-			 color: @color;
-		}
-	}
-	.inception (@arguments) when (@element = 08121991) {
-		&::-webkit-input-placeholder {
-			 color: @color;
-		}
-		&:-moz-placeholder {
-			 color: @color;
-		}
-		&::-moz-placeholder {
-			 color: @color;
-		}
-		&:-ms-input-placeholder {
-			 color: @color;
-		}
-	}
-	.inception(@arguments);
-}
-
-.rotate(...) {
-	@process: ~`(function(e){e=e||"0";var n=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return n.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"deg"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: rotate(@process);
-	-moz-transform: rotate(@process);
-	-ms-transform: rotate(@process);
-	-o-transform: rotate(@process);
-	transform: rotate(@process);
-}
-
-.rotate3d(...) {
-	@process: ~`(function(n){return n=n||"0, 0, 0, 0",n=n.replace(/,\s*\d+$/,function(n){return n+"deg"})})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: rotate3d(@process);
-	-moz-transform: rotate3d(@process);
-	-ms-transform: rotate3d(@process);
-	-o-transform: rotate3d(@process);
-	transform: rotate3d(@process);
-}
-
-.rotateX(...) {
-	@process: ~`(function(e){e=e||"0";var n=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return n.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"deg"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: rotateX(@process);
-	-moz-transform: rotateX(@process);
-	-ms-transform: rotateX(@process);
-	-o-transform: rotateX(@process);
-	transform: rotateX(@process);
-}
-
-.rotateY(...) {
-	@process: ~`(function(e){e=e||"0";var n=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return n.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"deg"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: rotateY(@process);
-	-moz-transform: rotateY(@process);
-	-ms-transform: rotateY(@process);
-	-o-transform: rotateY(@process);
-	transform: rotateY(@process);
-}
-
-.rotateZ(...) {
-	@process: ~`(function(e){e=e||"0";var n=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return n.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"deg"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: rotateZ(@process);
-	-moz-transform: rotateZ(@process);
-	-ms-transform: rotateZ(@process);
-	-o-transform: rotateZ(@process);
-	transform: rotateZ(@process);
-}
-
-.saturate(...) {
-	@process: ~`(function(n){n=n||"100%";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"%"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-filter: ~"saturate(@{process})";
-	-moz-filter: ~"saturate(@{process})";
-	-ms-filter: ~"saturate(@{process})";
-	filter: ~"saturate(@{process})";
-}
-
-.scale(...) {
-	@process: ~`(function(n){return n=n||"1"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: scale(@process);
-	-moz-transform: scale(@process);
-	-ms-transform: scale(@process);
-	-o-transform: scale(@process);
-	transform: scale(@process);
-}
-
-.scale3d(...) {
-	@process: ~`(function(n){return n=n||"1, 1, 1"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: scale3d(@process);
-	-moz-transform: scale3d(@process);
-	-ms-transform: scale3d(@process);
-	-o-transform: scale3d(@process);
-	transform: scale3d(@process);
-}
-
-.scaleX(...) {
-	@process: ~`(function(n){return n=n||"1"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: scaleX(@process);
-	-moz-transform: scaleX(@process);
-	-ms-transform: scaleX(@process);
-	-o-transform: scaleX(@process);
-	transform: scaleX(@process);
-}
-
-.scaleY(...) {
-	@process: ~`(function(n){return n=n||"1"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: scaleY(@process);
-	-moz-transform: scaleY(@process);
-	-ms-transform: scaleY(@process);
-	-o-transform: scaleY(@process);
-	transform: scaleY(@process);
-}
-
-.scaleZ(...) {
-	@process: ~`(function(n){return n=n||"1"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: scaleZ(@process);
-	-moz-transform: scaleZ(@process);
-	-ms-transform: scaleZ(@process);
-	-o-transform: scaleZ(@process);
-	transform: scaleZ(@process);
-}
-
-.selection(...) {
-	@process: ~`(function(e){function t(t,n){var r="}\n",s=a.split(","),c=(s[1]||"")+n+"{"+s[0]+r;"start"==t?e="0; } \n"+c:"startend"==t?e="0; } \n"+c.replace(r,""):e+="end"==t?c.replace(r,""):c}e=e||8121991;var n="@{state}",a=e;if(8121991==e)return e;switch(n){case"1":t("start","::selection"),t("end","::-moz-selection");break;case"2":t("startend","::selection");break;case"3":t("startend","::-moz-selection")}return e=e.replace(/;$/g,"")})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@state: 1; lesshat-selector { -lh-property: @process; }
-
-}
-
-.sepia(...) {
-	@process: ~`(function(n){n=n||"100%";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"%"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-filter: sepia(@process);
-	-moz-filter: sepia(@process);
-	-ms-filter: sepia(@process);
-	filter: sepia(@process);
-}
-
-.size(@square) {
-	@unit: 'px';
-	.process(@square) when (ispixel(@square)), (isem(@square)), (ispercentage(@square)), (iskeyword(@square)) {
-		width: @square;
-		height: @square;
-	}
-
-	.process(@square) when not (ispixel(@square)) and not (isem(@square)) and not (ispercentage(@square)) and not (isstring(@square)) and not (iskeyword(@square)) {
-		width: ~`@{square} + @{unit}`;
-		height: ~`@{square} + @{unit}`;
-	}
-
-	.process(@square);
-
-}
-
-.size(@width, @height) {
-	@unit: 'px';
-	.process(@width, @height) when (ispixel(@width)), (isem(@width)), (ispercentage(@width)), (iskeyword(@width)) {
-		.kittens(@height) when (ispixel(@height)), (isem(@height)), (ispercentage(@height)), (iskeyword(@height)) {
-			width: @width;
-			height: @height;
-		}
-		.kittens(@height) when not (ispixel(@height)) and not (isem(@height)) and not (ispercentage(@height)) and not (iskeyword(@height)) {
-			width: @width;
-			height: ~`@{height} + @{unit}`;
-		}
-		.kittens(@height);
-	}
-
-	.process(@width, @height) when (ispixel(@height)), (isem(@height)), (ispercentage(@height)), (iskeyword(@height)) {
-		.kittens(@width) when (ispixel(@width)), (isem(@width)), (ispercentage(@width)), (iskeyword(@width)) {}
-		.kittens(@width) when not (ispixel(@width)) and not (isem(@width)) and not (ispercentage(@width)) and not (iskeyword(@width)) {
-			width: ~`@{width} + @{unit}`;
-			height: @height;
-		}
-		.kittens(@width);
-	}
-
-	.process(@width, @height) when not (ispixel(@width)) and not (isem(@width)) and not (ispercentage(@width)) and not (iskeyword(@width)) and not (ispixel(@height)) and not (isem(@height)) and not (ispercentage(@height)) and not (iskeyword(@height))  {
-		width: ~`@{width} + @{unit}`;
-		height: ~`@{height} + @{unit}`;
-	}
-
-	.process(@width, @height);
-
-}
-
-.skew(...) {
-	@process: ~`(function(e){e=e||"0";var n=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return n.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"deg"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: skew(@process);
-	-moz-transform: skew(@process);
-	-ms-transform: skew(@process);
-	-o-transform: skew(@process);
-	transform: skew(@process);
-}
-
-.skewX(...) {
-	@process: ~`(function(e){e=e||"0";var n=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return n.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"deg"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: skewX(@process);
-	-moz-transform: skewX(@process);
-	-ms-transform: skewX(@process);
-	-o-transform: skewX(@process);
-	transform: skewX(@process);
-}
-
-.skewY(...) {
-	@process: ~`(function(e){e=e||"0";var n=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return n.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"deg"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: skewY(@process);
-	-moz-transform: skewY(@process);
-	-ms-transform: skewY(@process);
-	-o-transform: skewY(@process);
-	transform: skewY(@process);
 }
 
 .transform(...) {
@@ -784,52 +49,6 @@
 	transform-style: @process;
 }
 
-.transition(...) {
-	@process_webkit: ~`(function(r){r=r||"all 0 ease 0";var e=["background-size","border-radius","border-bottom-left-radius","border-bottom-right-radius","border-top-left-radius","border-top-right-radius","box-shadow","column","transform","filter"],t="-webkit-",o=/(?:\d)(?:ms|s)/gi,a=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%)/gi;return/^[^, ]*,/.test(r)&&(r=r.replace(/(?:,)(?![^(]*\))/g,"")),e.forEach(function(e,o){r.indexOf(e)!==-1&&(r=r.replace(new RegExp(e,"g"),function(r){return t+r}))}),o.test(r)||"0"===r||(r=r.replace(a,function(r){return r+=parseFloat(r,10)>10?"ms":"s"})),r})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_moz: ~`(function(e){e=e||"all 0 ease 0";var n=["background-size","box-shadow","column","transform","filter"],r="-moz-",t=/(?:\d)(?:ms|s)/gi,a=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),n.forEach(function(n,t){e.indexOf(n)!==-1&&(e=e.replace(new RegExp(n,"g"),function(e){return r+e}))}),t.test(e)||"0"===e||(e=e.replace(a,function(e){return e+=parseFloat(e,10)>10?"ms":"s"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_opera: ~`(function(e){e=e||"all 0 ease 0";var n=["transform"],r="-o-",t=/(?:\d)(?:ms|s)/gi,a=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),n.forEach(function(n,t){e.indexOf(n)!==-1&&(e=e.replace(new RegExp(n,"g"),function(e){return r+e}))}),t.test(e)||"0"===e||(e=e.replace(a,function(e){return e+=parseFloat(e,10)>10?"ms":"s"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process: ~`(function(n){n=n||"all 0 ease 0";var e=["-webkit-","-moz-","-o-",""],t=["column","transform","filter"],r=/(?:\d)(?:ms|s)/gi,o=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%)/gi;/^[^, ]*,/.test(n)&&(n=n.replace(/(?:,)(?![^(]*\))/g,""));var i=n.split(/(?:,)(?![^(]*\))/g);return i.forEach(function(n,r){t.forEach(function(t){n.indexOf(t)!==-1&&(i[r]="",e.forEach(function(o,a){i[r]+=n.trim().replace(new RegExp(t,"g"),function(n){return o+n}),a<e.length-1&&(i[r]+=",")}))})}),n=i.join(","),r.test(n)||"0"===n||(n=n.replace(o,function(n){return n+=parseFloat(n,10)>10?"ms":"s"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transition: @process_webkit;
-	-moz-transition: @process_moz;
-	-o-transition: @process_opera;
-	transition: @process;
-}
-
-.transition-delay(...) {
-	@process: ~`(function(r){r=r||"0";var s=/(?:\d)(?:ms|s)/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return s.test(r)||"0"===r||(r=r.replace(t,function(r){return r+=parseFloat(r,10)>10?"ms":"s"})),r})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transition-delay: @process;
-	-moz-transition-delay: @process;
-	-o-transition-delay: @process;
-	transition-delay: @process;
-}
-
-.transition-duration(...) {
-	@process: ~`(function(r){r=r||"0";var s=/ms|s/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return s.test(r)||"0"===r||(r=r.replace(t,function(r){return r+=parseFloat(r,10)>10?"ms":"s"})),r})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transition-duration: @process;
-	-moz-transition-duration: @process;
-	-o-transition-duration: @process;
-	transition-duration: @process;
-}
-
-.transition-property(...) {
-	@process_webkit: ~`(function(r){r=r||"all";var o=["background-size","border-radius","border-bottom-left-radius","border-bottom-right-radius","border-top-left-radius","border-top-right-radius","box-shadow","column","transform","filter"],t="-webkit-";return o.forEach(function(o,e){r.indexOf(o)!==-1&&(r=r.replace(new RegExp(o,"g"),function(r){return t+r}))}),r})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_moz: ~`(function(n){n=n||"all";var r=["background-size","box-shadow","column","transform","filter"],o="-moz-";return r.forEach(function(r,e){n.indexOf(r)!==-1&&(n=n.replace(new RegExp(r,"g"),function(n){return o+n}))}),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_opera: ~`(function(n){n=n||"all";var r=["transform"],e="-o-";return r.forEach(function(r,f){n.indexOf(r)!==-1&&(n=n.replace(new RegExp(r,"g"),function(n){return e+n}))}),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process: ~`(function(n){n=n||"all";var o=["-webkit-","-moz-","-o-",""],r=["column","transform","filter"],t=n.split(/(?:,)(?![^(]*\))/g);return t.forEach(function(n,f){r.forEach(function(r){n.indexOf(r)!==-1&&(t[f]="",o.forEach(function(i,c){t[f]+=n.trim().replace(new RegExp(r,"g"),function(n){return i+n}),c<o.length-1&&(t[f]+=",")}))})}),n=t.join(",")})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transition-property: @process_webkit;
-	-moz-transition-property: @process_moz;
-	-o-transition-property: @process_opera;
-	transition-property: @process;
-}
-
-.transition-timing-function(...) {
-	@process: ~`(function(e){return e=e||"ease"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transition-timing-function: @process;
-	-moz-transition-timing-function: @process;
-	-o-transition-timing-function: @process;
-	transition-timing-function: @process;
-}
-
 .translate(...) {
 	@process: ~`(function(n){n=n||"0";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"px"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
 	-webkit-transform: translate(@process);
@@ -839,15 +58,6 @@
 	transform: translate(@process);
 }
 
-.translate3d(...) {
-	@process: ~`(function(n){n=n||"0, 0, 0";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"px"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: translate3d(@process);
-	-moz-transform: translate3d(@process);
-	-ms-transform: translate3d(@process);
-	-o-transform: translate3d(@process);
-	transform: translate3d(@process);
-}
-
 .translateX(...) {
 	@process: ~`(function(n){n=n||"0";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"px"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
 	-webkit-transform: translateX(@process);
@@ -866,15 +76,6 @@
 	transform: translateY(@process);
 }
 
-.translateZ(...) {
-	@process: ~`(function(n){n=n||"0";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"px"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: translateZ(@process);
-	-moz-transform: translateZ(@process);
-	-ms-transform: translateZ(@process);
-	-o-transform: translateZ(@process);
-	transform: translateZ(@process);
-}
-
 .user-select(...) {
 	@process: ~`(function(n){return n=n||"auto"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
 	-webkit-user-select: @process;
diff --git a/packages/rocketchat-livechat/app/client/stylesheets/utils/_loading.import.less b/packages/rocketchat-livechat/app/client/stylesheets/utils/_loading.import.less
new file mode 100644
index 0000000000000000000000000000000000000000..838d5625823a5aa994d9b6f0cb2995d440c6d739
--- /dev/null
+++ b/packages/rocketchat-livechat/app/client/stylesheets/utils/_loading.import.less
@@ -0,0 +1,53 @@
+.loading-animation {
+	color: @secondary-font-color;
+	font-size: 1.3rem;
+	margin-left: 32px;
+	margin-top: 12px;
+	margin-bottom: 5px;
+}
+
+.loading-animation > div {
+	width: 3px;
+	height: 3px;
+	border-radius: 100%;
+	display: inline-block;
+	background-color: @secondary-font-color;
+	-webkit-animation: loading-bouncedelay 1.4s infinite ease-in-out both;
+	animation: loading-bouncedelay 1.4s infinite ease-in-out both;
+}
+
+.loading-animation .bounce1 {
+	-webkit-animation-delay: -0.32s;
+	animation-delay: -0.32s;
+}
+
+.loading-animation .bounce2 {
+	-webkit-animation-delay: -0.16s;
+	animation-delay: -0.16s;
+}
+
+@-webkit-keyframes loading-bouncedelay {
+	0%,
+	80%,
+	100% {
+		-webkit-transform: scale(0);
+	}
+
+	40% {
+		-webkit-transform: scale(1);
+	}
+}
+
+@keyframes loading-bouncedelay {
+	0%,
+	80%,
+	100% {
+		-webkit-transform: scale(0);
+		transform: scale(0);
+	}
+
+	40% {
+		-webkit-transform: scale(1);
+		transform: scale(1);
+	}
+}
diff --git a/packages/rocketchat-livechat/app/client/stylesheets/utils/_reset.import.less b/packages/rocketchat-livechat/app/client/stylesheets/utils/_reset.import.less
index fce81e7bf5d8e0f45517e0e26f3c535734c6bac0..274ac1571a3ff7801ee7bd375fc978b693b3e265 100644
--- a/packages/rocketchat-livechat/app/client/stylesheets/utils/_reset.import.less
+++ b/packages/rocketchat-livechat/app/client/stylesheets/utils/_reset.import.less
@@ -2,46 +2,139 @@
 * Eric Meyer's Reset CSS v2.0 (http://meyerweb.com/eric/tools/css/reset/)
 * http://cssreset.com
 */
-html, body, div, span, applet, object, iframe,
-h1, h2, h3, h4, h5, h6, p, blockquote, pre,
-a, abbr, acronym, address, big, cite, code,
-del, dfn, em, img, ins, kbd, q, s, samp,
-small, strike, strong, sub, sup, tt, var,
-b, u, i, center,
-dl, dt, dd, ol, ul, li,
-fieldset, form, label, legend,
-table, caption, tbody, tfoot, thead, tr, th, td,
-article, aside, canvas, details, embed,
-figure, figcaption, footer, header, hgroup,
-menu, nav, output, ruby, section, summary,
-time, mark, audio, video {
+
+html,
+body,
+div,
+span,
+applet,
+object,
+iframe,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+p,
+blockquote,
+pre,
+a,
+abbr,
+acronym,
+address,
+big,
+cite,
+code,
+del,
+dfn,
+em,
+img,
+ins,
+kbd,
+q,
+s,
+samp,
+small,
+strike,
+strong,
+sub,
+sup,
+tt,
+var,
+b,
+u,
+i,
+center,
+dl,
+dt,
+dd,
+ol,
+ul,
+li,
+fieldset,
+form,
+label,
+legend,
+table,
+caption,
+tbody,
+tfoot,
+thead,
+tr,
+th,
+td,
+article,
+aside,
+canvas,
+details,
+embed,
+figure,
+figcaption,
+footer,
+header,
+hgroup,
+menu,
+nav,
+output,
+ruby,
+section,
+summary,
+time,
+mark,
+audio,
+video {
 	margin: 0;
 	padding: 0;
-	border: 0;
 	font-size: 100%;
 	// font: inherit;
 	vertical-align: baseline;
+	border: 0 solid; // set default border style
+	&::after,
+	&::before {
+		border: 0 solid;
+	}
 }
+
 /* HTML5 display-role reset for older browsers */
-article, aside, details, figcaption, figure,
-footer, header, hgroup, menu, nav, section {
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+menu,
+nav,
+section {
 	display: block;
 }
+
 body {
 	line-height: 1;
 }
-ol, ul {
+
+ol,
+ul {
 	list-style: none;
 }
-blockquote, q {
+
+blockquote,
+q {
 	quotes: none;
 }
-blockquote:before, blockquote:after,
-q:before, q:after {
+
+blockquote::before,
+blockquote::after,
+q::before,
+q::after {
 	content: '';
 	content: none;
 }
+
 table {
 	border-collapse: collapse;
 	border-spacing: 0;
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-livechat/app/client/stylesheets/_variables.less b/packages/rocketchat-livechat/app/client/stylesheets/utils/_variables.import.less
similarity index 66%
rename from packages/rocketchat-livechat/app/client/stylesheets/_variables.less
rename to packages/rocketchat-livechat/app/client/stylesheets/utils/_variables.import.less
index 82fec29be9153d83b8063f276e0060087de63d4c..a8aa9a3b06f329074d9ab277e6ef275c5bb23483 100644
--- a/packages/rocketchat-livechat/app/client/stylesheets/_variables.less
+++ b/packages/rocketchat-livechat/app/client/stylesheets/utils/_variables.import.less
@@ -13,20 +13,20 @@
 //@primary-background-color: #38393d;
 
 @primary-background-color: #04436a;
-@secondary-background-color: #F4F4F4;
-@tertiary-background-color: #EAEAEA;
+@secondary-background-color: #f4f4f4;
+@tertiary-background-color: #eaeaea;
 
-@link-font-color: #008CE3;
+@link-font-color: #008ce3;
 
 @primary-font-color: #444444;
 @secondary-font-color: #7f7f7f;
 @tertiary-font-color: rgba(255, 255, 255, 0.6);
 @quaternary-font-color: rgba(255, 255, 255, 0.85);
-@info-font-color: #AAAAAA;
+@info-font-color: #aaaaaa;
 
-@status-online: #35AC19;
-@status-offline: rgba(150, 150, 150, 0.50);
-@status-busy: #D30230;
+@status-online: #35ac19;
+@status-offline: rgba(150, 150, 150, 0.5);
+@status-busy: #d30230;
 @status-away: #fcb316;
 
-@window-border-color: #E7E7E7;
+@window-border-color: #e7e7e7;
diff --git a/packages/rocketchat-livechat/app/client/views/avatar.coffee b/packages/rocketchat-livechat/app/client/views/avatar.coffee
index b0abe8754a17e541350f55cda4e2643c23d25398..5e2e62ab9ef3dccec20d19c86b9457726773d451 100644
--- a/packages/rocketchat-livechat/app/client/views/avatar.coffee
+++ b/packages/rocketchat-livechat/app/client/views/avatar.coffee
@@ -4,7 +4,7 @@ Template.avatar.helpers
 		if not username? and this.userId?
 			username = Meteor.users.findOne(this.userId)?.username
 
-		if not username?
+		if not username? or Meteor.user()?.username is username
 			return
 
 		Session.get "avatar_random_#{username}"
diff --git a/packages/rocketchat-livechat/app/client/views/livechatWindow.html b/packages/rocketchat-livechat/app/client/views/livechatWindow.html
index c7eb3fc4c3d34170f57a14cc423a3238ffae6bb7..f84029593a03adc9076d240b632e2b302fb1abc1 100644
--- a/packages/rocketchat-livechat/app/client/views/livechatWindow.html
+++ b/packages/rocketchat-livechat/app/client/views/livechatWindow.html
@@ -1,9 +1,20 @@
 <template name="livechatWindow">
 	{{#if livechatStarted}}
-		<div class="livechat-room">
+		<div class="livechat-room {{#if popoutActive}}popout{{/if}}">
 			<div class="title" style="background-color:{{color}}; color: {{fontColor}}">
 				<div class="toolbar">
 					&nbsp;
+					{{#unless popoutActive}}
+						{{#if isOpened}}
+							<svg class="minimize" title="Minimize" viewBox="0 0 448 448" xmlns="http://www.w3.org/2000/svg">
+								<path d="M448 328v48c0 22-18 40-40 40h-368c-22 0-40-18-40-40v-48c0-22 18-40 40-40h368c22 0 40 18 40 40z"></path>
+							</svg>
+						{{else}}
+							<svg class="maximize" title="Maximize" viewBox="0 0 448 448" xmlns="http://www.w3.org/2000/svg">
+								<path d="M64 352h320v-192h-320v192zM448 72v304c0 22-18 40-40 40h-368c-22 0-40-18-40-40v-304c0-22 18-40 40-40h368c22 0 40 18 40 40z"></path>
+							</svg>
+						{{/if}}
+					{{/unless}}
 					{{#if soundActive}}
 						<svg class="sound" title="Toggle notification sound" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg">
 							<path d="M912 1696q0-16-16-16-59 0-101.5-42.5t-42.5-101.5q0-16-16-16t-16 16q0 73 51.5 124.5t124.5 51.5q16 0 16-16zm816-288q0 52-38 90t-90 38h-448q0 106-75 181t-181 75-181-75-75-181h-448q-52 0-90-38t-38-90q50-42 91-88t85-119.5 74.5-158.5 50-206 19.5-260q0-152 117-282.5t307-158.5q-8-19-8-39 0-40 28-68t68-28 68 28 28 68q0 20-8 39 190 28 307 158.5t117 282.5q0 139 19.5 260t50 206 74.5 158.5 85 119.5 91 88z" />
@@ -14,9 +25,8 @@
 						</svg>
 					{{/if}}
 					{{#unless popoutActive}}
-						<svg class="popout" aria-label="{{_ "Open in a new window"}}" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
-							<path d="M392.857,292.354h-18.274c-2.669,0-4.859,0.855-6.563,2.573c-1.718,1.708-2.573,3.897-2.573,6.563v91.361 c0,12.563-4.47,23.315-13.415,32.262c-8.945,8.945-19.701,13.414-32.264,13.414H82.224c-12.562,0-23.317-4.469-32.264-13.414 c-8.945-8.946-13.417-19.698-13.417-32.262V155.31c0-12.562,4.471-23.313,13.417-32.259c8.947-8.947,19.702-13.418,32.264-13.418 h200.994c2.669,0,4.859-0.859,6.57-2.57c1.711-1.713,2.566-3.9,2.566-6.567V82.221c0-2.662-0.855-4.853-2.566-6.563 c-1.711-1.713-3.901-2.568-6.57-2.568H82.224c-22.648,0-42.016,8.042-58.102,24.125C8.042,113.297,0,132.665,0,155.313v237.542 c0,22.647,8.042,42.018,24.123,58.095c16.086,16.084,35.454,24.13,58.102,24.13h237.543c22.647,0,42.017-8.046,58.101-24.13 c16.085-16.077,24.127-35.447,24.127-58.095v-91.358c0-2.669-0.856-4.859-2.574-6.57 C397.709,293.209,395.519,292.354,392.857,292.354z"></path>
-							<path d="M506.199,41.971c-3.617-3.617-7.905-5.424-12.85-5.424H347.171c-4.948,0-9.233,1.807-12.847,5.424 c-3.617,3.615-5.428,7.898-5.428,12.847s1.811,9.233,5.428,12.85l50.247,50.248L198.424,304.067 c-1.906,1.903-2.856,4.093-2.856,6.563c0,2.479,0.953,4.668,2.856,6.571l32.548,32.544c1.903,1.903,4.093,2.852,6.567,2.852 s4.665-0.948,6.567-2.852l186.148-186.148l50.251,50.248c3.614,3.617,7.898,5.426,12.847,5.426s9.233-1.809,12.851-5.426 c3.617-3.616,5.424-7.898,5.424-12.847V54.818C511.626,49.866,509.813,45.586,506.199,41.971z"></path>
+						<svg class="popout" aria-label="{{_ "Open in a new window"}}" viewBox="0 0 448 448" xmlns="http://www.w3.org/2000/svg">
+							<path d="M320 232v-120c0-8.75-7.25-16-16-16h-120c-6.5 0-12.25 4-14.75 9.75-2.5 6-1.25 13 3.5 17.5l36 36-133.5 133.5c-6.25 6.25-6.25 16.25 0 22.5l25.5 25.5c6.25 6.25 16.25 6.25 22.5 0l133.5-133.5 36 36c3 3.25 7 4.75 11.25 4.75 2 0 4.25-0.5 6.25-1.25 5.75-2.5 9.75-8.25 9.75-14.75zM384 104v240c0 39.75-32.25 72-72 72h-240c-39.75 0-72-32.25-72-72v-240c0-39.75 32.25-72 72-72h240c39.75 0 72 32.25 72 72z"></path>
 						</svg>
 					{{/unless}}
 				</div>
diff --git a/packages/rocketchat-livechat/app/client/views/livechatWindow.js b/packages/rocketchat-livechat/app/client/views/livechatWindow.js
index 8785b0fe2fe7941cc6b7d29f4e529e05c2edb1b7..0fe40f00f572c8162dcaa4f1b857b1e30a04470c 100644
--- a/packages/rocketchat-livechat/app/client/views/livechatWindow.js
+++ b/packages/rocketchat-livechat/app/client/views/livechatWindow.js
@@ -41,6 +41,9 @@ Template.livechatWindow.helpers({
 	},
 	videoCalling() {
 		return LivechatVideoCall.isActive();
+	},
+	isOpened() {
+		return Livechat.isWidgetOpened();
 	}
 });
 
@@ -105,6 +108,10 @@ Template.livechatWindow.onCreated(function() {
 				Livechat.room = result.room._id;
 			}
 
+			if (result.agentData) {
+				Livechat.agent = result.agentData;
+			}
+
 			TAPi18n.setLanguage((result.language || defaultAppLanguage()).split('-').shift());
 
 			Triggers.setTriggers(result.triggers);
@@ -113,6 +120,14 @@ Template.livechatWindow.onCreated(function() {
 			result.departments.forEach((department) => {
 				Department.insert(department);
 			});
+
+			Livechat.ready();
+		}
+	});
+
+	$(window).on('focus', () => {
+		if (Livechat.isWidgetOpened()) {
+			$('textarea').focus();
 		}
 	});
 });
diff --git a/packages/rocketchat-livechat/app/client/views/loading.html b/packages/rocketchat-livechat/app/client/views/loading.html
new file mode 100644
index 0000000000000000000000000000000000000000..e13a3f77ba1c13393abbdeeae5bd9f80af50743a
--- /dev/null
+++ b/packages/rocketchat-livechat/app/client/views/loading.html
@@ -0,0 +1,8 @@
+<template name="loading">
+	<div class="loading-animation">
+		{{_ "Connecting to an Agent"}}
+		<div class="bounce1"></div>
+		<div class="bounce2"></div>
+		<div class="bounce3"></div>
+	</div>
+</template>
\ No newline at end of file
diff --git a/packages/rocketchat-livechat/app/client/views/message.coffee b/packages/rocketchat-livechat/app/client/views/message.coffee
index 313e7d787938b37c62f190989198e79598b1450c..ebe1b3b017a577ee64882fa5afd61683fcc799a2 100644
--- a/packages/rocketchat-livechat/app/client/views/message.coffee
+++ b/packages/rocketchat-livechat/app/client/views/message.coffee
@@ -40,6 +40,12 @@ Template.message.helpers
 	system: ->
 		return 'system' if this.t in ['s', 'p', 'f', 'r', 'au', 'ru', 'ul', 'wm', 'uj', 'livechat-close']
 
+	sender: ->
+		agent = Livechat.agent
+		if agent && @u.username is agent.username
+			return agent.name or agent.username
+		return @u.username
+
 
 Template.message.onViewRendered = (context) ->
 	view = this
diff --git a/packages/rocketchat-livechat/app/client/views/message.html b/packages/rocketchat-livechat/app/client/views/message.html
index ab01f7a29ff122b256eb64ba99a6884afc91d0d6..7dc9aba0c829470d31b5001ec07e70339953fdeb 100644
--- a/packages/rocketchat-livechat/app/client/views/message.html
+++ b/packages/rocketchat-livechat/app/client/views/message.html
@@ -1,21 +1,23 @@
 <template name="message">
-	<li id="{{_id}}" class="message sequential {{system}} {{t}} {{own}} {{isTemp}} {{error}}" data-username="{{u.username}}" data-date="{{date}}">
-		<span class="thumb thumb-small" data-username="{{u.username}}" tabindex="1">{{> avatar username=u.username}}</span>
-		<span class="user" data-username="{{u.username}}" tabindex="1">
-			{{#if own}}
-				{{_ "You"}}
-			{{else}}
-				{{u.username}}
-			{{/if}}
-		</span>
-		<span class="info">
-			<span class="time">{{time}}</span>
-			{{#if edit}}
-				<span class="edited">({{_ "edited"}})</span>
-			{{/if}}
-		</span>
-		<div class="body" dir="auto">
-			{{{body}}}
+	<li id="{{_id}}" class="message background-transparent-dark-hover sequential {{system}} {{t}} {{own}} {{isTemp}} {{error}}" data-username="{{u.username}}" data-date="{{date}}">
+		<div class="content">
+			<span class="thumb thumb-small" data-username="{{u.username}}" tabindex="1">{{> avatar username=u.username}}</span>
+			<span class="user" data-username="{{u.username}}" tabindex="1">
+				{{#if own}}
+					{{_ "You"}}
+				{{else}}
+					{{sender}}
+				{{/if}}
+			</span>
+			<div class="body" dir="auto">
+				{{{body}}}
+				<span class="info">
+					<span class="time">{{time}}</span>
+					{{#if edit}}
+						<span class="edited">({{_ "edited"}})</span>
+					{{/if}}
+				</span>
+			</div>
 		</div>
 	</li>
 </template>
diff --git a/packages/rocketchat-livechat/app/client/views/messages.html b/packages/rocketchat-livechat/app/client/views/messages.html
index 0f8004e3face7f706f2ecfa5712074474094d98c..7698ca27f444efb970a66d8d76b141b7b0eba8d0 100644
--- a/packages/rocketchat-livechat/app/client/views/messages.html
+++ b/packages/rocketchat-livechat/app/client/views/messages.html
@@ -1,4 +1,22 @@
 <template name="messages">
+	{{#with agentData}}
+	<div class="header">
+		<div class="picture">
+			<img src="{{avatar}}">
+		</div>
+		<div class="info">
+			<ul>
+				<li><h2>{{name}}</h2></li>
+				{{#if email}}
+					<li>{{email}}</li>
+				{{/if}}
+				{{#if phone}}
+					<li>{{phone}}</li>
+				{{/if}}
+			</ul>
+		</div>
+	</div>
+	{{/with}}
 	<div class="messages">
 		<div class="wrapper">
 			<ul>
@@ -7,28 +25,53 @@
 				{{/each}}
 			</ul>
 		</div>
-		<div class="new-message not">
+		<div class="new-message background-primary-action-color color-primary-action-contrast not">
 			<span>{{_ "New_messages"}}</span>
 		</div>
 
-		<div class="error">
+		<div class="error error-color error-background">
 			<span></span>
 		</div>
 	</div>
 	<div class="footer">
-		<div class="message-bar">
-			<div class="input-wrapper">
-				<textarea class="input-message" placeholder="{{_ "Type_your_message"}}"></textarea>
+		{{#if showConnecting}}
+			{{> loading}}
+		{{else}}
+			<div class="message-bar">
+				<div class="input-wrapper">
+					<textarea class="input-message" placeholder="{{_ "Type_your_message"}}"></textarea>
+				</div>
+				<div class="buttons">
+					<svg class="send-button" aria-label="{{_ "Send"}}" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1764 11q33 24 27 64l-256 1536q-5 29-32 45-14 8-31 8-11 0-24-5l-453-185-242 295q-18 23-49 23-13 0-22-4-19-7-30.5-23.5t-11.5-36.5v-349l864-1059-1069 925-395-162q-37-14-40-55-2-40 32-59l1664-960q15-9 32-9 20 0 36 11z"/></svg>
+					{{#if videoCallEnabled}}
+						<svg class="video-button" aria-label="{{_ "Video"}}"  viewBox="0 0 459 459" xmlns="http://www.w3.org/2000/svg"><path d="M357,191.25V102c0-15.3-10.2-25.5-25.5-25.5h-306C10.2,76.5,0,86.7,0,102v255c0,15.3,10.2,25.5,25.5,25.5h306 c15.3,0,25.5-10.2,25.5-25.5v-89.25l102,102V89.25L357,191.25z"/></svg>
+					{{/if}}
+				</div>
 			</div>
-			<div class="buttons">
-				<svg class="send-button" aria-label="{{_ "Send"}}" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1764 11q33 24 27 64l-256 1536q-5 29-32 45-14 8-31 8-11 0-24-5l-453-185-242 295q-18 23-49 23-13 0-22-4-19-7-30.5-23.5t-11.5-36.5v-349l864-1059-1069 925-395-162q-37-14-40-55-2-40 32-59l1664-960q15-9 32-9 20 0 36 11z"/></svg>
-				{{#if videoCallEnabled}}
-					<svg class="video-button" aria-label="{{_ "Video"}}"  viewBox="0 0 459 459" xmlns="http://www.w3.org/2000/svg"><path d="M357,191.25V102c0-15.3-10.2-25.5-25.5-25.5h-306C10.2,76.5,0,86.7,0,102v255c0,15.3,10.2,25.5,25.5,25.5h306 c15.3,0,25.5-10.2,25.5-25.5v-89.25l102,102V89.25L357,191.25z"/></svg>
-				{{/if}}
-			</div>
-		</div>
+		{{/if}}
 
-		{{> options show=showOptions}}
-		<button class="toggle-options">{{optionsLink}}</button>
+		{{#if usersTyping.users}}
+			{{#with usersTyping}}
+				<div class="typing">
+					<strong>{{users}}</strong>
+					{{#if multi}}
+						{{#if selfTyping}}
+							{{_ "are_also_typing"}}
+						{{else}}
+							{{_ "are_typing"}}
+						{{/if}}
+					{{else}}
+						{{#if selfTyping}}
+							{{_ "is_also_typing" context="male"}}
+						{{else}}
+							{{_ "is_typing" context="male"}}
+						{{/if}}
+					{{/if}}
+				</div>
+			{{/with}}
+		{{else}}
+			{{> options show=showOptions}}
+			<button class="toggle-options secondary-font-color">{{optionsLink}}</button>
+		{{/if}}
 	</div>
 </template>
diff --git a/packages/rocketchat-livechat/app/client/views/messages.js b/packages/rocketchat-livechat/app/client/views/messages.js
index cd6ca83ecc49fb40cc7afcc2315650aaec20124e..5bda8a026ac7def5d63074ab5c264ba1cdc6de91 100644
--- a/packages/rocketchat-livechat/app/client/views/messages.js
+++ b/packages/rocketchat-livechat/app/client/views/messages.js
@@ -1,4 +1,4 @@
-/* globals Livechat, LivechatVideoCall */
+/* globals Livechat, LivechatVideoCall, MsgTyping */
 
 Template.messages.helpers({
 	messages() {
@@ -29,6 +29,59 @@ Template.messages.helpers({
 	},
 	videoCallEnabled() {
 		return Livechat.videoCall;
+	},
+	showConnecting() {
+		return Livechat.connecting;
+	},
+	usersTyping() {
+		const users = MsgTyping.get(visitor.getRoom());
+		if (users.length === 0) {
+			return;
+		}
+		if (users.length === 1) {
+			return {
+				multi: false,
+				selfTyping: MsgTyping.selfTyping.get(),
+				users: users[0]
+			};
+		}
+		// usernames = _.map messages, (message) -> return message.u.username
+		let last = users.pop();
+		if (users.length > 4) {
+			last = t('others');
+		}
+		// else
+		let usernames = users.join(', ');
+		usernames = [usernames, last];
+		return {
+			multi: true,
+			selfTyping: MsgTyping.selfTyping.get(),
+			users: usernames.join(` ${t('and')} `)
+		};
+	},
+	agentData() {
+		const agent = Livechat.agent;
+		if (!agent) {
+			return null;
+		}
+
+		const agentData = {
+			avatar: getAvatarUrlFromUsername(agent.username)
+		};
+
+		if (agent.name) {
+			agentData.name = agent.name;
+		}
+
+		if (agent.emails && agent.emails[0] && agent.emails[0].address) {
+			agentData.email = agent.emails[0].address;
+		}
+
+		if (agent.customFields && agent.customFields.phone) {
+			agentData.phone = agent.customFields.phone;
+		}
+
+		return agentData;
 	}
 });
 
diff --git a/packages/rocketchat-livechat/app/client/views/offlineForm.html b/packages/rocketchat-livechat/app/client/views/offlineForm.html
index 50d443485526be8ad1246f0a1e185d6cf27ea254..655687876b9bf9b6ee876c17b6db08196720f4fa 100644
--- a/packages/rocketchat-livechat/app/client/views/offlineForm.html
+++ b/packages/rocketchat-livechat/app/client/views/offlineForm.html
@@ -6,7 +6,7 @@
 			<p class="offline-message">{{{offlineMessage}}}</p>
 
 			<form>
-				<div class="error">
+				<div class="error error-color error-background">
 					<span>{{{error}}}</span>
 				</div>
 
diff --git a/packages/rocketchat-livechat/app/client/views/options.html b/packages/rocketchat-livechat/app/client/views/options.html
index 8c57e9f6379daf7db4cd829510b8696c5fdd3ece..50bc5217f78d4fa1790d12305dcca5bb47e6966a 100644
--- a/packages/rocketchat-livechat/app/client/views/options.html
+++ b/packages/rocketchat-livechat/app/client/views/options.html
@@ -1,5 +1,5 @@
 <template name="options">
-	<div class="options-menu {{show}}">
+	<div class="options-menu content-background-color {{show}}">
 		<ul>
 			<li><button class="end-chat"><i class="icon-cancel"></i> {{_ "End_chat"}}</button></li>
 		</ul>
diff --git a/packages/rocketchat-livechat/app/client/views/register.html b/packages/rocketchat-livechat/app/client/views/register.html
index cdb108bca9cbf43e212876d312519dd79a75b077..9538e7113b9caef5f758fac3eca6487a4f3f6663 100644
--- a/packages/rocketchat-livechat/app/client/views/register.html
+++ b/packages/rocketchat-livechat/app/client/views/register.html
@@ -1,6 +1,6 @@
 <template name="register">
 	<div class="livechat-form">
-		<div class="error">
+		<div class="error error-color error-background">
 			<span>{{{error}}}</span>
 		</div>
 
@@ -11,11 +11,11 @@
 			<input type="text" name="name" id="guestName" placeholder="{{_ "Name"}}">
 			<input type="email" name="email" id="guestEmail" placeholder="{{_ "Email"}}">
 
-			{{#if hasDepartments}}
+			{{#if showDepartments}}
 				<select name="department">
 					<option value="">{{_ "Select_a_department"}}</option>
 					{{#each departments}}
-						<option value="{{_id}}">{{name}}</option>
+						<option value="{{_id}}" selected="{{selectedDepartment}}">{{name}}</option>
 					{{/each}}
 				</select>
 			{{/if}}
diff --git a/packages/rocketchat-livechat/app/client/views/register.js b/packages/rocketchat-livechat/app/client/views/register.js
index e7a9610688ac1b0f249b76217ad2e733b3b3a6bd..f1119080040c01c7db4a1f65a5187b6a2a747d8b 100644
--- a/packages/rocketchat-livechat/app/client/views/register.js
+++ b/packages/rocketchat-livechat/app/client/views/register.js
@@ -7,14 +7,17 @@ Template.register.helpers({
 	welcomeMessage() {
 		return '';
 	},
-	hasDepartments() {
-		return Department.find().count() > 1;
+	showDepartments() {
+		return Department.find({ showOnRegistration: true }).count() > 1;
 	},
 	departments() {
-		return Department.find();
+		return Department.find({ showOnRegistration: true });
 	},
 	videoCallEnabled() {
 		return Livechat.videoCall;
+	},
+	selectedDepartment() {
+		return this._id === Livechat.department;
 	}
 });
 
@@ -37,7 +40,7 @@ Template.register.events({
 		} else {
 			var departmentId = instance.$('select[name=department]').val();
 			if (!departmentId) {
-				var department = Department.findOne();
+				var department = Department.findOne({ showOnRegistration: true });
 				if (department) {
 					departmentId = department._id;
 				}
@@ -47,7 +50,7 @@ Template.register.events({
 				token: visitor.getToken(),
 				name: $name.val(),
 				email: $email.val(),
-				department: departmentId
+				department: Livechat.deparment || departmentId
 			};
 			Meteor.call('livechat:registerGuest', guest, function(error, result) {
 				if (error != null) {
diff --git a/packages/rocketchat-livechat/app/i18n/cs.i18n.json b/packages/rocketchat-livechat/app/i18n/cs.i18n.json
index 98ebc4fe0c1415dc2f3bd03c3da46b9d2f3e9dd1..96a789d1b1cb5c7a68de8494e78f4d09ec534036 100644
--- a/packages/rocketchat-livechat/app/i18n/cs.i18n.json
+++ b/packages/rocketchat-livechat/app/i18n/cs.i18n.json
@@ -18,6 +18,7 @@
   "Please_answer_survey": "Věnujte prosím chvilku času ohodnocení chatu.",
   "Please_fill_name_and_email": "Prosím vyplňte jméno a e-mail",
   "Powered_by": "Používá technologii",
+  "Request_video_chat": "Zažádat o video chat",
   "Select_a_department": "Vyberte oddělení",
   "Send": "Poslat",
   "Skip": "Přeskočit",
@@ -26,6 +27,7 @@
   "Survey_instructions": "Hodnoťte každou otázku dle vaší spokojenosti, 1 - zcela nespokojeni a 5 - zcela spokojeni.",
   "Thank_you_for_your_feedback": "Děkujeme Vám za Vaše hodnocení",
   "Thanks_We_ll_get_back_to_you_soon": "Díky! Odpovíme co nejdříve.",
+  "transcript_sent": "Kopie konverzace odeslána",
   "Type_your_email": "Zadejte svůj e-mail",
   "Type_your_message": "Napište zprávu",
   "Type_your_name": "Zadejte své jméno",
diff --git a/packages/rocketchat-livechat/app/i18n/hr.i18n.json b/packages/rocketchat-livechat/app/i18n/hr.i18n.json
index b73f6c436d4c44376f09324057c6b68d80e107de..48d2554c79c6efcf1b29ceb283f6c26fda21c863 100644
--- a/packages/rocketchat-livechat/app/i18n/hr.i18n.json
+++ b/packages/rocketchat-livechat/app/i18n/hr.i18n.json
@@ -27,6 +27,7 @@
   "Survey_instructions": "Ocijenite svako pitanje u skladu s Vaše zadovoljstvo, 1 što znači da su potpuno nezadovoljni i 5 što znači da su u potpunosti zadovoljni.",
   "Thank_you_for_your_feedback": "Hvala vam na povratnim informacijama",
   "Thanks_We_ll_get_back_to_you_soon": "Hvala! Javit ćemo vam se uskoro.",
+  "transcript_sent": "Prijepis poslan",
   "Type_your_email": "Upišite Vaš e-mail",
   "Type_your_message": "Upišite svoju poruku",
   "Type_your_name": "Upišite svoje ime",
diff --git a/packages/rocketchat-livechat/app/i18n/sv.i18n.json b/packages/rocketchat-livechat/app/i18n/sv.i18n.json
index 4ede7dd162e361c436b959861887da69976b372f..e1aacc1dfac4e142b3e4a2d4f3ebc478dce17076 100644
--- a/packages/rocketchat-livechat/app/i18n/sv.i18n.json
+++ b/packages/rocketchat-livechat/app/i18n/sv.i18n.json
@@ -11,6 +11,7 @@
   "How_satisfied_were_you_with_this_chat": "Hur nöjd var du med chatten?",
   "Installation": "Installation",
   "New_messages": "Nya meddelanden",
+  "No": "Nej",
   "Please_answer_survey": "Vänligen ta en stund för att svara på en snabb enkät om chatten.",
   "Please_fill_name_and_email": "Vänligen fyll i namn och e-postadress",
   "Powered_by": "powered by",
diff --git a/packages/rocketchat-livechat/app/package.json b/packages/rocketchat-livechat/app/package.json
index 6c51c870a3a7bcbadaac669ad7d024989374089d..f875db3e9ced1620aaee20b36995db5c72f1ab42 100644
--- a/packages/rocketchat-livechat/app/package.json
+++ b/packages/rocketchat-livechat/app/package.json
@@ -20,10 +20,11 @@
     "email": "support@rocket.chat"
   },
   "dependencies": {
-    "autolinker": "^1.3.2",
-    "babel-runtime": "^6.18.0",
-    "moment": "^2.16.0",
+    "autolinker": "^1.4.0",
     "jquery": "^2.1.0",
+    "babel-runtime": "^6.20.0",
+    "bcrypt": "^1.0.2",
+    "moment": "^2.17.1",
     "toastr": "^2.1.2"
   }
 }
diff --git a/packages/rocketchat-livechat/assets/rocket-livechat.js b/packages/rocketchat-livechat/assets/rocket-livechat.js
index e2129eacace6bbf2307e373dd3386ec328d84034..0fcac2ce9ffddf39a8447daa617759651010dad2 100644
--- a/packages/rocketchat-livechat/assets/rocket-livechat.js
+++ b/packages/rocketchat-livechat/assets/rocket-livechat.js
@@ -6,15 +6,9 @@
 	var hookQueue = [];
 	var ready = false;
 
-	var closeWidget = function() {
-		widget.dataset.state = 'closed';
-		widget.style.height = '30px';
-	};
-
-	var openWidget = function() {
-		widget.dataset.state = 'opened';
-		widget.style.height = '300px';
-	};
+	var widgetWidth = '320px';
+	var widgetHeightOpened = '350px';
+	var widgetHeightClosed = '30px';
 
 	// hooks
 	var callHook = function(action, params) {
@@ -29,6 +23,19 @@
 		iframe.contentWindow.postMessage(data, '*');
 	};
 
+	var closeWidget = function() {
+		widget.dataset.state = 'closed';
+		widget.style.height = widgetHeightClosed;
+		callHook('widgetClosed');
+	};
+
+	var openWidget = function() {
+		widget.dataset.state = 'opened';
+		widget.style.height = widgetHeightOpened;
+		callHook('widgetOpened');
+		document.querySelector('.rocketchat-widget iframe').focus();
+	};
+
 	var api = {
 		ready: function() {
 			ready = true;
@@ -75,6 +82,14 @@
 		callHook('setTheme', theme);
 	};
 
+	var setDepartment = function(department) {
+		callHook('setDepartment', department);
+	};
+
+	var clearDepartment = function() {
+		callHook('clearDepartment');
+	};
+
 	var currentPage = {
 		href: null,
 		title: null
@@ -107,8 +122,8 @@
 								'</div><div class="rocketchat-overlay"></div>';
 
 		chatWidget.style.position = 'fixed';
-		chatWidget.style.width = '300px';
-		chatWidget.style.height = '30px';
+		chatWidget.style.width = widgetWidth;
+		chatWidget.style.height = widgetHeightClosed;
 		chatWidget.style.borderTopLeftRadius = '5px';
 		chatWidget.style.borderTopRightRadius = '5px';
 		chatWidget.style.bottom = '0';
@@ -137,7 +152,7 @@
 			} else {
 				chatWidget.style.left = 'auto';
 				chatWidget.style.right = '50px';
-				chatWidget.style.width = '300px';
+				chatWidget.style.width = widgetWidth;
 			}
 		};
 
@@ -168,7 +183,9 @@
 	w.RocketChat.livechat = {
 		pageVisited: pageVisited,
 		setCustomField: setCustomField,
-		setTheme: setTheme
+		setTheme: setTheme,
+		setDepartment: setDepartment,
+		clearDepartment: clearDepartment
 	};
 
 	// proccess queue
diff --git a/packages/rocketchat-livechat/client/route.js b/packages/rocketchat-livechat/client/route.js
index 1958f4e4d44a706c085412a818623bdccebf9359..887ca7750d214fc1b0939289aa21dec7c128584b 100644
--- a/packages/rocketchat-livechat/client/route.js
+++ b/packages/rocketchat-livechat/client/route.js
@@ -59,6 +59,22 @@ AccountBox.addRoute({
 	pageTemplate: 'livechatTriggers'
 }, livechatManagerRoutes);
 
+AccountBox.addRoute({
+	name: 'livechat-trigger-edit',
+	path: '/triggers/:_id/edit',
+	sideNav: 'livechatFlex',
+	i18nPageTitle: 'Edit_Trigger',
+	pageTemplate: 'livechatTriggersForm'
+}, livechatManagerRoutes);
+
+AccountBox.addRoute({
+	name: 'livechat-trigger-new',
+	path: '/triggers/new',
+	sideNav: 'livechatFlex',
+	i18nPageTitle: 'New_Trigger',
+	pageTemplate: 'livechatTriggersForm'
+}, livechatManagerRoutes);
+
 AccountBox.addRoute({
 	name: 'livechat-installation',
 	path: '/installation',
diff --git a/packages/rocketchat-livechat/client/stylesheets/lesshat.less b/packages/rocketchat-livechat/client/stylesheets/lesshat.less
new file mode 100644
index 0000000000000000000000000000000000000000..7c9f0ae86a267eb3660d2381a0bba2620f0488f4
--- /dev/null
+++ b/packages/rocketchat-livechat/client/stylesheets/lesshat.less
@@ -0,0 +1,17 @@
+//  lesshat - The best mixin library in the world
+//
+// version: v4.1.0 (2016-07-19)
+
+.calc(...) {
+	@process: ~`(function(a){function c(c,t){var r=");\n",s=e.split(","),l=s[0]+":"+c+"("+(s[1].trim()||0)+r;"start"==t?a="0;\n"+l:a+=l}a=a||8121991;var t="@{state}",e=a;if(8121991==a)return a;switch(t){case"1":c("-webkit-calc","start"),c("-moz-calc"),c("calc");break;case"2":c("-webkit-calc","start"),c("-moz-calc");break;case"3":c("-webkit-calc","start"),c("calc");break;case"4":c("-webkit-calc","start");break;case"5":c("-moz-calc","start"),c("calc");break;case"6":c("-moz-calc","start");break;case"7":c("calc","start")}return a=a.replace(/;$/g,"")})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
+	@state: 1; -lh-property: @process;
+}
+
+.transform(...) {
+	@process: ~`(function(e){e=e||"none";var r={translate:"px",rotate:"deg",rotate3d:"deg",skew:"deg"};/^\w*\(?[a-z0-9.]*\)?/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,""));for(var t in r)e.indexOf(t)>=0&&(e=e.replace(new RegExp(t+"[\\w]?\\([a-z0-9, %]*\\)"),function(e){var n=/(\d+\.?\d*)(?!\w|%)/g;return"rotate3d"==t&&(n=/,\s*\d+$/),e.replace(n,function(e){return e+r[t]})}));return e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
+	-webkit-transform: @process;
+	-moz-transform: @process;
+	-ms-transform: @process;
+	-o-transform: @process;
+	transform: @process;
+}
diff --git a/packages/rocketchat-livechat/client/stylesheets/livechat.less b/packages/rocketchat-livechat/client/stylesheets/livechat.less
index 38715ab7ab5f936b87f245626167675e5d123d5f..7e268decb3fce3bf8afdaec64a0312700a4fdf0b 100644
--- a/packages/rocketchat-livechat/client/stylesheets/livechat.less
+++ b/packages/rocketchat-livechat/client/stylesheets/livechat.less
@@ -1,10 +1,20 @@
+@import "lesshat.less";
+
+@header-min-height: 30px;
+@footer-min-height: 55px;
+@link-font-color: #008ce3;
+@primary-font-color: #444444;
+@secondary-font-color: #7f7f7f;
+@info-font-color: #aaaaaa;
+
 .flex-list {
 	.active {
-		background-color: rgba(255,255,255,0.075);
+		background-color: rgba(255, 255, 255, 0.075);
 	}
 }
 
-.trigger-option, .trigger-value {
+.trigger-option,
+.trigger-value {
 	float: left;
 	display: inline-block;
 }
@@ -33,7 +43,7 @@
 		text-align: left;
 		width: 100%;
 		height: 200px;
-		background-color: #EFEFEF;
+		background-color: #efefef;
 		font-family: courier;
 		font-size: 12px;
 		display: block;
@@ -45,7 +55,8 @@
 	margin-bottom: 1em;
 }
 
-.livechat-settings-div, .livechat-preview-div {
+.livechat-settings-div,
+.livechat-preview-div {
 	width: 50%;
 	float: left;
 	height: 95%;
@@ -54,15 +65,14 @@
 }
 
 .livechat-settings-div {
-	border-right: 1px solid #CCC;
+	border-right: 1px solid #cccccc;
 }
 
 .livechat-preview {
 	width: 340px;
 	height: 350px;
 	margin: 0 auto;
-
-	border-bottom: 1px solid #CCC;
+	border-bottom: 1px solid #cccccc;
 	position: relative;
 
 	.preview-wrapper {
@@ -71,14 +81,6 @@
 		padding: 0 20px;
 		height: 300px;
 		bottom: 0;
-
-		@header-min-height: 30px;
-		@footer-min-height: 55px;
-		@link-font-color: #008CE3;
-		@primary-font-color: #444444;
-		@secondary-font-color: #7f7f7f;
-		@info-font-color: #AAAAAA;
-
 		font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif, "Meiryo UI";
 		font-size: 0.8rem;
 		color: @primary-font-color;
@@ -94,7 +96,7 @@
 			line-height: inherit;
 			padding: 5px;
 			margin: 5px 0;
-			border: 1px solid #E7E7E7;
+			border: 1px solid #e7e7e7;
 			border-radius: 5px;
 			outline: none;
 		}
@@ -122,14 +124,15 @@
 			border-radius: 0;
 			line-height: 16px;
 			position: relative;
-			cursor: pointer;background-color: #FFF;
+			cursor: pointer;
 			color: rgba(255, 255, 255, 0.85);
-			background-color: lighten(desaturate(@primary-background-color, 15%), 12.5%);
+
 			span {
 				position: relative;
 				z-index: 2;
 			}
-			&:before {
+
+			&::before {
 				background-color: rgba(0, 0, 0, 0.1);
 				content: " ";
 				position: absolute;
@@ -139,29 +142,27 @@
 				height: 100%;
 				opacity: 0;
 				z-index: 1;
-				.transition(opacity .1s ease-out);
+				transition: opacity 0.1s ease-out;
 			}
+
 			&:hover {
 				text-decoration: none;
-				color: #FFF;
-				&:before {
+				color: #ffffff;
+
+				&::before {
 					opacity: 1;
 				}
 			}
-			&.secondary {
-				background-color: @tertiary-background-color;
-				color: @primary-font-color;
-				&:before {
-					background-color: rgba(0, 0, 0, 0.045);
-				}
-			}
+
 			&.clean {
 				font-size: 14px;
 				box-shadow: 0 0 3px rgba(0, 0, 0, 0.08);
+
 				&.primary {
 					font-weight: 600;
 				}
 			}
+
 			&.button-block {
 				display: block;
 				width: 100%;
@@ -175,14 +176,13 @@
 
 			.title {
 				flex: 1 0 @header-min-height;
-
 				line-height: @header-min-height;
-
 				border-top-right-radius: 5px;
 				border-top-left-radius: 5px;
-				color: #FFF;
+				color: #ffffff;
 				z-index: 10;
 				cursor: pointer;
+
 				h1 {
 					margin: 0;
 					padding: 0 5px;
@@ -197,19 +197,21 @@
 					padding-right: 5px;
 				}
 			}
+
 			.messages {
 				flex: 1 1 100%;
-
-				background-color: #FFF;
-				border-left: 1px solid #E7E7E7;
-				border-right: 1px solid #E7E7E7;
+				background-color: #ffffff;
+				border-left: 1px solid #e7e7e7;
+				border-right: 1px solid #e7e7e7;
 				overflow-y: auto;
+
 				.wrapper {
 					padding-bottom: 6px;
 
 					ul {
 						list-style-type: none;
 						padding: 0;
+
 						li {
 							padding: 0;
 						}
@@ -222,14 +224,15 @@
 						line-height: 18px;
 						margin: 12px 10px 0;
 						min-height: 36px;
+
 						&:nth-child(1) {
 							margin-top: 0;
 						}
+
 						&.new-day {
 							margin-top: 60px;
-						}
-						&.new-day {
-							&:before {
+
+							&::before {
 								content: attr(data-date);
 								display: block;
 								position: absolute;
@@ -242,43 +245,51 @@
 								color: @secondary-font-color;
 								z-index: 10;
 								padding: 0 10px;
-								background-color: #FFF;
+								background-color: #ffffff;
 								min-width: 120px;
 							}
-							&:after {
+
+							&::after {
 								content: " ";
 								display: block;
 								position: absolute;
 								top: -20px;
 								left: 0;
 								width: 100%;
-								border-top: 1px solid #ddd;
+								border-top: 1px solid #dddddd;
 							}
 						}
+
 						.edit-message {
 							display: none;
 							cursor: pointer;
 						}
+
 						&.own:hover:not(.system) .edit-message {
 							display: inline-block;
 						}
+
 						.delete-message {
 							display: none;
 							cursor: pointer;
 						}
+
 						&.own:hover:not(.system) .delete-message {
 							display: inline-block;
 						}
+
 						.user {
 							display: inline-block;
 							font-weight: 600;
 							color: #444444;
 							margin-right: 5px;
 							outline: none;
+
 							&:hover {
-								color: #333;
+								color: #333333;
 							}
 						}
+
 						.thumb {
 							position: absolute;
 							left: 0;
@@ -287,78 +298,96 @@
 							width: 30px;
 							height: 30px;
 						}
+
 						.info {
 							font-size: 10px;
 							color: @info-font-color;
 						}
+
 						&.sequential {
-							// margin-top: 5px;
 							padding-top: 5px;
 							margin-top: 0;
 							margin-bottom: 0;
 							min-height: 20px;
+
 							.user {
 								display: none;
 							}
+
 							.thumb {
 								display: none;
 							}
+
 							.info {
 								position: absolute;
 								text-align: right;
 								left: -20px;
 								width: 55px;
+
 								.time {
 									display: none;
 								}
+
 								.edited {
 									display: inline-block;
 								}
+
 								.edit-message {
 									float: left;
 									margin-left: 1px;
 								}
+
 								.delete-message {
 									float: left;
 								}
 							}
+
 							&:hover {
 								.time {
 									display: inline-block;
 								}
+
 								.edited {
 									display: none;
 								}
 							}
 						}
+
 						&.system {
 							.body {
 								color: @info-font-color;
 								font-style: italic;
 								text-transform: lowercase;
+
 								em {
 									font-weight: 600;
 								}
 							}
 						}
+
 						.avatar-initials {
 							line-height: 40px;
 						}
+
 						a {
 							color: @link-font-color;
 							font-weight: 400;
+
 							&:hover {
 								color: darken(@link-font-color, 10%);
 								text-decoration: underline;
 							}
 						}
+
 						.body {
 							opacity: 1;
-							.transition(opacity 1s linear);
+							transition: opacity 1s linear;
 						}
+
 						&.temp .body {
-							opacity: .5;
+							opacity: 0.5;
 						}
+
 						&.msg-error .body {
 							text-decoration: line-through;
 						}
@@ -378,6 +407,7 @@
 						}
 					}
 				}
+
 				.new-message {
 					margin: 0 -65px;
 					position: absolute;
@@ -386,15 +416,16 @@
 					width: 130px;
 					height: 30px;
 					text-align: center;
-					color: #FFF;
+					color: #ffffff;
 					line-height: 30px;
 					font-size: 0.8em;
 					cursor: pointer;
 					bottom: 8px;
 					left: 50%;
 					z-index: 5;
-					.transition(transform 0.3s ease-out);
+					transition: transform 0.3s ease-out;
 					.transform(translateY(-40px));
+
 					&.not {
 						.transform(translateY(100%));
 					}
@@ -404,11 +435,10 @@
 					bottom: 40px;
 					position: fixed;
 					width: 100%;
-					background-color: #F7D799;
+					background-color: #f7d799;
 					padding: 5px;
 					z-index: 8;
-
-					.transition(transform 0.2s ease-out);
+					transition: transform 0.2s ease-out;
 					.transform(translateY(100%));
 
 					&.show {
@@ -416,27 +446,26 @@
 					}
 				}
 			}
+
 			.footer {
 				flex: 1 0 @footer-min-height;
-
 				z-index: 10;
-
-				background-color: #FCFCFC;
-				border-top: 1px solid #E7E7E7;
-				border-left: 1px solid #E7E7E7;
-				border-right: 1px solid #E7E7E7;
+				background-color: #fcfcfc;
+				border-top: 1px solid #e7e7e7;
+				border-left: 1px solid #e7e7e7;
+				border-right: 1px solid #e7e7e7;
 
 				.input-wrapper {
-					padding: 6px 6px 0 6px;
+					padding: 6px 6px 0;
 					padding-right: 30px;
+
 					textarea {
 						display: block;
 						padding: 6px 8px;
 						padding-right: 38px;
 						overflow-y: auto;
 						resize: none;
-						border: 1px solid #E7E7E7;
-						// margin: 10px;
+						border: 1px solid #e7e7e7;
 						border-radius: 5px;
 						max-height: 200px;
 						width: 100%;
@@ -444,7 +473,7 @@
 						-webkit-appearance: none;
 						height: 28px;
 						line-height: normal;
-						background-color: #fff;
+						background-color: #ffffff;
 						position: relative;
 						outline: none;
 					}
@@ -457,7 +486,7 @@
 					top: -28px;
 					color: @secondary-font-color;
 					cursor: pointer;
-					.transition(color .15s ease-out);
+					transition: color 0.15s ease-out;
 
 					&:hover {
 						color: @primary-font-color;
@@ -469,8 +498,8 @@
 				flex: 1 1 100%;
 				background-color: white;
 				padding: 1em 10px;
-				border-left: 1px solid #E7E7E7;
-				border-right: 1px solid #E7E7E7;
+				border-left: 1px solid #e7e7e7;
+				border-right: 1px solid #e7e7e7;
 
 				.offline-message {
 					padding: 1em 0;
@@ -481,7 +510,8 @@
 				}
 
 				form {
-					input, textarea {
+					input,
+					textarea {
 						display: block;
 						width: 100%;
 					}
@@ -496,7 +526,7 @@
 
 					.error {
 						display: none;
-						background-color: #F7D799;
+						background-color: #f7d799;
 						padding: 5px;
 
 						&.show {
@@ -508,18 +538,23 @@
 		}
 	}
 
-	&.closed, &.closed-offline {
+	&.closed,
+	&.closed-offline {
 		.preview-wrapper {
 			height: 32px;
+
 			.livechat-room .title .toolbar {
 				display: none;
 			}
+
 			.messages {
 				display: none;
 			}
+
 			.footer {
 				display: none;
 			}
+
 			.offline {
 				display: none;
 			}
@@ -532,7 +567,7 @@
 
 	li {
 		display: inline-block;
-		background-color: #DDD;
+		background-color: #dddddd;
 		border-radius: 10px;
 		padding: 2px 8px 2px 2px;
 		margin: 1px 0;
@@ -553,40 +588,16 @@
 	}
 }
 
-.user-view {
-	li {
-		color: @secondary-font-color;
-		line-height: 18px;
-		font-size: 12px;
-		font-weight: 300;
-	}
-}
-
-.icon-chat-empty.status-offline {
-	color: @status-offline;
-}
-
-.icon-chat-empty.status-online {
-	color: @status-online;
-}
-
-.icon-chat-empty.status-busy {
-	color: @status-busy;
-}
-
-.icon-chat-empty.status-away {
-	color: @status-away;
-}
-
 .visitor-custom-fields {
 	padding: 0 20px;
 }
 
-.visitor-navigation, .visitor-custom-fields {
+.visitor-navigation,
+.visitor-custom-fields {
 	.visitor-scroll {
 		height: 130px;
 		overflow-y: auto;
-		border: 1px solid #E7E7E7;
+		border: 1px solid #e7e7e7;
 		border-radius: 4px;
 		padding: 4px;
 		margin-top: 4px;
@@ -600,7 +611,6 @@
 					text-overflow: ellipsis;
 					display: block;
 					overflow: hidden;
-
 					color: @secondary-font-color;
 					text-decoration: underline;
 
@@ -615,8 +625,7 @@
 
 .livechat-section {
 	opacity: 0.5;
-
-	.transition(opacity .4s ease);
+	transition: opacity 0.4s ease;
 
 	&.available {
 		opacity: 1;
@@ -627,21 +636,16 @@
 	float: right;
 	margin-right: 10px;
 	font-size: 20px;
-	&.available {
-		color: @status-online;
-	}
-	&.not-available {
-		color: @status-offline;
-	}
 }
 
 .external-message {
 	padding: 10px;
 	position: relative;
-	&:after {
+
+	&::after {
 		content: " ";
 		position: absolute;
-		border-bottom: 1px solid #CCC;
+		border-bottom: 1px solid #cccccc;
 		left: 10px;
 		right: 10px;
 		bottom: 0;
@@ -649,9 +653,17 @@
 }
 
 .user-view {
+	li {
+		color: @secondary-font-color;
+		line-height: 18px;
+		font-size: 12px;
+		font-weight: 300;
+	}
+
 	nav.centered-buttons {
 		text-align: center;
 		margin-bottom: 1em;
+
 		button {
 			display: inline-block;
 			width: auto;
@@ -669,6 +681,7 @@
 
 .visitor-edit {
 	padding: 20px;
+
 	h3 {
 		font-size: 24px;
 		margin-bottom: 8px;
diff --git a/packages/rocketchat-livechat/client/stylesheets/load.js b/packages/rocketchat-livechat/client/stylesheets/load.js
deleted file mode 100644
index 3376dd0f6fd87d5408e7d56a33fc30e95f7b8bc3..0000000000000000000000000000000000000000
--- a/packages/rocketchat-livechat/client/stylesheets/load.js
+++ /dev/null
@@ -1,3 +0,0 @@
-RocketChat.theme.addPackageAsset(() => {
-	return Assets.getText('client/stylesheets/livechat.less');
-});
diff --git a/packages/rocketchat-livechat/client/views/app/livechatAppearance.html b/packages/rocketchat-livechat/client/views/app/livechatAppearance.html
index 430533d3493439b9389188e382530147be201152..a8d9651ef9697f1f6fec87df35b93374403ba704 100644
--- a/packages/rocketchat-livechat/client/views/app/livechatAppearance.html
+++ b/packages/rocketchat-livechat/client/views/app/livechatAppearance.html
@@ -1,148 +1,150 @@
 <template name="livechatAppearance">
-	<div class="livechat-settings-div">
-		<h2>{{_ "Settings"}}</h2>
+	{{#requiresPermission 'view-livechat-manager'}}
+		<div class="livechat-settings-div">
+			<h2>{{_ "Settings"}}</h2>
 
-		<form class="rocket-form">
-			<fieldset>
-				<legend>{{_ "Livechat_online"}}</legend>
-				<div class="input-line">
-					<label for="title">{{_ "Title"}}</label>
-					<input type="text" class="preview-settings" name="title" id="title" value="{{title}}">
-				</div>
-				<div class="input-line">
-					<label for="color">{{_ "Title_bar_color"}}</label>
-					<input type="text" class="preview-settings minicolors" name="color" id="color" value="{{color}}">
-				</div>
-			</fieldset>
-			<fieldset>
-				<legend>{{_ "Livechat_offline"}}</legend>
-				<div class="input-line">
-					<label for="displayOfflineForm">{{_ "Display_offline_form"}}</label>
-					<div class="inline-fields">
-						<input type="radio" class="preview-settings" name="displayOfflineForm" id="displayOfflineFormTrue" checked="{{displayOfflineFormTrueChecked}}" value="true">
-						<label for="displayOfflineFormTrue">{{_ "True"}}</label>
-						<input type="radio" class="preview-settings" name="displayOfflineForm" id="displayOfflineFormFalse" checked="{{displayOfflineFormFalseChecked}}" value="false">
-						<label for="displayOfflineFormFalse">{{_ "False"}}</label>
+			<form class="rocket-form">
+				<fieldset>
+					<legend>{{_ "Livechat_online"}}</legend>
+					<div class="input-line">
+						<label for="title">{{_ "Title"}}</label>
+						<input type="text" class="preview-settings" name="title" id="title" value="{{title}}">
 					</div>
+					<div class="input-line">
+						<label for="color">{{_ "Title_bar_color"}}</label>
+						<input type="text" class="preview-settings minicolors" name="color" id="color" value="{{color}}">
+					</div>
+				</fieldset>
+				<fieldset>
+					<legend>{{_ "Livechat_offline"}}</legend>
+					<div class="input-line">
+						<label for="displayOfflineForm">{{_ "Display_offline_form"}}</label>
+						<div class="inline-fields">
+							<input type="radio" class="preview-settings" name="displayOfflineForm" id="displayOfflineFormTrue" checked="{{displayOfflineFormTrueChecked}}" value="true">
+							<label for="displayOfflineFormTrue">{{_ "True"}}</label>
+							<input type="radio" class="preview-settings" name="displayOfflineForm" id="displayOfflineFormFalse" checked="{{displayOfflineFormFalseChecked}}" value="false">
+							<label for="displayOfflineFormFalse">{{_ "False"}}</label>
+						</div>
+					</div>
+					<div class="input-line">
+						<label for="offlineUnavailableMessage">{{_ "Offline_form_unavailable_message"}}</label>
+						<textarea class="preview-settings" name="offlineUnavailableMessage" id="offlineUnavailableMessage">{{offlineUnavailableMessage}}</textarea>
+					</div>
+					<div class="input-line">
+						<label for="offlineMessage">{{_ "Offline_message"}}</label>
+						<textarea class="preview-settings" name="offlineMessage" id="offlineMessage">{{offlineMessage}}</textarea>
+					</div>
+					<div class="input-line">
+						<label for="titleOffline">{{_ "Title_offline"}}</label>
+						<input type="text" class="preview-settings" name="titleOffline" id="titleOffline" value="{{titleOffline}}">
+					</div>
+					<div class="input-line">
+						<label for="colorOffline">{{_ "Title_bar_color_offline"}}</label>
+						<input type="text" class="preview-settings minicolors" name="colorOffline" id="colorOffline" value="{{colorOffline}}">
+					</div>
+					<div class="input-line">
+						<label for="emailOffline">{{_ "Email_address_to_send_offline_messages"}}</label>
+						<input type="text" class="preview-settings" name="emailOffline" id="emailOffline" value="{{emailOffline}}">
+					</div>
+					<div class="input-line">
+						<label for="offlineSuccessMessage">{{_ "Offline_success_message"}}</label>
+						<textarea class="preview-settings" name="offlineSuccessMessage" id="offlineSuccessMessage">{{offlineSuccessMessage}}</textarea>
+					</div>
+				</fieldset>
+				<div class="submit">
+					<button class="button secondary reset-settings"><i class="icon-ccw"></i>{{_ "Reset"}}</button>
+					<button class="button primary save"><i class="icon-floppy"></i>{{_ "Save"}}</button>
 				</div>
-				<div class="input-line">
-					<label for="offlineUnavailableMessage">{{_ "Offline_form_unavailable_message"}}</label>
-					<textarea class="preview-settings" name="offlineUnavailableMessage" id="offlineUnavailableMessage">{{offlineUnavailableMessage}}</textarea>
-				</div>
-				<div class="input-line">
-					<label for="offlineMessage">{{_ "Offline_message"}}</label>
-					<textarea class="preview-settings" name="offlineMessage" id="offlineMessage">{{offlineMessage}}</textarea>
-				</div>
-				<div class="input-line">
-					<label for="titleOffline">{{_ "Title_offline"}}</label>
-					<input type="text" class="preview-settings" name="titleOffline" id="titleOffline" value="{{titleOffline}}">
-				</div>
-				<div class="input-line">
-					<label for="colorOffline">{{_ "Title_bar_color_offline"}}</label>
-					<input type="text" class="preview-settings minicolors" name="colorOffline" id="colorOffline" value="{{colorOffline}}">
-				</div>
-				<div class="input-line">
-					<label for="emailOffline">{{_ "Email_address_to_send_offline_messages"}}</label>
-					<input type="text" class="preview-settings" name="emailOffline" id="emailOffline" value="{{emailOffline}}">
-				</div>
-				<div class="input-line">
-					<label for="offlineSuccessMessage">{{_ "Offline_success_message"}}</label>
-					<textarea class="preview-settings" name="offlineSuccessMessage" id="offlineSuccessMessage">{{offlineSuccessMessage}}</textarea>
-				</div>
-			</fieldset>
-			<div class="submit">
-				<button class="button secondary reset-settings"><i class="icon-ccw"></i>{{_ "Reset"}}</button>
-				<button class="button primary save"><i class="icon-floppy"></i>{{_ "Save"}}</button>
-			</div>
-		</form>
-	</div>
+			</form>
+		</div>
 
-	<div class="livechat-preview-div">
-		<h2>{{_ "Preview"}}</h2>
+		<div class="livechat-preview-div">
+			<h2>{{_ "Preview"}}</h2>
 
-		<select class="preview-mode">
-			<optgroup label="{{_ "Online"}}">
-				<option value="opened">{{_ "Chat_window"}}</option>
-				<option value="closed">{{_ "Chat_button"}}</option>
-			</optgroup>
-			<optgroup label="{{_ "Offline"}}">
-				<option value="opened-offline">{{_ "Offline_form"}}</option>
-				<option value="offline-unavailable">{{_ "Offline_unavailable"}}</option>
-				<option value="offline-success">{{_ "Success_message"}}</option>
-				<option value="closed-offline">{{_ "Chat_button"}}</option>
-			</optgroup>
-		</select>
+			<select class="preview-mode">
+				<optgroup label="{{_ "Online"}}">
+					<option value="opened">{{_ "Chat_window"}}</option>
+					<option value="closed">{{_ "Chat_button"}}</option>
+				</optgroup>
+				<optgroup label="{{_ "Offline"}}">
+					<option value="opened-offline">{{_ "Offline_form"}}</option>
+					<option value="offline-unavailable">{{_ "Offline_unavailable"}}</option>
+					<option value="offline-success">{{_ "Success_message"}}</option>
+					<option value="closed-offline">{{_ "Chat_button"}}</option>
+				</optgroup>
+			</select>
 
-		<div class="livechat-preview {{previewState}}">
-			<div class="preview-wrapper">
-				{{#with sampleData}}
-					<div class="livechat-room">
-						<div class="title" style="background-color:{{sampleColor}}">
-							<div class="toolbar">
-								&nbsp;
-								<i class="popout icon-link-ext" title="Open in a new window"></i>
-							</div>
-							<h1>{{sampleTitle}}</h1>
-						</div>
-						{{#if showOnline}}
-							<div class="messages">
-								<div class="wrapper">
-									<ul>
-										{{#each messages}}
-											<li id="{{_id}}" class="message {{sequential}}" data-username="{{u.username}}" data-date="{{date}}">
-												<span class="thumb thumb-small" data-username="{{u.username}}" tabindex="1">{{> avatar username=u.username}}</span>
-												<span class="user" data-username="{{u.username}}" tabindex="1">{{u.username}}</span>
-												<span class="info">
-													<span class="time">{{time}}</span>
-												</span>
-												<div class="body" dir="auto">
-													{{{body}}}
-												</div>
-											</li>
-										{{/each}}
-									</ul>
+			<div class="livechat-preview {{previewState}}">
+				<div class="preview-wrapper">
+					{{#with sampleData}}
+						<div class="livechat-room">
+							<div class="title" style="background-color:{{sampleColor}}">
+								<div class="toolbar">
+									&nbsp;
+									<i class="popout icon-link-ext" title="Open in a new window"></i>
 								</div>
+								<h1>{{sampleTitle}}</h1>
 							</div>
-							<div class="footer">
-								<div class="input-wrapper">
-									<textarea class="input-message" placeholder="Type your message"></textarea>
+							{{#if showOnline}}
+								<div class="messages">
+									<div class="wrapper">
+										<ul>
+											{{#each messages}}
+												<li id="{{_id}}" class="message {{sequential}}" data-username="{{u.username}}" data-date="{{date}}">
+													<span class="thumb thumb-small" data-username="{{u.username}}" tabindex="1">{{> avatar username=u.username}}</span>
+													<span class="user" data-username="{{u.username}}" tabindex="1">{{u.username}}</span>
+													<span class="info">
+														<span class="time">{{time}}</span>
+													</span>
+													<div class="body" dir="auto">
+														{{{body}}}
+													</div>
+												</li>
+											{{/each}}
+										</ul>
+									</div>
 								</div>
-								<i class="send-button icon-paper-plane" aria-label="{{_ "Send"}}"></i>
-							</div>
-						{{/if}}
+								<div class="footer">
+									<div class="input-wrapper">
+										<textarea class="input-message" placeholder="Type your message"></textarea>
+									</div>
+									<i class="send-button icon-paper-plane" aria-label="{{_ "Send"}}"></i>
+								</div>
+							{{/if}}
 
-						{{#if showOfflineForm}}
-							<div class="offline">
-								<p class="offline-message">{{{sampleOfflineMessage}}}</p>
+							{{#if showOfflineForm}}
+								<div class="offline">
+									<p class="offline-message">{{{sampleOfflineMessage}}}</p>
 
-								<form>
-									<input type="text" id="name" name="name" placeholder="{{_ "Type_your_name"}}">
+									<form>
+										<input type="text" id="name" name="name" placeholder="{{_ "Type_your_name"}}">
 
-									<input type="email" id="email" name="email" placeholder="{{_ "Type_your_email"}}">
+										<input type="email" id="email" name="email" placeholder="{{_ "Type_your_email"}}">
 
-									<textarea id="message" name="message" placeholder="{{_"Type_your_message"}}" rows="2"></textarea>
+										<textarea id="message" name="message" placeholder="{{_"Type_your_message"}}" rows="2"></textarea>
 
-									<div class="buttons">
-										<button class="button primary send">{{_ "Send"}}</button>
-									</div>
-								</form>
-							</div>
-						{{/if}}
+										<div class="buttons">
+											<button class="button primary send">{{_ "Send"}}</button>
+										</div>
+									</form>
+								</div>
+							{{/if}}
 
-						{{#if showOfflineSuccess}}
-							<div class="offline">
-								<p class="message-sent">{{{sampleOfflineSuccessMessage}}}</p>
-							</div>
-						{{/if}}
+							{{#if showOfflineSuccess}}
+								<div class="offline">
+									<p class="message-sent">{{{sampleOfflineSuccessMessage}}}</p>
+								</div>
+							{{/if}}
 
-						{{#if showOfflineUnavailable}}
-							<div class="offline">
-								<p class="offline-message">{{{sampleOfflineUnavailableMessage}}}</p>
-							</div>
-						{{/if}}
-					</div>
-				{{/with}}
+							{{#if showOfflineUnavailable}}
+								<div class="offline">
+									<p class="offline-message">{{{sampleOfflineUnavailableMessage}}}</p>
+								</div>
+							{{/if}}
+						</div>
+					{{/with}}
+				</div>
 			</div>
 		</div>
-	</div>
+	{{/requiresPermission}}
 </template>
diff --git a/packages/rocketchat-livechat/client/views/app/livechatCurrentChats.html b/packages/rocketchat-livechat/client/views/app/livechatCurrentChats.html
index 2229140be81e7314745d07c93bb892cb45753b36..9b66c52ac3f100f8d3e64ec051e74a14bb9ed19c 100644
--- a/packages/rocketchat-livechat/client/views/app/livechatCurrentChats.html
+++ b/packages/rocketchat-livechat/client/views/app/livechatCurrentChats.html
@@ -1,65 +1,64 @@
 <template name="livechatCurrentChats">
-	<fieldset>
-		<form class="form-inline" method="post">
-			<div class="form-group">
-				<label for="name">{{_ "Name"}}</label>
-				<input type="text" name="name">
-			</div>
+	{{#requiresPermission 'view-livechat-manager'}}
+		<fieldset>
+			<form class="form-inline" method="post">
+				<div class="form-group">
+					<label for="name">{{_ "Name"}}</label>
+					<input type="text" name="name">
+				</div>
 
-			<div class="form-group">
-				<label for="agent">{{_ "Served_By"}}</label>
-				<select name="agent">
-					<option value=""></option>
-					{{#each agents}}
-						<option value="{{_id}}">{{username}}</option>
-					{{/each}}
-				</select>
-			</div>
-			<div class="form-group">
-				<label for="status">{{_ "Status"}}</label>
-				<select name="status">
-					<option value=""></option>
-					<option value="opened">{{_ "Opened"}}</option>
-					<option value="closed">{{_ "Closed"}}</option>
-				</select>
-			</div>
-			<!--Added by Deepankar-->
-				<div class="input-group input-daterange" data-date-autoclose="true" data-date-todayHighlight="true" data-provide="datepicker" >
-					<span class="input-group-addon">From</span>
+				<div class="form-group">
+					<label for="agent">{{_ "Served_By"}}</label>
+					<select name="agent">
+						<option value=""></option>
+						{{#each agents}}
+							<option value="{{_id}}">{{username}}</option>
+						{{/each}}
+					</select>
+				</div>
+				<div class="form-group">
+					<label for="status">{{_ "Status"}}</label>
+					<select name="status">
+						<option value=""></option>
+						<option value="opened">{{_ "Opened"}}</option>
+						<option value="closed">{{_ "Closed"}}</option>
+					</select>
+				</div>
+				<div class="form-group input-daterange">
+					<span class="input-group-addon">{{_ "Date_From"}}</span>
 					<input type="text" class="form-control" id="from" name="from" >
-						<span class="input-group-addon">to</span>
+						<span class="input-group-addon">{{_ "Date_to"}}</span>
 					<input type="text" class="form-control" id="to" name="to">
-
-					<button class="button">{{_ "Filter"}}</button>
 				</div>
-			<!--Added by Deepankar-->
-		</form>
-	</fieldset>
-	<div class="list">
-		<table>
-			<thead>
-				<tr>
-					<th width="25%">{{_ "Name"}}</th>
-					<th width="25%">{{_ "Served_By"}}</th>
-					<th width="15%">{{_ "Started_At"}}</th>
-					<th width="15%">{{_ "Last_Message_At"}}</th>
-					<th width="10%">{{_ "Status"}}</th>
-				</tr>
-			</thead>
-			<tbody>
-				{{#each livechatRoom}}
-					<tr class="row-link">
-						<td>{{label}}</td>
-						<td>{{servedBy}}</td>
-						<td>{{startedAt}}</td>
-						<td>{{lastMessage}}</td>
-						<td>{{status}}</td>
+				<button class="button">{{_ "Filter"}}</button>
+			</form>
+		</fieldset>
+		<div class="list">
+			<table>
+				<thead>
+					<tr>
+						<th width="25%">{{_ "Name"}}</th>
+						<th width="25%">{{_ "Served_By"}}</th>
+						<th width="15%">{{_ "Started_At"}}</th>
+						<th width="15%">{{_ "Last_Message_At"}}</th>
+						<th width="10%">{{_ "Status"}}</th>
 					</tr>
-				{{/each}}
-			</tbody>
-		</table>
-	</div>
-	<div class="text-center">
-		<button class="button load-more">{{_ "Load_more"}}</button>
-	</div>
+				</thead>
+				<tbody>
+					{{#each livechatRoom}}
+						<tr class="row-link">
+							<td>{{label}}</td>
+							<td>{{servedBy}}</td>
+							<td>{{startedAt}}</td>
+							<td>{{lastMessage}}</td>
+							<td>{{status}}</td>
+						</tr>
+					{{/each}}
+				</tbody>
+			</table>
+		</div>
+		<div class="text-center">
+			<button class="button load-more">{{_ "Load_more"}}</button>
+		</div>
+	{{/requiresPermission}}
 </template>
diff --git a/packages/rocketchat-livechat/client/views/app/livechatCurrentChats.js b/packages/rocketchat-livechat/client/views/app/livechatCurrentChats.js
index 57bcdbd87b9c961974d70ab7cf6cb4292578a562..810391ba94bc74dfde6d7841794ef3c0f7ba8788 100644
--- a/packages/rocketchat-livechat/client/views/app/livechatCurrentChats.js
+++ b/packages/rocketchat-livechat/client/views/app/livechatCurrentChats.js
@@ -1,8 +1,10 @@
 import moment from 'moment';
 
+const LivechatRoom = new Mongo.Collection('livechatRoom');
+
 Template.livechatCurrentChats.helpers({
 	livechatRoom() {
-		return ChatRoom.find({ t: 'l' }, { sort: { ts: -1 } });
+		return LivechatRoom.find({ t: 'l' }, { sort: { ts: -1 } });
 	},
 	startedAt() {
 		return moment(this.ts).format('L LTS');
@@ -38,6 +40,18 @@ Template.livechatCurrentChats.events({
 			}
 		});
 
+		if (!_.isEmpty(filter.from)) {
+			filter.from = moment(filter.from, moment.localeData().longDateFormat('L')).toDate();
+		} else {
+			delete filter.from;
+		}
+
+		if (!_.isEmpty(filter.to)) {
+			filter.to = moment(filter.to, moment.localeData().longDateFormat('L')).toDate();
+		} else {
+			delete filter.to;
+		}
+
 		instance.filter.set(filter);
 		instance.limit.set(20);
 	}
@@ -53,3 +67,11 @@ Template.livechatCurrentChats.onCreated(function() {
 		this.subscribe('livechat:rooms', this.filter.get(), 0, this.limit.get());
 	});
 });
+
+Template.livechatCurrentChats.onRendered(function() {
+	this.$('.input-daterange').datepicker({
+		autoclose: true,
+		todayHighlight: true,
+		format: moment.localeData().longDateFormat('L').toLowerCase()
+	});
+});
diff --git a/packages/rocketchat-livechat/client/views/app/livechatCustomFieldForm.html b/packages/rocketchat-livechat/client/views/app/livechatCustomFieldForm.html
index 3dbfaa536b6d1c9c8c67c132435335c7cb46cd4c..991128748682dabc11713d3e230fcac2016d855c 100644
--- a/packages/rocketchat-livechat/client/views/app/livechatCustomFieldForm.html
+++ b/packages/rocketchat-livechat/client/views/app/livechatCustomFieldForm.html
@@ -1,46 +1,48 @@
 <template name="livechatCustomFieldForm">
-	<form id="customField-form" data-id="{{customField._id}}">
-		<div class="rocket-form">
-			{{#if Template.subscriptionsReady}}
-				<fieldset>
-					<div class="input-line">
-						<label>{{_ "Field"}}</label>
-						<div>
-							<input type="text" name="field" value="{{customField._id}}" readonly="{{$exists customField._id}}" placeholder="{{_ "Field"}}" />
+	{{#requiresPermission 'view-livechat-manager'}}
+		<form id="customField-form" data-id="{{customField._id}}">
+			<div class="rocket-form">
+				{{#if Template.subscriptionsReady}}
+					<fieldset>
+						<div class="input-line">
+							<label>{{_ "Field"}}</label>
+							<div>
+								<input type="text" name="field" value="{{customField._id}}" readonly="{{$exists customField._id}}" placeholder="{{_ "Field"}}" />
+							</div>
 						</div>
-					</div>
-					<div class="input-line">
-						<label>{{_ "Label"}}</label>
-						<div>
-							<input type="text" name="label" value="{{customField.label}}" placeholder="{{_ "Label"}}" />
+						<div class="input-line">
+							<label>{{_ "Label"}}</label>
+							<div>
+								<input type="text" name="label" value="{{customField.label}}" placeholder="{{_ "Label"}}" />
+							</div>
 						</div>
-					</div>
-					<div class="input-line">
-						<label>{{_ "Scope"}}</label>
-						<div>
-							<select name="scope">
-								<option value="visitor" selected="{{$eq customField.scope 'visitor'}}">{{_ "Visitor"}}</option>
-								<option value="room" selected="{{$eq customField.scope 'room'}}">{{_ "Room"}}</option>
-							</select>
+						<div class="input-line">
+							<label>{{_ "Scope"}}</label>
+							<div>
+								<select name="scope">
+									<option value="visitor" selected="{{$eq customField.scope 'visitor'}}">{{_ "Visitor"}}</option>
+									<option value="room" selected="{{$eq customField.scope 'room'}}">{{_ "Room"}}</option>
+								</select>
+							</div>
 						</div>
-					</div>
-					<div class="input-line">
-						<label>{{_ "Visibility"}}</label>
-						<div>
-							<select name="visibility">
-								<option value="visible" selected="{{$eq customField.visibility 'visible'}}">{{_ "Visible"}}</option>
-								<option value="hidden" selected="{{$eq customField.visibility 'hidden'}}">{{_ "Hidden"}}</option>
-							</select>
+						<div class="input-line">
+							<label>{{_ "Visibility"}}</label>
+							<div>
+								<select name="visibility">
+									<option value="visible" selected="{{$eq customField.visibility 'visible'}}">{{_ "Visible"}}</option>
+									<option value="hidden" selected="{{$eq customField.visibility 'hidden'}}">{{_ "Hidden"}}</option>
+								</select>
+							</div>
 						</div>
+					</fieldset>
+					<div class="submit">
+						<button class="button back" type="button"><i class="icon-left-big"></i><span>{{_ "Back"}}</span></button>
+						<button class="button primary save"><i class="icon-floppy"></i><span>{{_ "Save"}}</span></button>
 					</div>
-				</fieldset>
-				<div class="submit">
-					<button class="button back" type="button"><i class="icon-left-big"></i><span>{{_ "Back"}}</span></button>
-					<button class="button primary save"><i class="icon-floppy"></i><span>{{_ "Save"}}</span></button>
-				</div>
-			{{else}}
-				{{> loading}}
-			{{/if}}
-		</div>
-	</form>
+				{{else}}
+					{{> loading}}
+				{{/if}}
+			</div>
+		</form>
+	{{/requiresPermission}}
 </template>
diff --git a/packages/rocketchat-livechat/client/views/app/livechatCustomFields.html b/packages/rocketchat-livechat/client/views/app/livechatCustomFields.html
index c6d178d0af214f06f8969b730f1317c1057412c2..b03734f64485f218b68b9d7f9682220adfca658a 100644
--- a/packages/rocketchat-livechat/client/views/app/livechatCustomFields.html
+++ b/packages/rocketchat-livechat/client/views/app/livechatCustomFields.html
@@ -1,27 +1,29 @@
 <template name="livechatCustomFields">
-	<div class="list">
-		<table>
-			<thead>
-				<tr>
-					<th width="25%">{{_ "Field"}}</th>
-					<th width="25%">{{_ "Label"}}</th>
-					<th width="25%">{{_ "Scope"}}</th>
-					<th width="25%">{{_ "Visibility"}}</th>
-					<th>{{_ "Delete"}}</th>
-				</tr>
-			</thead>
-			<tbody>
-				{{#each customFields}}
-					<tr class="custom-field-info row-link" data-id="{{_id}}">
-						<td>{{_id}}</td>
-						<td>{{label}}</td>
-						<td>{{scope}}</td>
-						<td>{{visibility}}</td>
-						<td><a href="#remove" class="remove-custom-field"><i class="icon-trash"></i></a></td>
+	{{#requiresPermission 'view-livechat-manager'}}
+		<div class="list">
+			<table>
+				<thead>
+					<tr>
+						<th width="25%">{{_ "Field"}}</th>
+						<th width="25%">{{_ "Label"}}</th>
+						<th width="25%">{{_ "Scope"}}</th>
+						<th width="25%">{{_ "Visibility"}}</th>
+						<th>{{_ "Delete"}}</th>
 					</tr>
-				{{/each}}
-			</tbody>
-		</table>
-	</div>
-	<a href="{{pathFor 'livechat-customfield-new'}}" class="button primary">{{_ "New_Custom_Field"}}</a>
+				</thead>
+				<tbody>
+					{{#each customFields}}
+						<tr class="custom-field-info row-link" data-id="{{_id}}">
+							<td>{{_id}}</td>
+							<td>{{label}}</td>
+							<td>{{scope}}</td>
+							<td>{{visibility}}</td>
+							<td><a href="#remove" class="remove-custom-field"><i class="icon-trash"></i></a></td>
+						</tr>
+					{{/each}}
+				</tbody>
+			</table>
+		</div>
+		<a href="{{pathFor 'livechat-customfield-new'}}" class="button primary">{{_ "New_Custom_Field"}}</a>
+	{{/requiresPermission}}
 </template>
diff --git a/packages/rocketchat-livechat/client/views/app/livechatDashboard.html b/packages/rocketchat-livechat/client/views/app/livechatDashboard.html
index ae5a2b7df4fffcd938e5e53b0283ee761966c868..d5e3d425edac395dc52e0b2db4aa03039c7535d0 100644
--- a/packages/rocketchat-livechat/client/views/app/livechatDashboard.html
+++ b/packages/rocketchat-livechat/client/views/app/livechatDashboard.html
@@ -1,3 +1,5 @@
 <template name="livechatDashboard">
-	<h1>Dashboard</h1>
+	{{#requiresPermission 'view-livechat-manager'}}
+		<h1>Dashboard</h1>
+	{{/requiresPermission}}
 </template>
diff --git a/packages/rocketchat-livechat/client/views/app/livechatDepartmentForm.html b/packages/rocketchat-livechat/client/views/app/livechatDepartmentForm.html
index f9d3e063c9e69623b68a6203abf1aa6423dd8a30..2ea9125710de5f06cf4f1604d6eaf4556eb1d20c 100644
--- a/packages/rocketchat-livechat/client/views/app/livechatDepartmentForm.html
+++ b/packages/rocketchat-livechat/client/views/app/livechatDepartmentForm.html
@@ -1,82 +1,91 @@
 <template name="livechatDepartmentForm">
-	<form id="department-form" data-id="{{department._id}}">
-		<div class="rocket-form">
-			{{#if Template.subscriptionsReady}}
-				<fieldset>
-					<div class="input-line">
-						<label>{{_ "Enabled"}}</label>
-						<div>
-							<label><input type="radio" name="enabled" value="1" checked="{{$eq department.enabled true}}" /> {{_ "Yes"}}</label>
-							<label><input type="radio" name="enabled" value="0" checked="{{$eq department.enabled false}}" /> {{_ "No"}}</label>
+	{{#requiresPermission 'view-livechat-manager'}}
+		<form id="department-form" data-id="{{department._id}}">
+			<div class="rocket-form">
+				{{#if Template.subscriptionsReady}}
+					<fieldset>
+						<div class="input-line">
+							<label>{{_ "Enabled"}}</label>
+							<div>
+								<label><input type="radio" name="enabled" value="1" checked="{{$eq department.enabled true}}" /> {{_ "Yes"}}</label>
+								<label><input type="radio" name="enabled" value="0" checked="{{$eq department.enabled false}}" /> {{_ "No"}}</label>
+							</div>
 						</div>
-					</div>
-					<div class="input-line">
-						<label>{{_ "Name"}}</label>
-						<div>
-							<input type="text" name="name" value="{{department.name}}" placeholder="{{_ "Name"}}" />
+						<div class="input-line">
+							<label>{{_ "Name"}}</label>
+							<div>
+								<input type="text" name="name" value="{{department.name}}" placeholder="{{_ "Name"}}" />
+							</div>
 						</div>
-					</div>
-					<div class="input-line">
-						<label>{{_ "Description"}}</label>
-						<div>
-							<textarea name="description" rows="6">{{department.description}}</textarea>
+						<div class="input-line">
+							<label>{{_ "Description"}}</label>
+							<div>
+								<textarea name="description" rows="6">{{department.description}}</textarea>
+							</div>
 						</div>
-					</div>
-					<hr />
-					<h2>{{_ "Agents"}}</h2>
+						<div class="input-line">
+							<label>{{_ "Show_on_registration_page"}}</label>
+							<div>
+								<label><input type="radio" name="showOnRegistration" value="1" checked="{{showOnRegistration true}}" /> {{_ "Yes"}}</label>
+								<label><input type="radio" name="showOnRegistration" value="0" checked="{{showOnRegistration false}}" /> {{_ "No"}}</label>
+							</div>
+						</div>
+						<hr />
+						<h2>{{_ "Agents"}}</h2>
 
-					<fieldset>
-						<legend>{{_ "Available_agents"}}</legend>
+						<fieldset>
+							<legend>{{_ "Available_agents"}}</legend>
 
-						<ul class="department-agents available-agents">
-							{{#each availableAgents}}
-								<li><i class="icon-plus-circled"></i>{{username}}</li>
-							{{/each}}
-						</ul>
-					</fieldset>
+							<ul class="department-agents available-agents">
+								{{#each availableAgents}}
+									<li><i class="icon-plus-circled"></i>{{username}}</li>
+								{{/each}}
+							</ul>
+						</fieldset>
 
-					<fieldset>
-						<legend>{{_ "Selected_agents"}}</legend>
+						<fieldset>
+							<legend>{{_ "Selected_agents"}}</legend>
 
-						<div class="list">
-							<table>
-								<thead>
-									<tr>
-										<th width="25%">{{_ "Username"}}</th>
-										<th>{{_ "Count"}}</th>
-										<th>{{_ "Order"}}</th>
-										<th>&nbsp;</th>
-									</tr>
-								</thead>
-								<tbody>
-									{{#if selectedAgents}}
-										{{#each selectedAgents}}
-											<tr class="agent-info">
-												<td>{{username}}</td>
-												<td><input type="text" class="count-{{agentId}}" name="count" value="{{count}}" size="3"></td>
-												<td><input type="text" class="order-{{agentId}}" name="order" value="{{order}}" size="3"></td>
-												<td><a href="#remove" class="remove-agent"><i class="icon-trash"></i></a></td>
-											</tr>
-										{{/each}}
-									{{else}}
+							<div class="list">
+								<table>
+									<thead>
 										<tr>
-											<td colspan="4">{{_ "There_are_no_agents_added_to_this_department_yet"}}</td>
+											<th width="25%">{{_ "Username"}}</th>
+											<th>{{_ "Count"}}</th>
+											<th>{{_ "Order"}}</th>
+											<th>&nbsp;</th>
 										</tr>
-									{{/if}}
-								</tbody>
-							</table>
-						</div>
+									</thead>
+									<tbody>
+										{{#if selectedAgents}}
+											{{#each selectedAgents}}
+												<tr class="agent-info">
+													<td>{{username}}</td>
+													<td><input type="text" class="count-{{agentId}}" name="count" value="{{count}}" size="3"></td>
+													<td><input type="text" class="order-{{agentId}}" name="order" value="{{order}}" size="3"></td>
+													<td><a href="#remove" class="remove-agent"><i class="icon-trash"></i></a></td>
+												</tr>
+											{{/each}}
+										{{else}}
+											<tr>
+												<td colspan="4">{{_ "There_are_no_agents_added_to_this_department_yet"}}</td>
+											</tr>
+										{{/if}}
+									</tbody>
+								</table>
+							</div>
 
-					</fieldset>
+						</fieldset>
 
-				</fieldset>
-				<div class="submit">
-					<button class="button back" type="button"><i class="icon-left-big"></i><span>{{_ "Back"}}</span></button>
-					<button class="button primary save"><i class="icon-floppy"></i><span>{{_ "Save"}}</span></button>
-				</div>
-			{{else}}
-				{{> loading}}
-			{{/if}}
-		</div>
-	</form>
+					</fieldset>
+					<div class="submit">
+						<button class="button back" type="button"><i class="icon-left-big"></i><span>{{_ "Back"}}</span></button>
+						<button class="button primary save"><i class="icon-floppy"></i><span>{{_ "Save"}}</span></button>
+					</div>
+				{{else}}
+					{{> loading}}
+				{{/if}}
+			</div>
+		</form>
+	{{/requiresPermission}}
 </template>
diff --git a/packages/rocketchat-livechat/client/views/app/livechatDepartmentForm.js b/packages/rocketchat-livechat/client/views/app/livechatDepartmentForm.js
index ec40ba225e12ad95ab11b0a883122d532c3c6d7c..4b3825a8caa861eb3d3304479cf27c280299595f 100644
--- a/packages/rocketchat-livechat/client/views/app/livechatDepartmentForm.js
+++ b/packages/rocketchat-livechat/client/views/app/livechatDepartmentForm.js
@@ -12,6 +12,10 @@ Template.livechatDepartmentForm.helpers({
 	availableAgents() {
 		var selected = _.pluck(Template.instance().selectedAgents.get(), 'username');
 		return AgentUsers.find({ username: { $nin: selected }}, { sort: { username: 1 } });
+	},
+	showOnRegistration(value) {
+		let department = Template.instance().department.get();
+		return department.showOnRegistration === value || (department.showOnRegistration === undefined && value === true);
 	}
 });
 
@@ -24,6 +28,7 @@ Template.livechatDepartmentForm.events({
 		var enabled = instance.$('input[name=enabled]:checked').val();
 		var name = instance.$('input[name=name]').val();
 		var description = instance.$('textarea[name=description]').val();
+		var showOnRegistration = instance.$('input[name=showOnRegistration]:checked').val();
 
 		if (enabled !== '1' && enabled !== '0') {
 			return toastr.error(t('Please_select_enabled_yes_or_no'));
@@ -39,7 +44,8 @@ Template.livechatDepartmentForm.events({
 		var departmentData = {
 			enabled: enabled === '1' ? true : false,
 			name: name.trim(),
-			description: description.trim()
+			description: description.trim(),
+			showOnRegistration: showOnRegistration === '1' ? true : false
 		};
 
 		var departmentAgents = [];
diff --git a/packages/rocketchat-livechat/client/views/app/livechatDepartments.html b/packages/rocketchat-livechat/client/views/app/livechatDepartments.html
index 4da6e4e5fecd9be9d7e985145c8cebdd5d61de82..49a85d77eefc709d701db058ab057980d6e2c55d 100644
--- a/packages/rocketchat-livechat/client/views/app/livechatDepartments.html
+++ b/packages/rocketchat-livechat/client/views/app/livechatDepartments.html
@@ -1,28 +1,32 @@
 <template name="livechatDepartments">
-	<div class="list">
-		<table>
-			<thead>
-				<tr>
-					<th width="25%">{{_ "Name"}}</th>
-					<th width="25%">{{_ "Description"}}</th>
-					<th width="25%">{{_ "Num_Agents"}}</th>
-					<th width="25%">{{_ "Enabled"}}</th>
-					<th>{{_ "Delete"}}</th>
-				</tr>
-			</thead>
-			<tbody>
-				{{#each departments}}
-					<tr class="department-info row-link" data-id="{{_id}}">
-						<td>{{name}}</td>
-						<td>{{description}}</td>
-						<td>{{numAgents}}</td>
-						<td>{{#if enabled}}{{_ "Yes"}}{{else}}{{_ "No"}}{{/if}}</td>
-						<td><a href="#remove" class="remove-department"><i class="icon-trash"></i></a></td>
+	{{#requiresPermission 'view-livechat-manager'}}
+		<div class="list">
+			<table>
+				<thead>
+					<tr>
+						<th width="20%">{{_ "Name"}}</th>
+						<th width="30%">{{_ "Description"}}</th>
+						<th width="10%">{{_ "Num_Agents"}}</th>
+						<th width="20%">{{_ "Enabled"}}</th>
+						<th width="20%">{{_ "Show_on_registration_page"}}</th>
+						<th>{{_ "Delete"}}</th>
 					</tr>
-				{{/each}}
-			</tbody>
-		</table>
-	</div>
+				</thead>
+				<tbody>
+					{{#each departments}}
+						<tr class="department-info row-link" data-id="{{_id}}">
+							<td>{{name}}</td>
+							<td>{{description}}</td>
+							<td>{{numAgents}}</td>
+							<td>{{#if enabled}}{{_ "Yes"}}{{else}}{{_ "No"}}{{/if}}</td>
+							<td>{{#if showOnRegistration}}{{_ "Yes"}}{{else}}{{_ "No"}}{{/if}}</td>
+							<td><a href="#remove" class="remove-department"><i class="icon-trash"></i></a></td>
+						</tr>
+					{{/each}}
+				</tbody>
+			</table>
+		</div>
 
-	<a href="{{pathFor 'livechat-department-new'}}" class="button primary">{{_ "New_Department"}}</a>
+		<a href="{{pathFor 'livechat-department-new'}}" class="button primary">{{_ "New_Department"}}</a>
+	{{/requiresPermission}}
 </template>
diff --git a/packages/rocketchat-livechat/client/views/app/livechatInstallation.html b/packages/rocketchat-livechat/client/views/app/livechatInstallation.html
index 6d912bb3cca378198721177f7d2cefa6f1f5d4b3..92d646c9052d17de44544f09e941b1c442d1f305 100644
--- a/packages/rocketchat-livechat/client/views/app/livechatInstallation.html
+++ b/packages/rocketchat-livechat/client/views/app/livechatInstallation.html
@@ -1,8 +1,10 @@
 <template name="livechatInstallation">
-	<p>{{{_ "To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site"}}}</p>
+	{{#requiresPermission 'view-livechat-manager'}}
+		<p>{{{_ "To_install_RocketChat_Livechat_in_your_website_copy_paste_this_code_above_the_last_body_tag_on_your_site"}}}</p>
 
-	<div class="livechat-code">
-		<textarea class="clipboard" data-clipboard-target=".livechat-code textarea">{{script}}</textarea>
-		<button class="button clipboard" data-clipboard-target=".livechat-code textarea"><i class="icon-docs"></i>{{_ "Copy_to_clipboard"}}</button>
-	</div>
+		<div class="livechat-code">
+			<textarea class="clipboard" data-clipboard-target=".livechat-code textarea">{{script}}</textarea>
+			<button class="button clipboard" data-clipboard-target=".livechat-code textarea"><i class="icon-docs"></i>{{_ "Copy_to_clipboard"}}</button>
+		</div>
+	{{/requiresPermission}}
 </template>
diff --git a/packages/rocketchat-livechat/client/views/app/livechatIntegrations.html b/packages/rocketchat-livechat/client/views/app/livechatIntegrations.html
index 3803a76673fc6a6359674aa8542555e630abd49e..61670e4cad50985417f354860ec7d41f522fc365 100644
--- a/packages/rocketchat-livechat/client/views/app/livechatIntegrations.html
+++ b/packages/rocketchat-livechat/client/views/app/livechatIntegrations.html
@@ -1,41 +1,43 @@
 <template name="livechatIntegrations">
-	<div class="rocket-form">
-		<h2>{{_ "Webhooks"}}</h2>
-		<p>
-			{{_ "You_can_use_webhooks_to_easily_integrate_livechat_with_your_CRM"}}
-			<a href="https://rocket.chat/docs/administrator-guides/livechat/#integrations">{{_ "Click_here"}}</a> {{_ "to_see_more_details_on_how_to_integrate"}}
-		</p>
+	{{#requiresPermission 'view-livechat-manager'}}
+		<div class="rocket-form">
+			<h2>{{_ "Webhooks"}}</h2>
+			<p>
+				{{_ "You_can_use_webhooks_to_easily_integrate_livechat_with_your_CRM"}}
+				<a href="https://rocket.chat/docs/administrator-guides/livechat/#integrations">{{_ "Click_here"}}</a> {{_ "to_see_more_details_on_how_to_integrate"}}
+			</p>
 
-		<form id="integration-form">
-			<div class="input-line">
-				<label for="webhookUrl">{{_ "Webhook_URL"}}</label>
-				<div>
-					<input type="url" name="webhookUrl" id="webhookUrl" value="{{webhookUrl}}" placeholder="https://yourdomain.com/webhook/entrypoint">
+			<form id="integration-form">
+				<div class="input-line">
+					<label for="webhookUrl">{{_ "Webhook_URL"}}</label>
+					<div>
+						<input type="url" name="webhookUrl" id="webhookUrl" value="{{webhookUrl}}" placeholder="https://yourdomain.com/webhook/entrypoint">
+					</div>
 				</div>
-			</div>
-			<div class="input-line">
-				<label for="secretToken">{{_ "Secret_token"}}</label>
-				<div>
-					<input type="text" name="secretToken" id="secretToken" value="{{secretToken}}">
+				<div class="input-line">
+					<label for="secretToken">{{_ "Secret_token"}}</label>
+					<div>
+						<input type="text" name="secretToken" id="secretToken" value="{{secretToken}}">
+					</div>
 				</div>
-			</div>
-			<div class="input-line">
-				<label for="sendOnClose">
-					<input type="checkbox" name="sendOnClose" id="sendOnClose" value="1" checked="{{sendOnCloseChecked}}">
-					{{_ "Send_request_on_chat_close"}}
-				</label>
-			</div>
-			<div class="input-line">
-				<label for="sendOnOffline">
-					<input type="checkbox" name="sendOnOffline" id="sendOnOffline" value="1" checked="{{sendOnOfflineChecked}}">
-					{{_ "Send_request_on_offline_messages"}}
-				</label>
-			</div>
-			<div class="submit">
-				<button class="button danger reset-settings" type="button"><i class="icon-ccw"></i>{{_ "Reset"}}</button>
-				<button class="button secondary test" type="button" disabled="{{disableTest}}">{{_ "Send_Test"}}</button>
-				<button class="button primary save"><i class="icon-floppy"></i>{{_ "Save"}}</button>
-			</div>
-		</form>
-	</div>
+				<div class="input-line">
+					<label for="sendOnClose">
+						<input type="checkbox" name="sendOnClose" id="sendOnClose" value="1" checked="{{sendOnCloseChecked}}">
+						{{_ "Send_request_on_chat_close"}}
+					</label>
+				</div>
+				<div class="input-line">
+					<label for="sendOnOffline">
+						<input type="checkbox" name="sendOnOffline" id="sendOnOffline" value="1" checked="{{sendOnOfflineChecked}}">
+						{{_ "Send_request_on_offline_messages"}}
+					</label>
+				</div>
+				<div class="submit">
+					<button class="button danger reset-settings" type="button"><i class="icon-ccw"></i>{{_ "Reset"}}</button>
+					<button class="button secondary test" type="button" disabled="{{disableTest}}">{{_ "Send_Test"}}</button>
+					<button class="button primary save"><i class="icon-floppy"></i>{{_ "Save"}}</button>
+				</div>
+			</form>
+		</div>
+	{{/requiresPermission}}
 </template>
diff --git a/packages/rocketchat-livechat/client/views/app/livechatOfficeHours.html b/packages/rocketchat-livechat/client/views/app/livechatOfficeHours.html
index d6f03caacefcc481d00c27b62164efc53def78bb..d662002f4a7e83f758538bf1d94a07cfa1e0f34c 100644
--- a/packages/rocketchat-livechat/client/views/app/livechatOfficeHours.html
+++ b/packages/rocketchat-livechat/client/views/app/livechatOfficeHours.html
@@ -1,59 +1,61 @@
 <template name="livechatOfficeHours">
-	<div class="livechat-officeHours-div">
-		<form class="rocket-form" id="officeHoursForm">
+	{{#requiresPermission 'view-livechat-manager'}}
+		<div class="livechat-officeHours-div">
+			<form class="rocket-form" id="officeHoursForm">
 
-			<fieldset>
-				<legend>{{_ "Office_hours_enabled"}}</legend>
-				<input type="radio" class="preview-settings" name="enableOfficeHours" id="enableOfficeHoursTrue" checked="{{enableOfficeHoursTrueChecked}}" value="true">
-				<label for="displayOfflineFormTrue">{{_ "True"}}</label>
-				<input type="radio" class="preview-settings" name="enableOfficeHours" id="enableOfficeHoursFalse" checked="{{enableOfficeHoursFalseChecked}}" value="false">
-				<label for="displayOfflineFormFalse">{{_ "False"}}</label>
-			</fieldset>
+				<fieldset>
+					<legend>{{_ "Office_hours_enabled"}}</legend>
+					<input type="radio" class="preview-settings" name="enableOfficeHours" id="enableOfficeHoursTrue" checked="{{enableOfficeHoursTrueChecked}}" value="true">
+					<label for="displayOfflineFormTrue">{{_ "True"}}</label>
+					<input type="radio" class="preview-settings" name="enableOfficeHours" id="enableOfficeHoursFalse" checked="{{enableOfficeHoursFalseChecked}}" value="false">
+					<label for="displayOfflineFormFalse">{{_ "False"}}</label>
+				</fieldset>
 
-			<!-- days open -->
-			<fieldset>
-				<legend>{{_ "Open_days_of_the_week"}}</legend>
-				{{#each day in days}}
-					{{#if open day}}
-						<label class="dayOpenCheck"><input type="checkbox" name={{openName day}} checked>{{name day}}</label>
-					{{else}}
-						<label class="dayOpenCheck"><input type="checkbox" name={{openName day}}>{{name day}}</label>
-					{{/if}}
-				{{/each}}
-			</fieldset>
+				<!-- days open -->
+				<fieldset>
+					<legend>{{_ "Open_days_of_the_week"}}</legend>
+					{{#each day in days}}
+						{{#if open day}}
+							<label class="dayOpenCheck"><input type="checkbox" name={{openName day}} checked>{{name day}}</label>
+						{{else}}
+							<label class="dayOpenCheck"><input type="checkbox" name={{openName day}}>{{name day}}</label>
+						{{/if}}
+					{{/each}}
+				</fieldset>
 
-			<!-- times -->
-			<fieldset>
-				<legend>{{_ "Hours"}}</legend>
-				{{#each day in days}}
-					<div class="input-line">
-						<h1><strong>{{name day}}</strong></h1>
-						<table style="width:100%;">
-							<tr>
-								<td>{{_ "Open"}}:</td>
-								<td>{{_ "Close"}}:</td>
-							</tr>
-							<tr>
-								<td>
-									<div style="margin-right:30px">
-										<input type="time" class="preview-settings" name={{startName day}} id={{startName day}}  value={{start day}} style="width=100px;">
-									</div>
-								</td>
-								<td>
-									<div style="margin-right:30px">
-										<input type="time" class="preview-settings" name={{finishName day}} id={{finishName day}} value={{finish day}} style="width=100px;">
-									</div>
-								</td>
-							</tr>
-						</table>
-					</div>
-				{{/each}}
-			</fieldset>
+				<!-- times -->
+				<fieldset>
+					<legend>{{_ "Hours"}}</legend>
+					{{#each day in days}}
+						<div class="input-line">
+							<h1><strong>{{name day}}</strong></h1>
+							<table style="width:100%;">
+								<tr>
+									<td>{{_ "Open"}}:</td>
+									<td>{{_ "Close"}}:</td>
+								</tr>
+								<tr>
+									<td>
+										<div style="margin-right:30px">
+											<input type="time" class="preview-settings" name={{startName day}} id={{startName day}}  value={{start day}} style="width=100px;">
+										</div>
+									</td>
+									<td>
+										<div style="margin-right:30px">
+											<input type="time" class="preview-settings" name={{finishName day}} id={{finishName day}} value={{finish day}} style="width=100px;">
+										</div>
+									</td>
+								</tr>
+							</table>
+						</div>
+					{{/each}}
+				</fieldset>
 
 
-			<div class="submit">
-				<button class="button"><i class="icon-floppy"></i>{{_ "Save"}}</button>
-			</div>
-		</form>
-	</div>
-</template>
\ No newline at end of file
+				<div class="submit">
+					<button class="button"><i class="icon-floppy"></i>{{_ "Save"}}</button>
+				</div>
+			</form>
+		</div>
+	{{/requiresPermission}}
+</template>
diff --git a/packages/rocketchat-livechat/client/views/app/livechatOfficeHours.js b/packages/rocketchat-livechat/client/views/app/livechatOfficeHours.js
index aa4c2e6856bcc4b001b192376a23ce213fcf6c21..2d294b5aff6ac5a396cab3b4af8d8f9a3826320b 100644
--- a/packages/rocketchat-livechat/client/views/app/livechatOfficeHours.js
+++ b/packages/rocketchat-livechat/client/views/app/livechatOfficeHours.js
@@ -69,9 +69,8 @@ Template.livechatOfficeHours.events({
 		let value = e.currentTarget.value;
 		if (e.currentTarget.type === 'radio') {
 			value = value === 'true';
+			instance[e.currentTarget.name].set(value);
 		}
-
-		instance[e.currentTarget.name].set(value);
 	},
 	'submit .rocket-form'(e, instance) {
 		e.preventDefault();
diff --git a/packages/rocketchat-livechat/client/views/app/livechatQueue.html b/packages/rocketchat-livechat/client/views/app/livechatQueue.html
index 35f838b5f4c4899e2b101f4d1cd2e100a85200b9..454e9f513b499688ccbff819596bf44e05bc9052 100644
--- a/packages/rocketchat-livechat/client/views/app/livechatQueue.html
+++ b/packages/rocketchat-livechat/client/views/app/livechatQueue.html
@@ -1,5 +1,5 @@
 <template name="livechatQueue">
-	{{#if hasPermission}}
+	{{#requiresPermission 'view-livechat-manager'}}
 		{{#each departments}}
 			<p class="queue-department">
 				{{_ "Department"}}: <strong>{{name}}</strong>
@@ -34,7 +34,5 @@
 				</div>
 			</div>
 		{{/each}}
-	{{else}}
-		<p>{{_ "You_are_not_authorized_to_view_this_page"}}</p>
-	{{/if}}
+	{{/requiresPermission}}
 </template>
diff --git a/packages/rocketchat-livechat/client/views/app/livechatTriggers.html b/packages/rocketchat-livechat/client/views/app/livechatTriggers.html
index 25a155f3671db4602198479139e8ca53317c79c0..ea15e3b22c14e09e65748c811451d3a6fed4e718 100644
--- a/packages/rocketchat-livechat/client/views/app/livechatTriggers.html
+++ b/packages/rocketchat-livechat/client/views/app/livechatTriggers.html
@@ -1,32 +1,28 @@
 <template name="livechatTriggers">
-	<form id="trigger-form">
-		<div class="rocket-form">
-			<fieldset>
-				<legend>{{_ "Condition"}}</legend>
-				<div class="conditions">
-					{{#each conditions}}
-						{{> livechatTriggerCondition}}
+	{{#requiresPermission 'view-livechat-manager'}}
+		<div class="list">
+			<table>
+				<thead>
+					<tr>
+						<th width="30%">{{_ "Name"}}</th>
+						<th width="50%">{{_ "Description"}}</th>
+						<th width="20%">{{_ "Enabled"}}</th>
+						<th>{{_ "Delete"}}</th>
+					</tr>
+				</thead>
+				<tbody>
+					{{#each triggers}}
+						<tr class="trigger-info row-link" data-id="{{_id}}">
+							<td>{{name}}</td>
+							<td>{{description}}</td>
+							<td>{{#if enabled}}{{_ "Yes"}}{{else}}{{_ "No"}}{{/if}}</td>
+							<td><a href="#remove" class="remove-trigger"><i class="icon-trash"></i></a></td>
+						</tr>
 					{{/each}}
-					{{#unless conditions}}
-						{{> livechatTriggerCondition}}
-					{{/unless}}
-				</div>
-			</fieldset>
-			<fieldset>
-				<legend>{{_ "Action"}}</legend>
-				<div class="actions">
-					{{#each actions}}
-						{{> livechatTriggerAction}}
-					{{/each}}
-					{{#unless actions}}
-						{{> livechatTriggerAction}}
-					{{/unless}}
-				</div>
-			</fieldset>
-			<div class="submit">
-				<button class="button danger delete-trigger" type="button">{{_ "Delete"}}</button>
-				<button class="button primary save"><i class="icon-floppy"></i><span>{{_ "Save"}}</span></button>
-			</div>
+				</tbody>
+			</table>
 		</div>
-	</form>
+
+		<a href="{{pathFor 'livechat-trigger-new'}}" class="button primary">{{_ "New_Trigger"}}</a>
+	{{/requiresPermission}}
 </template>
diff --git a/packages/rocketchat-livechat/client/views/app/livechatTriggers.js b/packages/rocketchat-livechat/client/views/app/livechatTriggers.js
index 74adc00334bb43acdb71163ac6dbc9be28e16e29..cbe198de740bfae329e2d110e03abeab19b05153 100644
--- a/packages/rocketchat-livechat/client/views/app/livechatTriggers.js
+++ b/packages/rocketchat-livechat/client/views/app/livechatTriggers.js
@@ -1,68 +1,42 @@
-import toastr from 'toastr';
 Template.livechatTriggers.helpers({
-	conditions() {
-		var trigger = Template.instance().trigger.get();
-		if (!trigger) {
-			return [];
-		}
-
-		return trigger.conditions;
-	},
-	actions() {
-		var trigger = Template.instance().trigger.get();
-		if (!trigger) {
-			return [];
-		}
-
-		return trigger.actions;
+	triggers() {
+		return LivechatTrigger.find();
 	}
 });
 
 Template.livechatTriggers.events({
-	'submit #trigger-form'(e, instance) {
+	'click .remove-trigger'(e/*, instance*/) {
 		e.preventDefault();
-		var $btn = instance.$('button.save');
-
-		var oldBtnValue = $btn.html();
-		$btn.html(t('Saving'));
-
-		var data = {
-			conditions: [],
-			actions: []
-		};
+		e.stopPropagation();
 
-		$('.each-condition').each(function() {
-			data.conditions.push({
-				name: $('.trigger-condition', this).val(),
-				value: $('.' + $('.trigger-condition', this).val() + '-value').val()
-			});
-		});
-
-		$('.each-action').each(function() {
-			if ($('.trigger-action', this).val() === 'send-message') {
-				data.actions.push({
-					name: $('.trigger-action', this).val(),
-					params: {
-						name: $('[name=send-message-name]', this).val(),
-						msg: $('[name=send-message-msg]', this).val()
-					}
-				});
-			} else {
-				data.actions.push({
-					name: $('.trigger-action', this).val(),
-					value: $('.' + $('.trigger-action', this).val() + '-value').val()
+		swal({
+			title: t('Are_you_sure'),
+			type: 'warning',
+			showCancelButton: true,
+			confirmButtonColor: '#DD6B55',
+			confirmButtonText: t('Yes'),
+			cancelButtonText: t('Cancel'),
+			closeOnConfirm: false,
+			html: false
+		}, () => {
+			Meteor.call('livechat:removeTrigger', this._id, function(error/*, result*/) {
+				if (error) {
+					return handleError(error);
+				}
+				swal({
+					title: t('Removed'),
+					text: t('Trigger_removed'),
+					type: 'success',
+					timer: 1000,
+					showConfirmButton: false
 				});
-			}
+			});
 		});
+	},
 
-		Meteor.call('livechat:saveTrigger', data, function(error/*, result*/) {
-			$btn.html(oldBtnValue);
-			if (error) {
-				return handleError(error);
-			}
-
-			toastr.success(t('Saved'));
-		});
+	'click .trigger-info'(e/*, instance*/) {
+		e.preventDefault();
+		FlowRouter.go('livechat-trigger-edit', { _id: this._id });
 	},
 
 	'click .delete-trigger'(e/*, instance*/) {
@@ -78,7 +52,7 @@ Template.livechatTriggers.events({
 			closeOnConfirm: false,
 			html: false
 		}, () => {
-			Meteor.call('livechat:removeTrigger', function(error/*, result*/) {
+			Meteor.call('livechat:removeTrigger', this._id, function(error/*, result*/) {
 				if (error) {
 					return handleError(error);
 				}
@@ -96,9 +70,5 @@ Template.livechatTriggers.events({
 });
 
 Template.livechatTriggers.onCreated(function() {
-	this.subscribe('livechat:trigger');
-	this.trigger = new ReactiveVar(null);
-	this.autorun(() => {
-		this.trigger.set(LivechatTrigger.findOne());
-	});
+	this.subscribe('livechat:triggers');
 });
diff --git a/packages/rocketchat-livechat/client/views/app/livechatTriggersForm.html b/packages/rocketchat-livechat/client/views/app/livechatTriggersForm.html
new file mode 100644
index 0000000000000000000000000000000000000000..aad02c3ac4961a5476a24da9d51d487f05dbaf1a
--- /dev/null
+++ b/packages/rocketchat-livechat/client/views/app/livechatTriggersForm.html
@@ -0,0 +1,55 @@
+<template name="livechatTriggersForm">
+	{{#requiresPermission 'view-livechat-manager'}}
+		<form id="trigger-form">
+			<div class="rocket-form">
+				<fieldset>
+					<div class="input-line">
+						<label>{{_ "Enabled"}}</label>
+						<div>
+							<label><input type="radio" name="enabled" value="1" checked="{{$eq enabled true}}" /> {{_ "Yes"}}</label>
+							<label><input type="radio" name="enabled" value="0" checked="{{$eq enabled false}}" /> {{_ "No"}}</label>
+						</div>
+					</div>
+					<div class="input-line">
+						<label>{{_ "Name"}}</label>
+						<div>
+							<input type="text" name="name" value="{{name}}" />
+						</div>
+					</div>
+					<div class="input-line">
+						<label>{{_ "Description"}}</label>
+						<div>
+							<input type="text" name="description" value="{{description}}" />
+						</div>
+					</div>
+				</fieldset>
+				<fieldset>
+					<legend>{{_ "Condition"}}</legend>
+					<div class="conditions">
+						{{#each conditions}}
+							{{> livechatTriggerCondition}}
+						{{/each}}
+						{{#unless conditions}}
+							{{> livechatTriggerCondition}}
+						{{/unless}}
+					</div>
+				</fieldset>
+				<fieldset>
+					<legend>{{_ "Action"}}</legend>
+					<div class="actions">
+						{{#each actions}}
+							{{> livechatTriggerAction}}
+						{{/each}}
+						{{#unless actions}}
+							{{> livechatTriggerAction}}
+						{{/unless}}
+					</div>
+				</fieldset>
+				<div class="submit">
+					<button class="button back" type="button"><i class="icon-left-big"></i><span>{{_ "Back"}}</span></button>
+					<button class="button primary save"><i class="icon-floppy"></i><span>{{_ "Save"}}</span></button>
+				</div>
+			</div>
+		</form>
+	{{/requiresPermission}}
+</template>
diff --git a/packages/rocketchat-livechat/client/views/app/livechatTriggersForm.js b/packages/rocketchat-livechat/client/views/app/livechatTriggersForm.js
new file mode 100644
index 0000000000000000000000000000000000000000..2b16ff6583ab1d24ffeaa4205d9013975c266d21
--- /dev/null
+++ b/packages/rocketchat-livechat/client/views/app/livechatTriggersForm.js
@@ -0,0 +1,94 @@
+import toastr from 'toastr';
+Template.livechatTriggersForm.helpers({
+	name() {
+		const trigger = LivechatTrigger.findOne(FlowRouter.getParam('_id'));
+		return trigger && trigger.name;
+	},
+	description() {
+		const trigger = LivechatTrigger.findOne(FlowRouter.getParam('_id'));
+		return trigger && trigger.description;
+	},
+	enabled() {
+		const trigger = LivechatTrigger.findOne(FlowRouter.getParam('_id'));
+		return trigger && trigger.enabled;
+	},
+	conditions() {
+		const trigger = LivechatTrigger.findOne(FlowRouter.getParam('_id'));
+		if (!trigger) {
+			return [];
+		}
+
+		return trigger.conditions;
+	},
+	actions() {
+		const trigger = LivechatTrigger.findOne(FlowRouter.getParam('_id'));
+		if (!trigger) {
+			return [];
+		}
+
+		return trigger.actions;
+	}
+});
+
+Template.livechatTriggersForm.events({
+	'submit #trigger-form'(e, instance) {
+		e.preventDefault();
+		const $btn = instance.$('button.save');
+
+		const oldBtnValue = $btn.html();
+		$btn.html(t('Saving'));
+
+		const data = {
+			_id: FlowRouter.getParam('_id'),
+			name: instance.$('input[name=name]').val(),
+			description: instance.$('input[name=description]').val(),
+			enabled: instance.$('input[name=enabled]:checked').val() === '1' ? true : false,
+			conditions: [],
+			actions: []
+		};
+
+		$('.each-condition').each(function() {
+			data.conditions.push({
+				name: $('.trigger-condition', this).val(),
+				value: $('.' + $('.trigger-condition', this).val() + '-value').val()
+			});
+		});
+
+		$('.each-action').each(function() {
+			if ($('.trigger-action', this).val() === 'send-message') {
+				data.actions.push({
+					name: $('.trigger-action', this).val(),
+					params: {
+						name: $('[name=send-message-name]', this).val(),
+						msg: $('[name=send-message-msg]', this).val()
+					}
+				});
+			} else {
+				data.actions.push({
+					name: $('.trigger-action', this).val(),
+					value: $('.' + $('.trigger-action', this).val() + '-value').val()
+				});
+			}
+		});
+
+		Meteor.call('livechat:saveTrigger', data, function(error/*, result*/) {
+			$btn.html(oldBtnValue);
+			if (error) {
+				return handleError(error);
+			}
+
+			FlowRouter.go('livechat-triggers');
+
+			toastr.success(t('Saved'));
+		});
+	},
+
+	'click button.back'(e/*, instance*/) {
+		e.preventDefault();
+		FlowRouter.go('livechat-triggers');
+	}
+});
+
+Template.livechatTriggersForm.onCreated(function() {
+	this.subscribe('livechat:triggers', FlowRouter.getParam('_id'));
+});
diff --git a/packages/rocketchat-livechat/client/views/app/livechatUsers.html b/packages/rocketchat-livechat/client/views/app/livechatUsers.html
index 539eb625372f74258dc6002dfe87817cb7426854..33c7e7544708cadf3e3c03131b8a03d0c2bfcdd0 100644
--- a/packages/rocketchat-livechat/client/views/app/livechatUsers.html
+++ b/packages/rocketchat-livechat/client/views/app/livechatUsers.html
@@ -1,71 +1,72 @@
 <template name="livechatUsers">
-	<h2>{{_ "Livechat_managers"}}</h2>
-	<form id="form-manager" class="inline">
-		<label>{{_ "Add_manager"}}</label>
-		{{> inputAutocomplete settings=managerAutocompleteSettings name="username" class="search" placeholder=(_ "Search_by_username") autocomplete="off"}}
-		<button name="add" class="button primary add">{{_ "Add"}}</button>
-	</form>
-	<div class="list">
-		<table>
-			<thead>
-				<tr>
-					<th>&nbsp;</th>
-					<th width="34%">{{_ "Name"}}</th>
-					<th width="33%">{{_ "Username"}}</th>
-					<th width="33%">{{_ "Email"}}</th>
-					<th>&nbsp;</th>
-				</tr>
-			</thead>
-			<tbody>
-				{{#each managers}}
-					<tr class="user-info" data-id="{{_id}}">
-						<td>
-							<div class="user-image status-{{status}}">
-								{{> avatar username=username}}
-							</div>
-						</td>
-						<td>{{name}}</td>
-						<td>{{username}}</td>
-						<td>{{emailAddress}}</td>
-						<td><a href="#remove" class="remove-manager"><i class="icon-trash"></i></a></td>
+	{{#requiresPermission 'view-livechat-manager'}}
+		<h2>{{_ "Livechat_managers"}}</h2>
+		<form id="form-manager" class="inline">
+			<label>{{_ "Add_manager"}}</label>
+			{{> inputAutocomplete settings=managerAutocompleteSettings name="username" class="search" placeholder=(_ "Search_by_username") autocomplete="off"}}
+			<button name="add" class="button primary add">{{_ "Add"}}</button>
+		</form>
+		<div class="list">
+			<table>
+				<thead>
+					<tr>
+						<th>&nbsp;</th>
+						<th width="34%">{{_ "Name"}}</th>
+						<th width="33%">{{_ "Username"}}</th>
+						<th width="33%">{{_ "Email"}}</th>
+						<th>&nbsp;</th>
 					</tr>
-				{{/each}}
-			</tbody>
-		</table>
-	</div>
-	<h2>{{_ "Livechat_agents"}}</h2>
-	<form id="form-agent" class="inline">
-		<label>{{_ "Add_agent"}}</label>
-		{{> inputAutocomplete settings=agentAutocompleteSettings name="username" class="search" placeholder=(_ "Search_by_username") autocomplete="off"}}
-		<button name="add" class="button primary add">{{_ "Add"}}</button>
-	</form>
-	<div class="list">
-		<table>
-			<thead>
-				<tr>
-					<th>&nbsp;</th>
-					<th width="34%">{{_ "Name"}}</th>
-					<th width="33%">{{_ "Username"}}</th>
-					<th width="33%">{{_ "Email"}}</th>
-					<th>&nbsp;</th>
-				</tr>
-			</thead>
-			<tbody>
-				{{#each agents}}
-					<tr class="user-info" data-id="{{_id}}">
-						<td>
-							<div class="user-image status-{{status}}">
-								{{> avatar username=username}}
-							</div>
-						</td>
-						<td>{{name}}</td>
-						<td>{{username}}</td>
-						<td>{{emailAddress}}</td>
-						<td><a href="#remove" class="remove-agent"><i class="icon-trash"></i></a></td>
+				</thead>
+				<tbody>
+					{{#each managers}}
+						<tr class="user-info" data-id="{{_id}}">
+							<td>
+								<div class="user-image status-{{status}}">
+									{{> avatar username=username}}
+								</div>
+							</td>
+							<td>{{name}}</td>
+							<td>{{username}}</td>
+							<td>{{emailAddress}}</td>
+							<td><a href="#remove" class="remove-manager"><i class="icon-trash"></i></a></td>
+						</tr>
+					{{/each}}
+				</tbody>
+			</table>
+		</div>
+		<h2>{{_ "Livechat_agents"}}</h2>
+		<form id="form-agent" class="inline">
+			<label>{{_ "Add_agent"}}</label>
+			{{> inputAutocomplete settings=agentAutocompleteSettings name="username" class="search" placeholder=(_ "Search_by_username") autocomplete="off"}}
+			<button name="add" class="button primary add">{{_ "Add"}}</button>
+		</form>
+		<div class="list">
+			<table>
+				<thead>
+					<tr>
+						<th>&nbsp;</th>
+						<th width="34%">{{_ "Name"}}</th>
+						<th width="33%">{{_ "Username"}}</th>
+						<th width="33%">{{_ "Email"}}</th>
+						<th>&nbsp;</th>
 					</tr>
-				{{/each}}
-			</tbody>
-		</table>
-	</div>
+				</thead>
+				<tbody>
+					{{#each agents}}
+						<tr class="user-info" data-id="{{_id}}">
+							<td>
+								<div class="user-image status-{{status}}">
+									{{> avatar username=username}}
+								</div>
+							</td>
+							<td>{{name}}</td>
+							<td>{{username}}</td>
+							<td>{{emailAddress}}</td>
+							<td><a href="#remove" class="remove-agent"><i class="icon-trash"></i></a></td>
+						</tr>
+					{{/each}}
+				</tbody>
+			</table>
+		</div>
+	{{/requiresPermission}}
 </template>
-
diff --git a/packages/rocketchat-livechat/client/views/app/tabbar/visitorEdit.js b/packages/rocketchat-livechat/client/views/app/tabbar/visitorEdit.js
index 0b3291c888cef5f2b99e976cb41bd9ff36dab258..f743a751b8ace72a9b099c54dfc41eb45fbf12c1 100644
--- a/packages/rocketchat-livechat/client/views/app/tabbar/visitorEdit.js
+++ b/packages/rocketchat-livechat/client/views/app/tabbar/visitorEdit.js
@@ -10,8 +10,8 @@ Template.visitorEdit.helpers({
 
 	email() {
 		const visitor = Template.instance().visitor.get();
-		if (visitor.emails && visitor.emails.length > 0) {
-			return visitor.emails[0].address;
+		if (visitor.visitorEmails && visitor.visitorEmails.length > 0) {
+			return visitor.visitorEmails[0].address;
 		}
 	},
 
diff --git a/packages/rocketchat-livechat/client/views/app/tabbar/visitorForward.js b/packages/rocketchat-livechat/client/views/app/tabbar/visitorForward.js
index e7481e4af3b4377b70b1486e1435c3f0968384e8..97afe34d0a99ec98308b87ad11a878b4274a4050 100644
--- a/packages/rocketchat-livechat/client/views/app/tabbar/visitorForward.js
+++ b/packages/rocketchat-livechat/client/views/app/tabbar/visitorForward.js
@@ -45,7 +45,7 @@ Template.visitorForward.events({
 		if (instance.find('#forwardUser').value) {
 			transferData.userId = instance.find('#forwardUser').value;
 		} else if (instance.find('#forwardDepartment').value) {
-			transferData.deparmentId = instance.find('#forwardDepartment').value;
+			transferData.departmentId = instance.find('#forwardDepartment').value;
 		}
 
 		Meteor.call('livechat:transfer', transferData, (error, result) => {
diff --git a/packages/rocketchat-livechat/client/views/app/tabbar/visitorInfo.html b/packages/rocketchat-livechat/client/views/app/tabbar/visitorInfo.html
index a606fbc588cf7b9302debd8458233e3e72e03994..21e6041d869d6d4ed29d9d51349ebec51b12c993 100644
--- a/packages/rocketchat-livechat/client/views/app/tabbar/visitorInfo.html
+++ b/packages/rocketchat-livechat/client/views/app/tabbar/visitorInfo.html
@@ -11,11 +11,11 @@
 				{{#with user}}
 					<div class="info">
 						<h3 title="{{username}}"><i class="status-{{status}}"></i> {{username}}</h3>
-						<p>{{name}}</p>
+						<p class="secondary-font-color">{{name}}</p>
 
 						<ul>
 							{{#if utc}}<li><i class="icon-clock"></i>{{userTime}} (UTC {{utc}})</li>{{/if}}
-							{{#each emails}} <li><i class="icon-mail"></i> {{address}}{{#if verified}}&nbsp;<i class="icon-ok"></i>{{/if}}</li> {{/each}}
+							{{#each visitorEmails}} <li><i class="icon-mail"></i> {{address}}{{#if verified}}&nbsp;<i class="icon-ok success-color"></i>{{/if}}</li> {{/each}}
 							{{#each phone}} <li><i class="icon-phone"></i> {{phoneNumber}}</li> {{/each}}
 							{{#if lastLogin}} <li><i class="icon-calendar"></i> {{_ "Created_at"}}: {{createdAt}}</li> {{/if}}
 							{{#if lastLogin}} <li><i class="icon-calendar"></i> {{_ "Last_login"}}: {{lastLogin}}</li> {{/if}}
diff --git a/packages/rocketchat-livechat/client/views/app/tabbar/visitorNavigation.js b/packages/rocketchat-livechat/client/views/app/tabbar/visitorNavigation.js
index 60944d09bd53f489b2b6489a713a01ff8aa4e958..65f4df64c83cba585c79360e2e92a5ecfa0bc107 100644
--- a/packages/rocketchat-livechat/client/views/app/tabbar/visitorNavigation.js
+++ b/packages/rocketchat-livechat/client/views/app/tabbar/visitorNavigation.js
@@ -8,7 +8,9 @@ Template.visitorNavigation.helpers({
 	pageVisited() {
 		const room = ChatRoom.findOne({ _id: this.rid }, { fields: { 'v.token': 1 } });
 
-		return LivechatPageVisited.find({ token: room.v.token }, { sort: { ts: -1 } });
+		if (room && room.v && room.v.token) {
+			return LivechatPageVisited.find({ token: room.v.token }, { sort: { ts: -1 } });
+		}
 	},
 
 	pageTitle() {
diff --git a/packages/rocketchat-livechat/client/views/sideNav/livechat.js b/packages/rocketchat-livechat/client/views/sideNav/livechat.js
index 94586f60f6a5213cd3a45d90db69412072d9dff0..d716738f6a51a4a1aa0ffa792217df3e7c2bd093 100644
--- a/packages/rocketchat-livechat/client/views/sideNav/livechat.js
+++ b/packages/rocketchat-livechat/client/views/sideNav/livechat.js
@@ -62,7 +62,7 @@ Template.livechat.helpers({
 		const statusLivechat = Template.instance().statusLivechat.get();
 
 		return {
-			status: statusLivechat,
+			status: statusLivechat === 'available' ? 'status-online' : 'status-offline',
 			icon: statusLivechat === 'available' ? 'icon-toggle-on' : 'icon-toggle-off',
 			hint: statusLivechat === 'available' ? t('Available') : t('Not_Available')
 		};
@@ -114,7 +114,7 @@ Template.livechat.events({
 			if (isConfirm) {
 				Meteor.call('livechat:takeInquiry', this._id, (error, result) => {
 					if (!error) {
-						FlowRouter.go(RocketChat.roomTypes.getRouteLink(result.t, result));
+						RocketChat.roomTypes.openRouteLink(result.t, result);
 					}
 				});
 			}
diff --git a/packages/rocketchat-livechat/client/views/sideNav/livechatFlex.html b/packages/rocketchat-livechat/client/views/sideNav/livechatFlex.html
index 064a644e0d1256785749a98192d43c84b1d2f11c..4b348a757528228d29de9bac2463fb610f0de293 100644
--- a/packages/rocketchat-livechat/client/views/sideNav/livechatFlex.html
+++ b/packages/rocketchat-livechat/client/views/sideNav/livechatFlex.html
@@ -7,18 +7,16 @@
 	<div class="content">
 		<div class="wrapper">
 			<ul class="flex-list">
-				<li>
-					<!-- <a href="{{pathFor 'livechat-dashboard'}}" class="{{active 'livechat-dashboard'}}">{{_ "Dashboard"}}</a> -->
-					<a href="{{pathFor 'livechat-current-chats'}}" class="{{active 'livechat-current-chats'}}">{{_ "Current_Chats"}}</a>
-					<a href="{{pathFor 'livechat-users'}}" class="{{active 'livechat-users'}}">{{_ "User_management"}}</a>
-					<a href="{{pathFor 'livechat-departments'}}" class="{{active 'livechat-departments' 'livechat-department-edit'}}">{{_ "Departments"}}</a>
-					<a href="{{pathFor 'livechat-triggers'}}" class="{{active 'livechat-triggers'}}">{{_ "Triggers"}}</a>
-					<a href="{{pathFor 'livechat-customfields'}}" class="{{active 'livechat-customfields'}}">{{_ "Custom_Fields"}}</a>
-					<a href="{{pathFor 'livechat-installation'}}" class="{{active 'livechat-installation'}}">{{_ "Installation"}}</a>
-					<a href="{{pathFor 'livechat-appearance'}}" class="{{active 'livechat-appearance'}}">{{_ "Appearance"}}</a>
-					<a href="{{pathFor 'livechat-integrations'}}" class="{{active 'livechat-integrations'}}">{{_ "Integrations"}}</a>
-					<a href="{{pathFor 'livechat-officeHours'}}" class="{{active 'livechat-officeHours'}}">{{_ "Office_Hours"}}</a>
-				</li>
+				<li><!-- <a href="{{pathFor 'livechat-dashboard'}}" class="{{active 'livechat-dashboard'}}">{{_ "Dashboard"}}</a> --></li>
+				<li><a href="{{pathFor 'livechat-current-chats'}}" class="{{active 'livechat-current-chats'}}">{{_ "Current_Chats"}}</a></li>
+				<li><a href="{{pathFor 'livechat-users'}}" class="{{active 'livechat-users'}}">{{_ "User_management"}}</a></li>
+				<li><a href="{{pathFor 'livechat-departments'}}" class="{{active 'livechat-departments' 'livechat-department-edit'}}">{{_ "Departments"}}</a></li>
+				<li><a href="{{pathFor 'livechat-triggers'}}" class="{{active 'livechat-triggers'}}">{{_ "Triggers"}}</a></li>
+				<li><a href="{{pathFor 'livechat-customfields'}}" class="{{active 'livechat-customfields'}}">{{_ "Custom_Fields"}}</a></li>
+				<li><a href="{{pathFor 'livechat-installation'}}" class="{{active 'livechat-installation'}}">{{_ "Installation"}}</a></li>
+				<li><a href="{{pathFor 'livechat-appearance'}}" class="{{active 'livechat-appearance'}}">{{_ "Appearance"}}</a></li>
+				<li><a href="{{pathFor 'livechat-integrations'}}" class="{{active 'livechat-integrations'}}">{{_ "Integrations"}}</a></li>
+				<li><a href="{{pathFor 'livechat-officeHours'}}" class="{{active 'livechat-officeHours'}}">{{_ "Office_Hours"}}</a></li>
 			</ul>
 		</div>
 	</div>
diff --git a/packages/rocketchat-livechat/config.js b/packages/rocketchat-livechat/config.js
index 1270237727a9d0409fe69631b8542a88e13ba586..c935d988c41fcd3931855e68f33d24dce5e30d4b 100644
--- a/packages/rocketchat-livechat/config.js
+++ b/packages/rocketchat-livechat/config.js
@@ -14,6 +14,14 @@ Meteor.startup(function() {
 		i18nLabel: 'Display_offline_form'
 	});
 
+	RocketChat.settings.add('Livechat_validate_offline_email', true, {
+		type: 'boolean',
+		group: 'Livechat',
+		public: true,
+		section: 'Offline',
+		i18nLabel: 'Validate_email_address'
+	});
+
 	RocketChat.settings.add('Livechat_offline_form_unavailable', '', {
 		type: 'string',
 		group: 'Livechat',
@@ -184,7 +192,7 @@ Meteor.startup(function() {
 		type: 'boolean',
 		group: 'Livechat',
 		public: true,
-		i18nLabel: 'Office_Hours_Enabled'
+		i18nLabel: 'Office_hours_enabled'
 	});
 
 	RocketChat.settings.add('Livechat_videocall_enabled', false, {
@@ -211,4 +219,19 @@ Meteor.startup(function() {
 		enableQuery: { _id: 'Livechat_enable_transcript', value: true }
 	});
 
+	RocketChat.settings.add('Livechat_open_inquiery_show_connecting', false, {
+		type: 'boolean',
+		group: 'Livechat',
+		public: true,
+		i18nLabel: 'Livechat_open_inquiery_show_connecting',
+		enableQuery: { _id: 'Livechat_Routing_Method', value: 'Guest_Pool' }
+	});
+
+	RocketChat.settings.add('Livechat_AllowedDomainsList', '', {
+		type: 'string',
+		group: 'Livechat',
+		public: true,
+		i18nLabel: 'Livechat_AllowedDomainsList',
+		i18nDescription: 'Domains_allowed_to_embed_the_livechat_widget'
+	});
 });
diff --git a/packages/rocketchat-livechat/livechat.js b/packages/rocketchat-livechat/livechat.js
index 684227b212f84b7b071b01fbb42480f3dc525886..7fbc07b3df072b37922345f71d90daa17b8b19f6 100644
--- a/packages/rocketchat-livechat/livechat.js
+++ b/packages/rocketchat-livechat/livechat.js
@@ -11,6 +11,22 @@ WebApp.connectHandlers.use('/livechat', Meteor.bindEnvironment((req, res, next)
 	}
 	res.setHeader('content-type', 'text/html; charset=utf-8');
 
+	var domainWhiteList = RocketChat.settings.get('Livechat_AllowedDomainsList');
+
+	if (!_.isEmpty(domainWhiteList.trim())) {
+		domainWhiteList = _.map(domainWhiteList.split(','), function(domain) {
+			return domain.trim();
+		});
+
+		let d = req.headers.referer.match(/^(?:https?:\/\/)?(?:www\.)?([^\/]+)/)[1];
+		if (!_.contains(domainWhiteList, d)) {
+			res.setHeader('X-FRAME-OPTIONS', 'DENY');
+			return next();
+		}
+
+		res.setHeader('X-FRAME-OPTIONS', 'ALLOW-FROM ' + d);
+	}
+
 	const head = Assets.getText('public/head.html');
 
 	const html = `<html>
diff --git a/packages/rocketchat-livechat/package.js b/packages/rocketchat-livechat/package.js
index 6af2910319eb4317ef98beca9dfa24e827201793..bdae5fdbf47e4a26e5c5e634804df41e51dd159b 100644
--- a/packages/rocketchat-livechat/package.js
+++ b/packages/rocketchat-livechat/package.js
@@ -27,6 +27,7 @@ Package.onUse(function(api) {
 	api.use('rocketchat:authorization');
 	api.use('rocketchat:logger');
 	api.use('rocketchat:api');
+	api.use('rocketchat:streamer');
 	api.use('konecty:user-presence');
 	api.use('rocketchat:ui');
 	api.use('kadira:flow-router', 'client');
@@ -50,9 +51,7 @@ Package.onUse(function(api) {
 	api.addFiles('client/ui.js', 'client');
 	api.addFiles('client/route.js', 'client');
 
-	// add stylesheets to theme compiler
-	api.addAssets('client/stylesheets/livechat.less', 'server');
-	api.addFiles('client/stylesheets/load.js', 'server');
+	api.addFiles('client/stylesheets/livechat.less', 'client');
 
 	// collections
 	api.addFiles('client/collections/AgentUsers.js', 'client');
@@ -91,6 +90,8 @@ Package.onUse(function(api) {
 	api.addFiles('client/views/app/livechatQueue.js', 'client');
 	api.addFiles('client/views/app/livechatTriggers.html', 'client');
 	api.addFiles('client/views/app/livechatTriggers.js', 'client');
+	api.addFiles('client/views/app/livechatTriggersForm.html', 'client');
+	api.addFiles('client/views/app/livechatTriggersForm.js', 'client');
 	api.addFiles('client/views/app/livechatUsers.html', 'client');
 	api.addFiles('client/views/app/livechatUsers.js', 'client');
 	api.addFiles('client/views/app/livechatOfficeHours.html', 'client');
@@ -132,6 +133,7 @@ Package.onUse(function(api) {
 	api.addFiles('server/methods/closeByVisitor.js', 'server');
 	api.addFiles('server/methods/closeRoom.js', 'server');
 	api.addFiles('server/methods/getCustomFields.js', 'server');
+	api.addFiles('server/methods/getAgentData.js', 'server');
 	api.addFiles('server/methods/getInitialData.js', 'server');
 	api.addFiles('server/methods/loginByToken.js', 'server');
 	api.addFiles('server/methods/pageVisited.js', 'server');
@@ -190,6 +192,7 @@ Package.onUse(function(api) {
 	api.addFiles('server/publications/livechatManagers.js', 'server');
 	api.addFiles('server/publications/livechatRooms.js', 'server');
 	api.addFiles('server/publications/livechatQueue.js', 'server');
+	api.addFiles('server/publications/livechatTriggers.js', 'server');
 	api.addFiles('server/publications/visitorHistory.js', 'server');
 	api.addFiles('server/publications/visitorInfo.js', 'server');
 	api.addFiles('server/publications/visitorPageVisited.js', 'server');
diff --git a/packages/rocketchat-livechat/roomType.js b/packages/rocketchat-livechat/roomType.js
index fe1860cea324112f3f025d31f7398c4b324010fa..03e20cdef3764459908eaa09f0dd1ae0f20ad5f2 100644
--- a/packages/rocketchat-livechat/roomType.js
+++ b/packages/rocketchat-livechat/roomType.js
@@ -1,4 +1,4 @@
-/* globals openRoom */
+/* globals openRoom, LivechatInquiry */
 
 RocketChat.roomTypes.add('l', 5, {
 	template: 'livechat',
@@ -38,6 +38,22 @@ RocketChat.roomTypes.add('l', 5, {
 		return room && room.open === true;
 	},
 
+	getUserStatus(roomId) {
+		let guestName;
+		const room = Session.get('roomData' + roomId);
+
+		if (room) {
+			guestName = room.v && room.v.username;
+		} else {
+			const inquiry = LivechatInquiry.findOne({ rid: roomId });
+			guestName = inquiry && inquiry.v && inquiry.v.username;
+		}
+
+		if (guestName) {
+			return Session.get('user_' + guestName + '_status');
+		}
+	},
+
 	notSubscribedTpl: {
 		template: 'livechatNotSubscribed'
 	}
diff --git a/packages/rocketchat-livechat/server/lib/Livechat.js b/packages/rocketchat-livechat/server/lib/Livechat.js
index 34af055d948ad4af6fab95bae860c4ec348cc89d..2ba268ac2de26073ffd83086caa0bb79c266bbdb 100644
--- a/packages/rocketchat-livechat/server/lib/Livechat.js
+++ b/packages/rocketchat-livechat/server/lib/Livechat.js
@@ -41,11 +41,15 @@ RocketChat.Livechat = {
 		}
 
 		if (room == null) {
-			// if no department selected verify if there is at least one active and choose one randomly
+			// if no department selected verify if there is at least one active and pick the first
 			if (!guest.department) {
 				var departments = RocketChat.models.LivechatDepartment.findEnabledWithAgents();
 				if (departments.count() > 0) {
-					guest.department = departments.fetch()[0]._id;
+					departments.forEach((dept) => {
+						if (!guest.department && dept.showOnRegistration) {
+							guest.department = dept._id;
+						}
+					});
 				}
 			}
 
@@ -68,7 +72,9 @@ RocketChat.Livechat = {
 		if (guest.name) {
 			message.alias = guest.name;
 		}
-		return _.extend(RocketChat.sendMessage(guest, message, room), { newRoom: newRoom });
+
+		// return messages;
+		return _.extend(RocketChat.sendMessage(guest, message, room), { newRoom: newRoom, showConnecting: this.showConnecting() });
 	},
 	registerGuest({ token, name, email, department, phone, loginToken, username } = {}) {
 		check(token, String);
@@ -100,16 +106,11 @@ RocketChat.Livechat = {
 
 			var existingUser = null;
 
-			if (s.trim(email) !== '' && (existingUser = RocketChat.models.Users.findOneByEmailAddress(email))) {
-				if (existingUser.type !== 'visitor') {
-					throw new Meteor.Error('error-invalid-user', 'This email belongs to a registered user.');
-				}
-
-				updateUser.$addToSet = {
-					globalRoles: 'livechat-guest'
-				};
-
+			if (s.trim(email) !== '' && (existingUser = RocketChat.models.Users.findOneGuestByEmailAddress(email))) {
 				if (loginToken) {
+					if (!updateUser.$addToSet) {
+						updateUser.$addToSet = {};
+					}
 					updateUser.$addToSet['services.resume.loginTokens'] = loginToken;
 				}
 
@@ -121,7 +122,8 @@ RocketChat.Livechat = {
 					username: username,
 					globalRoles: ['livechat-guest'],
 					department: department,
-					type: 'visitor'
+					type: 'visitor',
+					joinDefaultChannels: false
 				};
 
 				if (this.connection) {
@@ -149,7 +151,7 @@ RocketChat.Livechat = {
 		}
 
 		if (email && email.trim() !== '') {
-			updateUser.$set.emails = [
+			updateUser.$set.visitorEmails = [
 				{ address: email }
 			];
 		}
@@ -171,7 +173,7 @@ RocketChat.Livechat = {
 		if (phone) {
 			updateData.phone = phone;
 		}
-		const ret = RocketChat.models.Users.saveUserById(_id, updateData);
+		const ret = RocketChat.models.Users.saveGuestById(_id, updateData);
 
 		Meteor.defer(() => {
 			RocketChat.callbacks.run('livechat.saveGuest', updateData);
@@ -200,7 +202,6 @@ RocketChat.Livechat = {
 		RocketChat.sendMessage(user, message, room);
 
 		RocketChat.models.Subscriptions.hideByRoomIdAndUserId(room._id, user._id);
-
 		RocketChat.models.Messages.createCommandWithRoomIdAndUser('promptTranscript', room._id, user);
 
 		Meteor.defer(() => {
@@ -285,10 +286,12 @@ RocketChat.Livechat = {
 			agent = RocketChat.Livechat.getNextAgent(transferData.departmentId);
 		}
 
-		if (agent && agent.agentId !== room.servedBy._id) {
-			room.usernames = _.without(room.usernames, room.servedBy.username).concat(agent.username);
+		const servedBy = room.servedBy;
+
+		if (agent && agent.agentId !== servedBy._id) {
+			room.usernames = _.without(room.usernames, servedBy.username).concat(agent.username);
 
-			RocketChat.models.Rooms.changeAgentByRoomId(room._id, room.usernames, agent);
+			RocketChat.models.Rooms.changeAgentByRoomId(room._id, agent);
 
 			let subscriptionData = {
 				rid: room._id,
@@ -306,13 +309,18 @@ RocketChat.Livechat = {
 				mobilePushNotifications: 'all',
 				emailNotifications: 'all'
 			};
-			RocketChat.models.Subscriptions.removeByRoomIdAndUserId(room._id, room.servedBy._id);
+			RocketChat.models.Subscriptions.removeByRoomIdAndUserId(room._id, servedBy._id);
 
 			RocketChat.models.Subscriptions.insert(subscriptionData);
 
-			RocketChat.models.Messages.createUserLeaveWithRoomIdAndUser(room._id, { _id: room.servedBy._id, username: room.servedBy.username });
+			RocketChat.models.Messages.createUserLeaveWithRoomIdAndUser(room._id, { _id: servedBy._id, username: servedBy.username });
 			RocketChat.models.Messages.createUserJoinWithRoomIdAndUser(room._id, { _id: agent.agentId, username: agent.username });
 
+			RocketChat.Livechat.stream.emit(room._id, {
+				type: 'agentData',
+				data: RocketChat.models.Users.getAgentInfo(agent.agentId)
+			});
+
 			return true;
 		}
 
@@ -381,8 +389,8 @@ RocketChat.Livechat = {
 			postData.crmData = room.crmData;
 		}
 
-		if (visitor.emails && visitor.emails.length > 0) {
-			postData.visitor.email = visitor.emails[0].address;
+		if (visitor.visitorEmails && visitor.visitorEmails.length > 0) {
+			postData.visitor.email = visitor.visitorEmails[0].address;
 		}
 		if (visitor.phone && visitor.phone.length > 0) {
 			postData.visitor.phone = visitor.phone[0].phoneNumber;
@@ -465,7 +473,8 @@ RocketChat.Livechat = {
 		check(departmentData, {
 			enabled: Boolean,
 			name: String,
-			description: Match.Optional(String)
+			description: Match.Optional(String),
+			showOnRegistration: Boolean
 		});
 
 		check(departmentAgents, [
@@ -482,7 +491,7 @@ RocketChat.Livechat = {
 			}
 		}
 
-		return RocketChat.models.LivechatDepartment.createOrUpdateDepartment(_id, departmentData.enabled, departmentData.name, departmentData.description, departmentAgents);
+		return RocketChat.models.LivechatDepartment.createOrUpdateDepartment(_id, departmentData, departmentAgents);
 	},
 
 	removeDepartment(_id) {
@@ -495,9 +504,20 @@ RocketChat.Livechat = {
 		}
 
 		return RocketChat.models.LivechatDepartment.removeById(_id);
+	},
+
+	showConnecting() {
+		if (RocketChat.settings.get('Livechat_Routing_Method') === 'Guest_Pool') {
+			return RocketChat.settings.get('Livechat_open_inquiery_show_connecting');
+		} else {
+			return false;
+		}
 	}
 };
 
+RocketChat.Livechat.stream = new Meteor.Streamer('livechat-room');
+RocketChat.Livechat.stream.allowRead('logged');
+
 RocketChat.settings.get('Livechat_history_monitor_type', (key, value) => {
 	RocketChat.Livechat.historyMonitorType = value;
 });
diff --git a/packages/rocketchat-livechat/server/lib/QueueMethods.js b/packages/rocketchat-livechat/server/lib/QueueMethods.js
index 85013f3a4feec3ce5d793c527f7311341043a6cc..7921aaa83073823185aa3c8966ee4bb477e0704d 100644
--- a/packages/rocketchat-livechat/server/lib/QueueMethods.js
+++ b/packages/rocketchat-livechat/server/lib/QueueMethods.js
@@ -18,11 +18,12 @@ RocketChat.QueueMethods = {
 			lm: new Date(),
 			code: roomCode,
 			label: guest.name || guest.username,
-			usernames: [agent.username, guest.username],
+			// usernames: [agent.username, guest.username],
 			t: 'l',
 			ts: new Date(),
 			v: {
 				_id: guest._id,
+				username: guest.username,
 				token: message.token
 			},
 			servedBy: {
@@ -53,6 +54,11 @@ RocketChat.QueueMethods = {
 		RocketChat.models.Rooms.insert(room);
 		RocketChat.models.Subscriptions.insert(subscriptionData);
 
+		RocketChat.Livechat.stream.emit(room._id, {
+			type: 'agentData',
+			data: RocketChat.models.Users.getAgentInfo(agent.agentId)
+		});
+
 		return room;
 	},
 	/* Guest Pool Queuing Method:
@@ -96,6 +102,11 @@ RocketChat.QueueMethods = {
 			department: guest.department,
 			agents: agentIds,
 			status: 'open',
+			v: {
+				_id: guest._id,
+				username: guest.username,
+				token: message.token
+			},
 			t: 'l'
 		};
 		const room = _.extend({
@@ -104,11 +115,12 @@ RocketChat.QueueMethods = {
 			lm: new Date(),
 			code: roomCode,
 			label: guest.name || guest.username,
-			usernames: [guest.username],
+			// usernames: [guest.username],
 			t: 'l',
 			ts: new Date(),
 			v: {
 				_id: guest._id,
+				username: guest.username,
 				token: message.token
 			},
 			cl: false,
diff --git a/packages/rocketchat-livechat/server/methods/getAgentData.js b/packages/rocketchat-livechat/server/methods/getAgentData.js
new file mode 100644
index 0000000000000000000000000000000000000000..98f8e2808ae88de59a98932a0797264eb15799bc
--- /dev/null
+++ b/packages/rocketchat-livechat/server/methods/getAgentData.js
@@ -0,0 +1,19 @@
+Meteor.methods({
+	'livechat:getAgentData'(roomId) {
+		check(roomId, String);
+
+		const room = RocketChat.models.Rooms.findOneById(roomId);
+		const user = Meteor.user();
+
+		// allow to only user to send transcripts from their own chats
+		if (!room || room.t !== 'l' || !room.v || !user.profile || room.v.token !== user.profile.token) {
+			throw new Meteor.Error('error-invalid-room', 'Invalid room');
+		}
+
+		if (!room.servedBy) {
+			return;
+		}
+
+		return RocketChat.models.Users.getAgentInfo(room.servedBy._id);
+	}
+});
diff --git a/packages/rocketchat-livechat/server/methods/getInitialData.js b/packages/rocketchat-livechat/server/methods/getInitialData.js
index 5cb96801983897180430e1273de6006a0d14b85f..41d5f5505116666a162f991c2032db2ad10a568f 100644
--- a/packages/rocketchat-livechat/server/methods/getInitialData.js
+++ b/packages/rocketchat-livechat/server/methods/getInitialData.js
@@ -24,7 +24,8 @@ Meteor.methods({
 				cl: 1,
 				u: 1,
 				usernames: 1,
-				v: 1
+				v: 1,
+				servedBy: 1
 			}
 		}).fetch();
 
@@ -49,9 +50,10 @@ Meteor.methods({
 		info.transcript = initSettings.Livechat_enable_transcript;
 		info.transcriptMessage = initSettings.Livechat_transcript_message;
 
+		info.agentData = room && room[0] && room[0].servedBy && RocketChat.models.Users.getAgentInfo(room[0].servedBy._id);
 
-		RocketChat.models.LivechatTrigger.find().forEach((trigger) => {
-			info.triggers.push(trigger);
+		RocketChat.models.LivechatTrigger.findEnabled().forEach((trigger) => {
+			info.triggers.push(_.pick(trigger, '_id', 'actions', 'conditions'));
 		});
 
 		RocketChat.models.LivechatDepartment.findEnabledWithAgents().forEach((department) => {
diff --git a/packages/rocketchat-livechat/server/methods/removeTrigger.js b/packages/rocketchat-livechat/server/methods/removeTrigger.js
index e9433e008905f46d60a6fc138671eab40d91db31..426e0be921b5b4d086c8eeb4ce41559bb8571321 100644
--- a/packages/rocketchat-livechat/server/methods/removeTrigger.js
+++ b/packages/rocketchat-livechat/server/methods/removeTrigger.js
@@ -1,9 +1,11 @@
 Meteor.methods({
-	'livechat:removeTrigger'(/*trigger*/) {
+	'livechat:removeTrigger'(triggerId) {
 		if (!Meteor.userId() || !RocketChat.authz.hasPermission(Meteor.userId(), 'view-livechat-manager')) {
 			throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'livechat:removeTrigger' });
 		}
 
-		return RocketChat.models.LivechatTrigger.removeAll();
+		check(triggerId, String);
+
+		return RocketChat.models.LivechatTrigger.removeById(triggerId);
 	}
 });
diff --git a/packages/rocketchat-livechat/server/methods/saveTrigger.js b/packages/rocketchat-livechat/server/methods/saveTrigger.js
index 396d48ce5ba8bdf4e86af5d578ddd2ccf394770b..d3bf4f03ace3c63c4bcdfac4d4bb789ddf9d0b92 100644
--- a/packages/rocketchat-livechat/server/methods/saveTrigger.js
+++ b/packages/rocketchat-livechat/server/methods/saveTrigger.js
@@ -4,6 +4,19 @@ Meteor.methods({
 			throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'livechat:saveTrigger' });
 		}
 
-		return RocketChat.models.LivechatTrigger.save(trigger);
+		check(trigger, {
+			_id: Match.Maybe(String),
+			name: String,
+			description: String,
+			enabled: Boolean,
+			conditions: Array,
+			actions: Array
+		});
+
+		if (trigger._id) {
+			return RocketChat.models.LivechatTrigger.updateById(trigger._id, trigger);
+		} else {
+			return RocketChat.models.LivechatTrigger.insert(trigger);
+		}
 	}
 });
diff --git a/packages/rocketchat-livechat/server/methods/sendOfflineMessage.js b/packages/rocketchat-livechat/server/methods/sendOfflineMessage.js
index bba6563f146e3d15e966ea59beb40d3f03082ae2..9dedcaec19a850736d790b1980b8162aa4ace15f 100644
--- a/packages/rocketchat-livechat/server/methods/sendOfflineMessage.js
+++ b/packages/rocketchat-livechat/server/methods/sendOfflineMessage.js
@@ -1,4 +1,6 @@
 /* globals DDPRateLimiter */
+const dns = Npm.require('dns');
+
 Meteor.methods({
 	'livechat:sendOfflineMessage'(data) {
 		check(data, {
@@ -7,6 +9,10 @@ Meteor.methods({
 			message: String
 		});
 
+		if (!RocketChat.settings.get('Livechat_display_offline_form')) {
+			return false;
+		}
+
 		const header = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Header') || '');
 		const footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || '');
 
@@ -26,6 +32,16 @@ Meteor.methods({
 			fromEmail = RocketChat.settings.get('From_Email');
 		}
 
+		if (RocketChat.settings.get('Livechat_validate_offline_email')) {
+			const emailDomain = data.email.substr(data.email.lastIndexOf('@') + 1);
+
+			try {
+				Meteor.wrapAsync(dns.resolveMx)(emailDomain);
+			} catch (e) {
+				throw new Meteor.Error('error-invalid-email-address', 'Invalid email address', { method: 'livechat:sendOfflineMessage' });
+			}
+		}
+
 		Meteor.defer(() => {
 			Email.send({
 				to: RocketChat.settings.get('Livechat_offline_email'),
diff --git a/packages/rocketchat-livechat/server/methods/startVideoCall.js b/packages/rocketchat-livechat/server/methods/startVideoCall.js
index 1a7194ea4126e978696a787630a448d133305316..a499cd75a497181eba897bff11dce020f2620c3c 100644
--- a/packages/rocketchat-livechat/server/methods/startVideoCall.js
+++ b/packages/rocketchat-livechat/server/methods/startVideoCall.js
@@ -27,7 +27,7 @@ Meteor.methods({
 		return {
 			roomId: room._id,
 			domain: RocketChat.settings.get('Jitsi_Domain'),
-			jitsiRoom: 'RocketChat' + CryptoJS.MD5(RocketChat.settings.get('uniqueID') + roomId).toString()
+			jitsiRoom: RocketChat.settings.get('Jitsi_URL_Room_Prefix') + CryptoJS.MD5(RocketChat.settings.get('uniqueID') + roomId).toString()
 		};
 	}
 });
diff --git a/packages/rocketchat-livechat/server/methods/takeInquiry.js b/packages/rocketchat-livechat/server/methods/takeInquiry.js
index b431c5721ea6755aa88ce35ca685eab16ffd6202..c89c9c5a00eb84e31167b0b85cc435f6780565a0 100644
--- a/packages/rocketchat-livechat/server/methods/takeInquiry.js
+++ b/packages/rocketchat-livechat/server/methods/takeInquiry.js
@@ -38,11 +38,9 @@ Meteor.methods({
 
 		// update room
 		const room = RocketChat.models.Rooms.findOneById(inquiry.rid);
-		const usernames = room.usernames.concat(agent.username);
 
-		RocketChat.models.Rooms.changeAgentByRoomId(inquiry.rid, usernames, agent);
+		RocketChat.models.Rooms.changeAgentByRoomId(inquiry.rid, agent);
 
-		room.usernames = usernames;
 		room.servedBy = {
 			_id: agent.agentId,
 			username: agent.username
@@ -51,6 +49,16 @@ Meteor.methods({
 		// mark inquiry as taken
 		RocketChat.models.LivechatInquiry.takeInquiry(inquiry._id);
 
+		// remove sending message from guest widget
+		// dont check if setting is true, because if settingwas switched off inbetween  guest entered pool,
+		// and inquiry being taken, message would not be switched off.
+		RocketChat.models.Messages.createCommandWithRoomIdAndUser('connected', room._id, user);
+
+		RocketChat.Livechat.stream.emit(room._id, {
+			type: 'agentData',
+			data: RocketChat.models.Users.getAgentInfo(agent.agentId)
+		});
+
 		// return room corresponding to inquiry (for redirecting agent to the room route)
 		return room;
 	}
diff --git a/packages/rocketchat-livechat/server/methods/transfer.js b/packages/rocketchat-livechat/server/methods/transfer.js
index b1efe6f0e6abe9d47a74cad9acb080fc3d4cf3d8..7502dc661b8a54397df10d5750e7d3c0c514d4e2 100644
--- a/packages/rocketchat-livechat/server/methods/transfer.js
+++ b/packages/rocketchat-livechat/server/methods/transfer.js
@@ -8,7 +8,7 @@ Meteor.methods({
 		check(transferData, {
 			roomId: String,
 			userId: Match.Optional(String),
-			deparmentId: Match.Optional(String)
+			departmentId: Match.Optional(String)
 		});
 
 		const room = RocketChat.models.Rooms.findOneById(transferData.roomId);
diff --git a/packages/rocketchat-livechat/server/models/LivechatDepartment.js b/packages/rocketchat-livechat/server/models/LivechatDepartment.js
index 08627f550ef5d818944bde7d47c3d9d2da8874d4..a1f9285f0ffc642d2b6a8f450fef96531204a6ba 100644
--- a/packages/rocketchat-livechat/server/models/LivechatDepartment.js
+++ b/packages/rocketchat-livechat/server/models/LivechatDepartment.js
@@ -4,6 +4,11 @@
 class LivechatDepartment extends RocketChat.models._Base {
 	constructor() {
 		super('livechat_department');
+
+		this.tryEnsureIndex({
+			numAgents: 1,
+			enabled: 1
+		});
 	}
 
 	// FIND
@@ -19,18 +24,17 @@ class LivechatDepartment extends RocketChat.models._Base {
 		return this.find(query, options);
 	}
 
-	createOrUpdateDepartment(_id, enabled, name, description, agents, extraData) {
+	createOrUpdateDepartment(_id, { enabled, name, description, showOnRegistration }, agents) {
 		agents = [].concat(agents);
 
 		var record = {
 			enabled: enabled,
 			name: name,
 			description: description,
-			numAgents: agents.length
+			numAgents: agents.length,
+			showOnRegistration: showOnRegistration
 		};
 
-		_.extend(record, extraData);
-
 		if (_id) {
 			this.update({ _id: _id }, { $set: record });
 		} else {
diff --git a/packages/rocketchat-livechat/server/models/LivechatDepartmentAgents.js b/packages/rocketchat-livechat/server/models/LivechatDepartmentAgents.js
index 681a6c73eecb8d3921995c3885d6b64f23c001da..ef725815b9ca31f847c89a4ba8bc07e34a82f063 100644
--- a/packages/rocketchat-livechat/server/models/LivechatDepartmentAgents.js
+++ b/packages/rocketchat-livechat/server/models/LivechatDepartmentAgents.js
@@ -74,7 +74,7 @@ class LivechatDepartmentAgents extends RocketChat.models._Base {
 		var agents = this.findByDepartmentId(departmentId).fetch();
 
 		if (agents.length === 0) {
-			return;
+			return [];
 		}
 
 		var onlineUsers = RocketChat.models.Users.findOnlineUserFromList(_.pluck(agents, 'username'));
@@ -93,7 +93,7 @@ class LivechatDepartmentAgents extends RocketChat.models._Base {
 		if (depAgents) {
 			return depAgents;
 		} else {
-			return null;
+			return [];
 		}
 	}
 
diff --git a/packages/rocketchat-livechat/server/models/LivechatTrigger.js b/packages/rocketchat-livechat/server/models/LivechatTrigger.js
index c7145759c0da8b85ef63370e4c6ed4b35b788c33..0231fb56b5d386941ee61621f869e742f74c61a0 100644
--- a/packages/rocketchat-livechat/server/models/LivechatTrigger.js
+++ b/packages/rocketchat-livechat/server/models/LivechatTrigger.js
@@ -6,19 +6,24 @@ class LivechatTrigger extends RocketChat.models._Base {
 		super('livechat_trigger');
 	}
 
-	// FIND
-	save(data) {
-		const trigger = this.findOne();
-
-		if (trigger) {
-			return this.update({ _id: trigger._id }, { $set: data });
-		} else {
-			return this.insert(data);
-		}
+	updateById(_id, data) {
+		return this.update({ _id }, { $set: data });
 	}
 
 	removeAll() {
-		this.remove({});
+		return this.remove({});
+	}
+
+	findById(_id) {
+		return this.find({ _id });
+	}
+
+	removeById(_id) {
+		return this.remove({ _id });
+	}
+
+	findEnabled() {
+		return this.find({ enabled: true });
 	}
 }
 
diff --git a/packages/rocketchat-livechat/server/models/Rooms.js b/packages/rocketchat-livechat/server/models/Rooms.js
index f62f9e6faadd56d420aa161c7d6ce7f82684b324..7d5aae50279ac373ce3e4be02a58ec78c8cebc15 100644
--- a/packages/rocketchat-livechat/server/models/Rooms.js
+++ b/packages/rocketchat-livechat/server/models/Rooms.js
@@ -44,15 +44,19 @@ RocketChat.models.Rooms.findLivechatByCode = function(code, fields) {
 
 	let options = {};
 
+	if (fields) {
+		options.fields = fields;
+	}
+
+	if (this.useCache) {
+		return this.cache.findByIndex('t,code', ['l', code], options);
+	}
+
 	const query = {
 		t: 'l',
 		code: code
 	};
 
-	if (fields) {
-		options.fields = fields;
-	}
-
 	return this.find(query, options);
 };
 
@@ -162,13 +166,12 @@ RocketChat.models.Rooms.findOpenByAgent = function(userId) {
 	return this.find(query);
 };
 
-RocketChat.models.Rooms.changeAgentByRoomId = function(roomId, newUsernames, newAgent) {
+RocketChat.models.Rooms.changeAgentByRoomId = function(roomId, newAgent) {
 	const query = {
 		_id: roomId
 	};
 	const update = {
 		$set: {
-			usernames: newUsernames,
 			servedBy: {
 				_id: newAgent.agentId,
 				username: newAgent.username
diff --git a/packages/rocketchat-livechat/server/models/Users.js b/packages/rocketchat-livechat/server/models/Users.js
index 1c800dac8cc9ef2e37a04641b0b71ff16aa72054..6941e0109060c5b483e32e1910164af79e70099f 100644
--- a/packages/rocketchat-livechat/server/models/Users.js
+++ b/packages/rocketchat-livechat/server/models/Users.js
@@ -19,7 +19,7 @@ RocketChat.models.Users.setOperator = function(_id, operator) {
  */
 RocketChat.models.Users.findOnlineAgents = function() {
 	var query = {
-		statusConnection: {
+		status: {
 			$exists: true,
 			$ne: 'offline'
 		},
@@ -49,7 +49,7 @@ RocketChat.models.Users.findAgents = function() {
  */
 RocketChat.models.Users.findOnlineUserFromList = function(userList) {
 	var query = {
-		statusConnection: {
+		status: {
 			$exists: true,
 			$ne: 'offline'
 		},
@@ -69,7 +69,7 @@ RocketChat.models.Users.findOnlineUserFromList = function(userList) {
  */
 RocketChat.models.Users.getNextAgent = function() {
 	var query = {
-		statusConnection: {
+		status: {
 			$exists: true,
 			$ne: 'offline'
 		},
@@ -214,3 +214,77 @@ RocketChat.models.Users.getNextVisitorUsername = function() {
 
 	return 'guest-' + (livechatCount.value.value + 1);
 };
+
+RocketChat.models.Users.saveGuestById = function(_id, data) {
+	const setData = {};
+	const unsetData = {};
+
+	if (data.name) {
+		if (!_.isEmpty(s.trim(data.name))) {
+			setData.name = s.trim(data.name);
+		} else {
+			unsetData.name = 1;
+		}
+	}
+
+	if (data.email) {
+		if (!_.isEmpty(s.trim(data.email))) {
+			setData.visitorEmails = [
+				{ address: s.trim(data.email) }
+			];
+		} else {
+			unsetData.visitorEmails = 1;
+		}
+	}
+
+	if (data.phone) {
+		if (!_.isEmpty(s.trim(data.phone))) {
+			setData.phone = [
+				{ phoneNumber: s.trim(data.phone) }
+			];
+		} else {
+			unsetData.phone = 1;
+		}
+	}
+
+	const update = {};
+
+	if (!_.isEmpty(setData)) {
+		update.$set = setData;
+	}
+
+	if (!_.isEmpty(unsetData)) {
+		update.$unset = unsetData;
+	}
+
+	if (_.isEmpty(update)) {
+		return true;
+	}
+
+	return this.update({ _id }, update);
+};
+
+RocketChat.models.Users.findOneGuestByEmailAddress = function(emailAddress) {
+	const query = {
+		'visitorEmails.address': new RegExp('^' + s.escapeRegExp(emailAddress) + '$', 'i')
+	};
+
+	return this.findOne(query);
+};
+
+RocketChat.models.Users.getAgentInfo = function(agentId) {
+	const query = {
+		_id: agentId
+	};
+
+	const options = {
+		fields: {
+			name: 1,
+			username: 1,
+			emails: 1,
+			customFields: 1
+		}
+	};
+
+	return this.findOne(query, options);
+};
diff --git a/packages/rocketchat-livechat/server/models/indexes.js b/packages/rocketchat-livechat/server/models/indexes.js
index de862be54c18bbbe52d781f128f3d2053d059fef..6dbd49633926c8014649317aad617b602ad8fd4a 100644
--- a/packages/rocketchat-livechat/server/models/indexes.js
+++ b/packages/rocketchat-livechat/server/models/indexes.js
@@ -1,4 +1,5 @@
 Meteor.startup(function() {
 	RocketChat.models.Rooms.tryEnsureIndex({ code: 1 });
 	RocketChat.models.Rooms.tryEnsureIndex({ open: 1 }, { sparse: 1 });
+	RocketChat.models.Users.tryEnsureIndex({ 'visitorEmails.address': 1 });
 });
diff --git a/packages/rocketchat-livechat/server/publications/livechatInquiries.js b/packages/rocketchat-livechat/server/publications/livechatInquiries.js
index db2b43bb2db02367c296b6a624dd22f89c67b600..e32adc9c8d96879af1dfa0774f7824ed5c8ccccd 100644
--- a/packages/rocketchat-livechat/server/publications/livechatInquiries.js
+++ b/packages/rocketchat-livechat/server/publications/livechatInquiries.js
@@ -7,6 +7,10 @@ Meteor.publish('livechat:inquiry', function() {
 		return this.error(new Meteor.Error('error-not-authorized', 'Not authorized', { publish: 'livechat:inquiry' }));
 	}
 
+	const query = {
+		agents: this.userId,
+		status: 'open'
+	};
 
-	return RocketChat.models.LivechatInquiry.find();
+	return RocketChat.models.LivechatInquiry.find(query);
 });
diff --git a/packages/rocketchat-livechat/server/publications/livechatRooms.js b/packages/rocketchat-livechat/server/publications/livechatRooms.js
index d4f498a49df135d9054ed1b9133f2fd391ed3232..b05e442fa9c740be7bb3633cac589d5f782d019e 100644
--- a/packages/rocketchat-livechat/server/publications/livechatRooms.js
+++ b/packages/rocketchat-livechat/server/publications/livechatRooms.js
@@ -11,8 +11,8 @@ Meteor.publish('livechat:rooms', function(filter = {}, offset = 0, limit = 20) {
 		name: Match.Maybe(String), // room name to filter
 		agent: Match.Maybe(String), // agent _id who is serving
 		status: Match.Maybe(String), // either 'opened' or 'closed'
-		from: Match.Maybe(String),
-		to: Match.Maybe(String)
+		from: Match.Maybe(Date),
+		to: Match.Maybe(Date)
 	});
 
 	let query = {};
@@ -29,12 +29,38 @@ Meteor.publish('livechat:rooms', function(filter = {}, offset = 0, limit = 20) {
 			query.open = { $exists: false };
 		}
 	}
-	if (filter.from && filter.to) {
-		var StartDate = new Date(filter.from);
-		var ToDate = new Date(filter.to);
-		ToDate.setDate(ToDate.getDate() + 1);
-		query['ts'] = { $gt: StartDate, $lt: ToDate };
+	if (filter.from) {
+		query.ts = {
+			$gte: filter.from
+		};
 	}
+	if (filter.to) {
+		filter.to.setDate(filter.to.getDate() + 1);
+		filter.to.setSeconds(filter.to.getSeconds() - 1);
 
-	return RocketChat.models.Rooms.findLivechat(query, offset, limit);
+		if (!query.ts) {
+			query.ts = {};
+		}
+		query.ts.$lte = filter.to;
+	}
+
+	let self = this;
+
+	let handle = RocketChat.models.Rooms.findLivechat(query, offset, limit).observeChanges({
+		added(id, fields) {
+			self.added('livechatRoom', id, fields);
+		},
+		changed(id, fields) {
+			self.changed('livechatRoom', id, fields);
+		},
+		removed(id) {
+			self.removed('livechatRoom', id);
+		}
+	});
+
+	this.ready();
+
+	this.onStop(() => {
+		handle.stop();
+	});
 });
diff --git a/packages/rocketchat-livechat/server/publications/livechatTriggers.js b/packages/rocketchat-livechat/server/publications/livechatTriggers.js
new file mode 100644
index 0000000000000000000000000000000000000000..3baeb011f402bb69c8a37a3f1dbba11b8828039b
--- /dev/null
+++ b/packages/rocketchat-livechat/server/publications/livechatTriggers.js
@@ -0,0 +1,15 @@
+Meteor.publish('livechat:triggers', function(_id) {
+	if (!this.userId) {
+		return this.error(new Meteor.Error('error-not-authorized', 'Not authorized', { publish: 'livechat:triggers' }));
+	}
+
+	if (!RocketChat.authz.hasPermission(this.userId, 'view-livechat-manager')) {
+		return this.error(new Meteor.Error('error-not-authorized', 'Not authorized', { publish: 'livechat:triggers' }));
+	}
+
+	if (_id !== undefined) {
+		return RocketChat.models.LivechatTrigger.findById(_id);
+	} else {
+		return RocketChat.models.LivechatTrigger.find();
+	}
+});
diff --git a/packages/rocketchat-livechat/server/publications/visitorHistory.js b/packages/rocketchat-livechat/server/publications/visitorHistory.js
index 00bddde40c6fe1231c40744c836802e06d124bbf..2b26b101ad14dd61a9df9dc49d640368803cf677 100644
--- a/packages/rocketchat-livechat/server/publications/visitorHistory.js
+++ b/packages/rocketchat-livechat/server/publications/visitorHistory.js
@@ -16,6 +16,7 @@ Meteor.publish('livechat:visitorHistory', function({ rid: roomId }) {
 	}
 
 	if (room && room.v && room.v._id) {
+		// CACHE: can we stop using publications here?
 		return RocketChat.models.Rooms.findByVisitorId(room.v._id);
 	} else {
 		return this.ready();
diff --git a/packages/rocketchat-livechat/server/startup.js b/packages/rocketchat-livechat/server/startup.js
index fe66acc87413432f03054d2b6eb982b38038dec2..dd06a08ef01e4374ee747d2e8b567331be5b4a9b 100644
--- a/packages/rocketchat-livechat/server/startup.js
+++ b/packages/rocketchat-livechat/server/startup.js
@@ -1,26 +1,16 @@
 Meteor.startup(() => {
-	RocketChat.roomTypes.setPublish('l', (code) => {
-		return RocketChat.models.Rooms.findLivechatByCode(code, {
-			name: 1,
-			t: 1,
-			cl: 1,
-			u: 1,
-			label: 1,
-			usernames: 1,
-			v: 1,
-			livechatData: 1,
-			topic: 1,
-			tags: 1,
-			sms: 1,
-			code: 1,
-			open: 1
-		});
+	RocketChat.roomTypes.setRoomFind('l', (code) => {
+		return RocketChat.models.Rooms.findLivechatByCode(code).fetch();
 	});
 
 	RocketChat.authz.addRoomAccessValidator(function(room, user) {
 		return room.t === 'l' && RocketChat.authz.hasPermission(user._id, 'view-livechat-rooms');
 	});
 
+	RocketChat.authz.addRoomAccessValidator(function(room, user) {
+		return room.t === 'l' && room.v && room.v._id === user._id;
+	});
+
 	RocketChat.callbacks.add('beforeLeaveRoom', function(user, room) {
 		if (room.t !== 'l') {
 			return user;
diff --git a/packages/rocketchat-livechat/server/unclosedLivechats.js b/packages/rocketchat-livechat/server/unclosedLivechats.js
index 3dd99efe20321f79619140678132d01d95542210..f5c64225ce8e175c437a8b91132650e977ac1c72 100644
--- a/packages/rocketchat-livechat/server/unclosedLivechats.js
+++ b/packages/rocketchat-livechat/server/unclosedLivechats.js
@@ -76,12 +76,12 @@ RocketChat.settings.get('Livechat_agent_leave_action', function(key, value) {
 	}
 });
 
-UserPresenceMonitor.onSetUserStatus((user, status, statusConnection) => {
+UserPresenceMonitor.onSetUserStatus((user, status/*, statusConnection*/) => {
 	if (!monitorAgents) {
 		return;
 	}
 	if (onlineAgents.exists(user._id)) {
-		if (statusConnection === 'offline' || user.statusLivechat === 'not-available') {
+		if (status === 'offline' || user.statusLivechat === 'not-available') {
 			onlineAgents.remove(user._id, () => {
 				runAgentLeaveAction(user._id);
 			});
diff --git a/packages/rocketchat-logger/client/views/viewLogs.coffee b/packages/rocketchat-logger/client/views/viewLogs.coffee
index cb86a98cce9895b638da0c1138230a6687314e65..29a96bf9e15a05163a64fef95a1dcc06429aa1e3 100644
--- a/packages/rocketchat-logger/client/views/viewLogs.coffee
+++ b/packages/rocketchat-logger/client/views/viewLogs.coffee
@@ -14,7 +14,7 @@ Template.viewLogs.helpers
 
 	ansispan: (string) ->
 		string = ansispan(string.replace(/\s/g, '&nbsp;').replace(/(\\n|\n)/g, '<br>'))
-		string = string.replace(/(.\d{8}-\d\d:\d\d:\d\d\.\d\d\d\(?.{0,2}\)?)/, '<span class="time">$1</span>')
+		string = string.replace(/(.\d{8}-\d\d:\d\d:\d\d\.\d\d\d\(?.{0,2}\)?)/, '<span class="terminal-time">$1</span>')
 		return string
 
 	formatTS: (date) ->
diff --git a/packages/rocketchat-logger/client/views/viewLogs.html b/packages/rocketchat-logger/client/views/viewLogs.html
index 2c136da2059bda5f2d02b25f8711205b6c49d785..88ab40c1914929d4cdde4280a7b67277c319d0ab 100644
--- a/packages/rocketchat-logger/client/views/viewLogs.html
+++ b/packages/rocketchat-logger/client/views/viewLogs.html
@@ -2,13 +2,13 @@
 	{{#if hasPermission}}
 		<div class="section terminal">
 			{{#each logs}}
-				<div>
-					<!-- <span class="time">{{formatTS ts}}</span>  -->
+				<div class="terminal-line">
+					{{!-- <span class="terminal-time">{{formatTS ts}}</span> --}}
 					{{{ansispan string}}}
 				</div>
 			{{/each}}
 		</div>
-		<div class="new-logs not">
+		<div class="new-logs not color-primary-action-color">
 			<i class="icon-down-big"></i>
 			<span>{{_ "New_logs"}}</span>
 		</div>
diff --git a/packages/rocketchat-mailer/client/views/mailer.html b/packages/rocketchat-mailer/client/views/mailer.html
index 2b50819d6fe5756fafef5b97b4c78abca7967ee5..93e136356216e00a6d7c40982a9d4a624ba642ae 100644
--- a/packages/rocketchat-mailer/client/views/mailer.html
+++ b/packages/rocketchat-mailer/client/views/mailer.html
@@ -1,6 +1,6 @@
 <template name="mailer">
 	<section class="page-container page-list">
-		<header class="fixed-title">
+		<header class="fixed-title border-component-color">
 			{{> burger}}
 			<h2>
 				<span class="room-title">{{_ "Mailer"}}</span>
@@ -19,7 +19,7 @@
 									<input type="text" name="from" value="" placeholder="{{fromEmail}}" />
 								</div>
 								<div>
-									<small class="settings-description">{{{_ "From_email_warning"}}}</small>
+									<small class="settings-description secondary-font-color">{{{_ "From_email_warning"}}}</small>
 								</div>
 							</div>
 							<div class="input-line">
@@ -28,7 +28,7 @@
 									<input type="checkbox" name="dryrun" value="1" />
 								</div>
 								<div>
-									<small class="settings-description">{{{_ "Dry_run_description"}}}</small>
+									<small class="settings-description secondary-font-color">{{{_ "Dry_run_description"}}}</small>
 								</div>
 							</div>
 							<div class="input-line">
@@ -37,7 +37,7 @@
 									<input type="text" name="query" value="" />
 								</div>
 								<div>
-									<small class="settings-description">{{{_ "Query_description"}}}</small>
+									<small class="settings-description secondary-font-color">{{{_ "Query_description"}}}</small>
 								</div>
 							</div>
 							<div class="input-line">
@@ -52,7 +52,7 @@
 									<textarea name="body" rows="10" style="height: auto"></textarea>
 								</div>
 								<div>
-									<small class="settings-description">{{{_ "Mailer_body_tags"}}}</small>
+									<small class="settings-description secondary-font-color">{{{_ "Mailer_body_tags"}}}</small>
 								</div>
 							</div>
 						</fieldset>
diff --git a/packages/rocketchat-mailer/client/views/mailerUnsubscribe.html b/packages/rocketchat-mailer/client/views/mailerUnsubscribe.html
index 1f2739055cddb0689b548d0a6642e4a63053f948..e00707e7b5fb2542815b7868c88c38a963d6b0c1 100644
--- a/packages/rocketchat-mailer/client/views/mailerUnsubscribe.html
+++ b/packages/rocketchat-mailer/client/views/mailerUnsubscribe.html
@@ -1,12 +1,12 @@
 <template name="mailerUnsubscribe">
-	<section class="full-page">
+	<section class="full-page color-tertiary-font-color">
 		<div class="wrapper">
 			<header>
 				<a class="logo" href="/">
 					<img src="images/logo/logo.svg?v=3" />
 				</a>
 			</header>
-			<div class="cms-page">
+			<div class="cms-page content-background-color">
 				{{_ "You_have_successfully_unsubscribed"}}
 			</div>
 		</div>
diff --git a/packages/rocketchat-markdown/markdown.coffee b/packages/rocketchat-markdown/markdown.coffee
index 61d11f0906a7e3bbe162771502fea4b5dcce15c7..2408f3a3621a364ecbac47820dc673fd9b51ee37 100644
--- a/packages/rocketchat-markdown/markdown.coffee
+++ b/packages/rocketchat-markdown/markdown.coffee
@@ -56,17 +56,17 @@ class Markdown
 		# >>>
 		# Text
 		# <<<
-		msg = msg.replace(/(?:&gt;){3}\n+([\s\S]*?)\n+(?:&lt;){3}/g, '<blockquote><span class="copyonly">&gt;&gt;&gt;</span>$1<span class="copyonly">&lt;&lt;&lt;</span></blockquote>')
+		msg = msg.replace(/(?:&gt;){3}\n+([\s\S]*?)\n+(?:&lt;){3}/g, '<blockquote class="background-transparent-darker-before"><span class="copyonly">&gt;&gt;&gt;</span>$1<span class="copyonly">&lt;&lt;&lt;</span></blockquote>')
 
 		# Support >Text for quote
-		msg = msg.replace(/^&gt;(.*)$/gm, '<blockquote><span class="copyonly">&gt;</span>$1</blockquote>')
+		msg = msg.replace(/^&gt;(.*)$/gm, '<blockquote class="background-transparent-darker-before"><span class="copyonly">&gt;</span>$1</blockquote>')
 
 		# Remove white-space around blockquote (prevent <br>). Because blockquote is block element.
-		msg = msg.replace(/\s*<blockquote>/gm, '<blockquote>')
+		msg = msg.replace(/\s*<blockquote class="background-transparent-darker-before">/gm, '<blockquote class="background-transparent-darker-before">')
 		msg = msg.replace(/<\/blockquote>\s*/gm, '</blockquote>')
 
 		# Remove new-line between blockquotes.
-		msg = msg.replace(/<\/blockquote>\n<blockquote>/gm, '</blockquote><blockquote>')
+		msg = msg.replace(/<\/blockquote>\n<blockquote/gm, '</blockquote><blockquote')
 
 		if not _.isString message
 			message.html = msg
diff --git a/packages/rocketchat-markdown/markdowncode.coffee b/packages/rocketchat-markdown/markdowncode.coffee
index 0d0bfd0d15cd8b1d9d07ba043ebae5135c54ee97..e74877286cc83b771897089345ad72582011a40c 100644
--- a/packages/rocketchat-markdown/markdowncode.coffee
+++ b/packages/rocketchat-markdown/markdowncode.coffee
@@ -23,7 +23,7 @@ class MarkdownCode
 
 			message.tokens.push
 				token: token
-				text: "#{p1}<span class=\"copyonly\">`</span><span><code class=\"inline\">#{p2}</code></span><span class=\"copyonly\">`</span>#{p3}"
+				text: "#{p1}<span class=\"copyonly\">`</span><span><code class=\"code-colors inline\">#{p2}</code></span><span class=\"copyonly\">`</span>#{p3}"
 
 			return token
 
@@ -70,7 +70,7 @@ class MarkdownCode
 					message.tokens.push
 						highlight: true
 						token: token
-						text: "<pre><code class='hljs " + result.language + "'><span class='copyonly'>```<br></span>" + result.value + "<span class='copyonly'><br>```</span></code></pre>"
+						text: "<pre><code class='code-colors hljs " + result.language + "'><span class='copyonly'>```<br></span>" + result.value + "<span class='copyonly'><br>```</span></code></pre>"
 
 					msgParts[index] = token
 				else
diff --git a/packages/rocketchat-mentions-flextab/client/views/mentionsFlexTab.coffee b/packages/rocketchat-mentions-flextab/client/views/mentionsFlexTab.coffee
index 4aef3aa7e71791f27c16376d36dd5bbbe3cf3569..0d6fab788374077235d6cc1416dedd939ae8e9ff 100644
--- a/packages/rocketchat-mentions-flextab/client/views/mentionsFlexTab.coffee
+++ b/packages/rocketchat-mentions-flextab/client/views/mentionsFlexTab.coffee
@@ -8,9 +8,6 @@ Template.mentionsFlexTab.helpers
 	message: ->
 		return _.extend(this, { customClass: 'mentions' })
 
-	notReadySubscription: ->
-		return 'notready' unless Template.instance().subscriptionsReady()
-
 	hasMore: ->
 		return Template.instance().hasMore.get()
 
diff --git a/packages/rocketchat-mentions-flextab/client/views/mentionsFlexTab.html b/packages/rocketchat-mentions-flextab/client/views/mentionsFlexTab.html
index 88b36c3e7418f29be1928b6f97625150a736ca59..42c5a38ef7428370237ff5d6a798d29f65de9e69 100644
--- a/packages/rocketchat-mentions-flextab/client/views/mentionsFlexTab.html
+++ b/packages/rocketchat-mentions-flextab/client/views/mentionsFlexTab.html
@@ -14,15 +14,11 @@
 			{{#each messages}}
 				{{#nrr nrrargs 'message' message}}{{/nrr}}
 			{{/each}}
-			{{#if hasMore}}
-				<li class="load-more">
-					{{#if Template.subscriptionsReady}}
-						<button>{{_ "Has_more"}}...</button>
-					{{else}}
-						<div class="load-more-loading">{{_ "Loading..."}}</div>
-					{{/if}}
-				</li>
-			{{/if}}
 		</ul>
+		{{#if hasMore}}
+			<div class="load-more">
+				{{> loading}}
+			</div>
+		{{/if}}
 	</div>
 </template>
diff --git a/packages/rocketchat-mentions-flextab/client/views/stylesheets/mentionsFlexTab.less b/packages/rocketchat-mentions-flextab/client/views/stylesheets/mentionsFlexTab.less
index eaf5a1253115ea83e9ef94c94691bf70ee04b1f5..c71664547c84e20e008152905b3bed6b0e2e2caa 100644
--- a/packages/rocketchat-mentions-flextab/client/views/stylesheets/mentionsFlexTab.less
+++ b/packages/rocketchat-mentions-flextab/client/views/stylesheets/mentionsFlexTab.less
@@ -1,33 +1,11 @@
 .mentioned-messages-list {
-	&.notready {
-		background-image: url(images/logo/loading.gif);
-		background-repeat: no-repeat;
-		background-position: 50% 50%;
-		height: 100px;
-
-		.message {
-			display: none;
-		}
-	}
-
-	li.empty {
-		text-align: center;
-		margin-top: 60px;
-	}
-
 	.message-cog-container {
 		.message-action {
 			display: none !important;
+
 			&.jump-to-message {
 				display: block !important;
 			}
 		}
 	}
-
-	.load-more {
-		text-transform: lowercase;
-		text-align: center;
-		line-height: 40px;
-		font-style: italic;
-	}
 }
diff --git a/packages/rocketchat-mentions/client.coffee b/packages/rocketchat-mentions/client.coffee
index a511cc6ba6db0a6124f733c91b2c12016e333488..2132253a829f559deff85422a6ca3a8d2e342f51 100644
--- a/packages/rocketchat-mentions/client.coffee
+++ b/packages/rocketchat-mentions/client.coffee
@@ -21,7 +21,7 @@ class MentionsClient
 				mentions = mentions.join('|')
 				msg = msg.replace new RegExp("(?:^|\\s|\\n)(@(#{mentions}):?)[:.,\s]?", 'g'), (match, mention, username) ->
 					if username is 'all' or username is 'here'
-						return match.replace mention, "<a class=\"mention-link mention-link-me mention-link-all\">#{mention}</a>"
+						return match.replace mention, "<a class=\"mention-link mention-link-me mention-link-all background-attention-color\">#{mention}</a>"
 
 					if not message.temp?
 						if not _.findWhere(message.mentions, {username: username})?
@@ -29,7 +29,7 @@ class MentionsClient
 
 					classes = 'mention-link'
 					if username is me
-						classes += ' mention-link-me'
+						classes += ' mention-link-me background-primary-action-color'
 
 					return match.replace mention, "<a class=\"#{classes}\" data-username=\"#{username}\">#{mention}</a>"
 
diff --git a/packages/rocketchat-message-attachments/client/messageAttachment.coffee b/packages/rocketchat-message-attachments/client/messageAttachment.coffee
index 195fb7cfb1ff347edff2064ce709a74a4a1b41c8..a03b2b66f35b3c6873293193e5fbf87b2b92f104 100644
--- a/packages/rocketchat-message-attachments/client/messageAttachment.coffee
+++ b/packages/rocketchat-message-attachments/client/messageAttachment.coffee
@@ -12,6 +12,8 @@ Template.messageAttachment.helpers
 
 		if Meteor.settings.public.sandstorm or url.match /^(https?:)?\/\//i
 			return url
+		else if navigator.userAgent.indexOf('Electron') > -1
+			return __meteor_runtime_config__.ROOT_URL_PATH_PREFIX + url
 		else
 			return Meteor.absoluteUrl().replace(/\/$/, '') + __meteor_runtime_config__.ROOT_URL_PATH_PREFIX + url
 
diff --git a/packages/rocketchat-message-attachments/client/messageAttachment.html b/packages/rocketchat-message-attachments/client/messageAttachment.html
index 7860efe8775ad7fa0f3919e44320f978be334cc6..b4f81b11ed1a84d3c8a511e0ab4c52f913c8eb69 100644
--- a/packages/rocketchat-message-attachments/client/messageAttachment.html
+++ b/packages/rocketchat-message-attachments/client/messageAttachment.html
@@ -3,7 +3,7 @@
 		<!-- <div>fallback: {{fallback}}</div> -->
 		{{pretext}}
 		<div class="attachment-block">
-			<div class="attachment-block-border" style="background-color: {{color}}"></div>
+			<div class="attachment-block-border background-info-font-color" style="background-color: {{color}}"></div>
 			{{#if author_name}}
 				{{#if author_link}}
 					<div class="attachment-author">
@@ -121,6 +121,13 @@
 					</div>
 				{{/unless}}
 			{{/if}}
+
+			{{#if description}}
+				<div class="attachment-description">
+					<p>{{{description}}}</p>
+				</div>
+			{{/if}}
+
 			{{#each attachments}}
 				{{injectIndex . ../index @index}} {{> messageAttachment}}
 			{{/each}}
diff --git a/packages/rocketchat-message-attachments/client/stylesheets/loader.coffee b/packages/rocketchat-message-attachments/client/stylesheets/loader.coffee
deleted file mode 100644
index 767a5689253734975995b2551924a8fbe54e9528..0000000000000000000000000000000000000000
--- a/packages/rocketchat-message-attachments/client/stylesheets/loader.coffee
+++ /dev/null
@@ -1,2 +0,0 @@
-RocketChat.theme.addPackageAsset ->
-	return Assets.getText 'client/stylesheets/messageAttachments.less'
diff --git a/packages/rocketchat-message-attachments/client/stylesheets/messageAttachments.less b/packages/rocketchat-message-attachments/client/stylesheets/messageAttachments.less
index edf23591ed6bbd5d6b3fd0a5bfed638d7dc5be6a..f0cf4996cace3db3a48190bb6e279201e543c128 100644
--- a/packages/rocketchat-message-attachments/client/stylesheets/messageAttachments.less
+++ b/packages/rocketchat-message-attachments/client/stylesheets/messageAttachments.less
@@ -12,9 +12,11 @@
 			top: 0;
 			bottom: 0;
 		}
+
 		html.rtl & {
 			padding-left: 0;
 			padding-right: 15px;
+
 			.attachment-block-border {
 				left: auto;
 				right: 0;
@@ -37,9 +39,10 @@
 			margin-right: 2px;
 			margin-bottom: -2px;
 		}
+
 		.time {
 			font-weight: normal;
-			font-size: .8em;
+			font-size: 0.8em;
 		}
 	}
 
@@ -86,7 +89,8 @@
 	.attachment-thumb {
 		padding-right: 10px;
 		padding-top: 5px;
-		line-height: 0px;
+		line-height: 0;
+
 		html.rtl & {
 			padding-right: 5px;
 			padding-top: 10px;
@@ -115,6 +119,7 @@
 		border-width: 1px;
 		border-radius: 5px;
 		margin-left: 5px;
+
 		html.rtl & {
 			margin-right: 5px;
 			margin-left: auto;
diff --git a/packages/rocketchat-message-attachments/package.js b/packages/rocketchat-message-attachments/package.js
index 0b43fed4b3024ff89c0725d359f6d273c80311f9..c6282012e225eb0bdb5ee401b58c70134c446828 100644
--- a/packages/rocketchat-message-attachments/package.js
+++ b/packages/rocketchat-message-attachments/package.js
@@ -11,13 +11,13 @@ Package.onUse(function(api) {
 		'ecmascript',
 		'coffeescript',
 		'underscore',
-		'rocketchat:lib'
+		'rocketchat:lib',
+		'less'
 	]);
 
 	api.addFiles('client/messageAttachment.html', 'client');
 	api.addFiles('client/messageAttachment.coffee', 'client');
 
 	// stylesheets
-	api.addAssets('client/stylesheets/messageAttachments.less', 'server');
-	api.addFiles('client/stylesheets/loader.coffee', 'server');
+	api.addFiles('client/stylesheets/messageAttachments.less', 'client');
 });
diff --git a/packages/rocketchat-message-pin/client/views/pinnedMessages.html b/packages/rocketchat-message-pin/client/views/pinnedMessages.html
index e932f46ee7a2c490f15820e1b2d1badf6344519d..57b080da5dfb65aec8472402d0e6dff59d00ebde 100644
--- a/packages/rocketchat-message-pin/client/views/pinnedMessages.html
+++ b/packages/rocketchat-message-pin/client/views/pinnedMessages.html
@@ -14,15 +14,11 @@
 			{{#each messages}}
 				{{#nrr nrrargs 'message' message}}{{/nrr}}
 			{{/each}}
-			{{#if hasMore}}
-				<li class="load-more">
-					{{#if Template.subscriptionsReady}}
-						<button>{{_ "Has_more"}}...</button>
-					{{else}}
-						<div class="load-more-loading">{{_ "Loading..."}}</div>
-					{{/if}}
-				</li>
-			{{/if}}
 		</ul>
+		{{#if hasMore}}
+			<div class="load-more">
+				{{> loading}}
+			</div>
+		{{/if}}
 	</div>
 </template>
diff --git a/packages/rocketchat-message-pin/client/views/stylesheets/messagepin.less b/packages/rocketchat-message-pin/client/views/stylesheets/messagepin.less
index f6fced030741ccb32ba459e731568d1009cefaf3..fdc99ceb45c981bbb20a4f77c846caadda0e6131 100644
--- a/packages/rocketchat-message-pin/client/views/stylesheets/messagepin.less
+++ b/packages/rocketchat-message-pin/client/views/stylesheets/messagepin.less
@@ -1,4 +1,4 @@
-.icon-pin.rotate-45:before {
+.icon-pin.rotate-45::before {
 	-ms-transform: rotate(45deg);
 	-webkit-transform: rotate(45deg);
 	transform: rotate(45deg);
@@ -18,7 +18,7 @@
 		font-style: italic;
 
 		.load-more-loading {
-			color: #aaa;
+			color: #aaaaaa;
 		}
 	}
 }
diff --git a/packages/rocketchat-message-pin/server/pinMessage.coffee b/packages/rocketchat-message-pin/server/pinMessage.coffee
index faa73ce57972ce4f9561ee5317927f65816ecaaf..f2049c584652f113f08988894039fe2f82f2e685 100644
--- a/packages/rocketchat-message-pin/server/pinMessage.coffee
+++ b/packages/rocketchat-message-pin/server/pinMessage.coffee
@@ -11,28 +11,33 @@ Meteor.methods
 		if Array.isArray(room.usernames) && room.usernames.indexOf(Meteor.user().username) is -1
 			return false
 
+		originalMessage = RocketChat.models.Messages.findOneById message._id
+
+		if not originalMessage?._id?
+			throw new Meteor.Error 'error-invalid-message', 'Message you are pinning was not found', { method: 'pinMessage', action: 'Message_pinning' }
+
 		# If we keep history of edits, insert a new message to store history information
 		if RocketChat.settings.get 'Message_KeepHistory'
 			RocketChat.models.Messages.cloneAndSaveAsHistoryById message._id
 
 		me = RocketChat.models.Users.findOneById Meteor.userId()
 
-		message.pinned = true
-		message.pinnedAt = pinnedAt || Date.now
-		message.pinnedBy =
+		originalMessage.pinned = true
+		originalMessage.pinnedAt = pinnedAt || Date.now
+		originalMessage.pinnedBy =
 			_id: Meteor.userId()
 			username: me.username
 
-		message = RocketChat.callbacks.run 'beforeSaveMessage', message
+		originalMessage = RocketChat.callbacks.run 'beforeSaveMessage', originalMessage
 
-		RocketChat.models.Messages.setPinnedByIdAndUserId message._id, message.pinnedBy, message.pinned
+		RocketChat.models.Messages.setPinnedByIdAndUserId originalMessage._id, originalMessage.pinnedBy, originalMessage.pinned
 
-		RocketChat.models.Messages.createWithTypeRoomIdMessageAndUser 'message_pinned', message.rid, '', me,
+		RocketChat.models.Messages.createWithTypeRoomIdMessageAndUser 'message_pinned', originalMessage.rid, '', me,
 			attachments: [
-				"text" : message.msg
-				"author_name" : message.u.username,
-				"author_icon" : getAvatarUrlFromUsername(message.u.username),
-				"ts" : message.ts
+				"text" : originalMessage.msg
+				"author_name" : originalMessage.u.username,
+				"author_icon" : getAvatarUrlFromUsername(originalMessage.u.username),
+				"ts" : originalMessage.ts
 			]
 
 	unpinMessage: (message) ->
@@ -47,20 +52,25 @@ Meteor.methods
 		if Array.isArray(room.usernames) && room.usernames.indexOf(Meteor.user().username) is -1
 			return false
 
+		originalMessage = RocketChat.models.Messages.findOneById message._id
+
+		if not originalMessage?._id?
+			throw new Meteor.Error 'error-invalid-message', 'Message you are unpinning was not found', { method: 'unpinMessage', action: 'Message_pinning' }
+
 		# If we keep history of edits, insert a new message to store history information
 		if RocketChat.settings.get 'Message_KeepHistory'
-			RocketChat.models.Messages.cloneAndSaveAsHistoryById message._id
+			RocketChat.models.Messages.cloneAndSaveAsHistoryById originalMessage._id
 
 		me = RocketChat.models.Users.findOneById Meteor.userId()
 
-		message.pinned = false
-		message.pinnedBy =
+		originalMessage.pinned = false
+		originalMessage.pinnedBy =
 			_id: Meteor.userId()
 			username: me.username
 
-		message = RocketChat.callbacks.run 'beforeSaveMessage', message
+		originalMessage = RocketChat.callbacks.run 'beforeSaveMessage', originalMessage
 
-		RocketChat.models.Messages.setPinnedByIdAndUserId message._id, message.pinnedBy, message.pinned
+		RocketChat.models.Messages.setPinnedByIdAndUserId originalMessage._id, originalMessage.pinnedBy, originalMessage.pinned
 
 
 		# Meteor.defer ->
diff --git a/packages/rocketchat-message-snippet/client/page/stylesheets/snippetPage.less b/packages/rocketchat-message-snippet/client/page/stylesheets/snippetPage.less
index 5b84f4153566ceade403563c9ef504ebd935545e..4110c87b2dbcb55d04de92851ec32865af26340f 100644
--- a/packages/rocketchat-message-snippet/client/page/stylesheets/snippetPage.less
+++ b/packages/rocketchat-message-snippet/client/page/stylesheets/snippetPage.less
@@ -4,62 +4,60 @@
 @snippet-page-right-border-size: 30px;
 @snippet-informations-span-line-height: @snippet-informations-height / 2;
 
-
 .snippet-page {
-  padding-top: @snippet-page-top-border-size;
-  padding-left: @snippet-page-left-border-size;
-  padding-right: @snippet-page-right-border-size;
-  overflow-y: auto;
-  overflow-x: hidden;
-  height: 100%;
-  width: auto;
-
-  pre code, h1, span {
-    -webkit-user-select: text;
-    -khtml-user-select: all;
-    -moz-user-select: all;
-    -ms-user-select: all;
-    user-select: all;
-  }
-
-  .snippet-informations {
-    display:inline-block;
-
-    width: 100%;
-    height: 60px;
-
-    div.avatar {
-      display: block;
-      float:left;
-      clear:left;
-      width: @snippet-informations-height;
-      height:@snippet-informations-height;
-      margin-right: 10px;
-    }
-    span.username {
-      display: block;
-      line-height: @snippet-informations-span-line-height;
-      width: 100%;
-    }
-    span.snippet-filename {
-      display:block;
-      line-height: @snippet-informations-span-line-height;
-      font-weight: bold;
-      width:100%;
-    }
-  }
-
-  span.info {
-    font-style: italic;
-    line-height: @snippet-informations-span-line-height;
-    color: darkgrey;
-  }
-
-  .download-button {
-    float: right;
-  }
-
-  h1 {
-  }
-
+	padding-top: @snippet-page-top-border-size;
+	padding-left: @snippet-page-left-border-size;
+	padding-right: @snippet-page-right-border-size;
+	overflow-y: auto;
+	overflow-x: hidden;
+	height: 100%;
+	width: auto;
+
+	pre code,
+	h1,
+	span {
+		-webkit-user-select: text;
+		-khtml-user-select: all;
+		-moz-user-select: all;
+		-ms-user-select: all;
+		user-select: all;
+	}
+
+	.snippet-informations {
+		display: inline-block;
+		width: 100%;
+		height: 60px;
+
+		.avatar {
+			display: block;
+			float: left;
+			clear: left;
+			width: @snippet-informations-height;
+			height: @snippet-informations-height;
+			margin-right: 10px;
+		}
+
+		.username {
+			display: block;
+			line-height: @snippet-informations-span-line-height;
+			width: 100%;
+		}
+
+		.snippet-filename {
+			display: block;
+			line-height: @snippet-informations-span-line-height;
+			font-weight: bold;
+			width: 100%;
+		}
+	}
+
+	.info {
+		font-style: italic;
+		line-height: @snippet-informations-span-line-height;
+		color: darkgrey;
+	}
+
+	.download-button {
+		float: right;
+	}
 }
diff --git a/packages/rocketchat-message-snippet/client/tabBar/views/snippetMessage.html b/packages/rocketchat-message-snippet/client/tabBar/views/snippetMessage.html
index 858266510f3b4f7b964e5fc3dc741e0dff8d2f40..9755eed5a7a5ac66e2038a9a3c88384c8b6c9ed8 100644
--- a/packages/rocketchat-message-snippet/client/tabBar/views/snippetMessage.html
+++ b/packages/rocketchat-message-snippet/client/tabBar/views/snippetMessage.html
@@ -1,5 +1,5 @@
 <template name="snippetMessage">
-	<li id="{{_id}}" class="message {{isSequential}} {{system}} {{t}} {{own}} {{isTemp}} {{chatops}} {{customClass}}" data-username="{{u.username}}" data-groupable="{{isGroupable}}" data-date="{{date}}" data-timestamp="{{timestamp}}">
+	<li id="{{_id}}" class="message background-transparent-dark-hover {{isSequential}} {{system}} {{t}} {{own}} {{isTemp}} {{chatops}} {{customClass}}" data-username="{{u.username}}" data-groupable="{{isGroupable}}" data-date="{{date}}" data-timestamp="{{timestamp}}">
 		<div class="day-divider">
 			<span>{{date}}</span>
 		</div>
diff --git a/packages/rocketchat-message-snippet/client/tabBar/views/snippetedMessages.html b/packages/rocketchat-message-snippet/client/tabBar/views/snippetedMessages.html
index dc894507e4349221a6d0fc8593847b227d921e53..91409e64631252d430ec70dcb452074d0657f5dc 100644
--- a/packages/rocketchat-message-snippet/client/tabBar/views/snippetedMessages.html
+++ b/packages/rocketchat-message-snippet/client/tabBar/views/snippetedMessages.html
@@ -14,15 +14,11 @@
 			{{#each messages}}
 				{{#nrr nrrargs 'snippetMessage' message}}{{/nrr}}
 			{{/each}}
-			{{#if hasMore}}
-				<li class="load-more">
-					{{#if Template.subscriptionsReady}}
-						<button>{{_ "Has_more"}}...</button>
-					{{else}}
-						<div class="load-more-loading">{{_ "Loading..."}}</div>
-					{{/if}}
-				</li>
-			{{/if}}
 		</ul>
+		{{#if hasMore}}
+			<div class="load-more">
+				{{> loading}}
+			</div>
+		{{/if}}
 	</div>
 </template>
diff --git a/packages/rocketchat-message-star/client/views/starredMessages.html b/packages/rocketchat-message-star/client/views/starredMessages.html
index 7487384a5f66f8e23252bb7d759a04734e3ae460..337e659bb56e1b83fc2203e3d632c66a622fbc78 100644
--- a/packages/rocketchat-message-star/client/views/starredMessages.html
+++ b/packages/rocketchat-message-star/client/views/starredMessages.html
@@ -14,15 +14,11 @@
 			{{#each messages}}
 				{{#nrr nrrargs 'message' message}}{{/nrr}}
 			{{/each}}
-			{{#if hasMore}}
-				<li class="load-more">
-					{{#if Template.subscriptionsReady}}
-						<button>{{_ "Has_more"}}...</button>
-					{{else}}
-						<div class="load-more-loading">{{_ "Loading..."}}</div>
-					{{/if}}
-				</li>
-			{{/if}}
 		</ul>
+		{{#if hasMore}}
+			<div class="load-more">
+				{{> loading}}
+			</div>
+		{{/if}}
 	</div>
 </template>
diff --git a/packages/rocketchat-message-star/client/views/stylesheets/messagestar.less b/packages/rocketchat-message-star/client/views/stylesheets/messagestar.less
index 9b6efe0ac051322f41275ae5311a0783b0199b40..1fabb34a91e1f1cad56c42ed989cefca8ac9c80f 100644
--- a/packages/rocketchat-message-star/client/views/stylesheets/messagestar.less
+++ b/packages/rocketchat-message-star/client/views/stylesheets/messagestar.less
@@ -12,7 +12,7 @@
 		font-style: italic;
 
 		.load-more-loading {
-			color: #aaa;
+			color: #aaaaaa;
 		}
 	}
 }
diff --git a/packages/rocketchat-migrations/migrations.js b/packages/rocketchat-migrations/migrations.js
index 6bd8c699aa180a58174deace3cb767b9af1659bf..ee54c145e6960a2c84009cabde2795b52845aa63 100644
--- a/packages/rocketchat-migrations/migrations.js
+++ b/packages/rocketchat-migrations/migrations.js
@@ -1,5 +1,5 @@
+/* eslint-disable */
 import moment from 'moment';
-
 /*
 	Adds migration capabilities. Migrations are defined like:
 
@@ -28,8 +28,7 @@ import moment from 'moment';
 	be in an inconsistant state.
 */
 
-// since we'll be at version 0 by default, we should have a migration set for
-// it.
+// since we'll be at version 0 by default, we should have a migration set for it.
 var DefaultMigration = {
 	version: 0,
 	up: function() {
@@ -276,7 +275,9 @@ Migrations._migrateTo = function(version, rerun) {
 		log.info('Running ' + direction + '() on version ' + migration.version + maybeName());
 
 		try {
-			migration[direction](migration);
+			RocketChat.models._CacheControl.withValue(false, function() {
+				migration[direction](migration);
+			});
 		} catch (e) {
 			console.log(makeABox([
 				"ERROR! SERVER STOPPED",
diff --git a/packages/rocketchat-oauth2-server-config/admin/client/views/oauthApp.html b/packages/rocketchat-oauth2-server-config/admin/client/views/oauthApp.html
index 51f3bb8c78cda1b490f3dfa22fb040c70efbe0d8..6038e7035a167caa4aa869b4bc8d21a40dee21b2 100644
--- a/packages/rocketchat-oauth2-server-config/admin/client/views/oauthApp.html
+++ b/packages/rocketchat-oauth2-server-config/admin/client/views/oauthApp.html
@@ -16,14 +16,14 @@
 							<label>{{_ "Application_Name"}}</label>
 							<div>
 								<input type="text" name="name" value="{{data.name}}" />
-								<div class="settings-description">{{_ "Give_the_application_a_name_This_will_be_seen_by_your_users"}}</div>
+								<div class="settings-description secondary-font-color">{{_ "Give_the_application_a_name_This_will_be_seen_by_your_users"}}</div>
 							</div>
 						</div>
 						<div class="input-line double-col">
 							<label>{{_ "Redirect_URI"}}</label>
 							<div>
 								<input type="text" name="redirectUri" value="{{data.redirectUri}}" />
-								<div class="settings-description">{{_ "After_OAuth2_authentication_users_will_be_redirected_to_this_URL"}}</div>
+								<div class="settings-description secondary-font-color">{{_ "After_OAuth2_authentication_users_will_be_redirected_to_this_URL"}}</div>
 							</div>
 						</div>
 						{{#if data.clientId}}
@@ -31,28 +31,28 @@
 								<label>{{_ "Client_ID"}}</label>
 								<div>
 									<input type="text" name="clientId" value="{{data.clientId}}" readonly="readonly" />
-									<div class="settings-description"><button class="clipboard" data-clipboard-target="[name=clientId]">{{_ "COPY_TO_CLIPBOARD"}}</button></div>
+									<div class="settings-description secondary-font-color"><button class="clipboard" data-clipboard-target="[name=clientId]">{{_ "COPY_TO_CLIPBOARD"}}</button></div>
 								</div>
 							</div>
 							<div class="input-line double-col">
 								<label>{{_ "Client_Secret"}}</label>
 								<div>
 									<input type="text" name="clientSecret" value="{{data.clientSecret}}" readonly="readonly" />
-									<div class="settings-description"><button class="clipboard" data-clipboard-target="[name=clientSecret]">{{_ "COPY_TO_CLIPBOARD"}}</button></div>
+									<div class="settings-description secondary-font-color"><button class="clipboard" data-clipboard-target="[name=clientSecret]">{{_ "COPY_TO_CLIPBOARD"}}</button></div>
 								</div>
 							</div>
 							<div class="input-line double-col">
 								<label>{{_ "Authorization_URL"}}</label>
 								<div>
 									<input type="text" name="authorization_url" value="{{data.authorization_url}}" readonly="readonly" />
-									<div class="settings-description"><button class="clipboard" data-clipboard-target="[name=authorization_url]">{{_ "COPY_TO_CLIPBOARD"}}</button></div>
+									<div class="settings-description secondary-font-color"><button class="clipboard" data-clipboard-target="[name=authorization_url]">{{_ "COPY_TO_CLIPBOARD"}}</button></div>
 								</div>
 							</div>
 							<div class="input-line double-col">
 								<label>{{_ "Access_Token_URL"}}</label>
 								<div>
 									<input type="text" name="access_token_url" value="{{data.access_token_url}}" readonly="readonly" />
-									<div class="settings-description"><button class="clipboard" data-clipboard-target="[name=access_token_url]">{{_ "COPY_TO_CLIPBOARD"}}</button></div>
+									<div class="settings-description secondary-font-color"><button class="clipboard" data-clipboard-target="[name=access_token_url]">{{_ "COPY_TO_CLIPBOARD"}}</button></div>
 								</div>
 							</div>
 						{{/if}}
diff --git a/packages/rocketchat-oauth2-server-config/oauth/client/oauth2-client.coffee b/packages/rocketchat-oauth2-server-config/oauth/client/oauth2-client.coffee
index c2acdd899d11a13db46046ecadea9d11e61d588b..d43d4ba16e2d88ebadbe468bc92e58563ef53e6c 100644
--- a/packages/rocketchat-oauth2-server-config/oauth/client/oauth2-client.coffee
+++ b/packages/rocketchat-oauth2-server-config/oauth/client/oauth2-client.coffee
@@ -44,4 +44,4 @@ Template.authorize.onRendered ->
 	@autorun (c) =>
 		if Meteor.user()?.oauth?.athorizedClients?.indexOf(@data.client_id()) > -1
 			c.stop()
-			$('button').click()
+			$('button[type=submit]').click()
diff --git a/packages/rocketchat-oauth2-server-config/oauth/client/oauth2-client.html b/packages/rocketchat-oauth2-server-config/oauth/client/oauth2-client.html
index 859460f7f822e2fa81223999b6ba7cd4280753bb..49915dcf473889937731fccb9f3e8fbe9b7ab9de 100644
--- a/packages/rocketchat-oauth2-server-config/oauth/client/oauth2-client.html
+++ b/packages/rocketchat-oauth2-server-config/oauth/client/oauth2-client.html
@@ -29,9 +29,8 @@
 				<input type="hidden" name="client_id" value="{{client_id}}">
 				<input type="hidden" name="redirect_uri" value="{{redirect_uri}}">
 				<input type="hidden" name="response_type" value="code">
-				<div class="buttons">
+				<div class="buttons-group">
 					<button id="logout-oauth" class="button danger logout">{{_ "Logout"}}</button>
-					<div class="horizontal-space"></div>
 					<button id="cancel-oauth" type="button" class="button cancel">{{_ "Cancel"}}</button>
 					<button type="submit" class="button primary save">{{_ "Authorize"}}</button>
 				</div>
diff --git a/packages/rocketchat-oauth2-server-config/oauth/client/stylesheets/load.coffee b/packages/rocketchat-oauth2-server-config/oauth/client/stylesheets/load.coffee
deleted file mode 100644
index 631ef382a4e69a8a6ebda08537da49d86e9d3f1e..0000000000000000000000000000000000000000
--- a/packages/rocketchat-oauth2-server-config/oauth/client/stylesheets/load.coffee
+++ /dev/null
@@ -1,2 +0,0 @@
-RocketChat.theme.addPackageAsset ->
-	return Assets.getText 'oauth/client/stylesheets/oauth2.less'
diff --git a/packages/rocketchat-oauth2-server-config/oauth/client/stylesheets/oauth2.less b/packages/rocketchat-oauth2-server-config/oauth/client/stylesheets/oauth2.less
index e83fecf16ffdd0e13633cfebcc82631ffe68222a..1ff8f6f0e3baf9dcc6acd7b9384247d8d19f2564 100644
--- a/packages/rocketchat-oauth2-server-config/oauth/client/stylesheets/oauth2.less
+++ b/packages/rocketchat-oauth2-server-config/oauth/client/stylesheets/oauth2.less
@@ -4,12 +4,14 @@
 	flex-direction: column;
 	align-items: center;
 	justify-content: center;
-	left: 0px;
-	right: 0px;
-	top: 0px;
-	bottom: 0px;
+	left: 0;
+	right: 0;
+	top: 0;
+	bottom: 0;
 
-	ul, li, ol {
+	ul,
+	li,
+	ol {
 		list-style: initial;
 	}
 
@@ -30,7 +32,7 @@
 		justify-content: center;
 		padding-bottom: 20px;
 		margin-bottom: 20px;
-		border-bottom: 1px solid #eee;
+		border-bottom: 1px solid #eeeeee;
 
 		.thumb {
 			height: 40px;
@@ -40,6 +42,7 @@
 
 		.username {
 			text-align: left;
+
 			h1 {
 				font-size: 18px;
 			}
@@ -64,7 +67,7 @@
 		justify-content: center;
 
 		.horizontal-space {
-			border-right: 1px solid #ddd;
+			border-right: 1px solid #dddddd;
 			height: 14px;
 			margin: 0 15px;
 		}
diff --git a/packages/rocketchat-oauth2-server-config/package.js b/packages/rocketchat-oauth2-server-config/package.js
index 6f7c70c0f403cac59960e01443873cf8421a0a2c..4ad16fbca1cdc45a65a65551f5c9cb6021034cd2 100644
--- a/packages/rocketchat-oauth2-server-config/package.js
+++ b/packages/rocketchat-oauth2-server-config/package.js
@@ -12,6 +12,7 @@ Package.onUse(function(api) {
 	api.use('rocketchat:api');
 	api.use('rocketchat:theme');
 	api.use('rocketchat:oauth2-server');
+	api.use('less');
 
 	api.use('templating', 'client');
 	api.use('kadira:flow-router', 'client');
@@ -25,8 +26,7 @@ Package.onUse(function(api) {
 	api.addFiles('oauth/server/oauth2-server.coffee', 'server');
 	api.addFiles('oauth/server/default-services.coffee', 'server');
 
-	api.addAssets('oauth/client/stylesheets/oauth2.less', 'server');
-	api.addFiles('oauth/client/stylesheets/load.coffee', 'server');
+	api.addFiles('oauth/client/stylesheets/oauth2.less', 'client');
 
 	// Client
 	api.addFiles('oauth/client/oauth2-client.html', 'client');
diff --git a/packages/rocketchat-oembed/client/oembedAudioWidget.html b/packages/rocketchat-oembed/client/oembedAudioWidget.html
index 2cd1035c87369e5eb1dbad946884cbfa11bc9ba9..b4eea0aa8d1a5390b29b7c66f09fb30f0108c6b3 100644
--- a/packages/rocketchat-oembed/client/oembedAudioWidget.html
+++ b/packages/rocketchat-oembed/client/oembedAudioWidget.html
@@ -5,7 +5,7 @@
 				<span class="collapse-switch icon-right-dir" data-index="{{index}}" data-collapsed="{{collapsed}}"></span>
 			{{else}}
 				<span class="collapse-switch icon-down-dir" data-index="{{index}}" data-collapsed="{{collapsed}}"></span>
-				<blockquote>
+				<blockquote class="background-transparent-darker-before">
 					<audio controls>
 						<source src="{{url}}" type="{{headers.contentType}}">
 						Your browser does not support the audio element.
diff --git a/packages/rocketchat-oembed/client/oembedFrameWidget.html b/packages/rocketchat-oembed/client/oembedFrameWidget.html
index 92f4297021aa3e1d34cc34381c56400b2a3540a1..04b58c3ed135a414f49159bce6f5993295b3fac2 100644
--- a/packages/rocketchat-oembed/client/oembedFrameWidget.html
+++ b/packages/rocketchat-oembed/client/oembedFrameWidget.html
@@ -1,6 +1,6 @@
 <template name="oembedFrameWidget">
 {{#if parsedUrl}}
-	<blockquote>
+	<blockquote class="background-transparent-darker-before">
 		{{#if meta.oembedProviderName}}
 			{{#if meta.oembedProviderUrl}}
 				<a href="{{meta.oembedProviderUrl}}" style="color: #9e9ea6">{{meta.oembedProviderName}}</a>
diff --git a/packages/rocketchat-oembed/client/oembedSandstormGrain.html b/packages/rocketchat-oembed/client/oembedSandstormGrain.html
index 97157a6b0b7c82fb45341fc28f8fd21b2de5f8d5..b5a2ac272b28897eebc9a5f9ef0b7183d61d0755 100644
--- a/packages/rocketchat-oembed/client/oembedSandstormGrain.html
+++ b/packages/rocketchat-oembed/client/oembedSandstormGrain.html
@@ -1,5 +1,5 @@
 <template name="oembedSandstormGrain">
-	<blockquote class="sandstorm-grain">
+	<blockquote class="sandstorm-grain background-transparent-darker-before">
 		<label>
 			<button onclick="sandstormOembed(event)" data-token="{{token}}"
 							data-descriptor="{{descriptor}}">
diff --git a/packages/rocketchat-oembed/client/oembedUrlWidget.coffee b/packages/rocketchat-oembed/client/oembedUrlWidget.coffee
index 8178ac87c5ab55c13ce617161f76c422053fdb52..e78fa4cf73733467ba5913546c8192ae421aa874 100644
--- a/packages/rocketchat-oembed/client/oembedUrlWidget.coffee
+++ b/packages/rocketchat-oembed/client/oembedUrlWidget.coffee
@@ -36,7 +36,13 @@ Template.oembedUrlWidget.helpers
 
 		url = decodedOgImage or this.meta.twitterImage
 
-		if url?[0] is '/' and this.parsedUrl?.host?
+		if not url?
+			return
+
+		if url.indexOf('//') is 0
+			url = "#{this.parsedUrl.protocol}#{url}"
+
+		else if url.indexOf('/') is 0 and this.parsedUrl?.host?
 			url = "#{this.parsedUrl.protocol}//#{this.parsedUrl.host}#{url}"
 
 		return url
diff --git a/packages/rocketchat-oembed/client/oembedUrlWidget.html b/packages/rocketchat-oembed/client/oembedUrlWidget.html
index 4ca23a82abc215bff22746b8f6d4ba1b4bd6a004..b410473155b5adb27c02719f370a12dd937c6d25 100644
--- a/packages/rocketchat-oembed/client/oembedUrlWidget.html
+++ b/packages/rocketchat-oembed/client/oembedUrlWidget.html
@@ -1,6 +1,6 @@
 <template name="oembedUrlWidget">
 	{{#if show}}
-		<blockquote>
+		<blockquote class="background-transparent-darker-before">
 			<div style="{{#if image}}min-height: 80px;{{/if}} padding: 10px 3px;">
 				{{#if image}}
 					{{#if meta.ogImageUserGenerated}}
diff --git a/packages/rocketchat-oembed/client/oembedVideoWidget.html b/packages/rocketchat-oembed/client/oembedVideoWidget.html
index f29fa1f6119c750699d62352cf85e69f65103391..1a913e2dfb04c262a16c3708ccd84036c0f98f26 100644
--- a/packages/rocketchat-oembed/client/oembedVideoWidget.html
+++ b/packages/rocketchat-oembed/client/oembedVideoWidget.html
@@ -1,6 +1,6 @@
 <template name="oembedVideoWidget">
 {{#if parsedUrl}}
-	<blockquote>
+	<blockquote class="background-transparent-darker-before">
 		<div><a href="{{url}}">{{parsedUrl.host}}</a></div>
 		<span>{{title}}</span>
 		{{#if collapsed}}
diff --git a/packages/rocketchat-oembed/client/oembedYoutubeWidget.html b/packages/rocketchat-oembed/client/oembedYoutubeWidget.html
index 614c11df2d4d505157f7690f240c58a42b3ef913..7295e633e17a65deae60b9031529c8c4d89b85eb 100644
--- a/packages/rocketchat-oembed/client/oembedYoutubeWidget.html
+++ b/packages/rocketchat-oembed/client/oembedYoutubeWidget.html
@@ -1,6 +1,6 @@
 <template name="oembedYoutubeWidget">
 	{{#if parsedUrl}}
-		<blockquote>
+		<blockquote class="background-transparent-darker-before">
 			<a href="{{url}}">{{parsedUrl.host}}</a>
 			{{#if collapsed}}
 				<span class="collapse-switch icon-right-dir" data-index="{{index}}" data-collapsed="{{collapsed}}"></span><br>
diff --git a/packages/rocketchat-otr/client/rocketchat.otr.room.js b/packages/rocketchat-otr/client/rocketchat.otr.room.js
index e5e7c591e4a4025128639b651a80beef6ac46175..a6defaec91e501acb2ca7c929180d86bd5300cdf 100644
--- a/packages/rocketchat-otr/client/rocketchat.otr.room.js
+++ b/packages/rocketchat-otr/client/rocketchat.otr.room.js
@@ -202,7 +202,7 @@ RocketChat.OTR.Room = class {
 					}
 
 					swal({
-						title: '<i class=\'icon-key alert-icon\'></i>' + TAPi18n.__('OTR'),
+						title: '<i class=\'icon-key alert-icon success-color\'></i>' + TAPi18n.__('OTR'),
 						text: TAPi18n.__('Username_wants_to_start_otr_Do_you_want_to_accept', { username: user.username }),
 						html: true,
 						showCancelButton: true,
@@ -237,7 +237,7 @@ RocketChat.OTR.Room = class {
 					this.reset();
 					const user = Meteor.users.findOne(this.peerId);
 					swal({
-						title: '<i class=\'icon-key alert-icon\'></i>' + TAPi18n.__('OTR'),
+						title: '<i class=\'icon-key alert-icon success-color\'></i>' + TAPi18n.__('OTR'),
 						text: TAPi18n.__('Username_denied_the_OTR_session', { username: user.username }),
 						html: true
 					});
@@ -249,7 +249,7 @@ RocketChat.OTR.Room = class {
 					this.reset();
 					const user = Meteor.users.findOne(this.peerId);
 					swal({
-						title: '<i class=\'icon-key alert-icon\'></i>' + TAPi18n.__('OTR'),
+						title: '<i class=\'icon-key alert-icon success-color\'></i>' + TAPi18n.__('OTR'),
 						text: TAPi18n.__('Username_ended_the_OTR_session', { username: user.username }),
 						html: true
 					});
diff --git a/packages/rocketchat-otr/client/stylesheets/otr.less b/packages/rocketchat-otr/client/stylesheets/otr.less
index c0e653fe050d1dac6678aa7a583c20416f98eabe..dd288cccd7a57d02a242f3ee1e82959645e40eb1 100644
--- a/packages/rocketchat-otr/client/stylesheets/otr.less
+++ b/packages/rocketchat-otr/client/stylesheets/otr.less
@@ -9,19 +9,18 @@
 }
 
 .message {
-	&.otr, &.otr-ack {
-		.info:before {
+	&.otr,
+	&.otr-ack {
+		.info::before {
 			font-family: 'fontello';
 			content: "\e952";
 			visibility: visible;
 			display: inline-block;
 		}
 	}
-}
 
-.message {
 	&.otr-ack {
-		.info:before {
+		.info::before {
 			color: green;
 		}
 	}
@@ -31,6 +30,7 @@
 	.input-message {
 		padding-right: 48px;
 	}
+
 	.inner-right-toolbar {
 		.otr-icon {
 			color: green;
diff --git a/packages/rocketchat-push-notifications/client/stylesheets/pushNotifications.less b/packages/rocketchat-push-notifications/client/stylesheets/pushNotifications.less
index 4a1d89635246eb1c9b5aa55d93e480cd87c05bfe..ad6f5d912f52592ae910cdf9bee90ad5ce83cb8b 100644
--- a/packages/rocketchat-push-notifications/client/stylesheets/pushNotifications.less
+++ b/packages/rocketchat-push-notifications/client/stylesheets/pushNotifications.less
@@ -15,6 +15,7 @@
 
 			div span {
 				font-size: 14px;
+
 				i.icon-pencil {
 					font-size: 12px;
 					margin-left: 3px;
diff --git a/packages/rocketchat-push-notifications/client/views/pushNotificationsFlexTab.html b/packages/rocketchat-push-notifications/client/views/pushNotificationsFlexTab.html
index 695c96ae245f61d5c3ddcff33b36bc0e39c05ae8..edcc49c4c9ffb7ed59d22ecd7bddc8ce17e7d948 100644
--- a/packages/rocketchat-push-notifications/client/views/pushNotificationsFlexTab.html
+++ b/packages/rocketchat-push-notifications/client/views/pushNotificationsFlexTab.html
@@ -15,9 +15,9 @@
 								<label><input type="radio" name="desktopNotifications" value="nothing" checked="{{$eq desktopNotifications 'nothing'}}" /> {{_ "Nothing"}}</label>
 								<br />
 								{{#if desktopNotificationDuration}}
-									<label>{{_ "Duration"}} ({{_ "seconds"}}) <input type="number" name="duration" min="0" value="{{desktopNotificationDuration}}"></label>
+									<label>{{_ "Duration"}} ({{_ "seconds"}}) <input type="number" name="duration" min="0" value="{{desktopNotificationDuration}}" class="content-background-color"></label>
 								{{else}}
-									<label>{{_ "Duration"}} ({{_ "seconds"}}) <input type="number" name="duration" min="0" value="" placeholder="{{_ "Use_User_Preferences_or_Global_Settings"}}"></label>
+									<label>{{_ "Duration"}} ({{_ "seconds"}}) <input type="number" name="duration" min="0" value="" placeholder="{{_ "Use_User_Preferences_or_Global_Settings"}}" class="content-background-color"></label>
 								{{/if}}
 
 								<button type="button" class="button cancel">{{_ "Cancel"}}</button>
@@ -36,7 +36,7 @@
 					</li>
 					{{/unless}}
 					<li>
-						<label>{{_ "Mobile_push"}}</label>
+						<label>{{_ "Mobile"}}</label>
 						<div>
 							{{#if editing 'mobilePushNotifications'}}
 								<label><input type="radio" name="mobilePushNotifications" value="all" checked="{{$eq mobilePushNotifications 'all'}}" /> {{_ "All_messages"}}</label>
@@ -68,7 +68,7 @@
 					</li>
 					{{#unless emailVerified}}
 					<li>
-						<div class="alert alert-warning">
+						<div class="alert alert-warning pending-background pending-border">
 							{{_ "You_wont_receive_email_notifications_because_you_have_not_verified_your_email"}}
 						</div>
 					</li>
diff --git a/packages/rocketchat-reactions/client/init.js b/packages/rocketchat-reactions/client/init.js
index 194f35bf968581aaffcb834b96ab643722ccc121..94373cb80a8e8834dff0858f807928bc67248ca0 100644
--- a/packages/rocketchat-reactions/client/init.js
+++ b/packages/rocketchat-reactions/client/init.js
@@ -7,7 +7,7 @@ Template.room.events({
 		let user = Meteor.user();
 		let room = RocketChat.models.Rooms.findOne({ _id: data._arguments[1].rid });
 
-		if (Array.isArray(room.muted) && room.muted.indexOf(user.username) !== -1) {
+		if (Array.isArray(room.muted) && room.muted.indexOf(user.username) !== -1 && !room.reactWhenReadOnly) {
 			return false;
 		}
 
@@ -57,10 +57,12 @@ Meteor.startup(function() {
 			let room = RocketChat.models.Rooms.findOne({ _id: message.rid });
 			let user = Meteor.user();
 
-			if (Array.isArray(room.muted) && room.muted.indexOf(user.username) !== -1) {
+			if (Array.isArray(room.muted) && room.muted.indexOf(user.username) !== -1 && !room.reactWhenReadOnly) {
 				return false;
 			} else if (!RocketChat.models.Subscriptions.findOne({ rid: message.rid })) {
 				return false;
+			} else if (message.private) {
+				return false;
 			}
 
 			return true;
diff --git a/packages/rocketchat-reactions/client/methods/setReaction.js b/packages/rocketchat-reactions/client/methods/setReaction.js
index ed3e7fa8b253290b2c962f9705d89a746ca374ea..2aff5c59d2840d9352c6953f1471280d8ec35edf 100644
--- a/packages/rocketchat-reactions/client/methods/setReaction.js
+++ b/packages/rocketchat-reactions/client/methods/setReaction.js
@@ -9,10 +9,12 @@ Meteor.methods({
 		let message = RocketChat.models.Messages.findOne({ _id: messageId });
 		let room = RocketChat.models.Rooms.findOne({ _id: message.rid });
 
-		if (Array.isArray(room.muted) && room.muted.indexOf(user.username) !== -1) {
+		if (Array.isArray(room.muted) && room.muted.indexOf(user.username) !== -1 && !room.reactWhenReadOnly) {
 			return false;
 		} else if (!RocketChat.models.Subscriptions.findOne({ rid: message.rid })) {
 			return false;
+		} else if (message.private) {
+			return false;
 		}
 
 		if (message.reactions && message.reactions[reaction] && message.reactions[reaction].usernames.indexOf(user.username) !== -1) {
@@ -25,8 +27,10 @@ Meteor.methods({
 			if (_.isEmpty(message.reactions)) {
 				delete message.reactions;
 				RocketChat.models.Messages.unsetReactions(messageId);
+				RocketChat.callbacks.run('unsetReaction', messageId, reaction);
 			} else {
 				RocketChat.models.Messages.setReactions(messageId, message.reactions);
+				RocketChat.callbacks.run('setReaction', messageId, reaction);
 			}
 		} else {
 			if (!message.reactions) {
@@ -40,6 +44,7 @@ Meteor.methods({
 			message.reactions[reaction].usernames.push(user.username);
 
 			RocketChat.models.Messages.setReactions(messageId, message.reactions);
+			RocketChat.callbacks.run('setReaction', messageId, reaction);
 		}
 
 		return;
diff --git a/packages/rocketchat-reactions/client/stylesheets/reaction.less b/packages/rocketchat-reactions/client/stylesheets/reaction.less
index c899b0c8c3834312899f47a9b9b89831b1dfd3f7..e16f4e2a9bbbe12a14017b493eb56c6c4dc7b6f5 100644
--- a/packages/rocketchat-reactions/client/stylesheets/reaction.less
+++ b/packages/rocketchat-reactions/client/stylesheets/reaction.less
@@ -2,6 +2,7 @@
 	.reactions {
 		padding: 0;
 		margin-top: 4px;
+
 		> li {
 			cursor: pointer;
 			position: relative;
@@ -9,18 +10,19 @@
 			line-height: 20px;
 			display: inline-block;
 			border-radius: 5px;
-			border: 1px solid #E7E7E7;
-			background-color: #FCFCFC;
+			border: 1px solid #e7e7e7;
+			background-color: #fcfcfc;
 			padding: 0 4px 0 2px;
-			color: #aaa;
+			color: #aaaaaa;
 
 			.reaction-emoji {
-				.emoji, .emojione {
+				.emoji,
+				.emojione {
 					min-width: 16px;
 					min-height: 16px;
 					width: 16px;
 					height: 16px;
-					margin: -.2ex .15em .2ex;
+					margin: -0.2ex 0.15em 0.2ex;
 				}
 			}
 
@@ -43,15 +45,14 @@
 			&.add-reaction {
 				visibility: hidden;
 				margin-left: 10px;
-				color: #888;
+				color: #888888;
 				opacity: 0;
 				padding: 0 2px;
-
-				.transition(opacity 0.2s ease);
+				transition: opacity 0.2s ease;
 
 				html.rtl & {
 					margin-right: 10px;
-					margin-left: 0px;
+					margin-left: 0;
 				}
 			}
 
diff --git a/packages/rocketchat-reactions/loadStylesheets.js b/packages/rocketchat-reactions/loadStylesheets.js
deleted file mode 100644
index 84dd4eef4230b37c660b9fb068cf2be54e5ff81d..0000000000000000000000000000000000000000
--- a/packages/rocketchat-reactions/loadStylesheets.js
+++ /dev/null
@@ -1,3 +0,0 @@
-RocketChat.theme.addPackageAsset(function() {
-	return Assets.getText('client/stylesheets/reaction.less');
-});
diff --git a/packages/rocketchat-reactions/package.js b/packages/rocketchat-reactions/package.js
index 3134920987a0faa9134a3cfe5b2fd508117ce127..cc1b2ea8551a4adee2a8fa6327d4b0c105e8370f 100644
--- a/packages/rocketchat-reactions/package.js
+++ b/packages/rocketchat-reactions/package.js
@@ -12,6 +12,7 @@ Package.onUse(function(api) {
 	api.use('rocketchat:lib');
 	api.use('rocketchat:theme');
 	api.use('rocketchat:ui');
+	api.use('less');
 
 	api.addFiles('client/init.js', 'client');
 
@@ -19,6 +20,5 @@ Package.onUse(function(api) {
 	api.addFiles('client/methods/setReaction.js', 'client');
 	api.addFiles('setReaction.js', 'server');
 
-	api.addAssets('client/stylesheets/reaction.less', 'server');
-	api.addFiles('loadStylesheets.js', 'server');
+	api.addFiles('client/stylesheets/reaction.less', 'client');
 });
diff --git a/packages/rocketchat-reactions/setReaction.js b/packages/rocketchat-reactions/setReaction.js
index 8b00073968462a5b3b5b7bb197501ea7c2f335e0..a76eb83e1e70856275c95241e71ea4d1a8cc41cc 100644
--- a/packages/rocketchat-reactions/setReaction.js
+++ b/packages/rocketchat-reactions/setReaction.js
@@ -7,6 +7,10 @@ Meteor.methods({
 
 		let message = RocketChat.models.Messages.findOneById(messageId);
 
+		if (!message) {
+			throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'setReaction' });
+		}
+
 		let room = Meteor.call('canAccessRoom', message.rid, Meteor.userId());
 
 		if (!room) {
@@ -15,7 +19,7 @@ Meteor.methods({
 
 		const user = Meteor.user();
 
-		if (Array.isArray(room.muted) && room.muted.indexOf(user.username) !== -1) {
+		if (Array.isArray(room.muted) && room.muted.indexOf(user.username) !== -1 && !room.reactWhenReadOnly) {
 			RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', {
 				_id: Random.id(),
 				rid: room._id,
@@ -37,8 +41,10 @@ Meteor.methods({
 			if (_.isEmpty(message.reactions)) {
 				delete message.reactions;
 				RocketChat.models.Messages.unsetReactions(messageId);
+				RocketChat.callbacks.run('unsetReaction', messageId, reaction);
 			} else {
 				RocketChat.models.Messages.setReactions(messageId, message.reactions);
+				RocketChat.callbacks.run('setReaction', messageId, reaction);
 			}
 		} else {
 			if (!message.reactions) {
@@ -52,6 +58,7 @@ Meteor.methods({
 			message.reactions[reaction].usernames.push(user.username);
 
 			RocketChat.models.Messages.setReactions(messageId, message.reactions);
+			RocketChat.callbacks.run('setReaction', messageId, reaction);
 		}
 
 		msgStream.emit(message.rid, message);
diff --git a/packages/rocketchat-sandstorm/client/setPath.js b/packages/rocketchat-sandstorm/client/setPath.js
new file mode 100644
index 0000000000000000000000000000000000000000..004ab4cee8ea0d3d4496f5feab6b796279f498fa
--- /dev/null
+++ b/packages/rocketchat-sandstorm/client/setPath.js
@@ -0,0 +1,12 @@
+function updateSandstormMetaData(msg) {
+	return window.parent.postMessage(msg, '*');
+}
+
+if (Meteor.settings.public.sandstorm) {
+	// Set the path of the parent frame when the grain's path changes.
+	// See https://docs.sandstorm.io/en/latest/developing/path/
+
+	FlowRouter.triggers.enter([({ path }) => {
+		updateSandstormMetaData({ setPath: path });
+	}]);
+}
diff --git a/packages/rocketchat-sandstorm/package.js b/packages/rocketchat-sandstorm/package.js
index a052ac15b38d74099d2a46753c033f4b99a271a1..bd68220fa2e1ae4f8b08708deb662010f0c3b889 100644
--- a/packages/rocketchat-sandstorm/package.js
+++ b/packages/rocketchat-sandstorm/package.js
@@ -6,8 +6,8 @@ Package.describe({
 });
 
 Package.onUse(function(api) {
-	api.use([ 'ecmascript', 'rocketchat:lib', 'jalik:ufs' ]);
+	api.use([ 'ecmascript', 'rocketchat:lib', 'jalik:ufs', 'kadira:flow-router']);
 
 	api.addFiles([ 'server/lib.js', 'server/events.js', 'server/powerbox.js' ], 'server');
-	api.addFiles([ 'client/powerboxListener.js' ], 'client');
+	api.addFiles([ 'client/powerboxListener.js', 'client/setPath.js' ], 'client');
 });
diff --git a/packages/rocketchat-slackbridge/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-slackbridge/.npm/package/npm-shrinkwrap.json
index 20e2ee7276f401899ccaba32f839ea1121e6ec32..093df3799e757e8b95a0eb92dcc76948d15b92fa 100644
--- a/packages/rocketchat-slackbridge/.npm/package/npm-shrinkwrap.json
+++ b/packages/rocketchat-slackbridge/.npm/package/npm-shrinkwrap.json
@@ -91,8 +91,8 @@
       "from": "cycle@>=1.0.0 <1.1.0"
     },
     "dashdash": {
-      "version": "1.14.0",
-      "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.0.tgz",
+      "version": "1.14.1",
+      "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
       "from": "dashdash@>=1.12.0 <2.0.0",
       "dependencies": {
         "assert-plus": {
@@ -103,8 +103,8 @@
       }
     },
     "debug": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz",
       "from": "debug@>=2.0.0 <3.0.0"
     },
     "delayed-stream": {
@@ -148,8 +148,8 @@
       "from": "forever-agent@>=0.6.1 <0.7.0"
     },
     "form-data": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.1.tgz",
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.2.tgz",
       "from": "form-data@>=2.1.1 <2.2.0"
     },
     "generate-function": {
@@ -270,24 +270,19 @@
       "from": "lodash@>=3.10.1 <4.0.0"
     },
     "mime-db": {
-      "version": "1.24.0",
-      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.24.0.tgz",
-      "from": "mime-db@>=1.24.0 <1.25.0"
+      "version": "1.25.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.25.0.tgz",
+      "from": "mime-db@>=1.25.0 <1.26.0"
     },
     "mime-types": {
-      "version": "2.1.12",
-      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.12.tgz",
+      "version": "2.1.13",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.13.tgz",
       "from": "mime-types@>=2.1.7 <2.2.0"
     },
     "ms": {
-      "version": "0.7.1",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
-      "from": "ms@0.7.1"
-    },
-    "node-uuid": {
-      "version": "1.4.7",
-      "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz",
-      "from": "node-uuid@>=1.4.7 <1.5.0"
+      "version": "0.7.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
+      "from": "ms@0.7.2"
     },
     "oauth-sign": {
       "version": "0.8.2",
@@ -309,11 +304,6 @@
       "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
       "from": "pinkie-promise@>=2.0.0 <3.0.0"
     },
-    "pkginfo": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz",
-      "from": "pkginfo@>=0.3.0 <0.4.0"
-    },
     "punycode": {
       "version": "1.4.1",
       "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
@@ -325,8 +315,8 @@
       "from": "qs@>=6.3.0 <6.4.0"
     },
     "request": {
-      "version": "2.76.0",
-      "resolved": "https://registry.npmjs.org/request/-/request-2.76.0.tgz",
+      "version": "2.79.0",
+      "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz",
       "from": "request@>=2.64.0 <3.0.0"
     },
     "retry": {
@@ -340,9 +330,9 @@
       "from": "semver@>=5.0.1 <5.1.0"
     },
     "slack-client": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/slack-client/-/slack-client-2.0.4.tgz",
-      "from": "slack-client@2.0.4"
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/slack-client/-/slack-client-2.0.6.tgz",
+      "from": "slack-client@2.0.6"
     },
     "sntp": {
       "version": "1.0.9",
@@ -392,8 +382,8 @@
       "from": "tunnel-agent@>=0.4.1 <0.5.0"
     },
     "tweetnacl": {
-      "version": "0.14.3",
-      "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.3.tgz",
+      "version": "0.14.4",
+      "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.4.tgz",
       "from": "tweetnacl@>=0.14.0 <0.15.0"
     },
     "ultron": {
@@ -406,14 +396,19 @@
       "resolved": "https://registry.npmjs.org/url-join/-/url-join-0.0.1.tgz",
       "from": "url-join@0.0.1"
     },
+    "uuid": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz",
+      "from": "uuid@>=3.0.0 <4.0.0"
+    },
     "verror": {
       "version": "1.3.6",
       "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz",
       "from": "verror@1.3.6"
     },
     "winston": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/winston/-/winston-2.2.0.tgz",
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/winston/-/winston-2.3.0.tgz",
       "from": "winston@>=2.1.1 <3.0.0",
       "dependencies": {
         "async": {
diff --git a/packages/rocketchat-slackbridge/README.md b/packages/rocketchat-slackbridge/README.md
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5ce00d638c508b078a97e1bcc6b8aa4bf841918f 100644
--- a/packages/rocketchat-slackbridge/README.md
+++ b/packages/rocketchat-slackbridge/README.md
@@ -0,0 +1,40 @@
+## Rocket.Chat Slack Bridge
+
+This package creates a bi-directional bridge between a single Slack installation and your Rocket.Chat installation.
+
+* Configure Rocket.Chat with your Slack API token
+* Invite 'rocketbot' to your Slack channel
+
+### Settings
+
+The following can be configured in your Rocket.Chat Administration SlackBridge panel.
+
+#### Enabled
+
+#### API Token
+
+#### Alias format
+
+#### Exclude bots
+
+#### SlackBridge Out Enabled
+
+#### SlackBridge Out All
+
+#### SlackBridge Out Channels
+
+### Features
+
+#### Group Chat Messages
+* Send and receive basic messages
+* Delete messages
+* Edit messages (Slack doesn't allow editing of BOT messages, so can't edit a Rocket msg in Slack)
+* React to messages (as BOT in Slack)
+
+#### Files
+
+#### Imports
+
+### TODO
+* Support multiple slack installations
+* Private IM's
diff --git a/packages/rocketchat-slackbridge/package.js b/packages/rocketchat-slackbridge/package.js
index 391129f9f38528aeb5f733d72ee0aef874801f0d..fc18d4da1b779a6ce2c48d59b27ae21f99838f25 100644
--- a/packages/rocketchat-slackbridge/package.js
+++ b/packages/rocketchat-slackbridge/package.js
@@ -20,5 +20,5 @@ Package.onUse(function(api) {
 });
 
 Npm.depends({
-	'slack-client': '2.0.4'
+	'slack-client': '2.0.6'
 });
diff --git a/packages/rocketchat-slackbridge/slackbridge.js b/packages/rocketchat-slackbridge/slackbridge.js
index ebb041d2918e7172b39efc5f20a5d2a8fb305428..cae745e0407f8e3e9921546e60f6548425619154 100644
--- a/packages/rocketchat-slackbridge/slackbridge.js
+++ b/packages/rocketchat-slackbridge/slackbridge.js
@@ -1,6 +1,7 @@
 /* globals logger */
 
 class SlackBridge {
+
 	constructor() {
 		this.util = Npm.require('util');
 		this.slackClient = Npm.require('slack-client');
@@ -10,23 +11,16 @@ class SlackBridge {
 		this.rtm = {};
 		this.connected = false;
 		this.userTags = {};
-		this.channelMap = {};
+		this.slackChannelMap = {};
+		this.reactionsMap = new Map();
 
 		RocketChat.settings.get('SlackBridge_APIToken', (key, value) => {
-			this.apiToken = value;
-			if (this.connected) {
-				this.disconnect();
-				this.connect();
-			} else if (RocketChat.settings.get('SlackBridge_Enabled')) {
-				this.connect();
-			}
-		});
-
-		RocketChat.settings.get('SlackBridge_Enabled', (key, value) => {
-			if (value && this.apiToken) {
-				this.connect();
-			} else {
-				this.disconnect();
+			if (value !== this.apiToken) {
+				this.apiToken = value;
+				if (this.connected) {
+					this.disconnect();
+					this.connect();
+				}
 			}
 		});
 
@@ -37,6 +31,14 @@ class SlackBridge {
 		RocketChat.settings.get('SlackBridge_ExcludeBotnames', (key, value) => {
 			this.excludeBotnames = value;
 		});
+
+		RocketChat.settings.get('SlackBridge_Enabled', (key, value) => {
+			if (value && this.apiToken) {
+				this.connect();
+			} else {
+				this.disconnect();
+			}
+		});
 	}
 
 	connect() {
@@ -46,16 +48,21 @@ class SlackBridge {
 			var RtmClient = this.slackClient.RtmClient;
 			this.rtm = new RtmClient(this.apiToken);
 			this.rtm.start();
-			this.setEvents();
+			this.registerForSlackEvents();
 			RocketChat.settings.get('SlackBridge_Out_Enabled', (key, value) => {
 				if (value) {
-					RocketChat.callbacks.add('afterSaveMessage', this.slackBridgeOut.bind(this), RocketChat.callbacks.priority.LOW, 'SlackBridge_Out');
+					this.registerForRocketEvents();
 				} else {
-					RocketChat.callbacks.remove('afterSaveMessage', 'SlackBridge_Out');
+					this.unregisterForRocketEvents();
 				}
 			});
 			Meteor.startup(() => {
-				this.populateChannelMap(); // If run outside of Meteor.startup, HTTP is not defined
+				try {
+					this.populateSlackChannelMap(); // If run outside of Meteor.startup, HTTP is not defined
+				} catch (err) {
+					logger.class.error('Error attempting to connect to Slack', err);
+					this.disconnect();
+				}
 			});
 		}
 	}
@@ -65,170 +72,174 @@ class SlackBridge {
 			this.connected = false;
 			this.rtm.disconnect && this.rtm.disconnect();
 			logger.connection.info('Disconnected');
-			RocketChat.callbacks.remove('afterSaveMessage', 'SlackBridge_Out');
+			this.unregisterForRocketEvents();
 		}
 	}
 
-	convertSlackMessageToRocketChat(message) {
-		if (!_.isEmpty(message)) {
-			message = message.replace(/<!everyone>/g, '@all');
-			message = message.replace(/<!channel>/g, '@all');
-			message = message.replace(/&gt;/g, '<');
-			message = message.replace(/&lt;/g, '>');
-			message = message.replace(/&amp;/g, '&');
-			message = message.replace(/:simple_smile:/g, ':smile:');
-			message = message.replace(/:memo:/g, ':pencil:');
-			message = message.replace(/:piggy:/g, ':pig:');
-			message = message.replace(/:uk:/g, ':gb:');
-			message = message.replace(/<(http[s]?:[^>]*)>/g, '$1');
-
-			message.replace(/(?:<@)([a-zA-Z0-9]+)(?:\|.+)?(?:>)/g, (match, userId) => {
+	convertSlackMsgTxtToRocketTxtFormat(slackMsgTxt) {
+		if (!_.isEmpty(slackMsgTxt)) {
+			slackMsgTxt = slackMsgTxt.replace(/<!everyone>/g, '@all');
+			slackMsgTxt = slackMsgTxt.replace(/<!channel>/g, '@all');
+			slackMsgTxt = slackMsgTxt.replace(/&gt;/g, '<');
+			slackMsgTxt = slackMsgTxt.replace(/&lt;/g, '>');
+			slackMsgTxt = slackMsgTxt.replace(/&amp;/g, '&');
+			slackMsgTxt = slackMsgTxt.replace(/:simple_smile:/g, ':smile:');
+			slackMsgTxt = slackMsgTxt.replace(/:memo:/g, ':pencil:');
+			slackMsgTxt = slackMsgTxt.replace(/:piggy:/g, ':pig:');
+			slackMsgTxt = slackMsgTxt.replace(/:uk:/g, ':gb:');
+			slackMsgTxt = slackMsgTxt.replace(/<(http[s]?:[^>]*)>/g, '$1');
+
+			slackMsgTxt.replace(/(?:<@)([a-zA-Z0-9]+)(?:\|.+)?(?:>)/g, (match, userId) => {
 				if (!this.userTags[userId]) {
-					this.findUser(userId) || this.addUser(userId); // This adds userTags for the userId
+					this.findRocketUser(userId) || this.addRocketUser(userId); // This adds userTags for the userId
 				}
 				let userTags = this.userTags[userId];
 				if (userTags) {
-					message = message.replace(userTags.slack, userTags.rocket);
+					slackMsgTxt = slackMsgTxt.replace(userTags.slack, userTags.rocket);
 				}
 			});
 		} else {
-			message = '';
+			slackMsgTxt = '';
 		}
-		return message;
+		return slackMsgTxt;
 	}
 
-	findChannel(channelId) {
-		logger.class.debug('Searching for Rocket.Chat channel', channelId);
-		return RocketChat.models.Rooms.findOneByImportId(channelId);
+	findRocketChannel(slackChannelId) {
+		return RocketChat.models.Rooms.findOneByImportId(slackChannelId);
 	}
 
-	addChannel(channelId, hasRetried = false) {
-		logger.class.debug('Adding channel from Slack', channelId);
-		let data = null;
+	addRocketChannel(slackChannelID, hasRetried = false) {
+		logger.class.debug('Adding Rocket.Chat channel from Slack', slackChannelID);
+		let slackResults = null;
 		let isGroup = false;
-		if (channelId.charAt(0) === 'C') {
-			data = HTTP.get('https://slack.com/api/channels.info', { params: { token: this.apiToken, channel: channelId } });
-		} else if (channelId.charAt(0) === 'G') {
-			data = HTTP.get('https://slack.com/api/groups.info', { params: { token: this.apiToken, channel: channelId } });
+		if (slackChannelID.charAt(0) === 'C') {
+			slackResults = HTTP.get('https://slack.com/api/channels.info', { params: { token: this.apiToken, channel: slackChannelID } });
+		} else if (slackChannelID.charAt(0) === 'G') {
+			slackResults = HTTP.get('https://slack.com/api/groups.info', { params: { token: this.apiToken, channel: slackChannelID } });
 			isGroup = true;
 		}
-		if (data && data.data && data.data.ok === true) {
-			let channelData = isGroup ? data.data.group : data.data.channel;
-			let existingRoom = RocketChat.models.Rooms.findOneByName(channelData.name);
+		if (slackResults && slackResults.data && slackResults.data.ok === true) {
+			let rocketChannelData = isGroup ? slackResults.data.group : slackResults.data.channel;
+			let existingRocketRoom = RocketChat.models.Rooms.findOneByName(rocketChannelData.name);
 
 			// If the room exists, make sure we have its id in importIds
-			if (existingRoom || channelData.is_general) {
-				channelData.rocketId = channelData.is_general ? 'GENERAL' : existingRoom._id;
-				RocketChat.models.Rooms.addImportIds(channelData.rocketId, channelData.id);
+			if (existingRocketRoom || rocketChannelData.is_general) {
+				rocketChannelData.rocketId = rocketChannelData.is_general ? 'GENERAL' : existingRocketRoom._id;
+				RocketChat.models.Rooms.addImportIds(rocketChannelData.rocketId, rocketChannelData.id);
 			} else {
-				let users = [];
-				for (let member of channelData.members) {
-					if (member !== channelData.creator) {
-						let user = this.findUser(member) || this.addUser(member);
-						if (user && user.username) {
-							users.push(user.username);
+				let rocketUsers = [];
+				for (let member of rocketChannelData.members) {
+					if (member !== rocketChannelData.creator) {
+						let rocketUser = this.findRocketUser(member) || this.addRocketUser(member);
+						if (rocketUser && rocketUser.username) {
+							rocketUsers.push(rocketUser.username);
 						}
 					}
 				}
-				let creator = channelData.creator ? this.findUser(channelData.creator) || this.addUser(channelData.creator) : null;
-				if (!creator) {
-					logger.class.error('Could not fetch room creator information', channelData.creator);
+				let rocketUserCreator = rocketChannelData.creator ? this.findRocketUser(rocketChannelData.creator) || this.addRocketUser(rocketChannelData.creator) : null;
+				if (!rocketUserCreator) {
+					logger.class.error('Could not fetch room creator information', rocketChannelData.creator);
 					return;
 				}
 
 				try {
-					let channel = RocketChat.createRoom(isGroup ? 'p' : 'c', channelData.name, creator.username, users);
-					channelData.rocketId = channel.rid;
+					let rocketChannel = RocketChat.createRoom(isGroup ? 'p' : 'c', rocketChannelData.name, rocketUserCreator.username, rocketUsers);
+					rocketChannelData.rocketId = rocketChannel.rid;
 				} catch (e) {
 					if (!hasRetried) {
 						logger.class.debug('Error adding channel from Slack. Will retry in 1s.', e.message);
 						// If first time trying to create channel fails, could be because of multiple messages received at the same time. Try again once after 1s.
 						Meteor._sleepForMs(1000);
-						return this.findChannel(channelId) || this.addChannel(channelId, true);
+						return this.findRocketChannel(slackChannelID) || this.addRocketChannel(slackChannelID, true);
 					} else {
 						console.log(e.message);
 					}
 				}
 
 				let roomUpdate = {
-					ts: new Date(channelData.created * 1000)
+					ts: new Date(rocketChannelData.created * 1000)
 				};
 				let lastSetTopic = 0;
-				if (!_.isEmpty(channelData.topic && channelData.topic.value)) {
-					roomUpdate.topic = channelData.topic.value;
-					lastSetTopic = channelData.topic.last_set;
+				if (!_.isEmpty(rocketChannelData.topic && rocketChannelData.topic.value)) {
+					roomUpdate.topic = rocketChannelData.topic.value;
+					lastSetTopic = rocketChannelData.topic.last_set;
 				}
-				if (!_.isEmpty(channelData.purpose && channelData.purpose.value) && channelData.purpose.last_set > lastSetTopic) {
-					roomUpdate.topic = channelData.purpose.value;
+				if (!_.isEmpty(rocketChannelData.purpose && rocketChannelData.purpose.value) && rocketChannelData.purpose.last_set > lastSetTopic) {
+					roomUpdate.topic = rocketChannelData.purpose.value;
 				}
-				RocketChat.models.Rooms.addImportIds(channelData.rocketId, channelData.id);
-				this.channelMap[channelData.rocketId] = { id: channelId, family: channelId.charAt(0) === 'C' ? 'channels' : 'groups' };
+				RocketChat.models.Rooms.addImportIds(rocketChannelData.rocketId, rocketChannelData.id);
+				this.slackChannelMap[rocketChannelData.rocketId] = { id: slackChannelID, family: slackChannelID.charAt(0) === 'C' ? 'channels' : 'groups' };
 			}
-			return RocketChat.models.Rooms.findOneById(channelData.rocketId);
+			return RocketChat.models.Rooms.findOneById(rocketChannelData.rocketId);
 		}
-
+		logger.class.debug('Channel not added');
 		return;
 	}
 
-	findUser(userId) {
-		logger.class.debug('Searching for Rocket.Chat user', userId);
-		let user = RocketChat.models.Users.findOneByImportId(userId);
-		if (user && !this.userTags[userId]) {
-			this.userTags[userId] = { slack: `<@${userId}>`, rocket: `@${user.username}` };
+	findRocketUser(slackUserID) {
+		let rocketUser = RocketChat.models.Users.findOneByImportId(slackUserID);
+		if (rocketUser && !this.userTags[slackUserID]) {
+			this.userTags[slackUserID] = { slack: `<@${slackUserID}>`, rocket: `@${rocketUser.username}` };
 		}
-		return user;
+		return rocketUser;
 	}
 
-	addUser(userId) {
-		logger.class.debug('Adding user from Slack', userId);
-		let data = HTTP.get('https://slack.com/api/users.info', { params: { token: this.apiToken, user: userId } });
-		if (data && data.data && data.data.ok === true && data.data.user) {
-			let userData = data.data.user;
-			let isBot = userData.is_bot === true;
-			let email = userData.profile && userData.profile.email || '';
-			let existingUser;
+	addRocketUser(slackUserID) {
+		logger.class.debug('Adding Rocket.Chat user from Slack', slackUserID);
+		let slackResults = HTTP.get('https://slack.com/api/users.info', { params: { token: this.apiToken, user: slackUserID } });
+		if (slackResults && slackResults.data && slackResults.data.ok === true && slackResults.data.user) {
+			let rocketUserData = slackResults.data.user;
+			let isBot = rocketUserData.is_bot === true;
+			let email = rocketUserData.profile && rocketUserData.profile.email || '';
+			let existingRocketUser;
 			if (!isBot) {
-				existingUser = RocketChat.models.Users.findOneByEmailAddress(email) || RocketChat.models.Users.findOneByUsername(userData.name);
+				existingRocketUser = RocketChat.models.Users.findOneByEmailAddress(email) || RocketChat.models.Users.findOneByUsername(rocketUserData.name);
 			} else {
-				existingUser = RocketChat.models.Users.findOneByUsername(userData.name);
+				existingRocketUser = RocketChat.models.Users.findOneByUsername(rocketUserData.name);
 			}
 
-			if (existingUser) {
-				userData.rocketId = existingUser._id;
-				userData.name = existingUser.username;
+			if (existingRocketUser) {
+				rocketUserData.rocketId = existingRocketUser._id;
+				rocketUserData.name = existingRocketUser.username;
 			} else {
-				let newUser = { password: Random.id() };
-				if (isBot || !email) {
-					newUser.username = userData.name;
-				} else {
+				let newUser = {
+					password: Random.id(),
+					username: rocketUserData.name
+				};
+
+				if (!isBot && email) {
 					newUser.email = email;
 				}
-				userData.rocketId = Accounts.createUser(newUser);
+
+				if (isBot) {
+					newUser.joinDefaultChannels = false;
+				}
+
+				rocketUserData.rocketId = Accounts.createUser(newUser);
 				let userUpdate = {
-					username: userData.name,
-					utcOffset: userData.tz_offset / 3600, // Slack's is -18000 which translates to Rocket.Chat's after dividing by 3600,
+					utcOffset: rocketUserData.tz_offset / 3600, // Slack's is -18000 which translates to Rocket.Chat's after dividing by 3600,
 					roles: isBot ? [ 'bot' ] : [ 'user' ]
 				};
 
-				if (userData.profile && userData.profile.real_name) {
-					userUpdate['name'] = userData.profile.real_name;
+				if (rocketUserData.profile && rocketUserData.profile.real_name) {
+					userUpdate['name'] = rocketUserData.profile.real_name;
 				}
 
-				if (userData.deleted) {
+				if (rocketUserData.deleted) {
 					userUpdate['active'] = false;
 					userUpdate['services.resume.loginTokens'] = [];
 				}
 
-				RocketChat.models.Users.update({ _id: userData.rocketId }, { $set: userUpdate });
+				RocketChat.models.Users.update({ _id: rocketUserData.rocketId }, { $set: userUpdate });
 
-				let user = RocketChat.models.Users.findOneById(userData.rocketId);
+				let user = RocketChat.models.Users.findOneById(rocketUserData.rocketId);
 
 				let url = null;
-				if (userData.profile) {
-					if (userData.profile.image_original) {
-						url = userData.profile.image_original;
-					} else if (userData.profile.image_512) {
-						url = userData.profile.image_512;
+				if (rocketUserData.profile) {
+					if (rocketUserData.profile.image_original) {
+						url = rocketUserData.profile.image_original;
+					} else if (rocketUserData.profile.image_512) {
+						url = rocketUserData.profile.image_512;
 					}
 				}
 				if (url) {
@@ -238,162 +249,224 @@ class SlackBridge {
 						logger.class.debug('Error setting user avatar', error.message);
 					}
 				}
-				RocketChat.addUserToDefaultChannels(user, true);
 			}
 
-			let importIds = [ userData.id ];
-			if (isBot && userData.profile && userData.profile.bot_id) {
-				importIds.push(userData.profile.bot_id);
+			let importIds = [ rocketUserData.id ];
+			if (isBot && rocketUserData.profile && rocketUserData.profile.bot_id) {
+				importIds.push(rocketUserData.profile.bot_id);
 			}
-			RocketChat.models.Users.addImportIds(userData.rocketId, importIds);
-			if (!this.userTags[userId]) {
-				this.userTags[userId] = { slack: `<@${userId}>`, rocket: `@${userData.name}` };
+			RocketChat.models.Users.addImportIds(rocketUserData.rocketId, importIds);
+			if (!this.userTags[slackUserID]) {
+				this.userTags[slackUserID] = { slack: `<@${slackUserID}>`, rocket: `@${rocketUserData.name}` };
 			}
-			logger.class.debug('User: ', userData.rocketId);
-			return RocketChat.models.Users.findOneById(userData.rocketId);
+			return RocketChat.models.Users.findOneById(rocketUserData.rocketId);
 		}
 		logger.class.debug('User not added');
 		return;
 	}
 
-	addAlias(username, msgObj) {
+	addAliasToRocketMsg(rocketUserName, rocketMsgObj) {
 		if (this.aliasFormat) {
-			var alias = this.util.format(this.aliasFormat, username);
+			var alias = this.util.format(this.aliasFormat, rocketUserName);
 
-			if (alias !== username) {
-				msgObj.alias = alias;
+			if (alias !== rocketUserName) {
+				rocketMsgObj.alias = alias;
 			}
 		}
 
-		return msgObj;
+		return rocketMsgObj;
 	}
 
-	sendMessage(room, user, message, msgDataDefaults, importing) {
-		if (message.type === 'message') {
-			let msgObj = {};
-			if (!_.isEmpty(message.subtype)) {
-				msgObj = this.processSubtypedMessage(room, user, message, importing);
-				if (!msgObj) {
+	createAndSaveRocketMessage(rocketChannel, rocketUser, slackMessage, rocketMsgDataDefaults, isImporting) {
+		if (slackMessage.type === 'message') {
+			let rocketMsgObj = {};
+			if (!_.isEmpty(slackMessage.subtype)) {
+				rocketMsgObj = this.processSlackSubtypedMessage(rocketChannel, rocketUser, slackMessage, isImporting);
+				if (!rocketMsgObj) {
 					return;
 				}
 			} else {
-				msgObj = {
-					msg: this.convertSlackMessageToRocketChat(message.text),
-					rid: room._id,
+				rocketMsgObj = {
+					msg: this.convertSlackMsgTxtToRocketTxtFormat(slackMessage.text),
+					rid: rocketChannel._id,
 					u: {
-						_id: user._id,
-						username: user.username
+						_id: rocketUser._id,
+						username: rocketUser.username
 					}
 				};
 
-				this.addAlias(user.username, msgObj);
+				this.addAliasToRocketMsg(rocketUser.username, rocketMsgObj);
 			}
-			_.extend(msgObj, msgDataDefaults);
-			if (message.edited) {
-				msgObj.editedAt = new Date(parseInt(message.edited.ts.split('.')[0]) * 1000);
+			_.extend(rocketMsgObj, rocketMsgDataDefaults);
+			if (slackMessage.edited) {
+				rocketMsgObj.editedAt = new Date(parseInt(slackMessage.edited.ts.split('.')[0]) * 1000);
 			}
-			if (message.subtype === 'bot_message') {
-				user = RocketChat.models.Users.findOneById('rocket.cat', { fields: { username: 1 } });
+			if (slackMessage.subtype === 'bot_message') {
+				rocketUser = RocketChat.models.Users.findOneById('rocket.cat', { fields: { username: 1 } });
 			}
 
-			if (message.pinned_to && message.pinned_to.indexOf(message.channel) !== -1) {
-				msgObj.pinned = true;
-				msgObj.pinnedAt = Date.now;
-				msgObj.pinnedBy = _.pick(user, '_id', 'username');
+			if (slackMessage.pinned_to && slackMessage.pinned_to.indexOf(slackMessage.channel) !== -1) {
+				rocketMsgObj.pinned = true;
+				rocketMsgObj.pinnedAt = Date.now;
+				rocketMsgObj.pinnedBy = _.pick(rocketUser, '_id', 'username');
 			}
-			if (message.subtype === 'bot_message') {
+			if (slackMessage.subtype === 'bot_message') {
 				Meteor.setTimeout(() => {
-					if (message.bot_id && message.ts && !RocketChat.models.Messages.findOneBySlackBotIdAndSlackTs(message.bot_id, message.ts)) {
-						RocketChat.sendMessage(user, msgObj, room, true);
+					if (slackMessage.bot_id && slackMessage.ts && !RocketChat.models.Messages.findOneBySlackBotIdAndSlackTs(slackMessage.bot_id, slackMessage.ts)) {
+						RocketChat.sendMessage(rocketUser, rocketMsgObj, rocketChannel, true);
 					}
 				}, 500);
 			} else {
-				RocketChat.sendMessage(user, msgObj, room, true);
+				logger.class.debug('Send message to Rocket.Chat');
+				RocketChat.sendMessage(rocketUser, rocketMsgObj, rocketChannel, true);
 			}
 		}
 	}
 
-	saveMessage(message, importing) {
-		let channel = message.channel ? this.findChannel(message.channel) || this.addChannel(message.channel) : null;
-		let user = null;
-		if (message.subtype === 'message_deleted' || message.subtype === 'message_changed') {
-			user = message.previous_message.user ? this.findUser(message.previous_message.user) || this.addUser(message.previous_message.user) : null;
-		} else if (message.subtype === 'bot_message') {
-			user = RocketChat.models.Users.findOneById('rocket.cat', { fields: { username: 1 } });
-		} else {
-			user = message.user ? this.findUser(message.user) || this.addUser(message.user) : null;
-		}
-		if (channel && user) {
-			let msgDataDefaults = {
-				_id: `slack-${message.channel}-${message.ts.replace(/\./g, '-')}`,
-				ts: new Date(parseInt(message.ts.split('.')[0]) * 1000)
-			};
-			if (importing) {
-				msgDataDefaults['imported'] = 'slackbridge';
+	/*
+	 https://api.slack.com/events/reaction_removed
+	 */
+	onSlackReactionRemoved(slackReactionMsg) {
+		if (slackReactionMsg) {
+			let rocketUser = this.getRocketUser(slackReactionMsg.user);
+			//Lets find our Rocket originated message
+			let rocketMsg = RocketChat.models.Messages.findOneBySlackTs(slackReactionMsg.item.ts);
+
+			if (!rocketMsg) {
+				//Must have originated from Slack
+				let rocketID = this.createRocketID(slackReactionMsg.item.channel, slackReactionMsg.item.ts);
+				rocketMsg = RocketChat.models.Messages.findOneById(rocketID);
 			}
-			try {
-				this.sendMessage(channel, user, message, msgDataDefaults, importing);
-			} catch (e) {
-				// http://www.mongodb.org/about/contributors/error-codes/
-				// 11000 == duplicate key error
-				if (e.name === 'MongoError' && e.code === 11000) {
+
+			if (rocketMsg && rocketUser) {
+				let rocketReaction = ':' + slackReactionMsg.reaction + ':';
+
+				//If the Rocket user has already been removed, then this is an echo back from slack
+				if (rocketMsg.reactions) {
+					let theReaction = rocketMsg.reactions[rocketReaction];
+					if (theReaction) {
+						if (theReaction.usernames.indexOf(rocketUser.username) === -1) {
+							return; //Reaction already removed
+						}
+					}
+				} else {
+					//Reaction already removed
 					return;
 				}
 
-				throw e;
+				//Stash this away to key off it later so we don't send it back to Slack
+				this.reactionsMap.set('unset'+rocketMsg._id+rocketReaction, rocketUser);
+				logger.class.debug('Removing reaction from Slack');
+				Meteor.runAsUser(rocketUser._id, () => {
+					Meteor.call('setReaction', rocketReaction, rocketMsg._id);
+				});
 			}
 		}
 	}
 
-	processSubtypedMessage(room, user, message, importing) {
-		let msgObj = null;
-		switch (message.subtype) {
+	/*
+	 https://api.slack.com/events/reaction_added
+	 */
+	onSlackReactionAdded(slackReactionMsg) {
+		if (slackReactionMsg) {
+			let rocketUser = this.getRocketUser(slackReactionMsg.user);
+
+			if (rocketUser.roles.includes('bot')) {
+				return;
+			}
+
+			//Lets find our Rocket originated message
+			let rocketMsg = RocketChat.models.Messages.findOneBySlackTs(slackReactionMsg.item.ts);
+
+			if (!rocketMsg) {
+				//Must have originated from Slack
+				let rocketID = this.createRocketID(slackReactionMsg.item.channel, slackReactionMsg.item.ts);
+				rocketMsg = RocketChat.models.Messages.findOneById(rocketID);
+			}
+
+			if (rocketMsg && rocketUser) {
+				let rocketReaction = ':' + slackReactionMsg.reaction + ':';
+
+				//If the Rocket user has already reacted, then this is Slack echoing back to us
+				if (rocketMsg.reactions) {
+					let theReaction = rocketMsg.reactions[rocketReaction];
+					if (theReaction) {
+						if (theReaction.usernames.indexOf(rocketUser.username) !== -1) {
+							return; //Already reacted
+						}
+					}
+				}
+
+				//Stash this away to key off it later so we don't send it back to Slack
+				this.reactionsMap.set('set'+rocketMsg._id+rocketReaction, rocketUser);
+				logger.class.debug('Adding reaction from Slack');
+				Meteor.runAsUser(rocketUser._id, () => {
+					Meteor.call('setReaction', rocketReaction, rocketMsg._id);
+				});
+			}
+		}
+	}
+
+	/**
+	 * We have received a message from slack and we need to save/delete/update it into rocket
+	 * https://api.slack.com/events/message
+	 */
+	onSlackMessage(slackMessage, isImporting) {
+		if (slackMessage.subtype) {
+			switch (slackMessage.subtype) {
+				case 'message_deleted':
+					this.processSlackMessageDeleted(slackMessage);
+					break;
+				case 'message_changed':
+					this.processSlackMessageChanged(slackMessage);
+					break;
+				default:
+					//Keeping backwards compatability for now, refactor later
+					this.processSlackNewMessage(slackMessage, isImporting);
+			}
+		} else {
+			//Simple message
+			this.processSlackNewMessage(slackMessage, isImporting);
+		}
+	}
+
+	processSlackSubtypedMessage(rocketChannel, rocketUser, slackMessage, isImporting) {
+		let rocketMsgObj = null;
+		switch (slackMessage.subtype) {
 			case 'bot_message':
-				if (message.username !== undefined && this.excludeBotnames && message.username.match(this.excludeBotnames)) {
+				if (slackMessage.username !== undefined && this.excludeBotnames && slackMessage.username.match(this.excludeBotnames)) {
 					return;
 				}
 
-				msgObj = {
-					msg: this.convertSlackMessageToRocketChat(message.text),
-					rid: room._id,
+				rocketMsgObj = {
+					msg: this.convertSlackMsgTxtToRocketTxtFormat(slackMessage.text),
+					rid: rocketChannel._id,
 					bot: true,
-					attachments: message.attachments,
-					username: message.username || message.bot_id
+					attachments: slackMessage.attachments,
+					username: slackMessage.username || slackMessage.bot_id
 				};
-				this.addAlias(message.username || message.bot_id, msgObj);
-				if (message.icons) {
-					msgObj.emoji = message.icons.emoji;
+				this.addAliasToRocketMsg(slackMessage.username || slackMessage.bot_id, rocketMsgObj);
+				if (slackMessage.icons) {
+					rocketMsgObj.emoji = slackMessage.icons.emoji;
 				}
-				return msgObj;
+				return rocketMsgObj;
 			case 'me_message':
-				return this.addAlias(user.username, {
-					msg: `_${this.convertSlackMessageToRocketChat(message.text)}_`
+				return this.addAliasToRocketMsg(rocketUser.username, {
+					msg: `_${this.convertSlackMsgTxtToRocketTxtFormat(slackMessage.text)}_`
 				});
-			case 'message_changed':
-				this.editMessage(room, user, message);
-				return;
-			case 'message_deleted':
-				if (message.previous_message) {
-					let _id = `slack-${message.channel}-${message.previous_message.ts.replace(/\./g, '-')}`;
-					msgObj = RocketChat.models.Messages.findOneById(_id);
-					if (msgObj) {
-						RocketChat.deleteMessage(msgObj, user);
-					}
-				}
-				return;
 			case 'channel_join':
-				if (importing) {
-					RocketChat.models.Messages.createUserJoinWithRoomIdAndUser(room._id, user, { ts: new Date(parseInt(message.ts.split('.')[0]) * 1000), imported: 'slackbridge' });
+				if (isImporting) {
+					RocketChat.models.Messages.createUserJoinWithRoomIdAndUser(rocketChannel._id, rocketUser, { ts: new Date(parseInt(slackMessage.ts.split('.')[0]) * 1000), imported: 'slackbridge' });
 				} else {
-					RocketChat.addUserToRoom(room._id, user);
+					RocketChat.addUserToRoom(rocketChannel._id, rocketUser);
 				}
 				return;
 			case 'group_join':
-				if (message.inviter) {
-					let inviter = message.inviter ? this.findUser(message.inviter) || this.addUser(message.inviter) : null;
-					if (importing) {
-						RocketChat.models.Messages.createUserAddedWithRoomIdAndUser(room._id, user, {
-							ts: new Date(parseInt(message.ts.split('.')[0]) * 1000),
+				if (slackMessage.inviter) {
+					let inviter = slackMessage.inviter ? this.findRocketUser(slackMessage.inviter) || this.addRocketUser(slackMessage.inviter) : null;
+					if (isImporting) {
+						RocketChat.models.Messages.createUserAddedWithRoomIdAndUser(rocketChannel._id, rocketUser, {
+							ts: new Date(parseInt(slackMessage.ts.split('.')[0]) * 1000),
 							u: {
 								_id: inviter._id,
 								username: inviter.username
@@ -401,67 +474,67 @@ class SlackBridge {
 							imported: 'slackbridge'
 						});
 					} else {
-						RocketChat.addUserToRoom(room._id, user, inviter);
+						RocketChat.addUserToRoom(rocketChannel._id, rocketUser, inviter);
 					}
 				}
 				return;
 			case 'channel_leave':
 			case 'group_leave':
-				if (importing) {
-					RocketChat.models.Messages.createUserLeaveWithRoomIdAndUser(room._id, user, {
-						ts: new Date(parseInt(message.ts.split('.')[0]) * 1000),
+				if (isImporting) {
+					RocketChat.models.Messages.createUserLeaveWithRoomIdAndUser(rocketChannel._id, rocketUser, {
+						ts: new Date(parseInt(slackMessage.ts.split('.')[0]) * 1000),
 						imported: 'slackbridge'
 					});
 				} else {
-					RocketChat.removeUserFromRoom(room._id, user);
+					RocketChat.removeUserFromRoom(rocketChannel._id, rocketUser);
 				}
 				return;
 			case 'channel_topic':
 			case 'group_topic':
-				if (importing) {
-					RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser('room_changed_topic', room._id, message.topic, user, { ts: new Date(parseInt(message.ts.split('.')[0]) * 1000), imported: 'slackbridge' });
+				if (isImporting) {
+					RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser('room_changed_topic', rocketChannel._id, slackMessage.topic, rocketUser, { ts: new Date(parseInt(slackMessage.ts.split('.')[0]) * 1000), imported: 'slackbridge' });
 				} else {
-					RocketChat.saveRoomTopic(room._id, message.topic, user, false);
+					RocketChat.saveRoomTopic(rocketChannel._id, slackMessage.topic, rocketUser, false);
 				}
 				return;
 			case 'channel_purpose':
 			case 'group_purpose':
-				if (importing) {
-					RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser('room_changed_topic', room._id, message.purpose, user, { ts: new Date(parseInt(message.ts.split('.')[0]) * 1000), imported: 'slackbridge' });
+				if (isImporting) {
+					RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser('room_changed_topic', rocketChannel._id, slackMessage.purpose, rocketUser, { ts: new Date(parseInt(slackMessage.ts.split('.')[0]) * 1000), imported: 'slackbridge' });
 				} else {
-					RocketChat.saveRoomTopic(room._id, message.purpose, user, false);
+					RocketChat.saveRoomTopic(rocketChannel._id, slackMessage.purpose, rocketUser, false);
 				}
 				return;
 			case 'channel_name':
 			case 'group_name':
-				if (importing) {
-					RocketChat.models.Messages.createRoomRenamedWithRoomIdRoomNameAndUser(room._id, message.name, user, { ts: new Date(parseInt(message.ts.split('.')[0]) * 1000), imported: 'slackbridge' });
+				if (isImporting) {
+					RocketChat.models.Messages.createRoomRenamedWithRoomIdRoomNameAndUser(rocketChannel._id, slackMessage.name, rocketUser, { ts: new Date(parseInt(slackMessage.ts.split('.')[0]) * 1000), imported: 'slackbridge' });
 				} else {
-					RocketChat.saveRoomName(room._id, message.name, user, false);
+					RocketChat.saveRoomName(rocketChannel._id, slackMessage.name, rocketUser, false);
 				}
 				return;
 			case 'channel_archive':
 			case 'group_archive':
-				if (!importing) {
-					RocketChat.archiveRoom(room);
+				if (!isImporting) {
+					RocketChat.archiveRoom(rocketChannel);
 				}
 				return;
 			case 'channel_unarchive':
 			case 'group_unarchive':
-				if (!importing) {
-					RocketChat.unarchiveRoom(room);
+				if (!isImporting) {
+					RocketChat.unarchiveRoom(rocketChannel);
 				}
 				return;
 			case 'file_share':
-				if (message.file && message.file.url_private_download !== undefined) {
+				if (slackMessage.file && slackMessage.file.url_private_download !== undefined) {
 					let details = {
-						message_id: `slack-${message.ts.replace(/\./g, '-')}`,
-						name: message.file.name,
-						size: message.file.size,
-						type: message.file.mimetype,
-						rid: room._id
+						message_id: `slack-${slackMessage.ts.replace(/\./g, '-')}`,
+						name: slackMessage.file.name,
+						size: slackMessage.file.size,
+						type: slackMessage.file.mimetype,
+						rid: rocketChannel._id
 					};
-					return this.uploadFile(details, message.file.url_private_download, user, room, new Date(parseInt(message.ts.split('.')[0]) * 1000), importing);
+					return this.uploadFileFromSlack(details, slackMessage.file.url_private_download, rocketUser, rocketChannel, new Date(parseInt(slackMessage.ts.split('.')[0]) * 1000), isImporting);
 				}
 				break;
 			case 'file_comment':
@@ -471,28 +544,28 @@ class SlackBridge {
 				logger.class.error('File mentioned not implemented');
 				return;
 			case 'pinned_item':
-				if (message.attachments && message.attachments[0] && message.attachments[0].text) {
-					msgObj = {
-						rid: room._id,
+				if (slackMessage.attachments && slackMessage.attachments[0] && slackMessage.attachments[0].text) {
+					rocketMsgObj = {
+						rid: rocketChannel._id,
 						t: 'message_pinned',
 						msg: '',
 						u: {
-							_id: user._id,
-							username: user.username
+							_id: rocketUser._id,
+							username: rocketUser.username
 						},
 						attachments: [{
-							'text' : this.convertSlackMessageToRocketChat(message.attachments[0].text),
-							'author_name' : message.attachments[0].author_subname,
-							'author_icon' : getAvatarUrlFromUsername(message.attachments[0].author_subname),
-							'ts' : new Date(parseInt(message.attachments[0].ts.split('.')[0]) * 1000)
+							'text' : this.convertSlackMsgTxtToRocketTxtFormat(slackMessage.attachments[0].text),
+							'author_name' : slackMessage.attachments[0].author_subname,
+							'author_icon' : getAvatarUrlFromUsername(slackMessage.attachments[0].author_subname),
+							'ts' : new Date(parseInt(slackMessage.attachments[0].ts.split('.')[0]) * 1000)
 						}]
 					};
 
-					if (!importing) {
-						RocketChat.models.Messages.setPinnedByIdAndUserId(`slack-${message.attachments[0].channel_id}-${message.attachments[0].ts.replace(/\./g, '-')}`, msgObj.u, true, new Date(parseInt(message.ts.split('.')[0]) * 1000));
+					if (!isImporting) {
+						RocketChat.models.Messages.setPinnedByIdAndUserId(`slack-${slackMessage.attachments[0].channel_id}-${slackMessage.attachments[0].ts.replace(/\./g, '-')}`, rocketMsgObj.u, true, new Date(parseInt(slackMessage.ts.split('.')[0]) * 1000));
 					}
 
-					return msgObj;
+					return rocketMsgObj;
 				} else {
 					logger.class.error('Pinned item with no attachment');
 				}
@@ -503,20 +576,6 @@ class SlackBridge {
 		}
 	}
 
-	/**
-	* Edits a message
-	**/
-	editMessage(room, user, message) {
-		let msgObj = {
-			//@TODO _id
-			_id: `slack-${message.channel}-${message.message.ts.replace(/\./g, '-')}`,
-			rid: room._id,
-			msg: this.convertSlackMessageToRocketChat(message.message.text)
-		};
-
-		RocketChat.updateMessage(msgObj, user);
-	}
-
 	/**
 	Uploads the file to the storage.
 	@param [Object] details an object with details about the upload. name, size, type, and rid
@@ -525,10 +584,11 @@ class SlackBridge {
 	@param [Object] room the Rocket.Chat room
 	@param [Date] timeStamp the timestamp the file was uploaded
 	**/
-	uploadFile(details, fileUrl, user, room, timeStamp, importing) {
+	//details, slackMessage.file.url_private_download, rocketUser, rocketChannel, new Date(parseInt(slackMessage.ts.split('.')[0]) * 1000), isImporting);
+	uploadFileFromSlack(details, slackFileURL, rocketUser, rocketChannel, timeStamp, isImporting) {
 		let url = Npm.require('url');
-		let requestModule = /https/i.test(fileUrl) ? Npm.require('https') : Npm.require('http');
-		var parsedUrl = url.parse(fileUrl, true);
+		let requestModule = /https/i.test(slackFileURL) ? Npm.require('https') : Npm.require('http');
+		var parsedUrl = url.parse(slackFileURL, true);
 		parsedUrl.headers = { 'Authorization': 'Bearer ' + this.apiToken };
 		requestModule.get(parsedUrl, Meteor.bindEnvironment((stream) => {
 			let fileId = Meteor.fileStore.create(details);
@@ -572,7 +632,7 @@ class SlackBridge {
 							attachments: [attachment]
 						};
 
-						if (importing) {
+						if (isImporting) {
 							msg.imported = 'slackbridge';
 						}
 
@@ -580,17 +640,31 @@ class SlackBridge {
 							msg['_id'] = details.message_id;
 						}
 
-						return RocketChat.sendMessage(user, msg, room, true);
+						return RocketChat.sendMessage(rocketUser, msg, rocketChannel, true);
 					}
 				});
 			}
 		}));
 	}
 
-	setEvents() {
+	registerForRocketEvents() {
+		RocketChat.callbacks.add('afterSaveMessage', this.onRocketMessage.bind(this), RocketChat.callbacks.priority.LOW, 'SlackBridge_Out');
+		RocketChat.callbacks.add('afterDeleteMessage', this.onRocketMessageDelete.bind(this), RocketChat.callbacks.priority.LOW, 'SlackBridge_Delete');
+		RocketChat.callbacks.add('setReaction', this.onRocketSetReaction.bind(this), RocketChat.callbacks.priority.LOW, 'SlackBridge_SetReaction');
+		RocketChat.callbacks.add('unsetReaction', this.onRocketUnSetReaction.bind(this), RocketChat.callbacks.priority.LOW, 'SlackBridge_UnSetReaction');
+	}
+
+	unregisterForRocketEvents() {
+		RocketChat.callbacks.remove('afterSaveMessage', 'SlackBridge_Out');
+		RocketChat.callbacks.remove('afterDeleteMessage', 'SlackBridge_Delete');
+		RocketChat.callbacks.remove('setReaction', 'SlackBridge_SetReaction');
+		RocketChat.callbacks.remove('unsetReaction', 'SlackBridge_UnSetReaction');
+	}
+
+	registerForSlackEvents() {
 		var CLIENT_EVENTS = this.slackClient.CLIENT_EVENTS;
 		this.rtm.on(CLIENT_EVENTS.RTM.AUTHENTICATED, () => {
-			logger.connection.info('Connected');
+			logger.connection.info('Connected to Slack');
 		});
 
 		this.rtm.on(CLIENT_EVENTS.RTM.UNABLE_TO_RTM_START, () => {
@@ -616,10 +690,24 @@ class SlackBridge {
 		* 	inviter: [message_subtype = 'group_join|channel_join' -> user_id]
 		* }
 		**/
-		this.rtm.on(RTM_EVENTS.MESSAGE, Meteor.bindEnvironment((message) => {
-			logger.events.debug('MESSAGE: ', message);
-			if (message) {
-				this.saveMessage(message);
+		this.rtm.on(RTM_EVENTS.MESSAGE, Meteor.bindEnvironment((slackMessage) => {
+			logger.events.debug('OnSlackEvent-MESSAGE: ', slackMessage);
+			if (slackMessage) {
+				this.onSlackMessage(slackMessage);
+			}
+		}));
+
+		this.rtm.on(RTM_EVENTS.REACTION_ADDED, Meteor.bindEnvironment((reactionMsg) => {
+			logger.events.debug('OnSlackEvent-REACTION_ADDED: ', reactionMsg);
+			if (reactionMsg) {
+				this.onSlackReactionAdded(reactionMsg);
+			}
+		}));
+
+		this.rtm.on(RTM_EVENTS.REACTION_REMOVED, Meteor.bindEnvironment((reactionMsg) => {
+			logger.events.debug('OnSlackEvent-REACTION_REMOVED: ', reactionMsg);
+			if (reactionMsg) {
+				this.onSlackReactionRemoved(reactionMsg);
 			}
 		}));
 
@@ -809,12 +897,12 @@ class SlackBridge {
 		this.rtm.on(RTM_EVENTS.TEAM_JOIN, Meteor.bindEnvironment(() => {}));
 	}
 
-	findSlackChannel(name) {
-		logger.class.debug('Searching for Slack channel or group', name);
+	findSlackChannel(rocketChannelName) {
+		logger.class.debug('Searching for Slack channel or group', rocketChannelName);
 		let response = HTTP.get('https://slack.com/api/channels.list', { params: { token: this.apiToken } });
 		if (response && response.data && _.isArray(response.data.channels) && response.data.channels.length > 0) {
 			for (let channel of response.data.channels) {
-				if (channel.name === name && channel.is_member === true) {
+				if (channel.name === rocketChannelName && channel.is_member === true) {
 					return channel;
 				}
 			}
@@ -822,7 +910,7 @@ class SlackBridge {
 		response = HTTP.get('https://slack.com/api/groups.list', { params: { token: this.apiToken } });
 		if (response && response.data && _.isArray(response.data.groups) && response.data.groups.length > 0) {
 			for (let group of response.data.groups) {
-				if (group.name === name) {
+				if (group.name === rocketChannelName) {
 					return group;
 				}
 			}
@@ -840,20 +928,20 @@ class SlackBridge {
 					latest = message.ts;
 				}
 				message.channel = options.channel;
-				this.saveMessage(message, true);
+				this.onSlackMessage(message, true);
 			}
 			return { has_more: response.data.has_more, ts: latest };
 		}
 	}
 
-	copyChannelInfo(rid, channelMap) {
+	copySlackChannelInfo(rid, channelMap) {
 		logger.class.debug('Copying users from Slack channel to Rocket.Chat', channelMap.id, rid);
 		let response = HTTP.get('https://slack.com/api/' + channelMap.family + '.info', { params: { token: this.apiToken, channel: channelMap.id } });
 		if (response && response.data) {
 			let data = channelMap.family === 'channels' ? response.data.channel : response.data.group;
 			if (data && _.isArray(data.members) && data.members.length > 0) {
 				for (let member of data.members) {
-					let user = this.findUser(member) || this.addUser(member);
+					let user = this.findRocketUser(member) || this.addRocketUser(member);
 					if (user) {
 						logger.class.debug('Adding user to room', user.username, rid);
 						RocketChat.addUserToRoom(rid, user, null, true);
@@ -883,7 +971,7 @@ class SlackBridge {
 			}
 
 			if (topic) {
-				let creator = this.findUser(topic_creator) || this.addUser(topic_creator);
+				let creator = this.findRocketUser(topic_creator) || this.addRocketUser(topic_creator);
 				logger.class.debug('Setting room topic', rid, topic, creator.username);
 				RocketChat.saveRoomTopic(rid, topic, creator, false);
 			}
@@ -895,7 +983,7 @@ class SlackBridge {
 		if (response && response.data && _.isArray(response.data.items) && response.data.items.length > 0) {
 			for (let pin of response.data.items) {
 				if (pin.message) {
-					let user = this.findUser(pin.message.user);
+					let user = this.findRocketUser(pin.message.user);
 					let msgObj = {
 						rid: rid,
 						t: 'message_pinned',
@@ -905,7 +993,7 @@ class SlackBridge {
 							username: user.username
 						},
 						attachments: [{
-							'text' : this.convertSlackMessageToRocketChat(pin.message.text),
+							'text' : this.convertSlackMsgTxtToRocketTxtFormat(pin.message.text),
 							'author_name' : user.username,
 							'author_icon' : getAvatarUrlFromUsername(user.username),
 							'ts' : new Date(parseInt(pin.message.ts.split('.')[0]) * 1000)
@@ -922,23 +1010,23 @@ class SlackBridge {
 		logger.class.info('importMessages: ', rid);
 		let rocketchat_room = RocketChat.models.Rooms.findOneById(rid);
 		if (rocketchat_room) {
-			if (this.channelMap[rid]) {
-				this.copyChannelInfo(rid, this.channelMap[rid]);
+			if (this.slackChannelMap[rid]) {
+				this.copySlackChannelInfo(rid, this.slackChannelMap[rid]);
 
-				logger.class.debug('Importing messages from Slack to Rocket.Chat', this.channelMap[rid], rid);
-				let results = this.importFromHistory(this.channelMap[rid].family, { channel: this.channelMap[rid].id, oldest: 1 });
+				logger.class.debug('Importing messages from Slack to Rocket.Chat', this.slackChannelMap[rid], rid);
+				let results = this.importFromHistory(this.slackChannelMap[rid].family, { channel: this.slackChannelMap[rid].id, oldest: 1 });
 				while (results && results.has_more) {
-					results = this.importFromHistory(this.channelMap[rid].family, { channel: this.channelMap[rid].id, oldest: results.ts });
+					results = this.importFromHistory(this.slackChannelMap[rid].family, { channel: this.slackChannelMap[rid].id, oldest: results.ts });
 				}
 
-				logger.class.debug('Pinning Slack channel messages to Rocket.Chat', this.channelMap[rid], rid);
-				this.copyPins(rid, this.channelMap[rid]);
+				logger.class.debug('Pinning Slack channel messages to Rocket.Chat', this.slackChannelMap[rid], rid);
+				this.copyPins(rid, this.slackChannelMap[rid]);
 
 				return callback();
 			} else {
 				let slack_room = this.findSlackChannel(rocketchat_room.name);
 				if (slack_room) {
-					this.channelMap[rid] = { id: slack_room.id, family: slack_room.id.charAt(0) === 'C' ? 'channels' : 'groups' };
+					this.slackChannelMap[rid] = { id: slack_room.id, family: slack_room.id.charAt(0) === 'C' ? 'channels' : 'groups' };
 					return this.importMessages(rid, callback);
 				} else {
 					logger.class.error('Could not find Slack room with specified name', rocketchat_room.name);
@@ -951,63 +1039,327 @@ class SlackBridge {
 		}
 	}
 
-	populateChannelMap() {
+	populateSlackChannelMap() {
 		logger.class.debug('Populating channel map');
 		let response = HTTP.get('https://slack.com/api/channels.list', { params: { token: this.apiToken } });
 		if (response && response.data && _.isArray(response.data.channels) && response.data.channels.length > 0) {
-			for (let channel of response.data.channels) {
-				let rocketchat_room = RocketChat.models.Rooms.findOneByName(channel.name, { fields: { _id: 1 } });
+			for (let slackChannel of response.data.channels) {
+				let rocketchat_room = RocketChat.models.Rooms.findOneByName(slackChannel.name, { fields: { _id: 1 } });
 				if (rocketchat_room) {
-					this.channelMap[rocketchat_room._id] = { id: channel.id, family: channel.id.charAt(0) === 'C' ? 'channels' : 'groups' };
+					this.slackChannelMap[rocketchat_room._id] = { id: slackChannel.id, family: slackChannel.id.charAt(0) === 'C' ? 'channels' : 'groups' };
 				}
 			}
 		}
 		response = HTTP.get('https://slack.com/api/groups.list', { params: { token: this.apiToken } });
 		if (response && response.data && _.isArray(response.data.groups) && response.data.groups.length > 0) {
-			for (let group of response.data.groups) {
-				let rocketchat_room = RocketChat.models.Rooms.findOneByName(group.name, { fields: { _id: 1 } });
+			for (let slackGroup of response.data.groups) {
+				let rocketchat_room = RocketChat.models.Rooms.findOneByName(slackGroup.name, { fields: { _id: 1 } });
 				if (rocketchat_room) {
-					this.channelMap[rocketchat_room._id] = { id: group.id, family: group.id.charAt(0) === 'C' ? 'channels' : 'groups' };
+					this.slackChannelMap[rocketchat_room._id] = { id: slackGroup.id, family: slackGroup.id.charAt(0) === 'C' ? 'channels' : 'groups' };
 				}
 			}
 		}
 	}
 
-	slackBridgeOut(message) {
+	onRocketMessageDelete(rocketMessageDeleted) {
+		logger.class.debug('onRocketMessageDelete', rocketMessageDeleted);
+
+		this.postDeleteMessageToSlack(rocketMessageDeleted);
+	}
+
+	onRocketSetReaction(rocketMsgID, reaction) {
+		logger.class.debug('onRocketSetReaction');
+
+		if (rocketMsgID && reaction) {
+			if (this.reactionsMap.delete('set'+rocketMsgID+reaction)) {
+				//This was a Slack reaction, we don't need to tell Slack about it
+				return;
+			}
+			let rocketMsg = RocketChat.models.Messages.findOneById(rocketMsgID);
+			if (rocketMsg) {
+				let slackChannel = this.slackChannelMap[rocketMsg.rid].id;
+				let slackTS = this.getSlackTS(rocketMsg);
+				this.postReactionAddedToSlack(reaction.replace(/:/g, ''), slackChannel, slackTS);
+			}
+		}
+	}
+
+	onRocketUnSetReaction(rocketMsgID, reaction) {
+		logger.class.debug('onRocketUnSetReaction');
+
+		if (rocketMsgID && reaction) {
+			if (this.reactionsMap.delete('unset'+rocketMsgID+reaction)) {
+				//This was a Slack unset reaction, we don't need to tell Slack about it
+				return;
+			}
+
+			let rocketMsg = RocketChat.models.Messages.findOneById(rocketMsgID);
+			if (rocketMsg) {
+				let slackChannel = this.slackChannelMap[rocketMsg.rid].id;
+				let slackTS = this.getSlackTS(rocketMsg);
+				this.postReactionRemoveToSlack(reaction.replace(/:/g, ''), slackChannel, slackTS);
+			}
+		}
+	}
+
+	onRocketMessage(rocketMessage) {
+		logger.class.debug('onRocketMessage', rocketMessage);
+
+		if (rocketMessage.editedAt) {
+			//This is an Edit Event
+			this.processRocketMessageChanged(rocketMessage);
+			return rocketMessage;
+		}
 		// Ignore messages originating from Slack
-		if (message._id.indexOf('slack-') === 0) {
-			return message;
+		if (rocketMessage._id.indexOf('slack-') === 0) {
+			return rocketMessage;
+		}
+
+		//Probably a new message from Rocket.Chat
+		let outSlackChannels = RocketChat.settings.get('SlackBridge_Out_All') ? _.keys(this.slackChannelMap) : _.pluck(RocketChat.settings.get('SlackBridge_Out_Channels'), '_id') || [];
+		//logger.class.debug('Out SlackChannels: ', outSlackChannels);
+		if (outSlackChannels.indexOf(rocketMessage.rid) !== -1) {
+			this.postMessageToSlack(this.slackChannelMap[rocketMessage.rid], rocketMessage);
 		}
-		let outChannels = RocketChat.settings.get('SlackBridge_Out_All') ? _.keys(this.channelMap) : _.pluck(RocketChat.settings.get('SlackBridge_Out_Channels'), '_id') || [];
-		logger.class.debug('Out Channels: ', outChannels);
-		if (outChannels.indexOf(message.rid) !== -1) {
-			logger.class.debug('Message out', message);
-			this.postMessage(this.channelMap[message.rid], message);
+		return rocketMessage;
+	}
+
+	/*
+	 https://api.slack.com/methods/reactions.add
+	 */
+	postReactionAddedToSlack(reaction, slackChannel, slackTS) {
+		if (reaction && slackChannel && slackTS) {
+			let data = {
+				token: this.apiToken,
+				name: reaction,
+				channel: slackChannel,
+				timestamp: slackTS
+			};
+
+			logger.class.debug('Posting Add Reaction to Slack');
+			const postResult = HTTP.post('https://slack.com/api/reactions.add', { params: data });
+			if (postResult.statusCode === 200 && postResult.data && postResult.data.ok === true) {
+				logger.class.debug('Reaction added to Slack');
+			}
 		}
-		return message;
 	}
 
-	postMessage(room, message) {
-		if (room && room.id) {
-			let iconUrl = getAvatarUrlFromUsername(message.u && message.u.username);
+	/*
+	 https://api.slack.com/methods/reactions.remove
+	 */
+	postReactionRemoveToSlack(reaction, slackChannel, slackTS) {
+		if (reaction && slackChannel && slackTS) {
+			let data = {
+				token: this.apiToken,
+				name: reaction,
+				channel: slackChannel,
+				timestamp: slackTS
+			};
+
+			logger.class.debug('Posting Remove Reaction to Slack');
+			const postResult = HTTP.post('https://slack.com/api/reactions.remove', { params: data });
+			if (postResult.statusCode === 200 && postResult.data && postResult.data.ok === true) {
+				logger.class.debug('Reaction removed from Slack');
+			}
+		}
+	}
+
+	postDeleteMessageToSlack(rocketMessage) {
+		if (rocketMessage) {
+			let data = {
+				token: this.apiToken,
+				ts: this.getSlackTS(rocketMessage),
+				channel: this.slackChannelMap[rocketMessage.rid].id,
+				as_user: true
+			};
+
+			logger.class.debug('Post Delete Message to Slack', data);
+			const postResult = HTTP.post('https://slack.com/api/chat.delete', { params: data });
+			if (postResult.statusCode === 200 && postResult.data && postResult.data.ok === true) {
+				logger.class.debug('Message deleted on Slack');
+			}
+		}
+	}
+
+	postMessageToSlack(slackChannel, rocketMessage) {
+		if (slackChannel && slackChannel.id) {
+			let iconUrl = getAvatarUrlFromUsername(rocketMessage.u && rocketMessage.u.username);
 			if (iconUrl) {
 				iconUrl = Meteor.absoluteUrl().replace(/\/$/, '') + iconUrl;
 			}
 			let data = {
 				token: this.apiToken,
-				text: message.msg,
-				channel: room.id,
-				username: message.u && message.u.username,
+				text: rocketMessage.msg,
+				channel: slackChannel.id,
+				username: rocketMessage.u && rocketMessage.u.username,
 				icon_url: iconUrl,
 				link_names: 1
 			};
-			logger.class.debug('Post Message', data);
+			logger.class.debug('Post Message To Slack', data);
 			const postResult = HTTP.post('https://slack.com/api/chat.postMessage', { params: data });
 			if (postResult.statusCode === 200 && postResult.data && postResult.data.message && postResult.data.message.bot_id && postResult.data.message.ts) {
-				RocketChat.models.Messages.setSlackBotIdAndSlackTs(message._id, postResult.data.message.bot_id, postResult.data.message.ts);
+				RocketChat.models.Messages.setSlackBotIdAndSlackTs(rocketMessage._id, postResult.data.message.bot_id, postResult.data.message.ts);
+				logger.class.debug('RocketMsgID=' + rocketMessage._id + ' SlackMsgID=' + postResult.data.message.ts + ' SlackBotID=' + postResult.data.message.bot_id);
+			}
+		}
+	}
+
+	/*
+	 https://api.slack.com/methods/chat.update
+	 */
+	postMessageUpdateToSlack(slackChannel, rocketMessage) {
+		if (slackChannel && slackChannel.id) {
+			let data = {
+				token: this.apiToken,
+				ts: this.getSlackTS(rocketMessage),
+				channel: slackChannel.id,
+				text: rocketMessage.msg,
+				as_user: true
+			};
+			logger.class.debug('Post UpdateMessage To Slack', data);
+			const postResult = HTTP.post('https://slack.com/api/chat.update', { params: data });
+			if (postResult.statusCode === 200 && postResult.data && postResult.data.ok === true) {
+				logger.class.debug('Message updated on Slack');
+			}
+		}
+	}
+
+	processRocketMessageChanged(rocketMessage) {
+		if (rocketMessage) {
+			if (rocketMessage.updatedBySlack) {
+				//We have already processed this
+				delete rocketMessage.updatedBySlack;
+				return;
 			}
+
+			//This was a change from Rocket.Chat
+			let slackChannel = this.slackChannelMap[rocketMessage.rid];
+			this.postMessageUpdateToSlack(slackChannel, rocketMessage);
 		}
 	}
+
+	/*
+	 https://api.slack.com/events/message/message_deleted
+	 */
+	processSlackMessageDeleted(slackMessage) {
+		if (slackMessage.previous_message) {
+			let rocketChannel = this.getRocketChannel(slackMessage);
+			let rocketUser = RocketChat.models.Users.findOneById('rocket.cat', { fields: { username: 1 } });
+
+			if (rocketChannel && rocketUser) {
+				//Find the Rocket message to delete
+				let rocketMsgObj = RocketChat.models.Messages
+					.findOneBySlackBotIdAndSlackTs(slackMessage.previous_message.bot_id, slackMessage.previous_message.ts);
+
+				if (!rocketMsgObj) {
+					//Must have been a Slack originated msg
+					let _id = this.createRocketID(slackMessage.channel, slackMessage.previous_message.ts);
+					rocketMsgObj = RocketChat.models.Messages.findOneById(_id);
+				}
+
+				if (rocketMsgObj) {
+					RocketChat.deleteMessage(rocketMsgObj, rocketUser);
+					logger.class.debug('Rocket message deleted by Slack');
+				}
+			}
+		}
+	}
+
+	/*
+	 https://api.slack.com/events/message/message_changed
+	 */
+	processSlackMessageChanged(slackMessage) {
+		if (slackMessage.previous_message) {
+			let currentMsg = RocketChat.models.Messages.findOneById(this.createRocketID(slackMessage.channel, slackMessage.message.ts));
+
+			//Only process this change, if its an actual update (not just Slack repeating back our Rocket original change)
+			if (currentMsg && (slackMessage.message.text !== currentMsg.msg)) {
+				let rocketChannel = this.getRocketChannel(slackMessage);
+				let rocketUser = slackMessage.previous_message.user ? this.findRocketUser(slackMessage.previous_message.user) || this.addRocketUser(slackMessage.previous_message.user) : null;
+
+				let rocketMsgObj = {
+					//@TODO _id
+					_id: this.createRocketID(slackMessage.channel, slackMessage.previous_message.ts),
+					rid: rocketChannel._id,
+					msg: this.convertSlackMsgTxtToRocketTxtFormat(slackMessage.message.text),
+					updatedBySlack: true	//We don't want to notify slack about this change since Slack initiated it
+				};
+
+				RocketChat.updateMessage(rocketMsgObj, rocketUser);
+				logger.class.debug('Rocket message updated by Slack');
+			}
+		}
+	}
+
+	/*
+	 This method will get refactored and broken down into single responsibilities
+	 */
+	processSlackNewMessage(slackMessage, isImporting) {
+		let rocketChannel = this.getRocketChannel(slackMessage);
+		let rocketUser = null;
+		if (slackMessage.subtype === 'bot_message') {
+			rocketUser = RocketChat.models.Users.findOneById('rocket.cat', { fields: { username: 1 } });
+		} else {
+			rocketUser = slackMessage.user ? this.findRocketUser(slackMessage.user) || this.addRocketUser(slackMessage.user) : null;
+		}
+		if (rocketChannel && rocketUser) {
+			let msgDataDefaults = {
+				_id: this.createRocketID(slackMessage.channel, slackMessage.ts),
+				ts: new Date(parseInt(slackMessage.ts.split('.')[0]) * 1000)
+			};
+			if (isImporting) {
+				msgDataDefaults['imported'] = 'slackbridge';
+			}
+			try {
+				this.createAndSaveRocketMessage(rocketChannel, rocketUser, slackMessage, msgDataDefaults, isImporting);
+			} catch (e) {
+				// http://www.mongodb.org/about/contributors/error-codes/
+				// 11000 == duplicate key error
+				if (e.name === 'MongoError' && e.code === 11000) {
+					return;
+				}
+
+				throw e;
+			}
+		}
+	}
+
+	/**
+	 * Retrieves the Slack TS from a Rocket msg that originated from Slack
+	 * @param rocketMsg
+	 * @returns Slack TS or undefined if not a message that originated from slack
+	 * @private
+	 */
+	getSlackTS(rocketMsg) {
+		//slack-G3KJGGE15-1483081061-000169
+		let slackTS;
+		let index = rocketMsg._id.indexOf('slack-');
+		if (index === 0) {
+			//This is a msg that originated from Slack
+			slackTS = rocketMsg._id.substr(6, rocketMsg._id.length);
+			index = slackTS.indexOf('-');
+			slackTS = slackTS.substr(index+1, slackTS.length);
+			slackTS = slackTS.replace('-', '.');
+		} else {
+			//This probably originated as a Rocket msg, but has been sent to Slack
+			slackTS = rocketMsg.slackTs;
+		}
+
+		return slackTS;
+	}
+
+	getRocketChannel(slackMessage) {
+		return slackMessage.channel ? this.findRocketChannel(slackMessage.channel) || this.addRocketChannel(slackMessage.channel) : null;
+	}
+
+	getRocketUser(slackUser) {
+		return slackUser ? this.findRocketUser(slackUser) || this.addRocketUser(slackUser) : null;
+	}
+
+	createRocketID(slackChannel, ts) {
+		return `slack-${slackChannel}-${ts.replace(/\./g, '-')}`;
+	}
+
 }
 
 RocketChat.SlackBridge = new SlackBridge;
diff --git a/packages/rocketchat-slashcommands-invite/server.coffee b/packages/rocketchat-slashcommands-invite/server.coffee
index f9adc943e1d288e0908ef644237786f16904f3e2..138e3da0047c44fe28a7d1ac731c25c3621fde97 100644
--- a/packages/rocketchat-slashcommands-invite/server.coffee
+++ b/packages/rocketchat-slashcommands-invite/server.coffee
@@ -25,7 +25,7 @@ class Invite
 			return
 
 		usernames = usernames.filter((username) ->
-			if not RocketChat.models.Rooms.findOneByIdContainigUsername(item.rid, username)?
+			if not RocketChat.models.Rooms.findOneByIdContainingUsername(item.rid, username)?
 				return true
 
 			# Cancel if user is already in this room
diff --git a/packages/rocketchat-slashcommands-join/server.coffee b/packages/rocketchat-slashcommands-join/server.coffee
index e196447f02481b8c00710585b9cba1bd9dea073b..bf66a39d62d892a7b302cf87bfd40ae00a35a66f 100644
--- a/packages/rocketchat-slashcommands-join/server.coffee
+++ b/packages/rocketchat-slashcommands-join/server.coffee
@@ -15,7 +15,7 @@ class Join
 		channel = channel.replace('#', '')
 
 		user = Meteor.users.findOne Meteor.userId()
-		room = RocketChat.models.Rooms.findOneByNameAndTypeNotContainigUsername(channel, 'c', user.username)
+		room = RocketChat.models.Rooms.findOneByNameAndTypeNotContainingUsername(channel, 'c', user.username)
 
 		if not room?
 			RocketChat.Notifications.notifyUser Meteor.userId(), 'message', {
diff --git a/packages/rocketchat-slashcommands-open/client.js b/packages/rocketchat-slashcommands-open/client.js
index 51376c2d95cc301b21c41d119118f44592934af8..10d74e9b2f0e16ba9ba8329cf0c7be77f5a20a41 100644
--- a/packages/rocketchat-slashcommands-open/client.js
+++ b/packages/rocketchat-slashcommands-open/client.js
@@ -22,7 +22,7 @@ function Open(command, params/*, item*/) {
 	subscription = ChatSubscription.findOne(query);
 
 	if (subscription) {
-		FlowRouter.go(RocketChat.roomTypes.getRouteLink(subscription.t, subscription), null, FlowRouter.current().queryParams);
+		RocketChat.roomTypes.openRouteLink(subscription.t, subscription, FlowRouter.current().queryParams);
 	}
 }
 
diff --git a/packages/rocketchat-spotify/lib/client/oembedSpotifyWidget.html b/packages/rocketchat-spotify/lib/client/oembedSpotifyWidget.html
index afc14afc6f169a53ba6b193b7016051c3a2bea95..7ea5a42a82732cb539d56ef653827bd03af1badd 100644
--- a/packages/rocketchat-spotify/lib/client/oembedSpotifyWidget.html
+++ b/packages/rocketchat-spotify/lib/client/oembedSpotifyWidget.html
@@ -1,6 +1,6 @@
 <template name="oembedSpotifyWidget">
 	{{#if parsedUrl}}
-		<blockquote>
+		<blockquote class="background-transparent-darker-before">
 			<a href="https://www.spotify.com" style="color: #9e9ea6">Spotify</a><br/>
 			{{#if match meta.ogAudio "spotify:artist:\\S+"}}
 				<a href="{{url}}">{{{meta.ogTitle}}}</a>
diff --git a/packages/rocketchat-theme/assets/stylesheets/animation.css b/packages/rocketchat-theme/assets/stylesheets/animation.css
deleted file mode 100644
index 027632fde28acdceaa5208fefa57ee52fb873d84..0000000000000000000000000000000000000000
--- a/packages/rocketchat-theme/assets/stylesheets/animation.css
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
-   Animation example, for spinners
-*/
-
-.animate-spin {
-  -moz-animation: spin 2s infinite linear;
-  -o-animation: spin 2s infinite linear;
-  -webkit-animation: spin 2s infinite linear;
-  animation: spin 2s infinite linear;
-  display: inline-block;
-}
-
-.animate-pulse {
-  -moz-animation: spin 1s infinite steps(8);
-  -o-animation: spin 1s infinite steps(8);
-  -webkit-animation: spin 1s infinite steps(8);
-  animation: spin 1s infinite steps(8);
-  display: inline-block;
-}
-
-@-moz-keyframes spin {
-  0% {
-    -moz-transform: rotate(0deg);
-    -o-transform: rotate(0deg);
-    -webkit-transform: rotate(0deg);
-    transform: rotate(0deg);
-  }
-  100% {
-    -moz-transform: rotate(359deg);
-    -o-transform: rotate(359deg);
-    -webkit-transform: rotate(359deg);
-    transform: rotate(359deg);
-  }
-}
-
-@-webkit-keyframes spin {
-  0% {
-    -moz-transform: rotate(0deg);
-    -o-transform: rotate(0deg);
-    -webkit-transform: rotate(0deg);
-    transform: rotate(0deg);
-  }
-  100% {
-    -moz-transform: rotate(359deg);
-    -o-transform: rotate(359deg);
-    -webkit-transform: rotate(359deg);
-    transform: rotate(359deg);
-  }
-}
-
-@-o-keyframes spin {
-  0% {
-    -moz-transform: rotate(0deg);
-    -o-transform: rotate(0deg);
-    -webkit-transform: rotate(0deg);
-    transform: rotate(0deg);
-  }
-  100% {
-    -moz-transform: rotate(359deg);
-    -o-transform: rotate(359deg);
-    -webkit-transform: rotate(359deg);
-    transform: rotate(359deg);
-  }
-}
-
-@-ms-keyframes spin {
-  0% {
-    -moz-transform: rotate(0deg);
-    -o-transform: rotate(0deg);
-    -webkit-transform: rotate(0deg);
-    transform: rotate(0deg);
-  }
-  100% {
-    -moz-transform: rotate(359deg);
-    -o-transform: rotate(359deg);
-    -webkit-transform: rotate(359deg);
-    transform: rotate(359deg);
-  }
-}
-
-@keyframes spin {
-  0% {
-    -moz-transform: rotate(0deg);
-    -o-transform: rotate(0deg);
-    -webkit-transform: rotate(0deg);
-    transform: rotate(0deg);
-  }
-  100% {
-    -moz-transform: rotate(359deg);
-    -o-transform: rotate(359deg);
-    -webkit-transform: rotate(359deg);
-    transform: rotate(359deg);
-  }
-}
diff --git a/packages/rocketchat-theme/assets/stylesheets/utils/_chatops.less b/packages/rocketchat-theme/assets/stylesheets/utils/_chatops.less
deleted file mode 100644
index dadbe4efea946d4d1902b049f5006446c1460c3b..0000000000000000000000000000000000000000
--- a/packages/rocketchat-theme/assets/stylesheets/utils/_chatops.less
+++ /dev/null
@@ -1,19 +0,0 @@
-li.chatops-message {
-	background-color: #f8f8f8;
-}
-
-.chatops-message div.body {
-	font-size: 12px;
-	font-weight: bold;
-	color: #7a7a7a;
-}
-
-li.chatops-message.sequential {
-	margin-top: -5px !important;
-}
-
-.github-tagline {
-	padding-top: 3px;
-	font-weight: 200;
-	color: white;
-}
diff --git a/packages/rocketchat-theme/assets/stylesheets/utils/_colors.import.less b/packages/rocketchat-theme/assets/stylesheets/utils/_colors.import.less
deleted file mode 100755
index ab142cdcd0cc677e0c925466a48e522278c53937..0000000000000000000000000000000000000000
--- a/packages/rocketchat-theme/assets/stylesheets/utils/_colors.import.less
+++ /dev/null
@@ -1,785 +0,0 @@
-/** ----------------------------------------------------------------------------
- * Derivative colours (fixed variants of inherited variables)
- */
-
-@default-action-color: darken(@secondary-background-color, 15%);
-@default-action-contrast: contrast(@default-action-color, #444);
-@primary-background-contrast: contrast(@primary-background-color, #444);
-@primary-action-contrast: contrast(@primary-action-color, #444);
-@secondary-action-contrast: contrast(@secondary-action-color, #444);
-@selection-background: lighten(@selection-color, 30%);
-@success-background: lighten(@success-color, 45%);
-@success-border: lighten(@success-color, 30%);
-@error-background: lighten(@error-color, 45%);
-@error-border: lighten(@error-color, 30%);
-@error-contrast: contrast(@error-color);
-@pending-background: lighten(@pending-color, 45%);
-@pending-border: lighten(@pending-color, 30%);
-@window-border-color: @component-color;
-
-/** ----------------------------------------------------------------------------
- * Document components
- */
-
-html {
-	.custom-scroll(transparent, @custom-scrollbar-color, 0);
-}
-
-.flex-nav,
-.flex-tab .content,
-.messages-container .wrapper,
-.list-view,
-.page-container .content,
-.rooms-list,
-.scrollable,
-.user-view {
-	.custom-scroll(transparent, @custom-scrollbar-color);
-}
-
-body {
-	color: @primary-font-color;
-	background-color: @content-background-color;
-	* {
-		border-color: @component-color;
-	}
-}
-
-code {
-	background-color: @transparent-dark;
-	border-color: @component-color;
-	color: @secondary-font-color;
-}
-
-blockquote:before {
-	background-color: @transparent-darker;
-}
-
-.main-content,
-.cms-page,
-.page-container {
-	background-color: @content-background-color;
-	header {
-		background-color: @content-background-color;
-		border-color: @component-color;
-	}
-}
-
-.page-container table {
-	overflow: hidden;
-	background-color: @secondary-background-color;
-	th,
-	td {
-		border-color: @component-color;
-	}
-	th {
-		background-color: @content-background-color;
-	}
-	tr {
-		background-color: @transparent-light;
-		&:nth-of-type(even) {
-			background-color: @transparent-lighter;
-		}
-	}
-	tr:hover td {
-		background-color: @content-background-color;
-	}
-}
-
-.burger i {
-	background-color: @primary-font-color;
-}
-
-
-/** ----------------------------------------------------------------------------
- * Admin and settings styles
- */
-
-.page-settings {
-	.content {
-		background-color: @transparent-dark;
-	}
-	.section {
-		background-color: @content-background-color;
-	}
-	.terminal {
-		background-color: #444;
-		color: white;
-		.time {
-			color: @secondary-font-color;
-		}
-	}
-}
-
-.page-list,
-.page-settings {
-	a {
-		color: @primary-font-color;
-		&:hover {
-			color: @primary-action-color;
-		}
-	}
-}
-
-.settings-file-preview .preview.no-file {
-	background-color: @transparent-light;
-	color: @secondary-font-color;
-}
-
-.new-logs {
-	background: @primary-action-contrast;
-	color: @primary-action-color;
-}
-
-.code-error-box {
-	.title {
-		background-color: @error-color;
-		color: white;
-	}
-	pre {
-		color: @error-color;
-		border-color: @error-border;
-		background-color: @transparent-lighter;
-	}
-}
-
-.code-mirror-box {
-	.buttons {
-		background-color: #f7f7f7; // matches plugin styles
-	}
-	&.code-mirror-box-fullscreen {
-		background-color: @content-background-color;
-	}
-}
-
-.avatar-suggestion-item {
-	background-color: @tertiary-background-color;
-	.avatar {
-		background-size: cover;
-		background-color: @tertiary-background-color;
-	}
-	.question-mark::before {
-		color: @secondary-font-color;
-	}
-}
-
-
-/** ----------------------------------------------------------------------------
- * Asides (external to main application views)
- */
-
-.spotlight {
-	background-color: @transparent-darker;
-	> .spotlight-input {
-		background-color: @secondary-background-color;
-		color: @secondary-font-color;
-		> i {
-			color: @secondary-font-color;
-		}
-	}
-}
-
-.mobile-message-menu {
-	background-color: @transparent-dark;
-}
-
-.full-page,
-.page-loading {
-	.gradient(shade(@primary-background-color), @primary-background-color);
-	color: @tertiary-font-color;
-	a {
-		color: @tertiary-font-color;
-	}
-	a:hover {
-		color: @primary-background-contrast;
-	}
-	.spinner > div {
-		background-color: @primary-background-contrast;
-	}
-}
-
-#login-card {
-	color: @primary-font-color;
-	background-color: @content-background-color;
-	.input-shade(@primary-font-color, @content-background-color);
-}
-
-.dropzone.over .dropzone-overlay {
-	background-color: @transparent-darker;
-	color: @content-background-color;
-	> div {
-		background-color: @transparent-darker;
-	}
-}
-
-
-/** ----------------------------------------------------------------------------
- * Room components
- */
-
-.new-message {
-	color: @primary-action-contrast;
-	background-color: @primary-action-color;
-}
-
-.ticks-bar {
-	.tick {
-		background-color: @primary-action-color;
-	}
-	.tick-all {
-		background-color: @selection-color;
-	}
-}
-
-.room-not-found {
-	color: @error-color;
-}
-
-.favorite-room {
-	color: @pending-color;
-}
-
-.toggle-favorite {
-	color: @component-color;
-}
-
-.container-bars {
-	.upload-progress {
-		background-color: @success-background;
-		color: @success-color;
-		&.upload-error {
-			background-color: @error-background;
-			border-color: @error-border;
-		}
-		.upload-progress-progress {
-			background-color: @success-background;
-		}
-	}
-	.unread-bar {
-		background-color: @component-color;
-		color: @primary-action-color;
-	}
-}
-
-.messages-container {
-	.edit-room-title {
-		.linkColors(@secondary-font-color, @primary-font-color);
-	}
-	.footer {
-		background: @content-background-color;
-	}
-	.message-form {
-		color: @secondary-font-color;
-		.input-message-container {
-			background-color: @content-background-color;
-		}
-		.message-buttons {
-			.buttonColors(@primary-font-color, @transparent-dark);
-		}
-	}
-	.new-message {
-		color: @primary-action-contrast;
-		background-color: @primary-action-color;
-	}
-	.messages-box {
-		.jump-recent {
-			background-color: @component-color;
-		}
-		&.selectable .selected {
-			background-color: @selection-background;
-		}
-		.load-more span {
-			background-color: @secondary-background-color;
-		}
-	}
-}
-
-.message-popup {
-	background: @content-background-color;
-}
-
-.message-popup-title {
-	background-color: @secondary-background-color;
-	// border-bottom-color: #E7E7E7;
-}
-
-.popup-item {
-	// color: @secondary-font-color;
-	&.selected {
-		color: @primary-action-contrast;
-		background-color: @primary-action-color;
-	}
-	span {
-		color: @secondary-font-color;
-	}
-}
-
-
-.messages-box {
-	.start {
-		color: @info-font-color;
-	}
-	.editing .body,
-	textarea.editing {
-		background-color: @selection-background;
-	}
-}
-
-
-/** ----------------------------------------------------------------------------
- * Message content
- */
-
-.message {
-	.body {
-		color: @primary-font-color;
-	}
-	&.system .body {
-		color: @info-font-color;
-	}
-	&:hover {
-		background-color: @transparent-dark;
-	}
-	.toggle-options {
-		color: @secondary-font-color;
-	}
-	.message-dropdown,
-	.options-menu {
-		color: @secondary-font-color;
-		background-color: @content-background-color;
-		ul li:hover {
-			color: @secondary-action-contrast;
-			background-color: @secondary-action-color;
-		}
-		.message-dropdown-close {
-			color: @content-background-color;
-			background-color: @info-font-color;
-		}
-	}
-	&.new-day::before {
-		background-color: @content-background-color;
-	}
-	&.new-day::after,
-	.info,
-	.user-view,
-	.message-alias {
-		color: @info-font-color;
-		border-color: @component-color;
-	}
-	.user {
-		color: @primary-font-color;
-	}
-	.is-bot,
-	.role-tag {
-		background-color: @info-font-color;
-		color: contrast(@info-font-color);
-	}
-	a {
-		.linkColors(@link-font-color, darken(@link-font-color, 10%));
-	}
-	a.mention-link {
-		background-color: @secondary-action-color;
-		color: @secondary-action-contrast;
-		&.mention-link-all,
-		&.mention-link-me {
-			color: @primary-action-contrast;
-			background-color: @primary-action-color;
-		}
-		&.mention-link-all {
-			color: contrast(@selection-color);
-			background-color: @selection-color;
-		}
-	}
-	.highlight-text {
-		background-color: @selection-background;
-	}
-	.attachment {
-		.attachment-block-border {
-			background-color: @info-font-color;
-		}
-	}
-}
-
-
-/** ----------------------------------------------------------------------------
- * Misc typography variants
- */
-
-a {
-	color: @primary-font-color;
-}
-
-a:active,
-a:hover {
-	color: @primary-action-color;
-}
-
-.message,
-.flex-tab {
-	a i,
-	a[class^="icon-"] {
-		color: @primary-font-color;
-		&:hover {
-			color: darken(@primary-font-color, 10%);
-		}
-	}
-}
-
-.load-more .load-more-loading,
-.secondary-text {
-	color: @secondary-font-color;
-}
-
-.alert-icon {
-	color: @success-color;
-}
-
-.error {
-	background-color: @error-background;
-	border-color: @error-color;
-	color: @error-color;
-}
-
-
-/** ----------------------------------------------------------------------------
- * Side nav
- */
-
-.side-nav {
-	color: @tertiary-font-color;
-	background-color: @primary-background-color;
-	* {
-		border-color: @transparent-darker;
-	}
-	a,
-	.info {
-		.linkColors(@tertiary-font-color, @tertiary-font-color);
-	}
-	.arrow:before,
-	.arrow:after {
-		background-color: @tertiary-font-color;
-	}
-	.info,
-	.options,
-	.content,
-	footer,
-	header {
-		background-color: @primary-background-color;
-	}
-	.rooms-list {
-		background-color: lighten(@primary-background-color, 2.5%);
-	}
-	.more:hover,
-	h3:hover,
-	.selected-users li {
-		background-color: @transparent-darker;
-	}
-	li.active .opt {
-		color: @tertiary-font-color;
-	}
-	.active a {
-		color: @primary-background-contrast;
-		background-color: @transparent-lighter;
-	}
-	.open-room:hover {
-		background-color: @transparent-lighter;
-	}
-	.has-alert a {
-		color: @primary-background-contrast;
-	}
-	.unread {
-		background-color: @success-color;
-	}
-	.unread-rooms {
-		background-color: @primary-action-color;
-		color: @primary-action-contrast;
-	}
-}
-
-
-/** ----------------------------------------------------------------------------
- * Flex tabs / admin fly-out panels
- */
-
-.flex-tab {
-	background-color: @secondary-background-color;
-	.content, .user-view, .list-view {
-		background-color: @secondary-background-color;
-	}
-	.message {
-		background-color: @transparent-lighter;
-		&.new-day::before {
-			background-color: @secondary-background-color;
-		}
-	}
-}
-
-.flex-tab-bar {
-	background-color: @content-background-color;
-	border-color: @component-color;
-	.tab-button {
-		&:hover {
-			background-color: @secondary-background-color;
-		}
-		&.active {
-			background-color: @secondary-background-color;
-			border-right-color: @selection-color;
-		}
-		&.attention {
-			.blink(@selection-color);
-		}
-	}
-	.counter {
-		background: @secondary-font-color;
-		color: white;
-	}
-}
-
-.webrtc-video {
-	&.webrtc-video-overlay,
-	.main-video,
-	.state-overlay::before,
-	.videos .video-item {
-		background-color: @transparent-darker;
-		color: white;
-	}
-	.main-video > div,
-	.video-muted-overlay,
-	.videos .video-item > div {
-		background-color: @transparent-darker;
-	}
-	video {
-		background-color: black;
-	}
-}
-
-
-/** ----------------------------------------------------------------------------
- * User status / user meta
- */
-
-i.status-online {
-	color: @status-online;
-}
-
-.account-box .status-online .thumb:after,
-.account-box .status.online:after,
-.options .status .online:after,
-.popup-user-status-online,
-.status-online:after,
-.user-image.status-online .avatar:after {
-	background-color: @status-online;
-	border-color: darken(@status-online, 10%);
-}
-
-i.status-away {
-	color: @status-away;
-}
-
-.account-box .status-away .thumb:after,
-.account-box .status.away:after,
-.options .status .online:after,
-.popup-user-status-away,
-.status-pending:after,
-.user-image.status-away .avatar:after {
-	background-color: @status-away;
-	border-color: darken(@status-away, 10%);
-}
-
-i.status-busy {
-	color: @status-busy;
-}
-
-.account-box .status-busy .thumb:after,
-.account-box .status.busy:after,
-.options .status .online:after,
-.popup-user-status-busy,
-.status-busy:after,
-.user-image.status-busy .avatar:after {
-	background-color: @status-busy;
-	border-color: darken(@status-busy, 10%);
-}
-
-i.status-offline {
-	color: @status-offline;
-}
-
-.account-box .status-offline .thumb:after,
-.account-box .status.offline:after,
-.options .status .online:after,
-.popup-user-status-offline,
-.status-offline:after,
-.user-image.status-offline .avatar:after {
-	background-color: @status-offline;
-	border-color: darken(@status-offline, 10%);
-}
-
-.popup-user-status {
-	border-color: @transparent-dark;
-}
-
-.popup-user-status-system {
-	border-color: transparent;
-}
-
-.user-view {
-	p {
-		color: @secondary-font-color;
-	}
-	.box:after,
-	.stats li,
-	.tags li {
-		background-color: @component-color;
-	}
-}
-
-
-/** ----------------------------------------------------------------------------
- * Buttons!
- */
-
-.actionLinks li {
-	.buttonColors(@secondary-action-contrast, @secondary-action-color);
-}
-
-// new layout buttons
-.button {
-	.buttonColors(@default-action-contrast, @default-action-color);
-	&.primary {
-		.buttonColors(@primary-action-contrast, @primary-action-color);
-	}
-	&.secondary {
-		.buttonColors(@secondary-action-contrast, @secondary-action-color);
-	}
-	&.danger {
-		.buttonColors(@error-contrast, @error-color);
-	}
-	&.external-login {
-		color: white;
-		&.facebook {
-			background-color: #325c99;
-		}
-		&.twitter {
-			background-color: #02acec;
-		}
-		&.google {
-			background-color: #dd4b39;
-		}
-		&.github {
-			background-color: #4c4c4c;
-		}
-		&.gitlab {
-			background-color: #373d47;
-		}
-		&.trello {
-			background-color: #026aa7;
-		}
-		&.meteor-developer {
-			background-color: #de4f4f;
-		}
-		&.wordpress {
-			background-color: #1e8cbe;
-		}
-		&.linkedin {
-			background-color: #1b86bc;
-		}
-	}
-}
-
-.side-nav {
-	.button {
-		.buttonColors(@tertiary-font-color, mix(@primary-action-color, @primary-background-color));
-	}
-	.options button {
-		.buttonColors(@tertiary-font-color, @primary-background-color);
-	}
-}
-
-
-/** ----------------------------------------------------------------------------
- * Feedback and overlay content
- */
-
-.icon-ok,
-.feedback-success {
-	color: @success-color;
-}
-
-.feedback-warning {
-	color: @pending-color;
-}
-
-.feedback-error {
-	color: @error-color;
-}
-
-.livechat-form .error,
-.offline .error {
-	background-color: @error-background;
-}
-
-.alert-warning {
-	color: @pending-color;
-	background-color: @pending-background;
-	border-color: @pending-border;
-}
-
-.alert-danger {
-	color: @error-color;
-	background-color: @error-background;
-	border-color: @error-border;
-}
-
-.side-nav .input-error,
-label.required:after {
-	color: @error-color;
-}
-
-.burger .unread-burger-alert {
-	background-color: @error-color;
-	color: @error-contrast;
-}
-
-
-/** ----------------------------------------------------------------------------
- * Forms
- */
-
-.input-shade(@primary-font-color, @content-background-color);
-.flex-nav {
-	.input-shade(@primary-background-contrast, @primary-background-color);
-	label,
-	legend {
-		color: @tertiary-font-color;
-	}
-}
-
-.flex-tab {
-	input,
-	select,
-	textarea {
-		background-color: @content-background-color;
-	}
-}
-
-.input-line {
-	&.setting-changed > label {
-		color: @selection-color;
-	}
-	i,
-	.settings-description {
-		color: @secondary-font-color;
-	}
-	.settings-alert {
-		background-color: @pending-background;
-		border-color: @pending-border;
-		color: @pending-color;
-	}
-}
-
-input:-webkit-autofill {
-	color: @primary-font-color !important;
-}
-
-input:-webkit-autofill {
-	background-color: transparent !important;
-}
diff --git a/packages/rocketchat-theme/assets/stylesheets/utils/_lesshat.import.less b/packages/rocketchat-theme/assets/stylesheets/utils/_lesshat.import.less
deleted file mode 100644
index 1ce1fc07fded5e103b603921e82f78964e9790f5..0000000000000000000000000000000000000000
--- a/packages/rocketchat-theme/assets/stylesheets/utils/_lesshat.import.less
+++ /dev/null
@@ -1,884 +0,0 @@
-//  lesshat - The best mixin library in the world
-//
-// version: v4.1.0 (2016-07-19)
-
-// TABLE OF MIXINS:
-	// align-content
-	// align-items
-	// align-self
-	// animation
-	// animation-delay
-	// animation-direction
-	// animation-duration
-	// animation-fill-mode
-	// animation-iteration-count
-	// animation-name
-	// animation-play-state
-	// animation-timing-function
-	// appearance
-	// backface-visibility
-	// background-clip
-	// background-image
-	// background-origin
-	// background-size
-	// blur
-	// border-bottom-left-radius
-	// border-bottom-right-radius
-	// border-image
-	// border-radius
-	// border-top-left-radius
-	// border-top-right-radius
-	// box-shadow
-	// box-sizing
-	// brightness
-	// calc
-	// column-count
-	// column-gap
-	// column-rule
-	// column-width
-	// columns
-	// contrast
-	// display
-	// drop-shadow
-	// filter
-	// flex
-	// flex-basis
-	// flex-direction
-	// flex-grow
-	// flex-shrink
-	// flex-wrap
-	// font-face
-	// grayscale
-	// hue-rotate
-	// hyphens
-	// invert
-	// justify-content
-	// keyframes
-	// opacity
-	// order
-	// perspective
-	// perspective-origin
-	// placeholder
-	// rotate
-	// rotate3d
-	// rotateX
-	// rotateY
-	// rotateZ
-	// saturate
-	// scale
-	// scale3d
-	// scaleX
-	// scaleY
-	// scaleZ
-	// selection
-	// sepia
-	// size
-	// skew
-	// skewX
-	// skewY
-	// transform
-	// transform-origin
-	// transform-style
-	// transition
-	// transition-delay
-	// transition-duration
-	// transition-property
-	// transition-timing-function
-	// translate
-	// translate3d
-	// translateX
-	// translateY
-	// translateZ
-	// user-select
-
-.align-content(...) {
-	@process: ~`(function(t){return t=t||"stretch"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_ms: ~`(function(e){return e=e||"stretch","flex-start"==e?e="start":"flex-end"==e?e="end":"space-between"==e?e="justify":"space-around"==e&&(e="distribute"),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-align-content: @process;
-	-ms-flex-line-pack: @process_ms;
-	align-content: @process;
-}
-
-.align-items(...) {
-	@process_olderwebkit: ~`(function(t){return t=t||"stretch","flex-start"==t?t="start":"flex-end"==t&&(t="end"),t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_moz: ~`(function(t){return t=t||"stretch","flex-start"==t?t="start":"flex-end"==t&&(t="end"),t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process: ~`(function(t){return t=t||"stretch"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_ms: ~`(function(t){return t=t||"stretch","flex-start"==t?t="start":"flex-end"==t&&(t="end"),t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-box-align: @process_olderwebkit;
-	-moz-box-align: @process_moz;
-	-webkit-align-items: @process;
-	-ms-flex-align: @process_ms;
-	align-items: @process;
-}
-
-.align-self(...) {
-	@process: ~`(function(n){return n=n||"auto"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_ms: ~`(function(t){return t=t||"auto","flex-start"==t?t="start":"flex-end"==t&&(t="end"),t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-align-self: @process;
-	-ms-flex-item-align: @process_ms;
-	align-self: @process;
-}
-
-.animation(...) {
-	@process: ~`(function(e){return e=e||"none",/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-animation: @process;
-	-moz-animation: @process;
-	-o-animation: @process;
-	animation: @process;
-}
-
-.animation-delay(...) {
-	@process: ~`(function(r){r=r||"0";var s=/(?:\d)(?:ms|s)/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return s.test(r)||"0"===r||(r=r.replace(t,function(r){return r+=parseFloat(r,10)>10?"ms":"s"})),r})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-animation-delay: @process;
-	-moz-animation-delay: @process;
-	-o-animation-delay: @process;
-	animation-delay: @process;
-}
-
-.animation-direction(...) {
-	@process: ~`(function(n){return n||"normal"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-animation-direction: @process;
-	-moz-animation-direction: @process;
-	-o-animation-direction: @process;
-	animation-direction: @process;
-}
-
-.animation-duration(...) {
-	@process: ~`(function(r){r=r||"0";var s=/ms|s/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return s.test(r)||"0"===r||(r=r.replace(t,function(r){return r+=parseFloat(r,10)>10?"ms":"s"})),r})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-animation-duration: @process;
-	-moz-animation-duration: @process;
-	-o-animation-duration: @process;
-	animation-duration: @process;
-}
-
-.animation-fill-mode(...) {
-	@process: ~`(function(n){return n||"none"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-animation-fill-mode: @process;
-	-moz-animation-fill-mode: @process;
-	-o-animation-fill-mode: @process;
-	animation-fill-mode: @process;
-}
-
-.animation-iteration-count(...) {
-	@process: ~`(function(n){return n||"0"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-animation-iteration-count: @process;
-	-moz-animation-iteration-count: @process;
-	-o-animation-iteration-count: @process;
-	animation-iteration-count: @process;
-}
-
-.animation-name(...) {
-	@process: ~`(function(n){return n||"none"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-animation-name: @process;
-	-moz-animation-name: @process;
-	-o-animation-name: @process;
-	animation-name: @process;
-}
-
-.animation-play-state(...) {
-	@process: ~`(function(n){return n||"running"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-animation-play-state: @process;
-	-moz-animation-play-state: @process;
-	-o-animation-play-state: @process;
-	animation-play-state: @process;
-}
-
-.animation-timing-function(...) {
-	@process: ~`(function(e){return e||"ease"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-animation-timing-function: @process;
-	-moz-animation-timing-function: @process;
-	-o-animation-timing-function: @process;
-	animation-timing-function: @process;
-}
-
-.appearance(...) {
-	@process: ~`(function(n){return n||"none"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-appearance: @process;
-	-moz-appearance: @process;
-	appearance: @process;
-}
-
-.backface-visibility(...) {
-	@process: ~`(function(i){return i||"visible"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-backface-visibility: @process;
-	-moz-backface-visibility: @process;
-	-ms-backface-visibility: @process;
-	-o-backface-visibility: @process;
-	backface-visibility: @process;
-}
-
-.background-clip(...) {
-	@process: ~`(function(r){return r||"border-box"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-background-clip: @process;
-	-moz-background-clip: @process;
-	background-clip: @process;
-}
-
-.background-image(...) {
-	@process_ms: ~`(function(t){function e(t){var e,r,s,a,n,i,o,c,g="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",d=0,l=0,f="",h=[];if(!t)return t;do e=t.charCodeAt(d++),r=t.charCodeAt(d++),s=t.charCodeAt(d++),c=e<<16|r<<8|s,a=c>>18&63,n=c>>12&63,i=c>>6&63,o=63&c,h[l++]=g.charAt(a)+g.charAt(n)+g.charAt(i)+g.charAt(o);while(d<t.length);f=h.join("");var u=t.length%3;return(u?f.slice(0,u-3):f)+"===".slice(u||3)}if(t=t||8121991,8121991==t)return t;var r=/linear|radial/g.test(t)&&t.split(/,(?=\s*(?:linear|radial|url))/g),s=[],a={"to bottom":'x1="0%" y1="0%" x2="0%" y2="100%"',"to left":'x1="100%" y1="0%" x2="0%" y2="0%"',"to top":'x1="0%" y1="100%" x2="0%" y2="0%"',"to right":'x1="0%" y1="0%" x2="100%" y2="0%"',get"top"(){return this["to bottom"]},get"180deg"(){return this["to bottom"]},get"right"(){return this["to left"]},get"270deg"(){return this["to left"]},get"bottom"(){return this["to top"]},get"90deg"(){return this["to right"]},get"0deg"(){return this["to top"]},get"left"(){return this["to right"]},"-45deg":'x1="0%" y1="0%" x2="100%" y2="100%"',"45deg":'x1="0%" y1="100%" x2="100%" y2="0%"',"ellipse at center":'cx="50%" cy="50%" r="75%"',get"135deg"(){return this["-45deg"]}},n={uri_data:"url(data:image/svg+xml;base64,",xml:'<?xml version="1.0" ?>',svg_start:'<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none">',linear_gradient_start:'<linearGradient id="lesshat-generated" gradientUnits="userSpaceOnUse"',radial_gradient_start:'<radialGradient id="lesshat-generated" gradientUnits="userSpaceOnUse"',linear_gradient_end:"</linearGradient>",radial_gradient_end:"</radialGradient>",rect_linear:'<rect x="0" y="0" width="1" height="1" fill="url(#lesshat-generated)" />',rect_radial:'<rect x="-50" y="-50" width="101" height="101" fill="url(#lesshat-generated)" />',svg_end:"</svg>"};if(r.length){r.forEach(function(t,e){var r={};if(Object.keys(a).some(function(e){return t.indexOf(e)>=0?(r.svg_direction=a[e],!0):void(r.svg_direction=!1)}),/linear/.test(t))r.svg_type="linear";else if(/radial/.test(t))r.svg_type="radial";else if(!/linear/.test(t)&&!/radial/.test(t))return r.url=t.trim(),r.svg_type="url",r.svg_direction=!0,s.push(r),!1;var n=t.match(/rgb|#[a-zA-Z0-9]|hsl/g).length;r.svg_stops=[],t=t.replace(/transparent/g,"rgba(0,0,0,0)"),t.match(/#[a-zA-Z0-9]/g)&&t.match(/(#[a-zA-Z0-9]+)\s*(\d+%)?/g).forEach(function(t){t=t.split(" "),r.svg_stops.push('<stop offset="'+(t[1]||!1)+'" stop-color="'+t[0]+'" stop-opacity="1"/>')}),t.match(/rgba?\(\d+,\s*\d+,\s*\d+(?:,\s*(0|1|\.\d+|0\.\d+))?\)/g)&&t.replace(/rgba?\((\d+,\s*\d+,\s*\d+)(?:,\s*(0|1|\.\d+|0\.\d+))?\)\s*(\d+%)?/g,function(t,e,s,a){r.svg_stops.push('<stop offset="'+(a||!1)+'" stop-color="rgb('+e+')" stop-opacity="'+(s||1)+'"/>')}),t.match(/hsla?\((\d+,\s*\d+%,\s*\d+%),\s*(0|1|\.\d+|0\.\d+)\)/g)&&t.replace(/hsla?\((\d+,\s*\d+%,\s*\d+%),\s*(0|1|\.\d+|0\.\d+)\)\s*(\d+%)?/g,function(t,e,s,a){r.svg_stops.push('<stop offset="'+(a||!1)+'" stop-color="hsl('+e+')" stop-opacity="'+(s||1)+'"/>')});var i=Math.floor(100/(n-1));r.svg_stops.forEach(function(t,e){/offset="false"/.test(t)&&(r.svg_stops[e]=t.replace(/offset="false"/,'offset="'+i*e+'%"'))}),r.svg_stops.sort(function(t,e){if(t=t.match(/offset="(\d+)%"/),e=e.match(/offset="(\d+)%"/),2==t.length&&2==e.length)return t[1]-e[1]}),s.push(r)});var i=[],o=s.every(function(t){for(var e in t)if(0==t[e]||0==t[e].length)return!1;return!0});if(!o)return 8121991;s.forEach(function(t,e){"linear"!=t.svg_type&&"radial"!=t.svg_type||(i[e]=n.xml+n.svg_start),"linear"==t.svg_type?(i[e]+=n.linear_gradient_start+" "+t.svg_direction+">",t.svg_stops.forEach(function(t){i[e]+=t}),i[e]+=n.linear_gradient_end,i[e]+=n.rect_linear,i[e]+=n.svg_end):"radial"==t.svg_type?(i[e]+=n.radial_gradient_start+" "+t.svg_direction+">",t.svg_stops.forEach(function(t){i[e]+=t}),i[e]+=n.radial_gradient_end,i[e]+=n.rect_radial,i[e]+=n.svg_end):"url"==t.svg_type&&(i[e]=t.url)}),i.forEach(function(t,r){/<\?xml version="1.0" \?>/g.test(t)&&(i[r]=n.uri_data+e(t)+")")}),t=i.join(",")}return t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_webkit: ~`(function(e){if(e=e||8121991,8121991==e)return e;var r={"to bottom":"top","to left":"right","to top":"bottom","to right":"left","ellipse at center":"center, ellipse cover","circle closest-side":"center center, circle contain","circle farthest-corner":"center center, circle cover","circle farthest-side":"center center, circle cover","ellipse closest-side":"center center, ellipse contain","ellipse farthest-corner":"center center, ellipse cover","ellipse farthest-side":"center center, ellipse cover"},t=/(radial-gradient\()([a-z- ]+)at\s+(\w+%?)\s*(\w*%?)/g,c=Object.keys(r);return c.some(function(c){return e.indexOf(c)>=0?(e=e.replace(new RegExp(c+"(?![ a-z0-9])","g"),r[c]),!0):void(t.test(e)&&(e=e.replace(t,function(e,r,t,c,i){return r.trim()+c.trim()+" "+i.trim()+","+t.replace(/closest-side/g,"contain").replace(/farthest-corner/g,"cover").trim()})))}),e=e.replace(/(\d+)\s*deg/g,function(e,r){return 90-r+"deg"}).replace(/(linear|radial)-gradient/g,"-webkit-$1-gradient")})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_moz: ~`(function(e){if(e=e||8121991,8121991==e)return e;var r={"to bottom":"top","to left":"right","to top":"bottom","to right":"left","ellipse at center":"center, ellipse cover","circle closest-side":"center center, circle contain","circle farthest-corner":"center center, circle cover","circle farthest-side":"center center, circle cover","ellipse closest-side":"center center, ellipse contain","ellipse farthest-corner":"center center, ellipse cover","ellipse farthest-side":"center center, ellipse cover"},t=/(radial-gradient\()([a-z- ]+)at\s+(\w+%?)\s*(\w*%?)/g,c=Object.keys(r);return c.some(function(c){return e.indexOf(c)>=0?(e=e.replace(new RegExp(c+"(?![ a-z0-9])","g"),r[c]),!0):void(t.test(e)&&(e=e.replace(t,function(e,r,t,c,n){return r.trim()+c.trim()+" "+n.trim()+","+t.replace(/closest-side/g,"contain").replace(/farthest-corner/g,"cover").trim()})))}),e=e.replace(/(\d+)\s*deg/g,function(e,r){return 90-r+"deg"}).replace(/(linear|radial)-gradient/g,"-moz-$1-gradient")})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_opera: ~`(function(e){if(e=e||8121991,8121991==e)return e;var r={"to bottom":"top","to left":"right","to top":"bottom","to right":"left","ellipse at center":"center, ellipse cover","circle closest-side":"center center, circle contain","circle farthest-corner":"center center, circle cover","circle farthest-side":"center center, circle cover","ellipse closest-side":"center center, ellipse contain","ellipse farthest-corner":"center center, ellipse cover","ellipse farthest-side":"center center, ellipse cover"},t=/(radial-gradient\()([a-z- ]+)at\s+(\w+%?)\s*(\w*%?)/g,c=Object.keys(r);return c.some(function(c){return e.indexOf(c)>=0?(e=e.replace(new RegExp(c+"(?![ a-z0-9])","g"),r[c]),!0):void(t.test(e)&&(e=e.replace(t,function(e,r,t,c,n){return r.trim()+c.trim()+" "+n.trim()+","+t.replace(/closest-side/g,"contain").replace(/farthest-corner/g,"cover").trim()})))}),e=e.replace(/(\d+)\s*deg/g,function(e,r){return 90-r+"deg"}).replace(/(linear|radial)-gradient/g,"-o-$1-gradient")})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process: ~`(function(t){if(t=t||8121991,8121991==t)return t;var e={top:"to bottom",right:"to left",bottom:"to top",left:"to right"},o=Object.keys(e);return o.some(function(o){if(t.indexOf(o)>=0&&!new RegExp("to\\s+"+o+"|at\\s+"+o,"g").test(t))return t=t.replace(new RegExp(o),e[o]),!0}),t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	background-image: @process_ms;
-	background-image: @process_webkit;
-	background-image: @process_moz;
-	background-image: @process_opera;
-	background-image: @process;
-}
-
-.background-origin(...) {
-	@process: ~`(function(n){return n||"padding-box"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-background-origin: @process;
-	-moz-background-origin: @process;
-	background-origin: @process;
-}
-
-.background-size(...) {
-	@process: ~`(function(t){t=t||"auto auto";var e=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return/^[^, ]*,/.test(t)&&(t=t.replace(/(?:,)(?![^(]*\))/g,"")),e.test(t)&&(t=t.replace(r,function(t){return 0==t&&t||t+"px"})),t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-background-size: @process;
-	-moz-background-size: @process;
-	background-size: @process;
-}
-
-.blur(...) {
-	@process: ~`(function(n){n=n||"0";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"px"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-filter: blur(@process);
-	-moz-filter: blur(@process);
-	-ms-filter: blur(@process);
-	filter: blur(@process);
-}
-
-.border-bottom-left-radius(...) {
-	@process: ~`(function(e){e=e||"0";var t=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),t.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"px"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-border-bottom-left-radius: @process; -webkit-background-clip: padding-box;
-	-moz-border-radius-bottomleft: @process; -moz-background-clip: padding;
-	border-bottom-left-radius: @process; background-clip: padding-box;
-}
-
-.border-bottom-right-radius(...) {
-	@process: ~`(function(e){e=e||"0";var t=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),t.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"px"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-border-bottom-right-radius: @process; -webkit-background-clip: padding-box;
-	-moz-border-radius-bottomright: @process; -moz-background-clip: padding;
-	border-bottom-right-radius: @process; background-clip: padding-box;
-}
-
-.border-image(...) {
-	@process: ~`(function(e){return e=e||8121991,/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-border-image: @process;
-	-moz-border-image: @process;
-	-o-border-image: @process;
-	border-image: @process;
-}
-
-.border-radius(...) {
-	@process: ~`(function(e){e=e||"0";var t=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),t.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"px"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-border-radius: @process; -webkit-background-clip: padding-box;
-	-moz-border-radius: @process; -moz-background-clip: padding;
-	border-radius: @process; background-clip: padding-box;
-}
-
-.border-top-left-radius(...) {
-	@process: ~`(function(e){e=e||"0";var t=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),t.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"px"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-border-top-left-radius: @process; -webkit-background-clip: padding-box;
-	-moz-border-radius-topleft: @process; -moz-background-clip: padding;
-	border-top-left-radius: @process; background-clip: padding-box;
-}
-
-.border-top-right-radius(...) {
-	@process: ~`(function(e){e=e||"0";var t=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),t.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"px"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-border-top-right-radius: @process; -webkit-background-clip: padding-box;
-	-moz-border-radius-topright: @process; -moz-background-clip: padding;
-	border-top-right-radius: @process; background-clip: padding-box;
-}
-
-.box-shadow(...) {
-	@process: ~`(function(e){e=e||"0";var t=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),t.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"px"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-box-shadow: @process;
-	-moz-box-shadow: @process;
-	box-shadow: @process;
-}
-
-.box-sizing(...) {
-	@process: ~`(function(n){return n=n||"content-box"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-box-sizing: @process;
-	-moz-box-sizing: @process;
-	box-sizing: @process;
-}
-
-.brightness(...) {
-	@process: ~`(function(n){return n=n||"1"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-filter: brightness(@process);
-	-moz-filter: brightness(@process);
-	-ms-filter: brightness(@process);
-	filter: brightness(@process);
-}
-
-.calc(...) {
-	@process: ~`(function(a){function c(c,t){var r=");\n",s=e.split(","),l=s[0]+":"+c+"("+(s[1].trim()||0)+r;"start"==t?a="0;\n"+l:a+=l}a=a||8121991;var t="@{state}",e=a;if(8121991==a)return a;switch(t){case"1":c("-webkit-calc","start"),c("-moz-calc"),c("calc");break;case"2":c("-webkit-calc","start"),c("-moz-calc");break;case"3":c("-webkit-calc","start"),c("calc");break;case"4":c("-webkit-calc","start");break;case"5":c("-moz-calc","start"),c("calc");break;case"6":c("-moz-calc","start");break;case"7":c("calc","start")}return a=a.replace(/;$/g,"")})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@state: 1; -lh-property: @process;
-
-}
-
-.column-count(...) {
-	@process: ~`(function(n){return n=n||"auto"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-column-count: @process;
-	-moz-column-count: @process;
-	column-count: @process;
-}
-
-.column-gap(...) {
-	@process: ~`(function(n){n=n||"normal";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"px"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-column-gap: @process;
-	-moz-column-gap: @process;
-	column-gap: @process;
-}
-
-.column-rule(...) {
-	@process: ~`(function(e){e=e||"medium none black";var n=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),n.test(e)&&(e=e.replace(t,function(e){return 0==e&&e||e+"px"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-column-rule: @process;
-	-moz-column-rule: @process;
-	column-rule: @process;
-}
-
-.column-width(...) {
-	@process: ~`(function(t){t=t||"auto";var n=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return n.test(t)&&(t=t.replace(r,function(t){return 0==t&&t||t+"px"})),t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-column-width: @process;
-	-moz-column-width: @process;
-	column-width: @process;
-}
-
-.columns(...) {
-	@process: ~`(function(t){t=t||"auto auto";var e=/^\d+$/;return/^[^, ]*,/.test(t)&&(t=t.replace(/(?:,)(?![^(]*\))/g,""),t=t.split(" ")),e.test(t[0])&&(t[0]=t[0]+"px"),t.join(" ")})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-columns: @process;
-	-moz-columns: @process;
-	columns: @process;
-}
-
-.contrast(...) {
-	@process: ~`(function(n){n=n||"100%";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"%"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-filter: ~"contrast(@{process})";
-	-moz-filter: ~"contrast(@{process})";
-	-ms-filter: ~"contrast(@{process})";
-	filter: ~"contrast(@{process})";
-}
-
-.display(...) {
-	@process_oldwebkit: ~`(function(e){return e="flex"==e||"inline-flex"==e?"-webkit-box":8121991})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_moz: ~`(function(n){return n="flex"==n||"inline-flex"==n?"-moz-box":8121991})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_webkit: ~`(function(e){return e="flex"==e||"inline-flex"==e?"-webkit-"+e:8121991})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_ms: ~`(function(e){return e="flex"==e?"-ms-flexbox":"inline-flex"==e?"-ms-inline-flexbox":8121991})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process: ~`(function(n){return"flex"!=n&&"inline-flex"!=n&&(n=8121991),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	display: @process_oldwebkit;
-	display: @process_moz;
-	display: @process_webkit;
-	display: @process_ms;
-	display: @process;
-}
-
-.drop-shadow(...) {
-	@process: ~`(function(e){if(e=e||8121991,8121991==e)return e;var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),r.test(e)&&(e=e.replace(t,function(e){return 0==e&&e||e+"px"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-filter: drop-shadow(@process);
-	-moz-filter: drop-shadow(@process);
-	-ms-filter: drop-shadow(@process);
-	filter: drop-shadow(@process);
-}
-
-.filter(...) {
-	@process: ~`(function(e){return e=e||"none",/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-filter: @process;
-	-moz-filter: @process;
-	-ms-filter: @process;
-	filter: @process;
-}
-
-.flex(...) {
-	@process_olderwebkit: ~`(function(t){return/^\d+/.test(t)?t=t.match(/^\d+/)[0]:""==t&&(t="0"),t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_moz: ~`(function(t){return/^\d+/.test(t)?t=t.match(/^\d+/)[0]:""==t&&(t="0"),t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process: ~`(function(t){return t=t||"0 1 auto",/^[^, ]*,/.test(t)&&(t=t.replace(/(?:,)(?![^(]*\))/g,"")),t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-box-flex: @process_olderwebkit;
-	-moz-box-flex: @process_moz;
-	-webkit-flex: @process;
-	-ms-flex: @process;
-	flex: @process;
-}
-
-.flex-basis(...) {
-	@process: ~`(function(t){t=t||"auto";var n=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return n.test(t)&&(t=t.replace(r,function(t){return 0==t&&t||t+"px"})),t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-flex-basis: @process;
-	flex-basis: @process;
-}
-
-.flex-direction(...) {
-	@process_oldestwebkit: ~`(function(r){return r="row"==r||"column"==r?"normal":"row-reverse"==r||"column-reverse"==r?"reverse":8121991})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_oldermoz: ~`(function(r){return r="row"==r||"column"==r?"normal":"row-reverse"==r||"column-reverse"==r?"reverse":8121991})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_olderwebkit: ~`(function(r){return r="row"==r||"row-reverse"==r?"horizontal":"column"==r||"column-reverse"==r?"vertical":8121991})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_moz: ~`(function(r){return r="row"==r||"row-reverse"==r?"horizontal":"column"==r||"column-reverse"==r?"vertical":8121991})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process: ~`(function(n){return n=n||"row"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-box-direction: @process_oldestwebkit;
-	-moz-box-direction: @process_oldermoz;
-	-webkit-box-orient: @process_olderwebkit;
-	-moz-box-orient: @process_moz;
-	-webkit-flex-direction: @process;
-	-ms-flex-direction: @process;
-	flex-direction: @process;
-}
-
-.flex-grow(...) {
-	@process: ~`(function(n){return n=n||"0"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-flex-grow: @process;
-	flex-grow: @process;
-}
-
-.flex-shrink(...) {
-	@process: ~`(function(n){return n=n||"1"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-flex-shrink: @process;
-	flex-shrink: @process;
-}
-
-.flex-wrap(...) {
-	@process: ~`(function(n){return n=n||"nowrap"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-flex-wrap: @process;
-	-ms-flex-wrap: @process;
-	flex-wrap: @process;
-}
-
-.font-face(@fontname, @fontfile, @fontweight:normal, @fontstyle:normal) {
-	font-family: "@{fontname}";
-	src: url("@{fontfile}.eot");
-	src: url("@{fontfile}.eot?#iefix") format("embedded-opentype"),
-			 url("@{fontfile}.woff") format("woff"),
-			 url("@{fontfile}.ttf") format("truetype"),
-			 url("@{fontfile}.svg#@{fontname}") format("svg");
-	font-weight: @fontweight;
-	font-style: @fontstyle;
-}
-
-.grayscale(...) {
-	@process: ~`(function(n){n=n||"0";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"%"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-filter: grayscale(@process);
-	-moz-filter: grayscale(@process);
-	-ms-filter: grayscale(@process);
-	filter: grayscale(@process);
-}
-
-.hue-rotate(...) {
-	@process: ~`(function(e){e=e||"0";var n=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return n.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"deg"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-filter: hue-rotate(@process);
-	-moz-filter: hue-rotate(@process);
-	-ms-filter: hue-rotate(@process);
-	filter: hue-rotate(@process);
-}
-
-.hyphens(...) {
-	@process: ~`(function(n){return n=n||"manual"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-hyphens: @process;
-	-moz-hyphens: @process;
-	-ms-hyphens: @process;
-	hyphens: @process;
-}
-
-.invert(...) {
-	@process: ~`(function(n){n=n||"100%";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"%"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-filter: invert(@process);
-	-moz-filter: invert(@process);
-	-ms-filter: invert(@process);
-	filter: invert(@process);
-}
-
-.justify-content(...) {
-	@process_oldestWebkit: ~`(function(e){return e=e||"start","flex-start"==e?e="start":"flex-end"==e?e="end":"space-between"!=e&&"space-around"!=e||(e="justify"),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_moz: ~`(function(e){return e=e||"start","flex-start"==e?e="start":"flex-end"==e?e="end":"space-between"!=e&&"space-around"!=e||(e="justify"),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_ms: ~`(function(t){return t=t||"start","flex-start"==t?t="start":"flex-end"==t?t="end":"space-between"==t?t="justify":"space-around"==t&&(t="distribute"),t})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process: ~`(function(t){return t=t||"flex-start"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-box-pack: @process_oldestWebkit;
-	-moz-box-pack: @process_moz;
-	-ms-flex-pack: @process_ms;
-	-webkit-justify-content: @process;
-	justify-content: @process;
-}
-
-.keyframes(...) {
-	@process: ~`(function(e){function a(a,r,k){var n="}\n",m=t.split(/(^[a-zA-Z0-9-]+),/g),o=r+" "+m[1]+"{",f=["-webkit-","-moz-","-ms-",""];k?s.forEach(function(a,r){e.indexOf(a)!==-1&&(m[2]=m[2].replace(new RegExp(a,"g"),function(e){return k+e}))}):m[2]=m[2].replace(/{([^}]+)}/g,function(e,a){var r=a.split(";");r.forEach(function(e,a){s.forEach(function(t){e.indexOf(t)!==-1&&(r[a]="",f.forEach(function(s){r[a]+=e.trim().replace(new RegExp(t,"g"),function(e){return s+e})+";"}))})});var t=r.join(";").replace(/;;/g,";");return e.replace(a,t)}),o+=m[2]+n,"start"==a?e="0; } \n"+o:"startend"==a?e="0; } \n"+o.replace(n,""):e+="end"==a?o.replace(n,""):o}e=e||8121991;var r="@{state}",t=e;if(8121991==e)return e;var s=["animation","transform","filter"];switch(r){case"1":a("start","@-webkit-keyframes","-webkit-"),a(null,"@-moz-keyframes","-moz-"),a(null,"@-o-keyframes","-o-"),a("end","@keyframes");break;case"2":a("start","@-webkit-keyframes","-webkit-"),a(null,"@-moz-keyframes","-moz-"),a("end","@keyframes");break;case"3":a("start","@-webkit-keyframes","-webkit-"),a(null,"@-moz-keyframes","-moz-"),a("end","@-o-keyframes","-o-");break;case"4":a("start","@-webkit-keyframes","-webkit-"),a(null,"@-o-keyframes","-o-"),a("end","@keyframes");break;case"5":a("start","@-webkit-keyframes","-webkit-"),a("end","@-moz-keyframes","-moz-");break;case"6":a("start","@-webkit-keyframes","-webkit-"),a("end","@-o-keyframes","-o-");break;case"7":a("start","@-webkit-keyframes","-webkit-"),a("end","@keyframes");break;case"8":a("startend","@-webkit-keyframes","-webkit-");break;case"9":a("start","@-moz-keyframes","-moz-"),a(null,"@-o-keyframes","-o-"),a("end","@keyframes");break;case"10":a("start","@-moz-keyframes","-moz-"),a("end","@-o-keyframes","-o-");break;case"11":a("start","@-moz-keyframes","-moz-"),a("end","@keyframes");break;case"12":a("startend","@-moz-keyframes","-moz-");break;case"13":a("start","@-o-keyframes","-o-"),a("end","@keyframes");break;case"14":a("startend","@-o-keyframes","-o-");break;case"15":a("startend","@keyframes")}return e+"}\n[not-existing] {\n  zoom: 1"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@state: 1; lesshat-selector { -lh-property: @process; }
-
-
-
-}
-
-.opacity(...) {
-	@process_ms: ~`(function(a){return a=a||"filter: alpha(opacity=100)","alpha(opacity="+Math.floor(100*a)+")"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process: ~`(function(n){return n=n||"1"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	 zoom: 1; filter: @process_ms;
-	-webkit-opacity: @process;
-	-moz-opacity: @process;
-	opacity: @process;
-}
-
-.order(...) {
-	@process: ~`(function(n){return n=n||"0"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-box-ordinal-group: @process;
-	-moz-box-ordinal-group: @process;
-	-ms-flex-order: @process;
-	-webkit-order: @process;
-	order: @process;
-}
-
-.perspective(...) {
-	@process: ~`(function(n){n=n||"none";var e=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return e.test(n)&&(n=n.replace(r,function(n){return 0==n&&n||n+"px"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-perspective: @process;
-	-moz-perspective: @process;
-	perspective: @process;
-}
-
-.perspective-origin(...) {
-	@process: ~`(function(e){e=e||"50% 50%";var t=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),t.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"%"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-perspective-origin: @process;
-	-moz-perspective-origin: @process;
-	perspective-origin: @process;
-}
-
-.placeholder(@color:#aaa, @element: 08121991) {
-	.inception (@arguments) when not (@element = 08121991) {
-		@{element}::-webkit-input-placeholder {
-			 color: @color;
-		}
-		@{element}:-moz-placeholder {
-			 color: @color;
-		}
-		@{element}::-moz-placeholder {
-			 color: @color;
-		}
-		@{element}:-ms-input-placeholder {
-			 color: @color;
-		}
-	}
-	.inception (@arguments) when (@element = 08121991) {
-		&::-webkit-input-placeholder {
-			 color: @color;
-		}
-		&:-moz-placeholder {
-			 color: @color;
-		}
-		&::-moz-placeholder {
-			 color: @color;
-		}
-		&:-ms-input-placeholder {
-			 color: @color;
-		}
-	}
-	.inception(@arguments);
-}
-
-.rotate(...) {
-	@process: ~`(function(e){e=e||"0";var n=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return n.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"deg"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: rotate(@process);
-	-moz-transform: rotate(@process);
-	-ms-transform: rotate(@process);
-	-o-transform: rotate(@process);
-	transform: rotate(@process);
-}
-
-.rotate3d(...) {
-	@process: ~`(function(n){return n=n||"0, 0, 0, 0",n=n.replace(/,\s*\d+$/,function(n){return n+"deg"})})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: rotate3d(@process);
-	-moz-transform: rotate3d(@process);
-	-ms-transform: rotate3d(@process);
-	-o-transform: rotate3d(@process);
-	transform: rotate3d(@process);
-}
-
-.rotateX(...) {
-	@process: ~`(function(e){e=e||"0";var n=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return n.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"deg"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: rotateX(@process);
-	-moz-transform: rotateX(@process);
-	-ms-transform: rotateX(@process);
-	-o-transform: rotateX(@process);
-	transform: rotateX(@process);
-}
-
-.rotateY(...) {
-	@process: ~`(function(e){e=e||"0";var n=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return n.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"deg"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: rotateY(@process);
-	-moz-transform: rotateY(@process);
-	-ms-transform: rotateY(@process);
-	-o-transform: rotateY(@process);
-	transform: rotateY(@process);
-}
-
-.rotateZ(...) {
-	@process: ~`(function(e){e=e||"0";var n=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return n.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"deg"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: rotateZ(@process);
-	-moz-transform: rotateZ(@process);
-	-ms-transform: rotateZ(@process);
-	-o-transform: rotateZ(@process);
-	transform: rotateZ(@process);
-}
-
-.saturate(...) {
-	@process: ~`(function(n){n=n||"100%";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"%"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-filter: ~"saturate(@{process})";
-	-moz-filter: ~"saturate(@{process})";
-	-ms-filter: ~"saturate(@{process})";
-	filter: ~"saturate(@{process})";
-}
-
-.scale(...) {
-	@process: ~`(function(n){return n=n||"1"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: scale(@process);
-	-moz-transform: scale(@process);
-	-ms-transform: scale(@process);
-	-o-transform: scale(@process);
-	transform: scale(@process);
-}
-
-.scale3d(...) {
-	@process: ~`(function(n){return n=n||"1, 1, 1"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: scale3d(@process);
-	-moz-transform: scale3d(@process);
-	-ms-transform: scale3d(@process);
-	-o-transform: scale3d(@process);
-	transform: scale3d(@process);
-}
-
-.scaleX(...) {
-	@process: ~`(function(n){return n=n||"1"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: scaleX(@process);
-	-moz-transform: scaleX(@process);
-	-ms-transform: scaleX(@process);
-	-o-transform: scaleX(@process);
-	transform: scaleX(@process);
-}
-
-.scaleY(...) {
-	@process: ~`(function(n){return n=n||"1"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: scaleY(@process);
-	-moz-transform: scaleY(@process);
-	-ms-transform: scaleY(@process);
-	-o-transform: scaleY(@process);
-	transform: scaleY(@process);
-}
-
-.scaleZ(...) {
-	@process: ~`(function(n){return n=n||"1"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: scaleZ(@process);
-	-moz-transform: scaleZ(@process);
-	-ms-transform: scaleZ(@process);
-	-o-transform: scaleZ(@process);
-	transform: scaleZ(@process);
-}
-
-.selection(...) {
-	@process: ~`(function(e){function t(t,n){var r="}\n",s=a.split(","),c=(s[1]||"")+n+"{"+s[0]+r;"start"==t?e="0; } \n"+c:"startend"==t?e="0; } \n"+c.replace(r,""):e+="end"==t?c.replace(r,""):c}e=e||8121991;var n="@{state}",a=e;if(8121991==e)return e;switch(n){case"1":t("start","::selection"),t("end","::-moz-selection");break;case"2":t("startend","::selection");break;case"3":t("startend","::-moz-selection")}return e=e.replace(/;$/g,"")})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@state: 1; lesshat-selector { -lh-property: @process; }
-
-}
-
-.sepia(...) {
-	@process: ~`(function(n){n=n||"100%";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"%"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-filter: sepia(@process);
-	-moz-filter: sepia(@process);
-	-ms-filter: sepia(@process);
-	filter: sepia(@process);
-}
-
-.size(@square) {
-	@unit: 'px';
-	.process(@square) when (ispixel(@square)), (isem(@square)), (ispercentage(@square)), (iskeyword(@square)) {
-		width: @square;
-		height: @square;
-	}
-
-	.process(@square) when not (ispixel(@square)) and not (isem(@square)) and not (ispercentage(@square)) and not (isstring(@square)) and not (iskeyword(@square)) {
-		width: ~`@{square} + @{unit}`;
-		height: ~`@{square} + @{unit}`;
-	}
-
-	.process(@square);
-
-}
-
-.size(@width, @height) {
-	@unit: 'px';
-	.process(@width, @height) when (ispixel(@width)), (isem(@width)), (ispercentage(@width)), (iskeyword(@width)) {
-		.kittens(@height) when (ispixel(@height)), (isem(@height)), (ispercentage(@height)), (iskeyword(@height)) {
-			width: @width;
-			height: @height;
-		}
-		.kittens(@height) when not (ispixel(@height)) and not (isem(@height)) and not (ispercentage(@height)) and not (iskeyword(@height)) {
-			width: @width;
-			height: ~`@{height} + @{unit}`;
-		}
-		.kittens(@height);
-	}
-
-	.process(@width, @height) when (ispixel(@height)), (isem(@height)), (ispercentage(@height)), (iskeyword(@height)) {
-		.kittens(@width) when (ispixel(@width)), (isem(@width)), (ispercentage(@width)), (iskeyword(@width)) {}
-		.kittens(@width) when not (ispixel(@width)) and not (isem(@width)) and not (ispercentage(@width)) and not (iskeyword(@width)) {
-			width: ~`@{width} + @{unit}`;
-			height: @height;
-		}
-		.kittens(@width);
-	}
-
-	.process(@width, @height) when not (ispixel(@width)) and not (isem(@width)) and not (ispercentage(@width)) and not (iskeyword(@width)) and not (ispixel(@height)) and not (isem(@height)) and not (ispercentage(@height)) and not (iskeyword(@height))  {
-		width: ~`@{width} + @{unit}`;
-		height: ~`@{height} + @{unit}`;
-	}
-
-	.process(@width, @height);
-
-}
-
-.skew(...) {
-	@process: ~`(function(e){e=e||"0";var n=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return n.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"deg"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: skew(@process);
-	-moz-transform: skew(@process);
-	-ms-transform: skew(@process);
-	-o-transform: skew(@process);
-	transform: skew(@process);
-}
-
-.skewX(...) {
-	@process: ~`(function(e){e=e||"0";var n=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return n.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"deg"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: skewX(@process);
-	-moz-transform: skewX(@process);
-	-ms-transform: skewX(@process);
-	-o-transform: skewX(@process);
-	transform: skewX(@process);
-}
-
-.skewY(...) {
-	@process: ~`(function(e){e=e||"0";var n=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return n.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"deg"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: skewY(@process);
-	-moz-transform: skewY(@process);
-	-ms-transform: skewY(@process);
-	-o-transform: skewY(@process);
-	transform: skewY(@process);
-}
-
-.transform(...) {
-	@process: ~`(function(e){e=e||"none";var r={translate:"px",rotate:"deg",rotate3d:"deg",skew:"deg"};/^\w*\(?[a-z0-9.]*\)?/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,""));for(var t in r)e.indexOf(t)>=0&&(e=e.replace(new RegExp(t+"[\\w]?\\([a-z0-9, %]*\\)"),function(e){var n=/(\d+\.?\d*)(?!\w|%)/g;return"rotate3d"==t&&(n=/,\s*\d+$/),e.replace(n,function(e){return e+r[t]})}));return e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: @process;
-	-moz-transform: @process;
-	-ms-transform: @process;
-	-o-transform: @process;
-	transform: @process;
-}
-
-.transform-origin(...) {
-	@process: ~`(function(e){e=e||"50% 50% 0";var t=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),t.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"%"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform-origin: @process;
-	-moz-transform-origin: @process;
-	-ms-transform-origin: @process;
-	-o-transform-origin: @process;
-	transform-origin: @process;
-}
-
-.transform-style(...) {
-	@process: ~`(function(n){return n=n||"flat"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform-style: @process;
-	-moz-transform-style: @process;
-	-ms-transform-style: @process;
-	-o-transform-style: @process;
-	transform-style: @process;
-}
-
-.transition(...) {
-	@process_webkit: ~`(function(r){r=r||"all 0 ease 0";var e=["background-size","border-radius","border-bottom-left-radius","border-bottom-right-radius","border-top-left-radius","border-top-right-radius","box-shadow","column","transform","filter"],t="-webkit-",o=/(?:\d)(?:ms|s)/gi,a=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%)/gi;return/^[^, ]*,/.test(r)&&(r=r.replace(/(?:,)(?![^(]*\))/g,"")),e.forEach(function(e,o){r.indexOf(e)!==-1&&(r=r.replace(new RegExp(e,"g"),function(r){return t+r}))}),o.test(r)||"0"===r||(r=r.replace(a,function(r){return r+=parseFloat(r,10)>10?"ms":"s"})),r})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_moz: ~`(function(e){e=e||"all 0 ease 0";var n=["background-size","box-shadow","column","transform","filter"],r="-moz-",t=/(?:\d)(?:ms|s)/gi,a=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),n.forEach(function(n,t){e.indexOf(n)!==-1&&(e=e.replace(new RegExp(n,"g"),function(e){return r+e}))}),t.test(e)||"0"===e||(e=e.replace(a,function(e){return e+=parseFloat(e,10)>10?"ms":"s"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_opera: ~`(function(e){e=e||"all 0 ease 0";var n=["transform"],r="-o-",t=/(?:\d)(?:ms|s)/gi,a=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),n.forEach(function(n,t){e.indexOf(n)!==-1&&(e=e.replace(new RegExp(n,"g"),function(e){return r+e}))}),t.test(e)||"0"===e||(e=e.replace(a,function(e){return e+=parseFloat(e,10)>10?"ms":"s"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process: ~`(function(n){n=n||"all 0 ease 0";var e=["-webkit-","-moz-","-o-",""],t=["column","transform","filter"],r=/(?:\d)(?:ms|s)/gi,o=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%)/gi;/^[^, ]*,/.test(n)&&(n=n.replace(/(?:,)(?![^(]*\))/g,""));var i=n.split(/(?:,)(?![^(]*\))/g);return i.forEach(function(n,r){t.forEach(function(t){n.indexOf(t)!==-1&&(i[r]="",e.forEach(function(o,a){i[r]+=n.trim().replace(new RegExp(t,"g"),function(n){return o+n}),a<e.length-1&&(i[r]+=",")}))})}),n=i.join(","),r.test(n)||"0"===n||(n=n.replace(o,function(n){return n+=parseFloat(n,10)>10?"ms":"s"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transition: @process_webkit;
-	-moz-transition: @process_moz;
-	-o-transition: @process_opera;
-	transition: @process;
-}
-
-.transition-delay(...) {
-	@process: ~`(function(r){r=r||"0";var s=/(?:\d)(?:ms|s)/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return s.test(r)||"0"===r||(r=r.replace(t,function(r){return r+=parseFloat(r,10)>10?"ms":"s"})),r})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transition-delay: @process;
-	-moz-transition-delay: @process;
-	-o-transition-delay: @process;
-	transition-delay: @process;
-}
-
-.transition-duration(...) {
-	@process: ~`(function(r){r=r||"0";var s=/ms|s/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return s.test(r)||"0"===r||(r=r.replace(t,function(r){return r+=parseFloat(r,10)>10?"ms":"s"})),r})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transition-duration: @process;
-	-moz-transition-duration: @process;
-	-o-transition-duration: @process;
-	transition-duration: @process;
-}
-
-.transition-property(...) {
-	@process_webkit: ~`(function(r){r=r||"all";var o=["background-size","border-radius","border-bottom-left-radius","border-bottom-right-radius","border-top-left-radius","border-top-right-radius","box-shadow","column","transform","filter"],t="-webkit-";return o.forEach(function(o,e){r.indexOf(o)!==-1&&(r=r.replace(new RegExp(o,"g"),function(r){return t+r}))}),r})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_moz: ~`(function(n){n=n||"all";var r=["background-size","box-shadow","column","transform","filter"],o="-moz-";return r.forEach(function(r,e){n.indexOf(r)!==-1&&(n=n.replace(new RegExp(r,"g"),function(n){return o+n}))}),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process_opera: ~`(function(n){n=n||"all";var r=["transform"],e="-o-";return r.forEach(function(r,f){n.indexOf(r)!==-1&&(n=n.replace(new RegExp(r,"g"),function(n){return e+n}))}),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	@process: ~`(function(n){n=n||"all";var o=["-webkit-","-moz-","-o-",""],r=["column","transform","filter"],t=n.split(/(?:,)(?![^(]*\))/g);return t.forEach(function(n,f){r.forEach(function(r){n.indexOf(r)!==-1&&(t[f]="",o.forEach(function(i,c){t[f]+=n.trim().replace(new RegExp(r,"g"),function(n){return i+n}),c<o.length-1&&(t[f]+=",")}))})}),n=t.join(",")})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transition-property: @process_webkit;
-	-moz-transition-property: @process_moz;
-	-o-transition-property: @process_opera;
-	transition-property: @process;
-}
-
-.transition-timing-function(...) {
-	@process: ~`(function(e){return e=e||"ease"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transition-timing-function: @process;
-	-moz-transition-timing-function: @process;
-	-o-transition-timing-function: @process;
-	transition-timing-function: @process;
-}
-
-.translate(...) {
-	@process: ~`(function(n){n=n||"0";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"px"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: translate(@process);
-	-moz-transform: translate(@process);
-	-ms-transform: translate(@process);
-	-o-transform: translate(@process);
-	transform: translate(@process);
-}
-
-.translate3d(...) {
-	@process: ~`(function(n){n=n||"0, 0, 0";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"px"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: translate3d(@process);
-	-moz-transform: translate3d(@process);
-	-ms-transform: translate3d(@process);
-	-o-transform: translate3d(@process);
-	transform: translate3d(@process);
-}
-
-.translateX(...) {
-	@process: ~`(function(n){n=n||"0";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"px"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: translateX(@process);
-	-moz-transform: translateX(@process);
-	-ms-transform: translateX(@process);
-	-o-transform: translateX(@process);
-	transform: translateX(@process);
-}
-
-.translateY(...) {
-	@process: ~`(function(n){n=n||"0";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"px"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: translateY(@process);
-	-moz-transform: translateY(@process);
-	-ms-transform: translateY(@process);
-	-o-transform: translateY(@process);
-	transform: translateY(@process);
-}
-
-.translateZ(...) {
-	@process: ~`(function(n){n=n||"0";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"px"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-transform: translateZ(@process);
-	-moz-transform: translateZ(@process);
-	-ms-transform: translateZ(@process);
-	-o-transform: translateZ(@process);
-	transform: translateZ(@process);
-}
-
-.user-select(...) {
-	@process: ~`(function(n){return n=n||"auto"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
-	-webkit-user-select: @process;
-	-moz-user-select: @process;
-	-ms-user-select: @process;
-	user-select: @process;
-}
diff --git a/packages/rocketchat-theme/assets/stylesheets/utils/_mixins.import.less b/packages/rocketchat-theme/assets/stylesheets/utils/_mixins.import.less
deleted file mode 100644
index 6737decfc2786241da9bc6d9e3c5563c2db4257f..0000000000000000000000000000000000000000
--- a/packages/rocketchat-theme/assets/stylesheets/utils/_mixins.import.less
+++ /dev/null
@@ -1,98 +0,0 @@
-.custom-scroll(@background, @thumb, @width: 8px, @height: 8px) {
-	-webkit-overflow-scrolling: touch;
-	&::-webkit-scrollbar {
-		height: @height;
-		width: @width;
-		background: @background;
-	}
-	&::-webkit-scrollbar-thumb {
-		background-color: @thumb;
-		-webkit-border-radius: 50px;
-	}
-	&::-webkit-scrollbar-corner {
-		background-color: @background;
-	}
-}
-
-.gradient(@startColor: #eee, @endColor: white) {
-	background-color: @startColor;
-	background: -webkit-gradient(linear, left top, left bottom, from(@startColor), to(@endColor));
-	background: -webkit-linear-gradient(top, @startColor, @endColor);
-	background: -moz-linear-gradient(top, @startColor, @endColor);
-	background: -ms-linear-gradient(top, @startColor, @endColor);
-	background: -o-linear-gradient(top, @startColor, @endColor);
-}
-
-.input-shade(@color, @bg) {
-	input,
-	select,
-	textarea {
-		color: @color;
-		background-color: transparent;
-		border-color: mix(contrast(@bg), @bg, 10%);
-		border-style: solid;
-		&::placeholder {
-			color: mix(@color, @bg, 75%);
-		}
-		&[disabled] {
-			background-color: mix(contrast(@bg), @bg, 10%);
-		}
-	}
-	.diabled label,
-	[disabled] label {
-		color: mix(@color, @bg, 75%);
-	}
-	.-autocomplete-container {
-		background-color: mix(contrast(@bg), @bg, 10%);
-	}
-	.-autocomplete-item.selected {
-		background-color: mix(contrast(@bg), @bg, 20%);
-	}
-	input[type="button"],
-	input[type="submit"] {
-		color: @color;
-		background: mix(contrast(@bg), @bg, 10%);
-		border-color: mix(contrast(@bg), @bg, 10%);
-	}
-}
-
-.blink(@color) {
-	animation-duration: 1000ms;
-	animation-name: blink;
-	animation-iteration-count: infinite;
-	animation-direction: alternate;
-	@keyframes blink {
-		from {
-			color: @color;
-		}
-		to {
-			opacity: inherit;
-		}
-	}
-	@-webkit-keyframes blink {
-		from {
-			color: @color;
-		}
-		to {
-			color: inherit;
-		}
-	}
-}
-
-.linkColors(@color, @hover) {
-	transition: color 0.2s ease-out;
-	color: @color;
-	&:hover {
-		color: @hover;
-	}
-}
-
-.buttonColors(@color, @bg) {
-	transition: color 0.2s ease-out, background-color 0.2s ease-out;
-	color: @color;
-	background-color: @bg;
-	&:hover {
-		color: lighten(@color, 10%);
-		background-color: darken(@bg, 5%);
-	}
-}
diff --git a/packages/rocketchat-theme/assets/stylesheets/utils/_preloader.import.less b/packages/rocketchat-theme/assets/stylesheets/utils/_preloader.import.less
deleted file mode 100644
index ec780839b802bd6b8b355181e361c0f5a552eb6b..0000000000000000000000000000000000000000
--- a/packages/rocketchat-theme/assets/stylesheets/utils/_preloader.import.less
+++ /dev/null
@@ -1,152 +0,0 @@
-@-webkit-keyframes scaled {
-	0% {
-		.transform(scale(1));
-	}
-	20% {
-		.transform(scale(1.55));
-	}
-	50% {
-		.transform(scale(1));
-	}
-	100% {
-		.transform(scale(1));
-	}
-}
-
-@-moz-keyframes scaled {
-	0% {
-		.transform(scale(1));
-	}
-	20% {
-		.transform(scale(1.55));
-	}
-	50% {
-		.transform(scale(1));
-	}
-	100% {
-		.transform(scale(1));
-	}
-}
-
-@-o-keyframes scaled {
-	0% {
-		.transform(scale(1));
-	}
-	20% {
-		.transform(scale(1.55));
-	}
-	50% {
-		.transform(scale(1));
-	}
-	100% {
-		.transform(scale(1));
-	}
-}
-
-@keyframes scaled {
-	0% {
-		.transform(scale(1));
-	}
-	20% {
-		.transform(scale(1.55));
-	}
-	50% {
-		.transform(scale(1));
-	}
-	100% {
-		.transform(scale(1));
-	}
-}
-
-@-webkit-keyframes minor {
-	0% {
-		.transform(scale(1));
-	}
-	20% {
-		.transform(scale(1.08));
-	}
-	50% {
-		.transform(scale(1));
-	}
-	100% {
-		.transform(scale(1));
-	}
-}
-
-@-moz-keyframes minor {
-	0% {
-		.transform(scale(1));
-	}
-	20% {
-		.transform(scale(1.08));
-	}
-	50% {
-		.transform(scale(1));
-	}
-	100% {
-		.transform(scale(1));
-	}
-}
-
-@-o-keyframes minor {
-	0% {
-		.transform(scale(1));
-	}
-	20% {
-		.transform(scale(1.08));
-	}
-	50% {
-		.transform(scale(1));
-	}
-	100% {
-		.transform(scale(1));
-	}
-}
-
-@keyframes minor {
-	0% {
-		.transform(scale(1));
-	}
-	20% {
-		.transform(scale(1.08));
-	}
-	50% {
-		.transform(scale(1));
-	}
-	100% {
-		.transform(scale(1));
-	}
-}
-
-.rocket-loader {
-	position: fixed;
-	top: 50%;
-	left: 50%;
-	margin-left: -75px;
-	margin-top: -75px;
-	z-index: 9999;
-	width: 150px;
-	height: 150px;
-	.inner {
-		.animation(minor 1s ease-out infinite 1.625s);
-		.transform-origin(100px, 100px);
-	}
-	.outer {
-		.animation(minor 1s ease-out infinite 1.625s);
-		.transform-origin(100px, 100px);
-	}
-	circle {
-		&:nth-child(1) {
-			.animation(scaled 1s ease-out infinite .3s);
-			.transform-origin(135px, 100px);
-		}
-		&:nth-child(2) {
-			.animation(scaled 1s ease-out infinite .15s);
-			.transform-origin(108px, 100px);
-		}
-		&:nth-child(3) {
-			.animation(scaled 1s ease-out infinite);
-			.transform-origin(81px, 100px);
-		}
-	}
-}
diff --git a/packages/rocketchat-theme/assets/stylesheets/base.less b/packages/rocketchat-theme/client/imports/base.less
similarity index 84%
rename from packages/rocketchat-theme/assets/stylesheets/base.less
rename to packages/rocketchat-theme/client/imports/base.less
index 2180e15a49ae173c2b9fe2339f2cbe3a9a8c5fbd..b8a72a6e11449af41f83406bffb2d90bd510e790 100644
--- a/packages/rocketchat-theme/assets/stylesheets/base.less
+++ b/packages/rocketchat-theme/client/imports/base.less
@@ -1,5 +1,6 @@
 .clearfix {
 	clear: both;
+
 	&::after {
 		content: "";
 		display: table;
@@ -8,14 +9,14 @@
 }
 
 *,
-*:before,
-*:after {
+*::before,
+*::after {
 	.box-sizing(border-box);
 }
 
 *:not(input):not(textarea),
-*:not(input):not(textarea):before,
-*:not(input):not(textarea):after {
+*:not(input):not(textarea)::before,
+*:not(input):not(textarea)::after {
 	-webkit-user-select: none;
 	-moz-user-select: none;
 	-ms-user-select: none;
@@ -25,7 +26,7 @@
 button {
 	background: none;
 	border-width: 0;
-	padding: 0px;
+	padding: 0;
 	text-align: left;
 	cursor: pointer;
 	text-transform: inherit;
@@ -65,6 +66,7 @@ button {
 a {
 	cursor: pointer;
 	text-decoration: none;
+
 	&:hover,
 	&:active {
 		text-decoration: none;
@@ -86,6 +88,7 @@ code {
 	unicode-bidi: embed;
 	direction: ltr;
 	font-family: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+
 	&.inline {
 		display: inline;
 		padding: 0 0.5em;
@@ -105,21 +108,24 @@ pre {
 
 blockquote {
 	.clearfix;
-	margin: .5em 0;
+	margin: 0.5em 0;
+
 	&:first-child {
 		margin-top: 0;
 	}
+
 	&:last-child {
 		margin-bottom: 0;
 	}
 	padding-left: 10px;
 	position: relative;
-	&:before {
+
+	&::before {
 		content: ' ';
 		width: 4px;
 		position: absolute;
 		border-radius: 2px;
-		left: 0px;
+		left: 0;
 		top: -1px;
 		bottom: -1px;
 	}
@@ -131,6 +137,7 @@ blockquote {
 	padding: 10px;
 	max-width: 100%;
 	margin: auto;
+
 	a {
 		font-weight: bold !important;
 		text-decoration: underline;
@@ -139,6 +146,7 @@ blockquote {
 
 .upload-preview {
 	padding: 1rem;
+
 	.upload-preview-file {
 		height: 200px;
 		background-size: contain;
@@ -173,29 +181,39 @@ blockquote {
 	user-select: none;
 }
 
-.first-unread {
+.first-unread,
+.cozy .first-unread,
+.compact .first-unread {
+	&.message,
+	&.sequential.message {
+		padding-top: 20px;
+	}
+
 	.body {
 		&::before {
 			content: "";
 			display: block;
-			height: 1px;
 			position: absolute;
-			right: 0px;
-			left: 20px;
-			top: 0px;
-			.transition(background-color, .5s, linear);
+			right: 0;
+			left: 0;
+			top: 0;
+			transition: background-color, 0.5s, linear;
+			height: 16px;
 		}
+
 		&::after {
 			content: "unread messages";
 			display: block;
 			position: absolute;
-			right: 0px;
-			top: -4px;
+			right: 0;
+			top: 0;
 			text-transform: uppercase;
-			font-size: 8px;
-			line-height: 10px;
+			font-size: 12px;
+			line-height: 16px;
 			padding: 0 5px;
-			.transition(color, .5s, linear);
+			transition: color, 0.5s, linear;
+			left: 0;
+			text-align: center;
 		}
 	}
 }
@@ -209,7 +227,7 @@ blockquote {
 	position: absolute;
 	width: 100%;
 	z-index: 1000000;
-	border-radius: 0px;
+	border-radius: 0;
 }
 
 .alert {
@@ -249,52 +267,87 @@ blockquote {
 	-webkit-overflow-scrolling: touch;
 }
 
-.rocket-form {
-	max-width: 620px;
-	width: 90%;
-	legend {
-		margin-bottom: 23px;
-		position: relative;
-		width: 100%;
-		display: block;
-		h3 {
-			margin-bottom: 5px !important;
-		}
-		&:after {
-			content: " ";
-			height: 1px;
-			display: block;
-			position: absolute;
-			width: 100%;
-			bottom: -10px;
-			left: 0;
-		}
-	}
-	fieldset {
-		display: block;
-		margin-bottom: 40px;
-		small {
-			font-size: 11px;
-		}
-	}
-	.logoutOthers {
-		text-align: right;
-	}
-	.submit {
-		margin-top: 20px;
-		text-align: right;
-	}
-	&.request-password {
-		margin: 0 auto;
+.page-container {
+	&:extend(.fill-all);
+	overflow-y: hidden;
+
+	.content {
+		&:extend(.fill-all);
+		padding: 25px 40px;
+		overflow-y: scroll;
+		margin-top: 60px;
+		-webkit-overflow-scrolling: touch;
+		.calc(height, ~'100% - 60px');
+
 		fieldset {
-			margin-top: 20px;
-			label {
+			margin-bottom: 1em;
+		}
+
+		.rocket-form {
+			fieldset {
+				display: block;
+				margin: 1em 0 1.5em;
+
+				small {
+					font-size: 11px;
+				}
+			}
+
+			legend {
+				margin: 12px 0;
+				position: relative;
+				width: 100%;
 				display: block;
+				font-weight: bold;
+
+				h3 {
+					margin-bottom: 5px !important;
+				}
+			}
+
+			.logoutOthers {
+				text-align: right;
+			}
+
+			.submit {
 				margin-top: 20px;
+				text-align: right;
+			}
+
+			&.request-password {
+				margin: 0 auto;
+
+				fieldset {
+					margin-top: 20px;
+
+					label {
+						display: block;
+						margin-top: 20px;
+					}
+				}
+
+				.submit {
+					text-align: center;
+				}
 			}
 		}
-		.submit {
-			text-align: center;
+	}
+
+	table {
+		overflow: hidden;
+		margin-bottom: 30px;
+		width: 100%;
+
+		th,
+		td {
+			vertical-align: middle;
+			padding: 0.6rem 0.7rem;
+			text-align: left;
+			border-width: 0 0 1px;
+		}
+
+		th {
+			white-space: nowrap;
 		}
 	}
 }
@@ -303,14 +356,21 @@ blockquote {
 	.clearfix;
 	display: block;
 	margin-bottom: 12px;
+
 	&:nth-last-child(1) {
 		margin-bottom: 0;
 	}
+
 	&.search {
-		.icon-spin {
+		i {
 			position: absolute;
-			right: 5px;
 			top: 10px;
+			left: 7px;
+		}
+
+		.icon-spin {
+			right: 5px;
+			left: auto;
 			font-weight: 400;
 			-webkit-animation-name: spin;
 			-webkit-animation-duration: 2000ms;
@@ -329,25 +389,20 @@ blockquote {
 			animation-iteration-count: infinite;
 			animation-timing-function: linear;
 		}
-		.icon-search,
-		.icon-right-open-small,
-		.icon-sort-alt-up,
-		.icon-lock,
-		.icon-comment {
-			position: absolute;
-			left: 2px;
-			top: 10px;
-		}
+
 		input {
 			padding-left: 30px;
 		}
 	}
+
 	> label {
 		display: block;
 		margin-bottom: 4px;
 	}
+
 	> div {
 		position: relative;
+
 		.right {
 			position: absolute;
 			right: 10px;
@@ -355,32 +410,38 @@ blockquote {
 			z-index: 10;
 		}
 	}
+
 	> div.-autocomplete-container {
 		position: absolute;
 	}
+
 	input[type='text'] {
 		display: block;
 	}
+
 	&.double-col {
 		> label {
 			width: 30%;
 			float: left;
 			margin-bottom: 0;
-			padding-right: 20px;
 			text-align: right;
 			line-height: 15px;
 			padding: 10px 20px 10px 0;
 		}
+
 		> div {
 			float: left;
 			width: 70%;
+
 			label {
 				display: inline-block;
 				margin-right: 4px;
 				line-height: 35px;
+
 				&:nth-last-child(1) {
 					margin-right: 0;
 				}
+
 				input {
 					margin-right: 4px;
 				}
@@ -393,6 +454,7 @@ blockquote {
 	from {
 		-ms-transform: rotate(0deg);
 	}
+
 	to {
 		-ms-transform: rotate(360deg);
 	}
@@ -402,6 +464,7 @@ blockquote {
 	from {
 		-moz-transform: rotate(0deg);
 	}
+
 	to {
 		-moz-transform: rotate(360deg);
 	}
@@ -411,6 +474,7 @@ blockquote {
 	from {
 		-webkit-transform: rotate(0deg);
 	}
+
 	to {
 		-webkit-transform: rotate(360deg);
 	}
@@ -420,6 +484,7 @@ blockquote {
 	from {
 		transform: rotate(0deg);
 	}
+
 	to {
 		transform: rotate(360deg);
 	}
@@ -451,13 +516,13 @@ blockquote {
 html {
 	overflow-y: scroll;
 	height: 100%;
+
 	&.noscroll {
 		overflow: hidden;
 	}
 }
 
 body {
-	font-family: @body-font-family;
 	font-size: 0.875rem;
 	height: 100%;
 	width: 100%;
@@ -469,6 +534,7 @@ body {
 }
 
 // input & form styles
+
 input,
 button,
 select,
@@ -505,9 +571,9 @@ input[type='password'] {
 }
 
 input.input-forward {
-	width: 0px;
+	width: 0;
 	visibility: hidden;
-	.transition(width .5s ease-in);
+	transition: width 0.5s ease-in;
 }
 
 input.input-forward.show {
@@ -516,7 +582,7 @@ input.input-forward.show {
 }
 
 input.search {
-	&:before {
+	&::before {
 		content: " ";
 		width: 30px;
 		height: 30px;
@@ -554,16 +620,18 @@ form.inline {
 }
 
 .-autocomplete-container {
-	box-shadow: 1px 1px 0px rgba(0, 0, 0, 0.2);
+	box-shadow: 1px 1px 0 rgba(0, 0, 0, 0.2);
 	border-width: 0;
 	border-radius: 0;
 	width: 100%;
 	top: auto !important;
+
 	p {
 		font-size: 14px;
-		padding: 8px 8px;
+		padding: 8px;
 	}
-	.loading {
+
+	.loading-animation {
 		position: relative;
 		min-height: 60px;
 	}
@@ -575,7 +643,7 @@ form.inline {
 	cursor: pointer;
 }
 
-label.required:after {
+label.required::after {
 	content: ' *';
 }
 
@@ -584,15 +652,18 @@ label.required:after {
 	cursor: not-allowed;
 	box-shadow: none !important;
 	border-width: 0;
+
 	i {
 		display: block;
 	}
+
 	div {
 		display: none;
 	}
 }
 
 // new layout buttons
+
 .button {
 	&:extend(.unselectable);
 	border-width: 0;
@@ -606,15 +677,61 @@ label.required:after {
 	line-height: 16px;
 	position: relative;
 	border-radius: 4px;
+
 	span {
 		position: relative;
 		z-index: 2;
 	}
+
 	&.button-block {
 		display: block;
 		margin-bottom: 4px;
 		width: 100%;
 	}
+
+	&[disabled] {
+		cursor: initial;
+	}
+
+	&.external-login {
+		color: white;
+
+		&.facebook {
+			background-color: #325c99;
+		}
+
+		&.twitter {
+			background-color: #02acec;
+		}
+
+		&.google {
+			background-color: #dd4b39;
+		}
+
+		&.github {
+			background-color: #4c4c4c;
+		}
+
+		&.gitlab {
+			background-color: #373d47;
+		}
+
+		&.trello {
+			background-color: #026aa7;
+		}
+
+		&.meteor-developer {
+			background-color: #de4f4f;
+		}
+
+		&.wordpress {
+			background-color: #1e8cbe;
+		}
+
+		&.linkedin {
+			background-color: #1b86bc;
+		}
+	}
 }
 
 .buttons-group {
@@ -622,26 +739,36 @@ label.required:after {
 	display: -moz-flex;
 	display: flex;
 	margin-bottom: 4px;
+
 	.button {
 		margin-left: 4px;
 	}
+
 	.button:first-child {
-		margin-left: 0px;
-		-webkit-flex-grow: 1;
-		-moz-flex-grow: 1;
+		margin-left: 0;
 		flex-grow: 1;
 	}
 }
 
+.oauth-panel {
+	.buttons-group {
+		.button:first-child {
+			flex-grow: 0;
+		}
+	}
+}
+
 .sec-header {
 	margin: 16px 0;
 	text-align: center;
+
 	> * {
 		display: inline-table;
 		width: auto;
 		vertical-align: middle;
 		line-height: 35px;
 	}
+
 	label {
 		margin-left: 20px;
 	}
@@ -655,22 +782,19 @@ label.required:after {
 	margin-left: 7px;
 	position: absolute;
 	top: 5px;
-	left: 0px;
-	.transition(transform .2s ease-out .1s);
+	left: 0;
+	will-change: transform;
+	transition: transform 0.2s ease-out 0.1s;
+
 	i {
 		display: block;
 		height: 2px;
 		width: 20px;
 		margin: 5px 0;
-		opacity: .8;
-		.transition(transform .2s ease-out, width .2s ease-out);
-		&:nth-child(1) {
-			//	.transition-delay(.06s);
-		}
-		&:nth-child(3) {
-			.transition-delay(.1s);
-		}
+		opacity: 0.8;
+		transition: transform 0.2s ease-out;
 	}
+
 	.unread-burger-alert {
 		border-radius: 20px;
 		position: absolute;
@@ -683,7 +807,25 @@ label.required:after {
 		top: 8px;
 		right: 4px;
 		z-index: 3;
-		padding: 0px 4px;
+		padding: 0 4px;
+	}
+
+	&.menu-opened {
+		i {
+			&:nth-child(1),
+			&:nth-child(3) {
+				opacity: 1;
+				.transform-origin(50%, 50%, 0);
+			}
+
+			&:nth-child(1) {
+				.transform(translate(-25%, 3px) rotate(-45deg) scale(0.5, 1));
+			}
+
+			&:nth-child(3) {
+				.transform(translate(-25%, -3px) rotate(45deg) scale(0.5, 1));
+			}
+		}
 	}
 }
 
@@ -693,8 +835,9 @@ label.required:after {
 	height: 25px;
 	z-index: 100;
 	.calc(top, ~"50% - 13px");
-	&:before,
-	&:after {
+
+	&::before,
+	&::after {
 		content: " ";
 		display: block;
 		width: 2px;
@@ -703,43 +846,53 @@ label.required:after {
 		.calc(top, ~"50% - 5px");
 		.calc(left, ~"50% - 5px");
 	}
-	&:before {
+
+	&::before {
 		.transform(rotate(135deg) translateX(-4px));
-		.transition(transform .185s ease-out, background .15s ease-out);
+		transition: transform 0.185s ease-out, background 0.15s ease-out;
 	}
-	&:after {
+
+	&::after {
 		.transform(rotate(-135deg) translateX(-4px));
-		.transition(transform .185s ease-out, background .15s ease-out);
+		transition: transform 0.185s ease-out, background 0.15s ease-out;
 	}
+
 	&.left {
-		&:before {
+		&::before {
 			.transform(rotate(45deg) translateY(-4px));
 		}
-		&:after {
+
+		&::after {
 			.transform(rotate(-45deg) translateY(4px));
 		}
 	}
+
 	&.top {
-		&:before {
+		&::before {
 			.transform(rotate(-135deg) translateX(2px) translateY(-2px));
 		}
-		&:after {
+
+		&::after {
 			.transform(rotate(135deg) translateX(-2px) translateY(-2px));
 		}
 	}
+
 	&.bottom {
-		&:before {
+		&::before {
 			.transform(rotate(-45deg) translateX(-2px) translateY(-2px));
 		}
-		&:after {
+
+		&::after {
 			.transform(rotate(45deg) translateX(2px) translateY(-2px));
 		}
 	}
+
 	&.close {
-		&:before {
+		&::before {
 			.transform(rotate(-135deg) translateX(0) translateY(0));
 		}
-		&:after {
+
+		&::after {
 			.transform(rotate(135deg) translateX(0) translateY(0));
 		}
 	}
@@ -751,28 +904,25 @@ label.required:after {
 	overflow: hidden;
 	position: relative;
 	border-radius: 4px;
+
 	.emoji,
 	.emojione {
 		width: 100%;
 		height: 100%;
-		margin: 0px;
+		margin: 0;
 	}
+
 	.avatar-image {
 		height: 100%;
 		width: 100%;
-		min-height: 20px;
-		min-width: 20px;
-		display: block;
-		position: relative;
 		background-size: cover;
 		background-repeat: no-repeat;
 		background-position: center;
-		border-radius: 4px;
 	}
-	&[initials]:before {
+
+	&[initials]::before {
 		content: attr(initials);
 		position: absolute;
-		position: absolute;
 		font-size: 22px;
 		text-align: center;
 		width: 100%;
@@ -795,11 +945,13 @@ label.required:after {
 	height: auto;
 	opacity: 1;
 	visibility: visible;
-	.transition(opacity .2s ease-out);
+	transition: opacity 0.2s ease-out;
+
 	&.animated-hidden {
 		visibility: hidden;
 		opacity: 0;
 	}
+
 	> .alert {
 		margin-bottom: 0;
 		padding: 5px;
@@ -812,19 +964,21 @@ label.required:after {
 	height: 100%;
 	cursor: pointer;
 	width: 100%;
+
 	.info {
 		position: relative;
 		height: 100%;
-		padding: 10px 0px 10px 18px;
+		padding: 10px 0 10px 18px;
 		z-index: 100;
+
 		.thumb {
 			float: left;
-			height: 100%;
 			position: relative;
 			width: 42px;
 			padding: 0;
 			height: 42px;
-			&:after {
+
+			&::after {
 				content: " ";
 				display: block;
 				width: 8px;
@@ -835,10 +989,12 @@ label.required:after {
 				top: 18px;
 				left: -14px;
 			}
+
 			.avatar-initials {
 				line-height: 44px;
 			}
 		}
+
 		.data {
 			float: left;
 			position: relative;
@@ -848,6 +1004,7 @@ label.required:after {
 			flex-flow: row nowrap;
 			.calc(width, ~"100% - 60px");
 		}
+
 		h4 {
 			display: block;
 			line-height: 18px;
@@ -859,9 +1016,10 @@ label.required:after {
 			position: relative;
 			width: 130px;
 			text-align: left;
-			.transition(color .15s ease-out);
+			transition: color 0.15s ease-out;
 		}
 	}
+
 	.options {
 		position: fixed;
 		top: @header-min-height;
@@ -873,18 +1031,22 @@ label.required:after {
 		-webkit-overflow-scrolling: touch;
 		direction: rtl;
 		.calc(height, ~'100% - ' @header-min-height + @footer-min-height);
-		.transition(transform .3s cubic-bezier(.5, 0, .1, 1));
+		transition: transform 0.3s cubic-bezier(0.5, 0, 0.1, 1);
 		z-index: 99;
+
 		&.animated-hidden {
 			.transform(translateY(-100%) translateY(-50px));
 		}
+
 		> .wrapper {
 			direction: ltr;
 		}
+
 		.status {
 			padding-left: 38px;
 			position: relative;
-			&:after {
+
+			&::after {
 				content: " ";
 				display: block;
 				width: 13px;
@@ -897,20 +1059,22 @@ label.required:after {
 				.calc(top, ~"50% - 8px");
 			}
 		}
+
 		span.soon {
-			// content: "em breve";
 			width: 100px;
 			position: absolute;
 			right: -30px;
 			font-size: 10px;
 			top: 17px;
 		}
+
 		i {
 			width: 26px;
 			display: inline-block;
 			text-align: center;
 			margin-left: 0 -1px 0 1px;
 		}
+
 		button,
 		a {
 			position: relative;
@@ -919,17 +1083,20 @@ label.required:after {
 			padding: 15px 12px;
 			line-height: 1;
 			text-decoration: none;
+
 			&:hover {
 				text-decoration: none;
 			}
 		}
+
 		.icon-logout {
-			&:before {
-				margin-right: 0px;
+			&::before {
+				margin-right: 0;
 			}
 		}
+
 		.icon-camera {
-			&:before {
+			&::before {
 				margin-left: 1px;
 			}
 		}
@@ -937,6 +1104,7 @@ label.required:after {
 }
 
 // rooms-box
+
 .flex-nav {
 	position: fixed;
 	top: 0;
@@ -946,23 +1114,28 @@ label.required:after {
 	overflow-y: auto;
 	overflow-x: hidden;
 	width: @rooms-box-width;
-	.transition(transform .15s cubic-bezier(.5, 0, .1, 1));
+	transition: transform 0.15s cubic-bezier(0.5, 0, 0.1, 1);
+
 	&.animated-hidden {
 		.transform(translateX(-100%));
+
 		header,
 		footer,
 		.content {
 			.transform(translateX(-100%));
 		}
 	}
+
 	header,
 	footer,
 	.content {
-		.transition(transform .425s cubic-bezier(0, .8, .05, 1));
+		transition: transform 0.425s cubic-bezier(0, 0.8, 0.05, 1);
 	}
+
 	> section {
 		&:extend(.fill-all);
 	}
+
 	header {
 		display: table;
 		position: absolute;
@@ -974,12 +1147,13 @@ label.required:after {
 		min-height: @header-min-height;
 		height: @header-min-height;
 		padding-left: 15px;
-		.transition-delay(.05s);
+
 		> div {
 			display: table-cell;
 			vertical-align: middle;
 			text-align: left;
 		}
+
 		h4 {
 			line-height: 24px;
 			font-size: 20px;
@@ -989,6 +1163,7 @@ label.required:after {
 			text-overflow: ellipsis;
 			position: relative;
 		}
+
 		p {
 			line-height: 18px;
 			margin-top: 4px;
@@ -996,6 +1171,7 @@ label.required:after {
 			font-size: 13px;
 		}
 	}
+
 	footer {
 		display: table;
 		position: absolute;
@@ -1006,13 +1182,14 @@ label.required:after {
 		z-index: 120;
 		text-align: left;
 		height: @footer-min-height;
-		.transition-delay(.22s);
+
 		> div {
 			display: table-cell;
 			vertical-align: middle;
 			text-align: left;
 		}
 	}
+
 	.content {
 		direction: rtl;
 		position: absolute;
@@ -1024,20 +1201,24 @@ label.required:after {
 		display: block;
 		-webkit-overflow-scrolling: touch;
 		padding: 20px 10px;
-		.transition-delay(.135s);
+
 		&.no-shadow {
 			box-shadow: 0 0 0;
 		}
+
 		> .wrapper {
 			direction: ltr;
+
 			.flex-control {
 				margin-bottom: 30px;
+
 				.search {
 					width: 100%;
 					margin-bottom: 10px;
 				}
 			}
 		}
+
 		h4 {
 			margin-bottom: 30px;
 			font-weight: 400;
@@ -1045,30 +1226,29 @@ label.required:after {
 			font-size: 13px;
 		}
 	}
+
 	.input-line {
 		margin-bottom: 25px;
+
 		&:nth-last-child(1) {
 			margin-bottom: 0;
 		}
+
 		label {
-			text-transform: uppercase;
 			font-weight: 400;
 			margin-bottom: 0;
 		}
+
 		input[type='text'],
 		input[type='password'],
 		select {
-			border-width: 0 0 1px 0;
-			padding: 0 8px;
+			padding: 0 8px 0 30px;
 			box-shadow: 0 0 0;
-			border-radius: 0;
-			-webkit-appearance: none;
-			-moz-appearance: none;
 			appearance: none;
-			-webkit-border-radius: 0px;
-			-moz-border-radius: 0px;
-			border-radius: 0px;
+			border-width: 1px;
+			border-radius: 4px;
 		}
+
 		.inline-fields {
 			input,
 			label,
@@ -1076,18 +1256,44 @@ label.required:after {
 				display: inline-block;
 			}
 		}
+
+		&.toggle {
+			font-size: 0;
+
+			> span {
+				display: inline-block;
+				width: calc(~"100% - 40px");
+				font-size: 14px;
+				vertical-align: top;
+			}
+
+			> div {
+				width: 40px;
+				display: inline-block;
+			}
+		}
+
+		&.no-icon {
+			input {
+				padding: 0 8px;
+			}
+		}
 	}
+
 	.input-submit {
 		margin: 35px 0 0 -4px;
 	}
+
 	.selected-users {
 		padding: 20px 0 0;
+
 		li {
 			display: inline-block;
 			padding: 5px;
 			margin-right: 2px;
 			margin-bottom: 2px;
 		}
+
 		i {
 			cursor: pointer;
 		}
@@ -1096,7 +1302,6 @@ label.required:after {
 
 .side-nav {
 	position: fixed;
-	display: block;
 	top: 0;
 	bottom: 0;
 	left: 0;
@@ -1104,9 +1309,10 @@ label.required:after {
 	height: auto;
 	overflow: visible;
 	z-index: 100;
-	padding: 12px 0 0 0;
-	.transition(transform .3s ease-out);
-	&:before {
+	padding: 12px 0 0;
+	will-change: transform;
+
+	&::before {
 		content: " ";
 		height: 1px;
 		width: 189px;
@@ -1114,6 +1320,7 @@ label.required:after {
 		position: absolute;
 		top: 59px;
 	}
+
 	.rooms-list {
 		direction: rtl;
 		position: absolute;
@@ -1124,12 +1331,14 @@ label.required:after {
 		overflow-y: auto;
 		display: block;
 		-webkit-overflow-scrolling: touch;
+
 		> .wrapper {
 			direction: ltr;
 			padding-left: 8px;
 			padding-bottom: 1em;
 		}
 	}
+
 	.more {
 		display: block;
 		width: 100%;
@@ -1137,22 +1346,25 @@ label.required:after {
 		padding: 4px 0 4px 10px;
 		margin-top: 2px;
 	}
+
 	.input-error {
-		text-align: center;
 		font-size: 12px;
 		padding: 0;
 		text-align: left;
 		margin-bottom: -20px;
 		margin-top: -12px;
+
 		strong {
 			display: block;
 			margin-bottom: 2px;
 		}
 	}
+
 	.empty {
 		font-size: 11px;
 		padding: 2px 10px;
 	}
+
 	.header {
 		position: absolute;
 		top: 0;
@@ -1163,6 +1375,7 @@ label.required:after {
 		min-height: @header-min-height;
 		height: @header-min-height;
 	}
+
 	> .arrow {
 		position: absolute;
 		top: 18px;
@@ -1170,24 +1383,28 @@ label.required:after {
 		z-index: 1000;
 		cursor: pointer;
 	}
+
 	.footer {
 		position: absolute;
 		bottom: 0;
 		left: 0;
 		width: 100%;
-		padding: 10px 15px 0px 15px;
+		padding: 10px 15px 0;
 		text-align: right;
 		min-height: @footer-min-height;
 		height: @footer-min-height;
+
 		.logo {
 			display: block;
 			width: 100%;
 			height: 100%;
 			margin-top: -1px;
+
 			&:hover {
 				text-decoration: none;
 			}
 		}
+
 		small {
 			font-size: 11px;
 			width: 100%;
@@ -1198,6 +1415,7 @@ label.required:after {
 			padding-right: 4px;
 			margin-top: 2px;
 		}
+
 		img {
 			display: inline-block;
 			max-width: 222px;
@@ -1205,24 +1423,23 @@ label.required:after {
 			margin-bottom: -10px;
 		}
 	}
+
 	.search-form {
-		.search {
-			padding-left: 25px;
-		}
 		> div {
 			position: relative;
 		}
-		margin-right: 20px;
 	}
+
 	h3 {
 		&:extend(.small-title);
 		cursor: pointer;
 		position: relative;
 		text-transform: uppercase;
 		font-weight: 500;
-		margin: 25px 0 0 0;
+		margin: 25px 0 0;
 		line-height: 28px;
 		padding-left: 10px;
+
 		&.add-room {
 			i {
 				position: absolute;
@@ -1231,6 +1448,7 @@ label.required:after {
 			}
 		}
 	}
+
 	.unread {
 		min-width: 15px;
 		padding: 0 2px;
@@ -1243,15 +1461,18 @@ label.required:after {
 		line-height: 16px;
 		font-weight: 800;
 	}
+
 	ul {
 		position: relative;
 		//left: 1px;
+
 		li {
 			white-space: nowrap;
 			max-width: 100%;
 			overflow: hidden;
 			text-overflow: ellipsis;
 			vertical-align: middle;
+
 			.remove,
 			.erase {
 				position: absolute;
@@ -1260,25 +1481,29 @@ label.required:after {
 				top: 2px;
 				opacity: 0;
 				.transform(translateX(-10px));
-				.transition(opacity .15s ease .35s, transform .12s ease-out .35s);
+				transition: opacity 0.15s ease 0.35s, transform 0.12s ease-out 0.35s;
 			}
+
 			&:hover {
 				.opt {
 					opacity: 1;
 					.transform(translateX(0));
 				}
 			}
+
 			&.has-unread {
 				.opt {
 					opacity: 0;
 				}
 			}
+
 			&.has-alert {
 				.name {
 					font-weight: bold;
 				}
 			}
 		}
+
 		a {
 			display: block;
 			border-radius: 2px 0 0 2px;
@@ -1292,13 +1517,16 @@ label.required:after {
 			text-overflow: ellipsis;
 			vertical-align: middle;
 			text-decoration: none;
+
 			&:hover {
 				text-decoration: none;
 			}
+
 			.archived {
 				font-style: italic;
 			}
 		}
+
 		.opt {
 			position: absolute;
 			right: 0;
@@ -1308,34 +1536,41 @@ label.required:after {
 			opacity: 0;
 			display: block;
 			top: 7px;
-			.transition(opacity .12s ease);
+			transition: opacity 0.12s ease;
+
 			i {
 				margin: 0 1px;
 			}
-			.icon-cancel-circled:before {
+
+			.icon-cancel-circled::before {
 				margin-left: 2px;
 			}
+
 			.icon-logout {
 				margin-left: 1px;
 			}
+
 			&.fixed {
 				opacity: 1;
 				.transform(translateX(0));
 			}
 		}
+
 		i {
 			font-size: 14px;
 			width: 16px;
 			display: inline-block;
 		}
+
 		input[type="text"] {
 			width: 100%;
 			font-size: 12px;
 		}
 	}
+
 	.unread-rooms {
 		position: absolute;
-		z-index: 1000;
+		z-index: 1;
 		width: 100%;
 		text-align: center;
 		line-height: 24px;
@@ -1347,23 +1582,28 @@ label.required:after {
 		-webkit-align-items: center;
 		justify-content: center;
 		-webkit-justify-content: center;
+
 		&.top-unread-rooms {
 			top: 60px;
 		}
+
 		&.bottom-unread-rooms {
 			bottom: 70px;
 		}
+
 		i {
 			margin-left: 5px;
 			font-size: 12px;
 		}
 	}
+
 	.unread-rooms-mode {
 		max-height: 0;
 		opacity: 0;
 		overflow: hidden;
+
 		&.has-unread {
-			.transition(max-height 1s ease-in, opacity .5s linear);
+			transition: max-height 1s ease-in, opacity 0.5s linear;
 			max-height: 5000px;
 			opacity: 1;
 		}
@@ -1377,38 +1617,24 @@ label.required:after {
 	animation: highlight 2s infinite;
 }
 
-.page-container {
-	&:extend(.fill-all);
-	overflow-y: hidden;
-	.content {
-		&:extend(.fill-all);
-		padding: 25px 40px;
-		overflow-y: scroll;
-		margin-top: 60px;
-		-webkit-overflow-scrolling: touch;
-		.calc(height, ~'100% - 60px');
-		fieldset {
-			margin-bottom: 1em;
-		}
-	}
-}
-
 .fixed-title {
 	position: absolute;
 	.flex-center;
 	flex-flow: row nowrap;
 	padding: 0 10px 0 20px;
-	border-width: 0 0 1px 0;
+	border-width: 0 0 1px;
 	z-index: 100;
 	top: 0;
 	left: 0;
 	width: 100%;
 	height: @header-min-height+1px;
+
 	&.visible {
 		h2 {
 			overflow: visible;
 		}
 	}
+
 	h2 {
 		width: 100%;
 		overflow: hidden;
@@ -1417,20 +1643,33 @@ label.required:after {
 		font-size: 22px;
 		font-weight: 500;
 		line-height: 29px;
+
 		.icon-at,
 		.icon-hash,
 		.icon-lock {
 			margin-right: -7px;
 		}
+
 		.icon-star,
 		.icon-star-empty {
 			margin-right: -4px;
 		}
 	}
+
+	.submit {
+		display: flex;
+
+		.button {
+			white-space: nowrap;
+			margin-left: 1rem;
+		}
+	}
+
 	.animated-hidden {
 		visibility: hidden;
 		display: none;
 	}
+
 	input[type='text'] {
 		.calc(width, ~'100% - 100px');
 		vertical-align: top;
@@ -1438,6 +1677,7 @@ label.required:after {
 		margin-left: -3px;
 		font-size: 20px;
 	}
+
 	.icon-pencil {
 		vertical-align: text-top;
 		margin-top: -7px;
@@ -1451,14 +1691,14 @@ label.required:after {
 	margin: 40px auto;
 	padding: 20px;
 	border-radius: 4px;
-	box-shadow: 1px 1px 4px rgba(0, 0, 0, .3);
+	box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.3);
+
 	.cms-page-close {
 		margin-bottom: 10px;
 		text-align: right;
 	}
 }
 
-
 .spotlight {
 	position: fixed;
 	top: 0;
@@ -1470,6 +1710,7 @@ label.required:after {
 	display: -webkit-flex;
 	justify-content: center;
 	padding: 0 40px;
+
 	> .spotlight-input {
 		position: relative;
 		width: 100%;
@@ -1479,14 +1720,16 @@ label.required:after {
 		margin-bottom: auto;
 		border-radius: 5px;
 		overflow: hidden;
-		box-shadow: 0px 15px 50px rgba(0, 0, 0, 0.5);
+		box-shadow: 0 15px 50px rgba(0, 0, 0, 0.5);
+
 		> input {
 			box-shadow: none;
-			border-width: 0px;
+			border-width: 0;
 			line-height: 46px;
 			height: 46px;
 			padding: 0 10px 0 46px;
 		}
+
 		> i {
 			position: absolute;
 			z-index: 10;
@@ -1495,10 +1738,12 @@ label.required:after {
 			text-align: center;
 			font-weight: 100;
 		}
+
 		.message-popup {
 			position: relative;
 			box-shadow: none;
 			border-radius: 0;
+
 			.popup-item {
 				border-top: 1px solid #eaeaea;
 				line-height: 40px;
@@ -1507,6 +1752,7 @@ label.required:after {
 				white-space: nowrap;
 				text-overflow: ellipsis;
 				overflow: hidden;
+
 				i {
 					margin-right: 4px;
 					line-height: 28px;
@@ -1514,11 +1760,13 @@ label.required:after {
 					border-radius: 20px;
 					width: 28px;
 				}
+
 				&.selected {
 					i {
 						box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.2);
 					}
 				}
+
 				span {
 					float: right;
 					border-radius: 2px;
@@ -1535,32 +1783,8 @@ label.required:after {
 	}
 }
 
-.mobile-message-menu {
-	position: fixed;
-	top: 0;
-	bottom: 0;
-	left: 0;
-	right: 0;
-	z-index: 1000;
-	justify-content: center;
-	padding: 0 40px;
-	> .buttons {
-		font-size: 24px;
-		position: absolute;
-		bottom: 0;
-		left: 10%;
-		right: 10%;
-		.button {
-			display: block;
-			text-align: center;
-		}
-	}
-	.mobile-menu-separator {
-		height: 10px;
-	}
-}
-
 // MAIN CONTENT + MAIN PAGES //
+
 .main-content {
 	position: fixed;
 	top: 0;
@@ -1569,35 +1793,38 @@ label.required:after {
 	right: 40px;
 	width: auto;
 	height: auto;
-	.transition(right .25s cubic-bezier(.5, 0, .1, 1));
+	will-change: transform;
+	transition: right 0.25s cubic-bezier(0.5, 0, 0.1, 1);
+
 	&.flex-opened {
 		right: @flex-tab-width + 40px;
-		.flex-tab {
-			right: 40px;
-			.transform(translateX(0));
-		}
 	}
+
 	&.layout1 {
 		right: @flex-tab-webrtc-width;
+
 		.flex-tab {
 			max-width: @flex-tab-webrtc-width;
-			.transform(translateX(0));
 		}
 	}
+
 	&.layout2 {
 		right: @flex-tab-webrtc-2-width;
+
 		.flex-tab {
 			max-width: @flex-tab-webrtc-2-width;
-			.transform(translateX(0));
 		}
 	}
+
 	&.main-modal {
-		left: 0px;
-		margin-right: 0px;
+		left: 0;
+		margin-right: 0;
 	}
+
 	.container-fluid {
 		padding-top: 0;
 	}
+
 	.history-date {
 		margin-bottom: 20px;
 	}
@@ -1608,10 +1835,12 @@ label.required:after {
 		h2 {
 			margin-bottom: 2rem;
 		}
+
 		h3 {
 			margin-bottom: 1rem;
 		}
 		padding: 20px 0;
+
 		> .info {
 			max-width: auto;
 			line-height: 24px;
@@ -1620,88 +1849,115 @@ label.required:after {
 			font-weight: 500;
 		}
 	}
+
 	.section {
-		border: 1px solid #ddd;
+		border: 1px solid #dddddd;
 		border-radius: 4px;
-		background-color: #fff;
+		background-color: #ffffff;
 		padding: 20px;
 		margin: 20px;
+
 		&.section-collapsed {
 			.section-content {
 				display: none;
 			}
 		}
-		.section-title {
+	}
+
+	.section-title {
+		display: flex;
+		font-size: 24px;
+		font-weight: 600;
+		line-height: 40px;
+
+		.section-title-text {
+			flex-grow: 1;
+		}
+
+		.section-title-right {
+			line-height: 0;
+		}
+	}
+
+	.section-content {
+		border: none !important;
+		border-radius: 0 !important;
+		padding: 20px 0 0 !important;
+
+		.input-line {
+			border-bottom: 1px solid #eeeeee;
+			padding: 20px 0;
+			margin-bottom: 0;
 			display: flex;
-			font-size: 24px;
-			font-weight: 600;
-			line-height: 40px;
-			.section-title-text {
-				flex-grow: 1;
+			align-items: flex-start;
+
+			&:last-child {
+				border-bottom: none;
+				padding-bottom: 0;
 			}
-			.section-title-right {
-				line-height: 0px;
+
+			&:first-child {
+				padding-top: 0;
 			}
-		}
-		.section-content {
-			border: none !important;
-			border-radius: 0px !important;
-			padding: 20px 0 0 0 !important;
-			.input-line {
-				border-bottom: 1px solid #eee;
-				padding: 20px 0;
-				margin-bottom: 0px;
-				&:last-child {
-					border-bottom: none;
-					padding-bottom: 0;
-				}
-				&:first-child {
-					padding-top: 0;
-				}
-				> label {
-					text-align: left;
-					font-weight: 500;
-					font-size: 16px;
-					line-height: 20px;
-				}
-				.settings-description {
-					padding: 5px;
-					line-height: 20px;
-				}
-				.settings-alert {
-					border-width: 1px;
-					font-weight: bold;
-					padding: 5px;
-				}
-				.horizontal {
-					display: flex;
-				}
-				.flex-grow-1 {
-					flex-grow: 1;
-				}
-				.color-editor {
-					width: 150px;
-					position: relative;
-				}
+
+			.horizontal {
+				display: flex;
 			}
-			.selected-rooms {
-				.remove-room {
-					cursor: pointer;
-				}
+
+			.flex-grow-1 {
+				flex-grow: 1;
+			}
+		}
+
+		.reset-setting {
+			margin-left: 20px;
+		}
+
+		.setting-label {
+			text-align: left;
+			font-weight: 500;
+			font-size: 16px;
+			line-height: 20px;
+			width: 25%;
+		}
+
+		.settings-description {
+			padding: 5px;
+			line-height: 20px;
+		}
+
+		.settings-alert {
+			border-width: 1px;
+			font-weight: bold;
+			padding: 5px;
+		}
+
+		.color-editor {
+			width: 150px;
+			position: relative;
+		}
+
+		.selected-rooms {
+			.remove-room {
+				cursor: pointer;
 			}
 		}
 	}
+
 	.settings-description {
 		.allow-text-selection;
 	}
+
 	.rocket-form {
 		max-width: none;
 		width: 100%;
 		padding: 0;
 	}
+
 	.settings-file-preview {
 		display: flex;
 		align-items: center;
+
 		input[type=file] {
 			position: absolute !important;
 			width: 100%;
@@ -1711,19 +1967,22 @@ label.required:after {
 			opacity: 0;
 			z-index: 10000;
 			cursor: pointer;
+
 			* {
 				cursor: pointer;
 			}
 		}
+
 		.preview {
 			height: 50px;
 			width: 100px;
 			border-radius: 4px;
 			overflow: hidden;
-			box-shadow: 0 0 1px rgba(0, 0, 0, .5) inset;
+			box-shadow: 0 0 1px rgba(0, 0, 0, 0.5) inset;
 			background-size: contain;
 			background-position: center center;
 			background-repeat: no-repeat;
+
 			&.no-file {
 				display: flex;
 				align-items: center;
@@ -1738,16 +1997,20 @@ label.required:after {
 	.content {
 		> div {
 			margin-bottom: 25px;
+
 			&:nth-last-child(1) {
 				margin-bottom: 0;
 			}
 		}
+
 		p {
 			margin-bottom: 12px;
+
 			&:nth-last-child(1) {
 				margin-bottom: 0;
 			}
 		}
+
 		.section {
 			h1 {
 				font-size: 20px;
@@ -1755,21 +2018,26 @@ label.required:after {
 				padding: 0 0 0 10px;
 				font-weight: 500;
 			}
+
 			&:first-of-type > h1 {
-				margin-top: 0px;
+				margin-top: 0;
 			}
+
 			.section-content {
 				border-width: 1px;
 				padding: 20px;
 				border-radius: 4px;
+
 				.section-helper {
 					padding: 20px 20px 40px;
+
 					pre {
 						display: inline;
 					}
 				}
 			}
 		}
+
 		h1,
 		h2,
 		h3,
@@ -1787,19 +2055,23 @@ label.required:after {
 			overflow: visible;
 		}
 	}
+
 	.logo {
 		display: block;
 		margin: 10px 0;
 		max-width: 325px;
 	}
+
 	.info {
 		max-width: 680px;
 		line-height: 20px;
 	}
+
 	.social {
 		h4 {
 			margin-bottom: 8px;
 		}
+
 		nav {
 			margin-left: -4px;
 		}
@@ -1810,38 +2082,46 @@ label.required:after {
 	.search {
 		margin-bottom: 12px;
 	}
+
 	.results {
 		padding: 10px 0;
-		border-width: 0 0 1px 0;
+		border-width: 0 0 1px;
 		margin-bottom: 10px;
 		font-weight: 300;
+
 		p {
 			font-size: 12px;
 			text-transform: uppercase;
 		}
 	}
+
 	.list {
 		a {
 			display: block;
 			padding: 3px;
 			margin-bottom: 5px;
+
 			.info {
 				h3 {
 					margin-bottom: 5px;
 				}
+
 				ul {
 					margin-left: 3px;
 				}
 			}
 		}
+
 		.room-info {
 			padding: 3px;
 			margin-bottom: 5px;
 			cursor: pointer;
+
 			h3 {
 				margin-bottom: 5px;
 			}
 		}
+
 		.user-image {
 			float: right;
 			margin-left: 12px;
@@ -1867,6 +2147,7 @@ label.required:after {
 	justify-content: center;
 	-webkit-justify-content: center;
 	width: 200px;
+
 	i {
 		font-size: 24px;
 	}
@@ -1882,10 +2163,12 @@ label.required:after {
 	justify-content: center;
 	-webkit-justify-content: center;
 	font-size: 30px;
+
 	div {
 		line-height: 40px;
 		text-align: center;
 	}
+
 	i {
 		font-size: 100px;
 		padding-bottom: 30px;
@@ -1894,63 +2177,93 @@ label.required:after {
 
 .container-bars {
 	position: absolute;
-	top: 60px;
-	width: 100%;
-	z-index: 11;
+	top: 55px;
+	z-index: 100;
 	font-weight: bold;
 	display: flex;
 	flex-direction: column;
+	border-radius: 4px;
+	overflow: hidden;
+	font-size: 1em;
+	left: 10px;
+	right: 10px;
+	box-shadow:
+		0 1px 1px 0 rgba(0, 0, 0, 0.2),
+		0 2px 10px 0 rgba(0, 0, 0, 0.16);
+	transition: transform 0.4s ease, visibility 0.3s ease, opacity 0.3s ease;
+	.transform(translateY(-10px));
+	opacity: 0;
+	visibility: hidden;
+
+	&.show {
+		opacity: 1;
+		visibility: visible;
+		.transform(translateY(0px));
+	}
+
 	> div {
-		line-height: 24px;
+		line-height: 28px;
 		padding: 0 10px;
-		border-width: 1px 0 0 0;
-		&:last-child {
-			box-shadow: 0px 1px 2px rgba(0, 0, 0, .2);
-		}
 	}
-	font-size: 12px;
+
 	.upload-progress {
-		height: 24px;
+		height: 28px;
 		position: relative;
+
 		.upload-progress-progress {
 			position: absolute;
-			left: 0px;
+			left: 0;
 			height: 100%;
 			width: 0%;
 			z-index: 1;
-			.transition(width, 1s, ease-out);
+			transition: width, 1s, ease-out;
 		}
+
 		.upload-progress-text {
 			padding: 0 10px;
 			position: absolute;
-			left: 0px;
-			right: 0px;
+			left: 0;
+			right: 0;
 			height: 100%;
 			z-index: 2;
+
 			> a {
 				float: right;
 				text-transform: uppercase;
 				cursor: pointer;
 			}
 		}
+
+		button {
+			float: right;
+			font-weight: bold;
+			text-transform: uppercase;
+		}
 	}
+
 	.unread-bar {
 		text-transform: uppercase;
 		text-align: center;
+
 		> button.mark-read {
 			float: right;
+
 			&:hover {
 				cursor: pointer;
 			}
 		}
+
 		.unread-count {
 			display: none;
 		}
+
 		> button.jump-to {
 			float: left;
+
 			.jump-to-small {
 				display: none;
 			}
+
 			&:hover {
 				cursor: pointer;
 			}
@@ -1959,6 +2272,7 @@ label.required:after {
 }
 
 // change to page-messages
+
 .messages-container {
 	position: absolute;
 	width: 100%;
@@ -1966,15 +2280,18 @@ label.required:after {
 	top: 0;
 	left: 0;
 	border-width: 0 1px 0 0;
+
 	.room-topic {
 		font-size: 14px;
 		opacity: 0.4;
 		margin-left: 10px;
 	}
+
 	.edit-room-title {
 		margin-left: 4px;
 		font-size: 16px;
 	}
+
 	.wrapper {
 		position: absolute;
 		width: 100%;
@@ -1986,32 +2303,39 @@ label.required:after {
 		word-wrap: break-word;
 		-webkit-overflow-scrolling: touch;
 	}
+
 	.footer {
 		position: absolute;
-		padding: 8px 20px 0px 20px;
-		border-width: 1px 0 0 0;
+		padding: 8px 20px 0;
+		border-width: 1px 0 0;
 		z-index: 100;
 		bottom: 0;
 		left: 0;
 		width: 100%;
 		min-height: @footer-min-height;
 	}
+
 	.message-form {
+		margin-bottom: 18px;
+
 		> .message-input {
 			border-width: 1px;
 			overflow: hidden;
 			border-radius: 5px;
 			position: relative;
 			display: flex;
+
 			.input-message-container {
 				position: relative;
 				width: 100%;
+
 				.inner-left-toolbar {
 					position: absolute;
 					left: 13px;
 					top: 9px;
 				}
 			}
+
 			> .message-buttons {
 				flex: 0 0 35px;
 				text-align: center;
@@ -2021,10 +2345,12 @@ label.required:after {
 				align-items: center;
 				justify-content: center;
 				position: relative;
-				.transition(background-color 0.1s linear, color 0.1s linear);
+				transition: background-color 0.1s linear, color 0.1s linear;
+
 				i {
 					font-size: 18px;
 				}
+
 				input {
 					position: absolute;
 					top: 0;
@@ -2034,15 +2360,18 @@ label.required:after {
 					overflow: hidden;
 					opacity: 0;
 					cursor: pointer;
+					width: 100%;
 				}
+
 				input::-webkit-file-upload-button {
 					cursor: pointer;
 				}
 			}
 		}
+
 		textarea {
 			display: block;
-			margin: 0px;
+			margin: 0;
 			padding-top: 9px;
 			padding-bottom: 9px;
 			padding-left: 49px;
@@ -2052,6 +2381,7 @@ label.required:after {
 			line-height: 16px;
 			border-width: 0 1px 0 0;
 		}
+
 		.users-typing {
 			float: left;
 			height: 23px;
@@ -2064,9 +2394,10 @@ label.required:after {
 			max-width: 100%;
 			z-index: 10;
 		}
+
 		.formatting-tips {
 			float: right;
-			height: 23px;
+			height: 25px;
 			font-size: 11px;
 			padding: 3px;
 			display: -webkit-flex;
@@ -2075,22 +2406,27 @@ label.required:after {
 			overflow: hidden;
 			position: absolute;
 			right: 20px;
-			opacity: .5;
+			opacity: 0.5;
 			white-space: nowrap;
-			.transition(opacity .2 linear);
+			transition: opacity 0.2 linear;
+
 			> * {
 				margin: 0 3px;
 			}
+
 			&:hover {
 				opacity: 1;
 			}
+
 			q {
 				padding: 0 0 0 3px;
 				border-width: 0 0 0 3px;
-				&:before {
+
+				&::before {
 					content: none !important;
 				}
 			}
+
 			code {
 				line-height: 13px;
 				overflow: hidden;
@@ -2098,22 +2434,34 @@ label.required:after {
 				font-size: 10px;
 				white-space: nowrap;
 			}
+
 			.hidden-br {
 				display: inline-block;
 			}
-			.icon-level-down:before {
+
+			.icon-level-down::before {
 				transform: rotate(90deg);
 			}
 		}
+
+		.stream-info {
+			font-size: 12px;
+			height: 25px;
+			padding: 3px;
+			float: left;
+		}
+
 		.editing-commands {
 			display: none;
 			text-transform: lowercase;
+
 			.editing-commands-cancel {
 				float: left;
 				height: 23px;
 				font-size: 11px;
 				padding: 3px;
 			}
+
 			.editing-commands-save {
 				float: right;
 				height: 23px;
@@ -2121,16 +2469,23 @@ label.required:after {
 				padding: 3px;
 			}
 		}
+
 		&.editing {
 			.formatting-tips,
 			.users-typing {
 				display: none;
 			}
+
 			.editing-commands {
 				display: block;
 			}
+
+			.stream-info {
+				display: none;
+			}
 		}
 	}
+
 	.add-user-search {
 		height: 100%;
 		overflow: hidden;
@@ -2138,6 +2493,7 @@ label.required:after {
 		vertical-align: top;
 		width: 100%;
 	}
+
 	&.admin {
 		.message:hover:not(.system) .message-action {
 			display: inline-block;
@@ -2145,27 +2501,6 @@ label.required:after {
 	}
 }
 
-.message-popup-items {
-	.loading {
-		display: none;
-	}
-}
-
-.message-popup-results {
-	&.notready {
-		.message-popup-items {
-			position: relative;
-			height: 100px;
-			.loading {
-				display: flex;
-			}
-		}
-		.popup-item {
-			display: none;
-		}
-	}
-}
-
 .message-popup-position {
 	position: relative;
 }
@@ -2173,21 +2508,23 @@ label.required:after {
 .message-popup {
 	position: absolute;
 	z-index: 101;
-	bottom: 0px;
-	left: 0px;
-	right: 0px;
+	bottom: 0;
+	left: 0;
+	right: 0;
 	overflow: hidden;
-	box-shadow: 0 -1px 10px 0 rgba(0, 0, 0, 0.2), 0 1px 1px rgba(0, 0, 0, 0.16);
+	box-shadow:
+		0 -1px 10px 0 rgba(0, 0, 0, 0.2),
+		0 1px 1px rgba(0, 0, 0, 0.16);
 	border-radius: 5px;
 }
 
 .message-popup.popup-down {
 	bottom: auto;
-	top: 0px;
+	top: 0;
 }
 
 .message-popup-title {
-	border-width: 0 0 1px 0;
+	border-width: 0 0 1px;
 	padding: 0 20px;
 	line-height: 32px;
 	font-size: 14px;
@@ -2224,20 +2561,32 @@ label.required:after {
 
 .messages-box {
 	position: relative;
-	margin: 60px 20px 0px 0px;
+	margin: 60px 20px 0 0;
 	overflow: hidden;
 	width: 100%;
 	.calc(height, ~'100% - 120px');
+
+	.message-cog-container {
+		.message-action {
+			&.jump-to-search-message {
+				display: none !important;
+			}
+		}
+	}
+
 	.wrapper.has-more-next {
 		padding-bottom: 24px;
 	}
+
 	ul {
 		padding: 21px 0 10px;
 	}
+
 	.start {
 		text-align: center;
 		margin-top: 12px;
 	}
+
 	.new-message {
 		.unselectable;
 		margin: 0 -65px;
@@ -2252,12 +2601,14 @@ label.required:after {
 		bottom: 8px;
 		left: 50%;
 		z-index: 15;
-		.transition(transform 0.3s ease-out);
+		transition: transform 0.3s ease-out;
 		.transform(translateY(0));
+
 		&.not {
 			.transform(translateY(150%));
 		}
 	}
+
 	.jump-recent {
 		z-index: 15;
 		position: absolute;
@@ -2271,21 +2622,25 @@ label.required:after {
 		right: 20px;
 		border-top-left-radius: 4px;
 		border-top-right-radius: 4px;
-		button {
-			.unselectable;
-			cursor: pointer;
-		}
-		.transition(transform 0.3s ease-out);
+		transition: transform 0.3s ease-out;
 		.transform(translateY(0));
+
 		&.not {
 			.transform(translateY(150%));
 		}
+
+		button {
+			.unselectable;
+			cursor: pointer;
+		}
 	}
+
 	.editing {
 		.body {
 			border-radius: 4px;
 		}
 	}
+
 	&.selectable .message {
 		cursor: pointer;
 	}
@@ -2298,6 +2653,7 @@ label.required:after {
 	height: 100%;
 	z-index: 10;
 	pointer-events: none;
+
 	.tick {
 		height: 2px;
 		width: 100%;
@@ -2312,25 +2668,29 @@ label.required:after {
 	position: relative;
 	line-height: 20px;
 	min-height: 40px;
+
 	&.highlight {
 		-webkit-animation: highlight 3s;
 		-moz-animation: highlight 3s;
 		-o-animation: highlight 3s;
 		animation: highlight 3s;
 	}
+
 	&:nth-child(1) {
 		margin-top: 0;
 	}
+
 	.day-divider {
 		height: 50px;
 		display: none;
 		text-align: center;
 		left: 0;
 		position: absolute;
-		top: 0px;
+		top: 0;
 		right: 0;
 		align-items: center;
 		justify-content: center;
+
 		span {
 			padding: 0 8px;
 			z-index: 1;
@@ -2338,7 +2698,8 @@ label.required:after {
 			font-size: 12px;
 			font-weight: 600;
 		}
-		&:before {
+
+		&::before {
 			position: absolute;
 			content: " ";
 			display: block;
@@ -2349,9 +2710,11 @@ label.required:after {
 			right: 0;
 		}
 	}
+
 	&.new-day {
 		margin-top: 60px;
-		&:before {
+
+		&::before {
 			content: attr(data-date);
 			display: block;
 			position: absolute;
@@ -2365,46 +2728,55 @@ label.required:after {
 			padding: 0 10px;
 			min-width: 140px;
 		}
-		&:after {
+
+		&::after {
 			content: " ";
 			display: block;
 			position: absolute;
 			top: -20px;
 			left: 0;
-			border-width: 1px 0 0 0;
+			border-width: 1px 0 0;
 			width: 100%;
 		}
 	}
+
 	.message-action {
 		display: none;
 		cursor: pointer;
 	}
+
 	&:hover:not(.system) .message-action {
 		display: block;
 	}
+
 	.message-cog-container {
 		position: relative;
 		display: inline-block;
+
 		.message-cog {
 			visibility: hidden;
 			cursor: pointer;
 		}
 	}
+
 	@keyframes dropdown-in {
 		0% {
 			display: none;
 			opacity: 0;
 		}
+
 		1% {
 			display: block;
 			opacity: 0;
 			transform: scale(0);
 		}
+
 		100% {
 			opacity: 1;
 			transform: scale(1);
 		}
 	}
+
 	.message-dropdown {
 		position: absolute;
 		top: -5px;
@@ -2413,95 +2785,116 @@ label.required:after {
 		display: none;
 		border-radius: 4px;
 		overflow: hidden;
-		box-shadow: 0px 1px 1px 0 rgba(0, 0, 0, 0.2), 0 2px 10px 0 rgba(0, 0, 0, .16);
-		transition: transform .15s ease-in-out, opacity .15s ease-in-out;
-		animation: dropdown-in .15s ease-in-out;
+		box-shadow:
+			0 1px 1px 0 rgba(0, 0, 0, 0.2),
+			0 2px 10px 0 rgba(0, 0, 0, 0.16);
+		transition: transform 0.15s ease-in-out, opacity 0.15s ease-in-out;
+		animation: dropdown-in 0.15s ease-in-out;
+
 		ul {
 			display: flex;
 			display: -webkit-flex;
-			padding: 0px;
+			padding: 0;
 			font-size: 14px;
+
 			li {
 				display: block;
-				padding: 0px 8px;
+				padding: 0 8px;
 				font-weight: 400;
 				line-height: 26px;
 				cursor: pointer;
+
 				&:first-child {
 					padding-left: 6px;
 					border-width: 0 1px 0 0;
 				}
+
 				&:last-child {
 					padding-right: 13px;
 				}
 			}
 		}
 	}
+
 	.user {
 		display: inline-block;
 		font-weight: 600;
 		margin-right: 5px;
 	}
+
 	.thumb {
 		position: absolute;
 		left: 20px;
 		display: block;
 		width: 40px;
 		height: 40px;
+
 		&:not(.thumb-small) {
 			.avatar {
 				width: 40px;
 				height: 40px;
 			}
 		}
+
 		&.thumb-small {
 			position: initial;
 			width: 20px;
 			height: 20px;
 			display: inline-block;
 			vertical-align: bottom;
+
 			.avatar {
 				width: 20px;
 				height: 20px;
 			}
 		}
 	}
+
 	.info {
 		font-size: 12px;
+
 		.edited {
 			border-left: 1px dotted;
 			padding-left: 3px;
 			margin-left: 3px;
 		}
+
 		.is-bot,
 		.role-tag {
 			padding: 1px 4px;
 			border-radius: 2px;
 		}
 	}
+
 	.private {
 		margin-left: 10px;
 	}
+
 	&.sequential {
 		min-height: 20px;
 		padding-top: 4px;
 		padding-bottom: 4px;
-		margin-top: 0px;
+		margin-top: 0;
+
 		.user {
 			display: none;
 		}
+
 		.thumb:not(.thumb-small) {
 			display: none;
 		}
+
 		.info {
 			position: absolute;
 			text-align: right;
 			left: 5px;
 			width: 60px;
+
 			.time,
 			.role-tag {
 				display: none;
 			}
+
 			.edited {
 				display: block;
 				border-left: 0;
@@ -2509,100 +2902,115 @@ label.required:after {
 				padding-left: 0;
 				white-space: nowrap;
 			}
+
 			.private {
 				display: none;
 			}
+
 			.message-action {
 				float: left;
 				margin-left: 1px;
 			}
 		}
+
 		.body {
-			margin-top: 0px;
+			margin-top: 0;
 		}
-		// .message-dropdown {
-		//	top: 100%;
-		//	left: 0;
-		// }
+
 		&:hover {
-			.time {
-				// display: inline-block;
-			}
 			.edited {
 				display: none;
 			}
 		}
 	}
+
 	&.system {
 		.body {
 			font-style: italic;
+
 			em {
 				font-weight: 600;
 			}
+
 			.attachment {
 				font-style: normal;
 			}
 		}
 	}
+
 	.avatar-initials {
 		line-height: 40px;
 	}
+
 	button {
 		font-weight: 400;
+
 		&:hover {
 			text-decoration: underline;
 		}
 	}
+
 	.body {
 		opacity: 1;
-		.transition(opacity 1s linear);
+		transition: opacity 1s linear;
 		margin-top: 2px;
+
 		.inline-image {
 			background-size: contain;
 			background-repeat: no-repeat;
 			background-position: center left;
 			display: inline-block;
-			line-height: 0px;
-			box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .1);
+			line-height: 0;
+			box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
 			border-radius: 3px;
 			overflow: hidden;
+
 			img {
 				max-height: 200px;
 				max-width: 100%;
 				opacity: 0;
 			}
 		}
+
 		> h1 {
 			font-size: 3em;
 			line-height: 1em;
 		}
+
 		> h2 {
 			font-size: 2.5em;
 			line-height: 1em;
 		}
+
 		> h3 {
 			font-size: 2em;
 			line-height: 1em;
 		}
+
 		> h4 {
 			font-size: 1.5em;
 			line-height: 1em;
 		}
+
 		blockquote.sandstorm-grain {
 			img {
 				width: 50px;
 			}
+
 			label {
 				cursor: pointer;
 			}
+
 			button {
 				display: block;
 			}
 		}
 	}
+
 	&.temp .body {
-		opacity: .5;
+		opacity: 0.5;
 	}
+
 	.message-alias {
 		font-weight: 400;
 		padding-left: 2px;
@@ -2613,6 +3021,7 @@ body:not(.is-cordova) {
 	.message:hover:not(.system) .message-cog {
 		visibility: visible;
 	}
+
 	.message {
 		.body,
 		.user.user-card-message,
@@ -2621,6 +3030,7 @@ body:not(.is-cordova) {
 			-moz-user-select: text;
 			-ms-user-select: text;
 			user-select: text;
+
 			* {
 				-webkit-user-select: text;
 				-moz-user-select: text;
@@ -2634,73 +3044,11 @@ body:not(.is-cordova) {
 .cozy {
 	.message {
 		padding: 4px 20px 4px 70px;
-		.body {
-			margin-top: 0;
-		}
-	}
-}
 
-.compact {
-	.message {
-		min-height: 26px;
-		padding: 5px 15px 0 37px;
 		.body {
-			display: inline;
-			.inline-image img {
-				max-height: 100px;
-			}
-			.inline-video {
-				max-height: 150px;
-			}
-			.attachment {
-				.attachment-title > a {
-					font-size: 0.9em;
-				}
-				.attachment-author img {
-					border-radius: 2px;
-				}
-			}
-			blockquote iframe {
-				height: 150px;
-				width: 266px;
-			}
-		}
-		.info {
-			.avatar-image {
-				border-radius: 2px;
-			}
-			.role-tag {
-				display: none;
-			}
-		}
-		.thumb {
-			height: 20px;
-			width: 20px;
-			left: 10px;
-			.avatar {
-				width: 20px;
-				height: 20px;
-			}
-		}
-		&.sequential {
-			.thumb:not(.thumb-small),
-			.user {
-				display: inline-block;
-			}
-			.info {
-				position: relative;
-				text-align: right;
-				left: 0;
-				.time,
-				.edited {
-					display: inline-block;
-				}
-			}
+			margin-top: 0;
 		}
 	}
-	.message-cog-container .message-cog {
-		visibility: visible;
-	}
 }
 
 .flex-tab-bar {
@@ -2710,13 +3058,17 @@ body:not(.is-cordova) {
 	top: 0;
 	right: 0;
 	z-index: 130;
+	will-change: transform;
+
 	.tab-button {
 		position: relative;
 		cursor: pointer;
 		text-align: center;
+
 		button {
 			height: 38px;
 		}
+
 		.counter {
 			position: absolute;
 			font-size: 9px;
@@ -2729,11 +3081,14 @@ body:not(.is-cordova) {
 			top: 4px;
 			text-align: center;
 		}
+
 		&.active {
 			border-right: 3px solid;
+
 			button {
 				margin-left: 3px;
 			}
+
 			.counter {
 				margin-right: -3px;
 			}
@@ -2745,49 +3100,67 @@ body:not(.is-cordova) {
 	.message {
 		min-height: 26px;
 		padding: 5px 15px 0 37px;
+
 		.body {
 			display: inline;
+
 			.inline-image img {
 				max-height: 100px;
 			}
+
 			.inline-video {
 				max-height: 150px;
 			}
+
 			.attachment {
 				.attachment-title > a {
 					font-size: 0.9em;
 				}
+
 				.attachment-author img {
 					border-radius: 2px;
 				}
 			}
+
 			blockquote iframe {
 				height: 150px;
 				width: 266px;
 			}
 		}
+
 		.info {
 			.avatar-image {
 				border-radius: 2px;
 			}
+
 			.role-tag {
 				display: none;
 			}
 		}
+
 		.thumb {
 			height: 20px;
 			width: 20px;
 			left: 10px;
+
+			.avatar {
+				width: 20px;
+				height: 20px;
+			}
 		}
+
 		&.sequential {
-			.thumb:not(.thumb-small),
-			.user {
+			.thumb:not(.thumb-small),.user {
+
+				/* stylelint-disable-line */
 				display: inline-block;
 			}
+
 			.info {
 				position: relative;
 				text-align: right;
 				left: 0;
+
 				.time,
 				.edited {
 					display: inline-block;
@@ -2795,62 +3168,70 @@ body:not(.is-cordova) {
 			}
 		}
 	}
+
 	.message-cog-container .message-cog {
 		visibility: visible;
 	}
 }
 
 // FLEX-TAB and FLEX-TAB views
+
 .flex-tab {
-	overflow-x: visible;
 	position: fixed;
-	z-index: 110;
-	max-width: @flex-tab-width;
-	width: 90%;
-	bottom: 0;
-	right: 0;
 	top: 0;
-	.transform(translateX(100%));
-	.transition(transform .25s cubic-bezier(.5, 0, .1, 1));
+	bottom: 0;
+	left: 100%;
+	width: 90%;
+	max-width: @flex-tab-width;
+	z-index: 110;
+	overflow-x: visible;
+	transition: transform 0.25s cubic-bezier(0.5, 0, 0.1, 1);
+
 	.control {
 		.header {
 			text-align: center;
 			padding: 5px 30px 20px;
 			margin: 5px 0 15px;
+
 			h2 {
 				font-size: 20px;
 				line-height: 25px;
 				font-weight: 300;
 			}
 		}
+
 		.button {
 			min-height: 36px;
 			margin: 0 1px;
 		}
+
 		.more {
 			position: absolute;
 			left: 0;
-			top: 0px;
+			top: 0;
 			height: 60px;
 			width: 30px;
-			border-width: 0 0 1px 0;
+			border-width: 0 0 1px;
 			cursor: pointer;
 			.transform(translateX(-27px));
-			.transition(transform .25s ease-out .475s, background .075s ease-out .5s);
+			transition: transform 0.25s ease-out 0.475s, background 0.075s ease-out 0.5s;
+
 			i {
 				.transform-origin(50%, 50%, 0);
-				.transition(transform .3s ease-out);
+				transition: transform 0.3s ease-out;
 				height: 12.5px;
 				vertical-align: top;
 				margin-top: 1px;
 			}
+
 			.flex-opened & {
-				.transition-delay(0s);
 				.transform(translateX(0));
 			}
 		}
+
 		.search-form {
 			width: 100%;
+
 			.icon-plus {
 				position: absolute;
 				top: 11px;
@@ -2858,12 +3239,14 @@ body:not(.is-cordova) {
 				font-size: 13px;
 			}
 		}
+
 		.info-tabs {
 			position: absolute;
 			top: 0;
 			text-align: right;
 			height: 60px;
 			right: 20px;
+
 			a {
 				float: left;
 				display: inline-block;
@@ -2872,25 +3255,30 @@ body:not(.is-cordova) {
 				line-height: 60px;
 				vertical-align: middle;
 				border-width: 0 0 0 1px;
+
 				&:last-child {
 					border-width: 0 1px 0 0;
 				}
 			}
 		}
 	}
+
 	.content {
 		&:extend(.fill-all);
 		overflow-x: hidden;
 		overflow-y: auto;
 		top: auto;
 		-webkit-overflow-scrolling: touch;
+
 		> div {
-			.transition(transform .45s cubic-bezier(.5, 0, 0, 1), opacity .125s ease-out .1s);
+			transition: transform 0.45s cubic-bezier(0.5, 0, 0, 1), opacity 0.125s ease-out 0.1s;
 		}
+
 		> .animated-hidden {
 			.transform(translateX(100%));
 			opacity: 0;
 		}
+
 		> .animated {
 			position: absolute;
 			top: 0;
@@ -2898,8 +3286,10 @@ body:not(.is-cordova) {
 			width: 100%;
 			height: 100%;
 		}
+
 		> .title {
 			height: @header-min-height;
+
 			h2 {
 				padding: 0 20px;
 				font-size: 20px;
@@ -2908,18 +3298,21 @@ body:not(.is-cordova) {
 			}
 		}
 	}
+
 	footer {
 		position: absolute;
 		bottom: 0;
 		left: 0;
 		width: 100%;
-		padding: 9px 15px 0px 15px;
+		padding: 9px 15px 0;
 		z-index: 100;
 		text-align: right;
 		height: @footer-min-height;
 	}
+
 	.social {
 		text-align: center;
+
 		h4 {
 			font-weight: 300;
 			position: absolute;
@@ -2928,13 +3321,16 @@ body:not(.is-cordova) {
 			left: 0;
 			font-size: 13px;
 		}
+
 		.share {
 			border-radius: 50%;
 			min-height: 40px;
 			line-height: 20px;
-			&:before {
+
+			&::before {
 				border-radius: 50%;
 			}
+
 			span {
 				display: none;
 			}
@@ -2948,43 +3344,53 @@ body:not(.is-cordova) {
 	overflow-x: hidden;
 	z-index: 10;
 	padding: 20px;
+
 	.list {
 		display: flex;
 		flex-flow: column nowrap;
 		position: relative;
 		width: 100%;
+
 		.message {
-			padding: 8px 0px 4px 50px;
+			padding: 8px 0 4px 50px;
 		}
 	}
+
 	> .title {
 		margin: 0 0 20px;
+
 		h2 {
 			font-size: 20px;
 			line-height: 25px;
 			font-weight: 300;
 		}
+
 		p {
 			font-size: 12px;
 			margin-top: 4px;
 		}
+
 		b {
 			font-weight: 600;
 		}
+
 		.see-all {
 			float: right;
 			border-width: 0;
 			text-decoration: underline;
 			cursor: pointer;
+
 			&:hover {
 				text-decoration: none;
 			}
 		}
 	}
+
 	.show-more-users {
-		margin: 1em auto 0 auto;
+		margin: 1em auto 0;
 		display: block;
 	}
+
 	&.uploaded-files-list {
 		a {
 			&.file-name {
@@ -2992,10 +3398,13 @@ body:not(.is-cordova) {
 				padding: 10px 5px;
 				border-bottom: 1px solid #eaeaea;
 				display: block;
+				border-width: 0 0 1px;
+
 				&:hover {
 					color: #006db0;
 					text-decoration: underline;
 				}
+
 				p {
 					overflow: hidden;
 					text-overflow: ellipsis;
@@ -3003,18 +3412,16 @@ body:not(.is-cordova) {
 				}
 			}
 		}
-		a.file-name {
-			padding: 10px 5px;
-			border-width: 0 0 1px 0;
-			display: block;
-		}
+
 		i {
 			float: left;
 			margin-right: 10px;
+
 			&.file-delete {
 				float: right;
 				padding-top: 10px;
 			}
+
 			&.file-download {
 				float: right;
 				padding-top: 11px;
@@ -3027,24 +3434,30 @@ body:not(.is-cordova) {
 	z-index: 15;
 	overflow-y: auto;
 	overflow-x: hidden;
+
 	.about {
 		width: 100%;
 		margin-bottom: 20px;
 	}
+
 	.thumb {
 		width: 100%;
 		height: 350px;
 		padding: 20px;
 	}
+
 	nav {
 		padding: 0 20px;
+
 		.back {
 			float: right;
 		}
 	}
+
 	.info {
 		white-space: normal;
 		padding: 0 20px;
+
 		h3 {
 			-webkit-user-select: text;
 			-moz-user-select: text;
@@ -3057,7 +3470,8 @@ body:not(.is-cordova) {
 			width: 100%;
 			overflow: hidden;
 			white-space: nowrap;
-			i:after {
+
+			i::after {
 				content: " ";
 				display: inline-block;
 				width: 8px;
@@ -3066,6 +3480,7 @@ body:not(.is-cordova) {
 				vertical-align: middle;
 			}
 		}
+
 		p {
 			-webkit-user-select: text;
 			-moz-user-select: text;
@@ -3075,11 +3490,13 @@ body:not(.is-cordova) {
 			font-size: 12px;
 			font-weight: 300;
 		}
+
 		.role-tag {
 			padding: 1px 4px;
 			border-radius: 2px;
 		}
 	}
+
 	.stats {
 		li {
 			margin-bottom: 3px;
@@ -3089,15 +3506,18 @@ body:not(.is-cordova) {
 			border-radius: 2px;
 		}
 	}
+
 	.box {
 		position: relative;
 		margin-bottom: 25px;
 		font-size: 13px;
+
 		h4 {
 			&:extend(.small-title);
 			margin-bottom: 6px;
 		}
-		&:after {
+
+		&::after {
 			content: " ";
 			height: 1px;
 			width: 100%;
@@ -3106,6 +3526,7 @@ body:not(.is-cordova) {
 			position: absolute;
 		}
 	}
+
 	.tags {
 		li {
 			display: inline-block;
@@ -3113,11 +3534,13 @@ body:not(.is-cordova) {
 			border-right: 2px;
 		}
 	}
+
 	.links {
 		i {
 			margin-right: 5px;
 			font-size: 13px;
 		}
+
 		a {
 			white-space: nowrap;
 			max-width: 100%;
@@ -3128,8 +3551,9 @@ body:not(.is-cordova) {
 			padding: 0 5px;
 			line-height: 22px;
 			position: relative;
-			.transition(background .18s ease, colo .18s ease);
-			&:before {
+			transition: background 0.18s ease, color 0.18s ease;
+
+			&::before {
 				content: attr(data-stats);
 				position: absolute;
 				right: 5px;
@@ -3137,33 +3561,40 @@ body:not(.is-cordova) {
 				font-size: 11px;
 				opacity: 0;
 			}
+
 			&:hover {
 				padding-right: 34px;
 				text-decoration: none;
-				&:before {
+
+				&::before {
 					opacity: 1;
 				}
 			}
+
 			span {
 				font-weight: 300;
 			}
 		}
 	}
+
 	.contact-code {
 		margin: -5px 0 10px 0;
 		font-size: 12px;
 	}
+
 	.channels {
 		h3 {
 			font-size: 24px;
 			margin-bottom: 8px;
 			line-height: 22px;
 		}
+
 		p {
 			line-height: 18px;
 			font-size: 12px;
 			font-weight: 300;
 		}
+
 		a {
 			white-space: nowrap;
 			max-width: 100%;
@@ -3174,8 +3605,9 @@ body:not(.is-cordova) {
 			padding: 0 5px;
 			line-height: 22px;
 			position: relative;
-			.transition(background .18s ease, colo .18s ease);
-			&:before {
+			transition: background 0.18s ease, color 0.18s ease;
+
+			&::before {
 				content: attr(data-stats);
 				position: absolute;
 				right: 5px;
@@ -3183,51 +3615,63 @@ body:not(.is-cordova) {
 				font-size: 11px;
 				opacity: 0;
 			}
+
 			span {
 				font-weight: 300;
 			}
 		}
 	}
+
 	.edit-form {
-		padding: 20px 20px 0 20px;
+		padding: 20px 20px 0;
 		white-space: normal;
+
 		h3 {
 			font-size: 24px;
 			margin-bottom: 8px;
 			line-height: 22px;
 		}
+
 		p {
 			line-height: 18px;
 			font-size: 12px;
 			font-weight: 300;
 		}
+
 		> .input-line {
 			margin-top: 20px;
+
 			#password {
 				width: 70%;
 			}
 		}
+
 		nav {
 			padding: 0;
+
 			&.buttons {
 				margin-top: 2em;
 			}
 		}
+
 		.form-divisor {
 			text-align: center;
 			margin: 2em 0;
 			height: 9px;
+
 			> span {
 				padding: 0 1em;
 			}
 		}
 	}
+
 	.room-info-content > div {
-		margin: 0 0 20px 0;
+		margin: 0 0 20px;
 	}
 }
 
 @user-image-square: 20px;
+
 .user-image {
 	margin: 4px;
 	height: @user-image-square;
@@ -3236,22 +3680,24 @@ body:not(.is-cordova) {
 	font-size: 12px;
 	position: relative;
 	display: inline-table;
-	.avatar {
-		&:before {
-			font-size: 10px;
-		}
-	}
+
 	&:hover,
 	&.selected {
 		.avatar {
-			&:after {
+			&::after {
 				.transform(scaleX(1))
 			}
 		}
 	}
+
 	.avatar {
 		overflow: visible;
-		&:after {
+
+		&::before {
+			font-size: 10px;
+		}
+
+		&::after {
 			content: " ";
 			height: 6px;
 			width: 6px;
@@ -3261,30 +3707,37 @@ body:not(.is-cordova) {
 			top: 8px;
 			border-radius: 3px;
 		}
+
 		.avatar-initials {
 			line-height: @user-image-square;
 		}
 	}
+
 	p {
 		display: none;
 	}
+
 	.lines & {
 		width: 100%;
 		margin: 0;
-		&:after {
+
+		&::after {
 			display: none;
 		}
+
 		button {
 			.clearfix;
 			padding: 5px 0;
 			height: 30px;
 			display: block;
+
 			> div {
 				float: left;
 				width: @user-image-square;
 				height: @user-image-square;
 			}
 		}
+
 		p {
 			float: left;
 			display: block;
@@ -3298,6 +3751,7 @@ body:not(.is-cordova) {
 			.calc(width, ~"100% - 45px");
 		}
 	}
+
 	button {
 		display: block;
 		width: 100%;
@@ -3308,26 +3762,32 @@ body:not(.is-cordova) {
 .user-profile {
 	white-space: normal;
 	overflow: hidden;
+
 	.thumb {
 		float: left;
 		width: 75px;
+
 		img {
 			width: 60px;
 			height: 60px;
 		}
 	}
+
 	.info {
 		display: block;
 		margin-left: 75px;
+
 		h3 {
 			font-size: 14px;
 			margin-bottom: 8px;
 			font-weight: 600;
 		}
+
 		p {
 			font-size: 12px;
 			margin-bottom: 6px;
 		}
+
 		a {
 			&:hover {
 				text-decoration: none;
@@ -3348,9 +3808,11 @@ body:not(.is-cordova) {
 	height: 100%;
 	z-index: 1000;
 	visibility: hidden;
+
 	&.fluid {
 		.modal {
 			height: 100%;
+
 			main {
 				position: absolute;
 				overflow-y: scroll;
@@ -3358,33 +3820,41 @@ body:not(.is-cordova) {
 			}
 		}
 	}
+
 	&.opened {
 		.animation(fadeIn .1s ease-out forwards);
+
 		.modal {
 			.animation(modalEnter .35s cubic-bezier(.5, 0, .1, 1) forwards .1s);
 		}
 	}
+
 	&.closed {
 		.animation(fadeOut .2s ease-out forwards);
+
 		.modal {
 			.animation(modalExit .25s cubic-bezier(.5, 0, .1, 1) forwards);
 		}
 	}
+
 	&.overflow {
 		.modal {
 			overflow: visible;
+
 			main {
 				overflow: visible;
 				position: relative;
 			}
 		}
 	}
+
 	.wrapper {
 		display: table;
 		height: 100%;
 		width: 100%;
 		position: relative;
 	}
+
 	.window {
 		display: table-cell;
 		vertical-align: middle;
@@ -3393,21 +3863,24 @@ body:not(.is-cordova) {
 		height: 100%;
 		position: relative;
 	}
+
 	fieldset {
 		margin-bottom: 8px;
 	}
+
 	legend {
-		position: relative;
 		z-index: 2;
 		display: block;
 		margin-bottom: 18px;
 		position: relative;
 		text-transform: uppercase;
 		font-size: 13px;
+
 		i {
 			margin-right: 4px;
 		}
-		&:before {
+
+		&::before {
 			content: " ";
 			width: 100%;
 			height: 1px;
@@ -3417,6 +3890,7 @@ body:not(.is-cordova) {
 			z-index: 1;
 		}
 	}
+
 	.modal {
 		display: block;
 		max-width: 800px;
@@ -3426,9 +3900,10 @@ body:not(.is-cordova) {
 		overflow: hidden;
 		text-align: left;
 		border-radius: 4px;
-		box-shadow: 4px 4px 0 rgba(0, 0, 0, .15);
+		box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.15);
 		padding: 56px 0;
 		opacity: 0;
+
 		header {
 			height: 55px;
 			position: absolute;
@@ -3439,6 +3914,7 @@ body:not(.is-cordova) {
 			text-align-last: right;
 			padding: 0 25px;
 			box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
+
 			h3 {
 				display: inline-block;
 				margin: 0;
@@ -3449,6 +3925,7 @@ body:not(.is-cordova) {
 				text-overflow: ellipsis;
 				overflow: hidden;
 			}
+
 			.close {
 				position: absolute;
 				width: 20px;
@@ -3456,11 +3933,13 @@ body:not(.is-cordova) {
 				right: 20px;
 				top: 16px;
 				opacity: 1;
+
 				i {
 					font-size: 24px;
 				}
 			}
 		}
+
 		main {
 			display: block;
 			width: 100%;
@@ -3469,6 +3948,7 @@ body:not(.is-cordova) {
 			overflow-x: hidden;
 			padding: 20px 25px;
 		}
+
 		footer {
 			height: 55px;
 			position: absolute;
@@ -3490,6 +3970,7 @@ body:not(.is-cordova) {
 			font-weight: 300;
 		}
 	}
+
 	img {
 		width: 200px;
 	}
@@ -3507,12 +3988,16 @@ body:not(.is-cordova) {
 	max-width: 520px;
 	padding: 20px;
 	margin: 20px auto;
-	box-shadow: 0 0 6px 10px rgba(0, 0, 0, 0.1);
-	border-radius: 2px;
+	box-shadow:
+		0 1px 1px 0 rgba(0, 0, 0, 0.2),
+		0 2px 10px 0 rgba(0, 0, 0, 0.16);
+	border-radius: 4px;
 	position: relative;
 	z-index: 1;
+
 	header {
 		padding: 18px 0 23px;
+
 		p {
 			margin: 8px 0 0;
 			font-size: 14px;
@@ -3520,43 +4005,44 @@ body:not(.is-cordova) {
 			font-weight: 300;
 		}
 	}
+
 	h2 {
 		&:extend(.rocket-h2);
 		line-height: 24px;
 		margin: 0;
 	}
+
 	h3 {
 		&:extend(.rocket-h3);
 	}
+
 	img {
 		width: 200px;
 	}
+
 	a {
 		margin: 4px 0;
 		display: inline-block;
 	}
+
 	.options {
 		display: none;
 		width: 100%;
 		font-size: 10px;
 	}
-	.submit {
-		margin: 12px 0;
-	}
-	.remember {
-		float: left;
-	}
-	.remember input {
-		margin-right: 4px;
-	}
-	.forgot {
-		float: right;
-		line-height: 20px;
+
+	.submit,
+	.register,
+	.forgot-password,
+	.back-to-login {
+		margin-top: 12px;
 	}
-	.input-text {
-		margin: 0 0 14px 0;
+
+	.input-line {
+		margin: 0 0 14px;
 		position: relative;
-		&:before {
+
+		&::before {
 			content: " ";
 			width: 100%;
 			height: 40px;
@@ -3565,49 +4051,41 @@ body:not(.is-cordova) {
 			left: 0;
 			cursor: text;
 		}
+
 		&.active {
-			&:before {
+			&::before {
 				visibility: hidden;
 			}
 		}
+
 		input,
 		select {
 			box-shadow: 0 0 0;
 			position: relative;
-			margin-top: 10px;
 			padding: 4px 8px;
 			font-size: 18px;
-			border-width: 0 0 1px 0;
+			border-width: 0 0 1px;
 			font-weight: 400;
-			border-radius: 0px;
+			border-radius: 0;
+
 			&:focus {
 				border-color: #13679a !important;
 			}
 		}
-		.select-arrow {
-			right: 0px;
-		}
+
 		label {
-			position: absolute;
-			top: 20px;
-			left: 8px;
+			margin-left: 8px;
 			display: block;
-			font-size: 18px;
+			font-size: 12px;
 			text-align: left;
 			color: #a9a9a9;
 			transition: all 0.3s;
 		}
-		&.focus label {
-			top: 0;
-			font-size: 12px;
-		}
-		input:-webkit-autofill {
-			-webkit-box-shadow: 0 0 0px 1000px #f4f4f4 inset;
-		}
+
 		.input-error {
 			text-align: left;
 			color: #b40202;
-			padding-left: 4px;
+			padding-left: 8px;
 			font-weight: bold;
 			font-size: 14px;
 		}
@@ -3615,26 +4093,17 @@ body:not(.is-cordova) {
 }
 
 .social-login {
-	text-align: center;
-	position: relative;
-	z-index: 1;
-	display: -webkit-flex;
-	display: flex;
-	flex-wrap: wrap;
-	-webkit-flex-wrap: wrap;
 	margin-bottom: 20px;
+
 	h3 {
 		&:extend(.rocket-h3);
 		margin-top: 0;
 		margin-bottom: 12px;
 	}
+
 	.button {
-		border-radius: 2px;
-		min-height: 40px;
-		line-height: 20px;
+		line-height: 22px;
 		font-size: 18px;
-		margin: 2px;
-		padding: 0;
 		-webkit-flex-grow: 1;
 		flex-grow: 1;
 	}
@@ -3648,6 +4117,7 @@ body:not(.is-cordova) {
 	width: 100%;
 	min-height: 100%;
 	z-index: 101;
+
 	.wrapper {
 		text-align: center;
 		z-index: 10;
@@ -3655,8 +4125,10 @@ body:not(.is-cordova) {
 		width: 100%;
 		padding: 20px;
 	}
+
 	.logo {
 		display: block;
+
 		> img {
 			display: inline-block;
 			position: relative;
@@ -3668,31 +4140,36 @@ body:not(.is-cordova) {
 			max-width: 100%;
 		}
 	}
+
 	a {
 		font-weight: 300;
 	}
+
 	.cell {
 		display: table-cell;
 		vertical-align: middle;
 		text-align: center;
 	}
+
 	header {
 		display: block;
 		position: relative;
 		z-index: 1;
 	}
+
 	.text {
 		font-weight: 300;
-		margin-bottom: 25px;
 		margin: 0 auto 25px;
 		max-width: 580px;
 		position: relative;
 		z-index: 1;
+
 		.button {
 			font-weight: 400;
 			padding: 16px 20px;
 			margin-top: 20px;
 		}
+
 		h1 {
 			font-weight: 600;
 			text-transform: uppercase;
@@ -3701,12 +4178,15 @@ body:not(.is-cordova) {
 			margin-bottom: 20px;
 			display: none;
 		}
+
 		h2 {
 			&:extend(.rocket-h2);
 		}
+
 		h3 {
 			&:extend(.rocket-h3);
 		}
+
 		p {
 			margin: 18px 0;
 			font-size: 16px;
@@ -3714,20 +4194,24 @@ body:not(.is-cordova) {
 			font-weight: 400;
 		}
 	}
+
 	footer {
 		padding: 20px 0 0;
 		position: relative;
 		z-index: 1;
+
 		h4 {
 			text-transform: uppercase;
 			margin-bottom: 8px;
 			font-size: 12px;
 			font-weight: 300;
 		}
+
 		div.switch-language {
 			margin-top: 20px;
 		}
 	}
+
 	a.meteor {
 		position: fixed;
 		right: 30px;
@@ -3738,13 +4222,16 @@ body:not(.is-cordova) {
 		background-size: 100% auto;
 		text-indent: -9999em;
 	}
+
 	.share {
 		border-radius: 50%;
 		min-height: 40px;
 		line-height: 20px;
-		&:before {
+
+		&::before {
 			border-radius: 50%;
 		}
+
 		span {
 			display: none;
 		}
@@ -3758,8 +4245,12 @@ body:not(.is-cordova) {
 
 .mention-link {
 	border-radius: 4px;
-	padding: 0px 4px 2px 4px;
-	font-weight: bold;
+
+	&.mention-link-me,
+	&.mention-link-all {
+		font-weight: bold;
+		padding: 0 4px 2px;
+	}
 }
 
 .highlight-text {
@@ -3773,17 +4264,20 @@ body:not(.is-cordova) {
 }
 
 .avatar-suggestion-item {
-	margin: 5px 0px;
+	margin: 5px 0;
 	text-align: left;
 	.flex-center;
 	flex-flow: row nowrap;
 	width: 100%;
 	padding: 12px;
 	border-width: 1px;
-	.transition(background-color .15s ease-out, border-color .15s ease-out);
+	border-radius: 4px;
+	transition: background-color 0.15s ease-out, border-color 0.15s ease-out;
+
 	&:first-child {
 		margin-top: 10px;
 	}
+
 	.avatar {
 		height: 55px;
 		max-height: 55px;
@@ -3796,6 +4290,7 @@ body:not(.is-cordova) {
 		text-align: center;
 		position: relative;
 	}
+
 	.question-mark {
 		&::before {
 			position: absolute;
@@ -3807,15 +4302,27 @@ body:not(.is-cordova) {
 			line-height: 55px;
 		}
 	}
+
 	.action {
 		text-align: right;
 		padding-left: 20px;
 	}
+
 	.button {
 		min-width: 120px;
 		cursor: pointer;
 		text-align: center;
 	}
+
+	.input-line {
+		display: flex;
+		align-items: center;
+	}
+
+	#avatarurl {
+		margin-right: 20px;
+	}
+
 	input[type=file] {
 		position: absolute !important;
 		width: 100%;
@@ -3825,42 +4332,32 @@ body:not(.is-cordova) {
 		opacity: 0;
 		z-index: 10000;
 		cursor: pointer;
+
 		* {
 			cursor: pointer;
 		}
 	}
+
 	.avatar-file-input::-webkit-file-upload-button {
 		visibility: hidden;
 	}
 }
 
-.page-container table {
-	margin-bottom: 30px;
-	width: 100%;
-	th,
-	td {
-		vertical-align: middle;
-		padding: .6rem .7rem;
-		text-align: left;
-		border-width: 0 0 1px 0;
-	}
-	th {
-		white-space: nowrap;
-	}
-}
-
 .statistics-table {
 	margin-bottom: 30px;
 	width: 100%;
+
 	th,
 	td {
 		text-align: left;
 		padding: 6px 8px;
 	}
+
 	th {
 		text-align: right;
 		width: 30%;
 	}
+
 	td {
 		width: 70%;
 	}
@@ -3868,9 +4365,11 @@ body:not(.is-cordova) {
 
 .rocket-team {
 	display: block;
+
 	li {
 		display: inline-block;
 	}
+
 	a {
 		display: inline-block;
 		width: 50px;
@@ -3894,6 +4393,20 @@ body:not(.is-cordova) {
 	#rocket-chat {
 		.flex-opened {
 			right: 40px;
+
+			.flex-tab {
+				.transform(translateX(-100%));
+			}
+		}
+
+		&.embedded-view {
+			.flex-opened {
+				right: 0;
+
+				.flex-tab {
+					transform: none;
+				}
+			}
 		}
 	}
 }
@@ -3904,66 +4417,37 @@ body:not(.is-cordova) {
 			visibility: visible;
 			display: inline-block;
 		}
-		.side-nav {
-			top: 0;
-			// .transform(translateX(-100%));
-			.transition(transform .3s ease-out);
-		}
+
 		.main-content {
 			left: 0;
 			z-index: 120;
-			&.notransition {
-				.transition(transform .0s);
-			}
 		}
+
 		.main-content,
 		.flex-tab-bar {
-			.transition(transform .2s linear);
+			transition: transform 0.2s linear;
+
+			&.notransition {
+				transition: transform 0;
+			}
 		}
+
 		.fixed-title h2 {
 			margin-left: 45px;
 		}
-		.flex-tab {
-			top: 0;
-		}
+
 		.messages-box {
 			padding: 0 10px;
 		}
-		&.menu-opened {
-			.side-nav {
-				.transform(translateX(0));
-			}
-			.burger {
-				i {
-					&:nth-child(1) {
-						opacity: 1;
-						width: 10px;
-						.transform-origin(50%, 50%, 0);
-						.transform(translateY(3px) rotate(-45deg));
-					}
-					&:nth-child(2) {
-						//.transform(rotate(180deg));
-					}
-					&:nth-child(3) {
-						opacity: 1;
-						width: 10px;
-						.transform-origin(50%, 50%, 0);
-						.transform(translateY(-3px) rotate(45deg));
-					}
-				}
-			}
-			.main-content,
-			.flex-tab-bar {
-				.transform(translateX(@rooms-box-width));
-			}
-		}
 	}
+
 	.sweet-alert {
 		h2 {
 			font-size: 20px;
 			line-height: 30px;
 			margin: 10px 0;
 		}
+
 		button {
 			margin-top: 6px;
 			padding: 10px 22px;
@@ -3991,6 +4475,7 @@ body:not(.is-cordova) {
 	.dropzone-overlay {
 		display: none;
 	}
+
 	&.over .dropzone-overlay {
 		position: fixed;
 		top: 0;
@@ -3998,12 +4483,11 @@ body:not(.is-cordova) {
 		bottom: 0;
 		right: 0;
 		z-index: 1000000;
-		display: block;
 		font-size: 42px;
 		display: flex;
 		align-items: center;
 		justify-content: center;
-		margin: 0 51px 0 12px;
+
 		> div {
 			padding: 40px;
 			border-radius: 10px;
@@ -4014,24 +4498,20 @@ body:not(.is-cordova) {
 	}
 }
 
-@media (min-width: 780px) {
-	.dropzone.over .dropzone-overlay {
-		margin: 0 51px 0 270px;
-	}
-}
-
 .is-cordova {
 	.flex-tab {
 		.control {
 			padding-left: 50px;
 		}
+
 		button.more {
 			width: 60px;
 			.transform(translateX(-57px));
 		}
 	}
+
 	.connection-status > .alert {
-		border-width: 0 0 1px 0;
+		border-width: 0 0 1px;
 	}
 }
 
@@ -4040,28 +4520,26 @@ body:not(.is-cordova) {
 		padding-left: 10px;
 		padding-right: 10px;
 	}
-	.mobile-message-menu {
-		-webkit-user-select: none;
-		-moz-user-select: none;
-		-ms-user-select: none;
-		user-select: none;
-	}
 }
 
 @media all and(max-height: 480px) {
 	#login-card {
 		padding: 10px;
 		margin: 10px auto;
-		.input-text {
+
+		.input-line {
 			margin-bottom: 6px;
 		}
+
 		.submit {
-			margin: 0px;
+			margin: 0;
 		}
 	}
+
 	.social-login {
 		margin-bottom: 10px;
 	}
+
 	.message-form textarea {
 		max-height: 100px !important;
 	}
@@ -4074,6 +4552,13 @@ body:not(.is-cordova) {
 }
 
 .webrtc-video {
+	&.webrtc-video-overlay,
+	.main-video,
+	.state-overlay::before,
+	.videos .video-item {
+		color: #ffffff;
+	}
+
 	&.webrtc-video-overlay {
 		position: fixed;
 		left: 0;
@@ -4084,20 +4569,24 @@ body:not(.is-cordova) {
 		display: flex;
 		flex-direction: column;
 		justify-content: center;
+
 		.main-video {
-			video {
+			.webrtc-video-element {
 				max-width: 100%;
 				width: auto;
 			}
 		}
 	}
+
 	.main-video {
 		text-align: center;
-		video {
+
+		.webrtc-video-element {
 			width: 100%;
 			min-height: 299px;
 		}
-		>div {
+
+		> div {
 			margin-top: -28px;
 			position: relative;
 			line-height: 25px;
@@ -4106,10 +4595,12 @@ body:not(.is-cordova) {
 			font-weight: bold;
 		}
 	}
+
 	.video-flip {
 		transform: scaleX(-1);
 		filter: FlipH;
 	}
+
 	.videos {
 		display: -webkit-flex;
 		display: -moz-flex;
@@ -4120,6 +4611,7 @@ body:not(.is-cordova) {
 		justify-content: center;
 		-webkit-justify-content: center;
 		-moz-justify-content: center;
+
 		.video-item {
 			position: relative;
 			margin-right: 3px;
@@ -4127,6 +4619,7 @@ body:not(.is-cordova) {
 			width: 93px;
 			overflow: hidden;
 			text-align: center;
+
 			&.state-overlay::before {
 				content: attr(data-state-text);
 				position: absolute;
@@ -4140,21 +4633,24 @@ body:not(.is-cordova) {
 				font-size: 12px;
 				font-weight: bold;
 			}
-			video {
+
+			.webrtc-video-element {
 				height: 70px;
 				max-width: 100px;
 			}
-			>div {
+
+			> div {
 				line-height: 16px;
 				font-size: 12px;
 				text-align: center;
 				text-overflow: ellipsis;
 				overflow: hidden;
-				padding: 0px 2px;
+				padding: 0 2px;
 				margin-top: -16px;
 				position: relative;
 				font-weight: bold;
 			}
+
 			.video-muted-overlay {
 				position: absolute;
 				bottom: 16px;
@@ -4177,25 +4673,30 @@ body:not(.is-cordova) {
 	}
 }
 
+.webrtc-video-element {
+	background-color: #000000;
+}
+
 .alert-icon {
 	font-size: 80px;
 	display: block;
 	margin-bottom: 20px;
 }
 
-.minicolors-theme-rocketchat {
-	.minicolors-swatch {
-		height: 33px;
-		width: 33px;
-		top: 1px;
-		left: 1px;
-		border-radius: 5px 0 0 5px;
-		overflow: hidden;
-		border-width: 0 1px 0 0;
-	}
-	input {
-		text-indent: 34px;
-	}
+.colorpicker-input {
+	text-indent: 34px;
+}
+
+.colorpicker-swatch {
+	height: 33px;
+	width: 33px;
+	top: 1px;
+	left: 1px;
+	border-radius: 5px 0 0 5px;
+	overflow: hidden;
+	border-width: 0 1px 0 0;
+	display: block;
+	position: absolute;
 }
 
 .inline-video {
@@ -4208,51 +4709,43 @@ body:not(.is-cordova) {
 .attention-message {
 	padding-top: 50px;
 	font-size: 24px;
+
 	i {
 		display: block;
 		margin-bottom: 20px;
 		font-size: 40px;
 	}
+
 	span {
 		display: block;
 	}
 }
 
 .load-more {
-	text-transform: lowercase;
-	text-align: center;
-	line-height: 40px;
-	font-style: italic;
+	position: relative;
+	padding: 1rem 0;
 }
 
 .search-messages-list {
 	.message-cog-container {
 		.message-action {
 			display: none !important;
+
 			&.jump-to-star-message {
 				display: block !important;
 			}
 		}
 	}
+
 	.no-results {
 		text-align: center;
 	}
 }
 
-.messages-box {
-	.message-cog-container {
-		.message-action {
-			&.jump-to-search-message {
-				display: none !important;
-			}
-		}
-	}
-}
-
 .terminal {
 	position: absolute;
-	top: 0px;
-	bottom: 0px;
+	top: 0;
+	bottom: 0;
 	margin: 0;
 	right: 0;
 	left: 0;
@@ -4261,20 +4754,23 @@ body:not(.is-cordova) {
 	padding: 8px 10px !important;
 	font-family: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
 	font-weight: 500;
-	-webkit-user-select: text;
-	-moz-user-select: text;
-	-ms-user-select: text;
-	user-select: text;
-	margin-bottom: 0px !important;
-	* {
-		-webkit-user-select: text;
-		-moz-user-select: text;
-		-ms-user-select: text;
-		user-select: text;
-	}
-	> div {
-		word-break: break-all;
-	}
+	margin-bottom: 0 !important;
+	background-color: #444444 !important;
+	color: #ffffff;
+}
+
+.terminal-line {
+	word-break: break-all;
+}
+
+.terminal-time {
+	color: #7f7f7f;
+}
+
+.code-colors {
+	background-color: #f8f8f8;
+	border-color: #cccccc;
+	color: #333333;
 }
 
 .new-logs {
@@ -4289,8 +4785,9 @@ body:not(.is-cordova) {
 	cursor: pointer;
 	bottom: 8px;
 	left: 50%;
-	.transition(transform 0.3s ease-out);
+	transition: transform 0.3s ease-out;
 	.transform(translateY(0));
+
 	&.not {
 		.transform(translateY(150%));
 	}
@@ -4307,7 +4804,8 @@ body:not(.is-cordova) {
 		font-weight: bold;
 		margin-top: 5px;
 	}
-	pre {
+
+	.script-error {
 		font-size: 12px;
 		font-weight: bold;
 		padding: 6px;
@@ -4319,16 +4817,21 @@ body:not(.is-cordova) {
 	.title {
 		display: none;
 	}
+
 	.button-fullscreen {
 		display: initial;
 	}
+
 	.button-restore {
 		display: none;
 	}
+
 	.buttons {
 		text-align: right;
-		border-width: 0px 1px 1px 1px;
+		border-width: 0 1px 1px;
+		background-color: #f7f7f7;
 	}
+
 	&.code-mirror-box-fullscreen {
 		height: auto;
 		position: fixed;
@@ -4341,25 +4844,31 @@ body:not(.is-cordova) {
 		display: flex;
 		flex-direction: column;
 		align-items: stretch;
+
 		.buttons {
 			border-width: 0;
 		}
+
 		.title {
 			display: initial;
 			padding-left: 10px;
 			font-size: 16px;
 			line-height: 30px;
 		}
+
 		.button-fullscreen {
 			display: none;
 		}
+
 		.button-restore {
 			display: initial;
 		}
+
 		.CodeMirror {
 			flex-grow: 1;
 			display: flex;
 			flex-direction: column;
+
 			.CodeMirror-scroll {
 				flex-grow: 1;
 			}
@@ -4377,18 +4886,22 @@ body:not(.is-cordova) {
 			left: 0;
 		}
 	}
+
 	.container-bars {
 		.unread-bar {
 			.unread-count {
 				display: inline-block;
 			}
+
 			.unread-count-since {
 				display: none;
 			}
+
 			> button.jump-to {
 				.jump-to-small {
 					display: inline-block;
 				}
+
 				.jump-to-large {
 					display: none;
 				}
@@ -4408,7 +4921,7 @@ body:not(.is-cordova) {
 	position: absolute;
 	right: -8px;
 	top: -5px;
-	opacity: .6;
+	opacity: 0.6;
 }
 
 .collapse-switch {
@@ -4416,6 +4929,7 @@ body:not(.is-cordova) {
 }
 
 // kinda hacky, needed in oembedFrageWidget.html
+
 br.only-after-a {
 	display: none;
 }
@@ -4435,9 +4949,11 @@ a + br.only-after-a {
 .hide-avatars {
 	.message {
 		padding-left: 20px;
+
 		.thumb.user-card-message:not(.thumb-small) {
 			display: none;
 		}
+
 		.user.user-card-message {
 			margin-left: -5px;
 		}
@@ -4452,15 +4968,19 @@ a + br.only-after-a {
 					position: static;
 					width: auto;
 					float: right;
+
 					.message-cog-container {
 						float: left;
 					}
+
 					.message-dropdown {
 						left: auto;
 						right: -2px;
+
 						ul {
 							flex-direction: row-reverse;
-							li:first-child i:before {
+
+							li:first-child i::before {
 								content: "\d7";
 							}
 						}
@@ -4478,10 +4998,12 @@ a + br.only-after-a {
 		width: auto;
 		vertical-align: middle;
 	}
+
 	label {
 		display: inline-block;
 		max-width: 100%;
 	}
+
 	.form-group {
 		display: inline-block;
 	}
@@ -4491,20 +5013,30 @@ a + br.only-after-a {
 	.main-content.main-modal {
 		right: 0;
 	}
+
 	.messages-container {
 		border-width: 0;
+
 		.messages-box {
 			margin-top: 0;
 		}
+
 		.footer {
 			min-height: 36px;
 			padding: 0;
+
+			.message-form {
+				margin-bottom: 0;
+			}
+
 			.message-input {
 				border-width: 0;
 			}
+
 			.stream-info {
 				display: none;
 			}
+
 			.formatting-tips {
 				display: none;
 			}
@@ -4512,5 +5044,12 @@ a + br.only-after-a {
 	}
 }
 
-#swipebox-slider .slide .swipebox-inline-container, #swipebox-slider .slide .swipebox-video-container, #swipebox-slider .slide img {padding: 40px;}
-#swipebox-overlay {background: rgba(13, 13, 13, 0.5);}
+#swipebox-slider .slide .swipebox-inline-container,
+#swipebox-slider .slide .swipebox-video-container,
+#swipebox-slider .slide img {
+	padding: 40px;
+}
+
+#swipebox-overlay {
+	background: rgba(13, 13, 13, 0.5);
+}
diff --git a/packages/rocketchat-theme/client/imports/forms.less b/packages/rocketchat-theme/client/imports/forms.less
new file mode 100644
index 0000000000000000000000000000000000000000..92f187a4dd78496bc97af02ae3c5c93aa5927cb8
--- /dev/null
+++ b/packages/rocketchat-theme/client/imports/forms.less
@@ -0,0 +1,104 @@
+.input {
+	&.radio {
+		min-height: 13px;
+		position: relative;
+
+		input {
+			position: absolute;
+			top: 0;
+			left: 0;
+			opacity: 0;
+			outline: 0;
+			z-index: -1;
+			width: 0;
+			height: 0;
+
+			&:checked + label::after {
+				opacity: 1;
+			}
+		}
+
+		label {
+			cursor: pointer;
+			user-select: none;
+			padding-left: 20px;
+
+			&::before {
+				content: '';
+				position: absolute;
+				top: 0;
+				left: 0;
+				width: 15px;
+				height: 15px;
+				border-width: 1px;
+				border-radius: 50%;
+			}
+
+			&::after {
+				content: '';
+				position: absolute;
+				top: 4px;
+				left: 4px;
+				width: 7px;
+				height: 7px;
+				border-radius: 50%;
+				opacity: 0;
+				transition: opacity 0.2s ease-out;
+			}
+		}
+	}
+
+	&.checkbox.toggle {
+		min-height: 20px;
+		position: relative;
+
+		input {
+			position: absolute;
+			top: 0;
+			left: 0;
+			opacity: 0;
+			outline: 0;
+			z-index: -1;
+			width: 0;
+			height: 0;
+
+			&:checked + label::after {
+				left: 25px;
+			}
+		}
+
+		label {
+			cursor: pointer;
+			user-select: none;
+			display: block;
+			min-height: 20px;
+			vertical-align: top;
+
+			&::before {
+				display: block;
+				position: absolute;
+				content: '';
+				z-index: 0;
+				top: 0;
+				left: 0;
+				box-shadow: none;
+				width: 40px;
+				height: 16px;
+				border-radius: 50px;
+				transition: background-color 0.2s ease-out;
+			}
+
+			&::after {
+				content: '';
+				position: absolute;
+				left: 1px;
+				top: 1px;
+				border-radius: 50%;
+				width: 14px;
+				height: 14px;
+				z-index: 1;
+				transition: left 0.2s ease-out;
+			}
+		}
+	}
+}
diff --git a/packages/rocketchat-theme/assets/stylesheets/utils/_keyframes.import.less b/packages/rocketchat-theme/client/imports/keyframes.less
similarity index 98%
rename from packages/rocketchat-theme/assets/stylesheets/utils/_keyframes.import.less
rename to packages/rocketchat-theme/client/imports/keyframes.less
index a1ef83ee5b6fda55fdbcbe762c0a6b300b9522ad..8aa3df96f1da34e7f83d2bb7a7cc7c92b7a75e19 100644
--- a/packages/rocketchat-theme/assets/stylesheets/utils/_keyframes.import.less
+++ b/packages/rocketchat-theme/client/imports/keyframes.less
@@ -1,13 +1,16 @@
 // keyframes
+
 @-webkit-keyframes fadeIn {
 	0% {
 		opacity: 0;
 		visibility: hidden;
 	}
+
 	1% {
 		opacity: 0;
 		visibility: visible;
 	}
+
 	100% {
 		opacity: 1;
 		visibility: visible;
@@ -19,10 +22,12 @@
 		opacity: 0;
 		visibility: hidden;
 	}
+
 	1% {
 		opacity: 0;
 		visibility: visible;
 	}
+
 	100% {
 		opacity: 1;
 		visibility: visible;
@@ -34,10 +39,12 @@
 		opacity: 1;
 		visibility: visible;
 	}
+
 	99% {
 		opacity: 0;
 		visibility: visible;
 	}
+
 	100% {
 		opacity: 0;
 		visibility: hidden;
@@ -49,10 +56,12 @@
 		opacity: 1;
 		visibility: visible;
 	}
+
 	99% {
 		opacity: 0;
 		visibility: visible;
 	}
+
 	100% {
 		opacity: 0;
 		visibility: hidden;
@@ -63,6 +72,7 @@
 	0% {
 		background: #ffff99;
 	}
+
 	100% {
 		background: none;
 	}
@@ -72,6 +82,7 @@
 	0% {
 		background: #ffff99;
 	}
+
 	100% {
 		background: none;
 	}
@@ -81,6 +92,7 @@
 	0% {
 		background: #ffff99;
 	}
+
 	100% {
 		background: none;
 	}
@@ -90,6 +102,7 @@
 	0% {
 		background: #ffff99;
 	}
+
 	100% {
 		background: none;
 	}
@@ -100,11 +113,13 @@
 		opacity: 0;
 		visibility: hidden;
 	}
+
 	1% {
 		opacity: 0;
 		visibility: visible;
 		.transform(translateY(-150px));
 	}
+
 	100% {
 		opacity: 1;
 		visibility: visible;
@@ -117,11 +132,13 @@
 		opacity: 0;
 		visibility: hidden;
 	}
+
 	1% {
 		opacity: 0;
 		visibility: visible;
 		-webkit-transform: translateY(-150px);
 	}
+
 	100% {
 		opacity: 1;
 		visibility: visible;
@@ -134,11 +151,13 @@
 		opacity: 1;
 		visibility: visible;
 	}
+
 	99% {
 		opacity: 0;
 		visibility: visible;
 		.transform(translateY(150px));
 	}
+
 	100% {
 		opacity: 0;
 		visibility: hidden;
@@ -150,11 +169,13 @@
 		opacity: 1;
 		visibility: visible;
 	}
+
 	99% {
 		opacity: 0;
 		visibility: visible;
 		-webkit-transform: translateY(150px);
 	}
+
 	100% {
 		opacity: 0;
 		visibility: hidden;
diff --git a/packages/rocketchat-theme/client/imports/lesshat.less b/packages/rocketchat-theme/client/imports/lesshat.less
new file mode 100644
index 0000000000000000000000000000000000000000..0979dd5275e4c8ca63c69433f10d0dcaa5aac34f
--- /dev/null
+++ b/packages/rocketchat-theme/client/imports/lesshat.less
@@ -0,0 +1,85 @@
+//  lesshat - The best mixin library in the world
+//
+// version: v4.1.0 (2016-07-19)
+
+.animation(...) {
+	@process: ~`(function(e){return e=e||"none",/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
+	-webkit-animation: @process;
+	-moz-animation: @process;
+	-o-animation: @process;
+	animation: @process;
+}
+
+.box-sizing(...) {
+	@process: ~`(function(n){return n=n||"content-box"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
+	-webkit-box-sizing: @process;
+	-moz-box-sizing: @process;
+	box-sizing: @process;
+}
+
+.calc(...) {
+	@process: ~`(function(a){function c(c,t){var r=");\n",s=e.split(","),l=s[0]+":"+c+"("+(s[1].trim()||0)+r;"start"==t?a="0;\n"+l:a+=l}a=a||8121991;var t="@{state}",e=a;if(8121991==a)return a;switch(t){case"1":c("-webkit-calc","start"),c("-moz-calc"),c("calc");break;case"2":c("-webkit-calc","start"),c("-moz-calc");break;case"3":c("-webkit-calc","start"),c("calc");break;case"4":c("-webkit-calc","start");break;case"5":c("-moz-calc","start"),c("calc");break;case"6":c("-moz-calc","start");break;case"7":c("calc","start")}return a=a.replace(/;$/g,"")})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
+	@state: 1; -lh-property: @process;
+}
+
+.transform(...) {
+	@process: ~`(function(e){e=e||"none";var r={translate:"px",rotate:"deg",rotate3d:"deg",skew:"deg"};/^\w*\(?[a-z0-9.]*\)?/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,""));for(var t in r)e.indexOf(t)>=0&&(e=e.replace(new RegExp(t+"[\\w]?\\([a-z0-9, %]*\\)"),function(e){var n=/(\d+\.?\d*)(?!\w|%)/g;return"rotate3d"==t&&(n=/,\s*\d+$/),e.replace(n,function(e){return e+r[t]})}));return e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
+	-webkit-transform: @process;
+	-moz-transform: @process;
+	-ms-transform: @process;
+	-o-transform: @process;
+	transform: @process;
+}
+
+.transform-origin(...) {
+	@process: ~`(function(e){e=e||"50% 50% 0";var t=/\d/gi,r=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return/^[^, ]*,/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,"")),t.test(e)&&(e=e.replace(r,function(e){return 0==e&&e||e+"%"})),e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
+	-webkit-transform-origin: @process;
+	-moz-transform-origin: @process;
+	-ms-transform-origin: @process;
+	-o-transform-origin: @process;
+	transform-origin: @process;
+}
+
+.transform-style(...) {
+	@process: ~`(function(n){return n=n||"flat"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
+	-webkit-transform-style: @process;
+	-moz-transform-style: @process;
+	-ms-transform-style: @process;
+	-o-transform-style: @process;
+	transform-style: @process;
+}
+
+.translate(...) {
+	@process: ~`(function(n){n=n||"0";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"px"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
+	-webkit-transform: translate(@process);
+	-moz-transform: translate(@process);
+	-ms-transform: translate(@process);
+	-o-transform: translate(@process);
+	transform: translate(@process);
+}
+
+.translateX(...) {
+	@process: ~`(function(n){n=n||"0";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"px"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
+	-webkit-transform: translateX(@process);
+	-moz-transform: translateX(@process);
+	-ms-transform: translateX(@process);
+	-o-transform: translateX(@process);
+	transform: translateX(@process);
+}
+
+.translateY(...) {
+	@process: ~`(function(n){n=n||"0";var r=/\d/gi,t=/(?:\s|^)(\.?\d+\.?\d*)(?![^(]*\)|\w|%|\.)/gi;return r.test(n)&&(n=n.replace(t,function(n){return 0==n&&n||n+"px"})),n})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
+	-webkit-transform: translateY(@process);
+	-moz-transform: translateY(@process);
+	-ms-transform: translateY(@process);
+	-o-transform: translateY(@process);
+	transform: translateY(@process);
+}
+
+.user-select(...) {
+	@process: ~`(function(n){return n=n||"auto"})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
+	-webkit-user-select: @process;
+	-moz-user-select: @process;
+	-ms-user-select: @process;
+	user-select: @process;
+}
diff --git a/packages/rocketchat-theme/assets/stylesheets/utils/_reset.import.less b/packages/rocketchat-theme/client/imports/reset.less
similarity index 94%
rename from packages/rocketchat-theme/assets/stylesheets/utils/_reset.import.less
rename to packages/rocketchat-theme/client/imports/reset.less
index 1da139742a577a2d2b1051dd1de6867612937776..274ac1571a3ff7801ee7bd375fc978b693b3e265 100644
--- a/packages/rocketchat-theme/assets/stylesheets/utils/_reset.import.less
+++ b/packages/rocketchat-theme/client/imports/reset.less
@@ -96,7 +96,6 @@ video {
 	}
 }
 
-
 /* HTML5 display-role reset for older browsers */
 
 article,
@@ -127,10 +126,10 @@ q {
 	quotes: none;
 }
 
-blockquote:before,
-blockquote:after,
-q:before,
-q:after {
+blockquote::before,
+blockquote::after,
+q::before,
+q::after {
 	content: '';
 	content: none;
 }
diff --git a/packages/rocketchat-theme/assets/stylesheets/rtl.less b/packages/rocketchat-theme/client/imports/rtl.less
similarity index 84%
rename from packages/rocketchat-theme/assets/stylesheets/rtl.less
rename to packages/rocketchat-theme/client/imports/rtl.less
index f08412ad0ee937fd9aaccbf660050eb44796bf1a..123b9e68f4f78d2324e9d5e404e5df4e5226a1fd 100644
--- a/packages/rocketchat-theme/assets/stylesheets/rtl.less
+++ b/packages/rocketchat-theme/client/imports/rtl.less
@@ -1,144 +1,186 @@
 .rtl {
 	direction: rtl;
+
 	// Mix-ins
 	.right(@right) {
 		right: @right;
 		left: auto;
 	}
-	.left (@left) {
+
+	.left(@left) {
 		left: @left;
 		right: auto;
 	}
+
 	.margin-right(@margin-right) {
 		margin-right: @margin-right;
 		margin-left: auto;
 	}
+
 	.margin-left(@margin-left) {
 		margin-left: @margin-left;
 		margin-right: auto;
 	}
+
 	.padding-right(@padding-right) {
 		padding-right: @padding-right;
-		padding-left: 0px;
+		padding-left: 0;
 	}
+
 	.padding-left(@padding-left) {
 		padding-left: @padding-left;
-		padding-right: 0px;
+		padding-right: 0;
 	}
+
 	button {
 		text-align: right;
 	}
+
 	.text-right {
 		text-align: left;
 	}
+
 	.side-nav {
-		.right(0px);
+		.right(0);
+
 		.header {
-			.right(0px);
+			.right(0);
+
 			.account-box {
 				.info {
-					padding: 10px 18px 10px 0px;
+					padding: 10px 18px 10px 0;
+
 					.thumb {
 						float: right;
 					}
-					.thumb:after {
+
+					.thumb::after {
 						.right(-14px);
 					}
+
 					.data {
 						float: right;
 						padding: 0 10px 0 25px;
+
 						.wrp {
 							text-align: right;
 						}
 					}
 				}
+
 				.options {
-					.right(0px);
+					.right(0);
+
 					.status {
 						.padding-right(38px);
 					}
+
 					span.soon {
 						.left(-30px);
 					}
-					.status:after {
+
+					.status::after {
 						.right(18px);
 					}
 				}
+
 				.options._hidden {
 					transform: translateX(100%);
 				}
 			}
 		}
+
 		> .arrow {
 			.left(8px);
 		}
+
 		.arrow {
 			transform: rotateY(180deg);
 		}
+
 		.footer {
-			.right(0px);
+			.right(0);
 		}
+
 		.rooms-list {
 			direction: ltr;
+
 			> .wrapper {
 				direction: rtl;
 				.padding-right(8px);
+
 				h3.add-room {
 					i {
 						.left(6px);
 					}
 				}
+
 				h3 {
 					.padding-right(10px);
 				}
+
 				ul a {
 					padding: 6px 6px 7px 25px;
 				}
 			}
 		}
+
 		.more {
-			padding: 4px 10px 4px 0px;
+			padding: 4px 10px 4px 0;
 		}
+
 		.empty {
 			.padding-right(10px);
 		}
+
 		ul .opt {
-			.left(0px);
+			.left(0);
 			.padding-left(10px);
 			text-align: left;
 		}
+
 		.flex-nav {
-			.right(0px);
+			.right(0);
+
 			> section {
-				.right(0px);
+				.right(0);
 			}
+
 			header {
-				.right(0px);
+				.right(0);
 				.padding-right(15px);
+
 				> div {
 					text-align: right;
 				}
 			}
+
 			.content {
 				> .wrapper {
 					direction: rtl;
 				}
 			}
+
 			.input-submit {
-				margin: 35px -4px 0 0px;
+				margin: 35px -4px 0 0;
 			}
-			.button:before {
-				.right(0px);
+
+			.button::before {
+				.right(0);
 			}
+
 			footer {
-				.right(0px);
+				.right(0);
 				text-align: right;
+
 				> div {
 					text-align: right;
 				}
 			}
+
 			&.animated-hidden {
 				.transform(translateX(100%));
+
 				header,
 				footer,
 				.content {
@@ -146,47 +188,55 @@
 				}
 			}
 		}
+
 		.search-form {
 			.search {
 				.padding-right(25px);
 			}
+
 			.margin-left(20px);
 		}
+
 		h3 {
 			.padding-right(10px);
+
 			&.add-room {
 				i {
 					.left(6px);
 				}
 			}
 		}
+
 		.unread {
 			.left(6px);
 		}
 	}
-	.side-nav:before {
+
+	.side-nav::before {
 		.right(8px);
 	}
+
 	.main-content {
-		left: 0;
+		left: 40px;
 		right: @rooms-box-width;
-		.margin-left(40px);
+		transition: left 0.25s cubic-bezier(0.5, 0, 0.1, 1);
+
 		&.flex-opened {
-			left: @flex-tab-width;
-			.flex-tab {
-				.left(40px);
-			}
+			left: @flex-tab-width + 40px;
 		}
 	}
+
 	.page-settings {
 		.content {
 			> .info {
 				padding-left: 20px;
 			}
 		}
+
 		.section {
 			border-right: none;
-			border-left: 1px solid #ddd;
+			border-left: 1px solid #dddddd;
+
 			.section-content {
 				.input-line {
 					> label {
@@ -196,46 +246,58 @@
 			}
 		}
 	}
+
 	.messages-box {
-		margin: 60px 0px 0px 20px;
+		margin: 60px 0 0 20px;
+
 		.new-message {
 			.right(50%);
 		}
 	}
+
 	.terminal {
 		direction: ltr;
 	}
+
 	.container-bars {
 		.upload-progress {
 			.upload-progress-progress {
-				.right(0px);
+				.right(0);
 			}
+
 			.upload-progress-text {
 				> a {
 					float: left;
 				}
 			}
 		}
+
 		.unread-bar {
 			> a.mark-read {
 				float: left;
 			}
+
 			> a.jump-to {
 				float: right;
 			}
 		}
 	}
+
 	.messages-container {
 		.right(0);
+
 		.edit-room-title {
 			.margin-right(4px);
 		}
+
 		.wrapper {
 			.right(0);
 		}
+
 		.footer {
 			.right(0);
 		}
+
 		.message-form {
 			> div {
 				.input-message-container {
@@ -244,6 +306,7 @@
 					}
 				}
 			}
+
 			textarea {
 				padding-right: 49px;
 				padding-left: 8px;
@@ -251,35 +314,41 @@
 				border-width: 0 0 0 1px;
 				border-right-width: 0;
 			}
+
 			> .stream-info {
 				float: right;
 			}
+
 			> .formatting-tips {
 				float: left;
 				position: relative;
 				right: auto;
+
 				q {
 					padding: 0 3px 0 0;
 					border-right: 3px solid;
-					border-left: 0px none;
-					border-right-color: #CCC;
+					border-left: 0 none;
+					// border-right-color: #cccccc;
 				}
 			}
 		}
 	}
+
 	.account-box {
 		.options {
 			direction: ltr;
+
 			> .wrapper {
 				direction: rtl;
 			}
 		}
 	}
+
 	.flex-tab-bar {
 		.left(0);
 		border-right: 1px solid #eaeaea;
 		border-left: none;
-		z-index: 13;
+
 		.tab-button {
 			&.active {
 				.margin-right(-1px);
@@ -288,36 +357,43 @@
 			}
 		}
 	}
+
 	.flex-tab {
+		.right(100%);
 		border-left: unset;
 		border-width: 0 1px 0 0;
-		border-right-color: @tertiary-background-color;
-		.left(0);
-		.transform(translateX(-100%));
+		// border-right-color: @tertiary-background-color;
+
 		.control {
 			text-align: right;
-			padding: 12px 30px 12px;
+			padding: 12px 30px;
+
 			> a,
 			> form {
 				float: right;
 			}
+
 			.more {
 				.right(0);
 				.transform(translateX(27px));
 			}
+
 			.search-form {
 				padding: 0 0 0 4px;
 				width: 100%;
+
 				.icon-plus {
 					.right(4px);
 				}
 			}
+
 			.info-tabs {
 				text-align: left;
 				.left(20px);
 			}
 		}
 	}
+
 	.flex-opened {
 		.flex-tab {
 			.control {
@@ -327,26 +403,31 @@
 			}
 		}
 	}
+
 	.input-line {
 		&.search {
 			.icon-spin {
 				.left(5px);
 			}
+
 			.icon-search,
 			.icon-right-open-small {
 				.right(2px);
 			}
+
 			input {
 				padding-right: 20px;
 				padding-left: 8px;
 				text-align: right;
 			}
 		}
+
 		> div {
 			.right {
 				.left(10px);
 			}
 		}
+
 		&.double-col {
 			> label {
 				float: right;
@@ -354,13 +435,17 @@
 				text-align: left;
 				padding: 10px 0 10px 20px;
 			}
+
 			> div {
 				float: right;
+
 				label {
 					.margin-left(4px);
+
 					&:nth-last-child(1) {
 						.margin-left(0);
 					}
+
 					input {
 						.margin-left(4px);
 					}
@@ -368,31 +453,37 @@
 			}
 		}
 	}
+
 	.user-image {
 		.avatar {
-			&:after {
+			&::after {
 				.right(-12px);
 			}
 		}
 	}
+
 	.lines .user-image {
 		button {
 			> div {
 				float: right;
 			}
 		}
+
 		p {
 			float: right;
 			.padding-right(10px);
 		}
 	}
+
 	.user-view {
 		nav {
 			.margin-right(-4px);
+
 			.back {
 				float: left;
 			}
 		}
+
 		.stats {
 			li {
 				border-right: unset;
@@ -400,103 +491,124 @@
 			}
 		}
 	}
+
 	@media all and(max-width: 1100px) {
 		#rocket-chat {
 			.flex-opened {
 				left: 0;
 				right: @rooms-box-width;
+
+				.flex-tab {
+					.transform(translateX(calc(~'100% + 40px')));
+				}
 			}
 		}
 	}
+
 	@media all and(max-width: 780px) {
 		#rocket-chat {
 			.main-content {
 				right: 0;
 			}
+
 			.fixed-title h2 {
 				margin-right: 45px;
 			}
-			&.menu-opened {
-				.burger {
-					i {
-						&:nth-child(1) {
-							.transform(translateY(3px) rotate(45deg));
-						}
-						&:nth-child(3) {
-							.transform(translateY(-3px) rotate(-45deg));
-						}
-					}
-				}
-				.main-content {
-					.transform(translateX(-@rooms-box-width));
-				}
-			}
 		}
 	}
+
 	.burger {
 		.margin-right(7px);
-		.right(0px);
+		.right(0);
+
 		.unread-burger-alert {
 			.left(4px);
 		}
+
+		&.menu-opened {
+			i {
+				&:nth-child(1) {
+					.transform(translate(25%, 3px) rotate(45deg) scale(0.5, 1));
+				}
+
+				&:nth-child(3) {
+					.transform(translate(25%, -3px) rotate(-45deg) scale(0.5, 1));
+				}
+			}
+		}
 	}
+
 	.arrow {
-		&:before,
-		&:after {
+		&::before,
+		&::after {
 			.calc(right, ~"50% - 5px");
 		}
-		&:before {
+
+		&::before {
 			.transform(rotate(135deg) translateX(4px));
 		}
-		&:after {
+
+		&::after {
 			.transform(rotate(-135deg) translateX(4px));
 		}
+
 		&.left {
-			&:before {
+			&::before {
 				.transform(rotate(-45deg) translateY(-4px));
 			}
-			&:after {
+
+			&::after {
 				.transform(rotate(45deg) translateY(4px));
 			}
 		}
+
 		&.top {
-			&:before {
+			&::before {
 				.transform(rotate(45deg) translateX(-2px) translateY(2px));
 			}
-			&:after {
+
+			&::after {
 				.transform(rotate(-45deg) translateX(2px) translateY(2px));
 			}
 		}
+
 		&.bottom {
-			&:before {
+			&::before {
 				.transform(rotate(-45deg) translateX(-2px) translateY(-2px));
 			}
-			&:after {
+
+			&::after {
 				.transform(rotate(45deg) translateX(2px) translateY(-2px));
 			}
 		}
+
 		&.close {
-			&:before {
+			&::before {
 				.transform(rotate(-45deg));
 			}
-			&:after {
+
+			&::after {
 				.transform(rotate(45deg));
 			}
 		}
 	}
+
 	.message {
 		padding-left: 20px;
 		padding-right: 70px;
+
 		.message-dropdown {
 			.right(-2px);
+
 			ul {
 				li {
 					&:first-child {
 						padding-right: 6px;
 						padding-left: 8px;
-						border-left: 1px solid #eee;
+						border-left: 1px solid #eeeeee;
 						border-right: unset;
 					}
+
 					&:last-child {
 						padding-left: 13px;
 						padding-right: 8px;
@@ -504,81 +616,102 @@
 				}
 			}
 		}
+
 		.user {
 			margin-left: 5px;
 			margin-right: 0;
 		}
+
 		.thumb {
 			.right(20px);
 		}
+
 		.info {
 			.edited {
-				border-right: 1px dotted #BAB8B8;
+				border-right: 1px dotted #bab8d8;
 				border-left: unset;
 				.padding-right(3px);
 				.margin-right(3px);
 			}
 		}
+
 		.private {
-			.margin-right(10px); //
+			.margin-right(10px);
+			//
 		}
+
 		&.sequential {
 			padding-top: 4px;
+
 			.info {
 				text-align: left;
 				.right(5px);
+
 				.edited {
 					border-right: 0;
 					.margin-right(0);
 					.padding-right(0);
 				}
+
 				.message-action {
-					float: right; //
-					.margin-right(1px); //
+					float: right;
+					//
+					.margin-right(1px);
+					//
 				}
 			}
 		}
 	}
+
 	blockquote {
 		.padding-right(10px);
-		&:before {
-			.right(0px);
+
+		&::before {
+			.right(0);
 		}
 	}
+
 	.first-unread {
 		.body {
 			&::before {
 				right: 20px;
-				left: 0px;
+				left: 0;
 			}
+
 			&::after {
-				.left(0px);
+				.left(0);
 			}
 		}
 	}
+
 	.ticks-bar {
 		.left(2px);
 	}
+
 	.fixed-title {
 		padding: 0 20px 0 10px;
 		.right(0);
 	}
+
 	.list-view {
 		> .title {
 			.see-all {
 				float: left;
 			}
 		}
+
 		&.uploaded-files-list {
 			a {
 				direction: ltr;
 			}
+
 			i {
 				float: right;
 				.margin-left(10px);
 			}
 		}
 	}
+
 	.page-list {
 		.list {
 			a {
@@ -588,10 +721,12 @@
 					}
 				}
 			}
+
 			.user-image {
 				float: left;
 				.margin-right(12px);
 			}
+
 			table {
 				thead {
 					th {
@@ -601,12 +736,14 @@
 			}
 		}
 	}
+
 	.statistics-table {
 		th,
 		td {
 			text-align: right;
 		}
 	}
+
 	.minicolors-theme-rocketchat {
 		.minicolors-swatch {
 			.right(1px);
@@ -614,14 +751,18 @@
 			border-width: 0 0 0 1px;
 		}
 	}
+
 	.code-mirror-box {
 		direction: ltr;
+
 		.buttons {
 			text-align: left;
 		}
+
 		&.code-mirror-box-fullscreen {
 			left: 40px;
 			right: 260px;
+
 			.title {
 				padding-right: 10px;
 				padding-left: unset;
@@ -629,6 +770,7 @@
 			}
 		}
 	}
+
 	@media all and (max-width: 780px) {
 		.code-mirror-box {
 			&.code-mirror-box-fullscreen {
@@ -636,40 +778,49 @@
 			}
 		}
 	}
+
 	.rocket-form {
 		legend {
-			&:after {
+			&::after {
 				right: 0;
 			}
 		}
+
 		.logoutOthers {
 			text-align: left;
 		}
+
 		.submit {
 			text-align: left;
 		}
 	}
+
 	/* Overridding classes from swipebox.min.css */
 	#swipebox-close {
 		.left(0);
 	}
-	@media screen and (min-width:800px) {
+
+	@media screen and (min-width: 800px) {
 		#swipebox-close {
 			.left(10px);
 		}
 	}
+
 	#swipebox-overlay {
 		direction: ltr;
 	}
+
 	/* Override toastr messages to show on hte left side */
 	.toast-top-right {
 		.left(12px);
 	}
+
 	.spotlight {
 		> .spotlight-input {
 			.icon-search {
 				left: 0;
 			}
+
 			.message-popup {
 				.popup-item {
 					span {
diff --git a/packages/rocketchat-theme/assets/stylesheets/global/_variables.less b/packages/rocketchat-theme/client/imports/variables.less
similarity index 100%
rename from packages/rocketchat-theme/assets/stylesheets/global/_variables.less
rename to packages/rocketchat-theme/client/imports/variables.less
diff --git a/packages/rocketchat-theme/client/main.less b/packages/rocketchat-theme/client/main.less
new file mode 100644
index 0000000000000000000000000000000000000000..75a37e24dc40e5a209446ee79cf97bcac87932a7
--- /dev/null
+++ b/packages/rocketchat-theme/client/main.less
@@ -0,0 +1,7 @@
+@import "imports/variables.less";
+@import "imports/reset.less";
+@import "imports/lesshat.less";
+@import "imports/keyframes.less";
+@import "imports/rtl.less";
+@import "imports/forms.less";
+@import "imports/base.less";
diff --git a/packages/rocketchat-theme/client/minicolors/jquery.minicolors.css b/packages/rocketchat-theme/client/minicolors/jquery.minicolors.css
deleted file mode 100644
index 47dffa5ecfa603362a4a37a14a8a51155ff7a36c..0000000000000000000000000000000000000000
--- a/packages/rocketchat-theme/client/minicolors/jquery.minicolors.css
+++ /dev/null
@@ -1,278 +0,0 @@
-.minicolors {
-    position: relative;
-}
-
-.minicolors-sprite {
-    background-image: url(data:image/png;base64,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);
-}
-
-.minicolors-no-data-uris .minicolors-sprite {
-    background-image: url(jquery.minicolors.png);
-}
-
-.minicolors-swatch {
-    position: absolute;
-    vertical-align: middle;
-    background-position: -80px 0;
-    border: solid 1px #ccc;
-    cursor: text;
-    padding: 0;
-    margin: 0;
-    display: inline-block;
-}
-
-.minicolors-swatch-color {
-    position: absolute;
-    top: 0;
-    left: 0;
-    right: 0;
-    bottom: 0;
-}
-
-.minicolors input[type=hidden] + .minicolors-swatch {
-    width: 28px;
-    position: static;
-    cursor: pointer;
-}
-
-.minicolors input[type=hidden][disabled] + .minicolors-swatch {
-    cursor: default;
-}
-
-/* Panel */
-.minicolors-panel {
-    position: absolute;
-    width: 173px;
-    height: 152px;
-    background: white;
-    border: solid 1px #CCC;
-    box-shadow: 0 0 20px rgba(0, 0, 0, .2);
-    z-index: 99999;
-    -moz-box-sizing: content-box;
-    -webkit-box-sizing: content-box;
-    box-sizing: content-box;
-    display: none;
-}
-
-.minicolors-panel.minicolors-visible {
-    display: block;
-}
-
-/* Panel positioning */
-.minicolors-position-top .minicolors-panel {
-    top: -154px;
-}
-
-.minicolors-position-right .minicolors-panel {
-    right: 0;
-}
-
-.minicolors-position-bottom .minicolors-panel {
-    top: auto;
-}
-
-.minicolors-position-left .minicolors-panel {
-    left: 0;
-}
-
-.minicolors-with-opacity .minicolors-panel {
-    width: 194px;
-}
-
-.minicolors .minicolors-grid {
-    position: absolute;
-    top: 1px;
-    left: 1px;
-    width: 150px;
-    height: 150px;
-    background-position: -120px 0;
-    cursor: crosshair;
-}
-
-.minicolors .minicolors-grid-inner {
-    position: absolute;
-    top: 0;
-    left: 0;
-    width: 150px;
-    height: 150px;
-}
-
-.minicolors-slider-saturation .minicolors-grid {
-    background-position: -420px 0;
-}
-
-.minicolors-slider-saturation .minicolors-grid-inner {
-    background-position: -270px 0;
-    background-image: inherit;
-}
-
-.minicolors-slider-brightness .minicolors-grid {
-    background-position: -570px 0;
-}
-
-.minicolors-slider-brightness .minicolors-grid-inner {
-    background-color: black;
-}
-
-.minicolors-slider-wheel .minicolors-grid {
-    background-position: -720px 0;
-}
-
-.minicolors-slider,
-.minicolors-opacity-slider {
-    position: absolute;
-    top: 1px;
-    left: 152px;
-    width: 20px;
-    height: 150px;
-    background-color: white;
-    background-position: 0 0;
-    cursor: row-resize;
-}
-
-.minicolors-slider-saturation .minicolors-slider {
-    background-position: -60px 0;
-}
-
-.minicolors-slider-brightness .minicolors-slider {
-    background-position: -20px 0;
-}
-
-.minicolors-slider-wheel .minicolors-slider {
-    background-position: -20px 0;
-}
-
-.minicolors-opacity-slider {
-    left: 173px;
-    background-position: -40px 0;
-    display: none;
-}
-
-.minicolors-with-opacity .minicolors-opacity-slider {
-    display: block;
-}
-
-/* Pickers */
-.minicolors-grid .minicolors-picker {
-    position: absolute;
-    top: 70px;
-    left: 70px;
-    width: 12px;
-    height: 12px;
-    border: solid 1px black;
-    border-radius: 10px;
-    margin-top: -6px;
-    margin-left: -6px;
-    background: none;
-}
-
-.minicolors-grid .minicolors-picker > div {
-    position: absolute;
-    top: 0;
-    left: 0;
-    width: 8px;
-    height: 8px;
-    border-radius: 8px;
-    border: solid 2px white;
-    -moz-box-sizing: content-box;
-    -webkit-box-sizing: content-box;
-    box-sizing: content-box;
-}
-
-.minicolors-picker {
-    position: absolute;
-    top: 0;
-    left: 0;
-    width: 18px;
-    height: 2px;
-    background: white;
-    border: solid 1px black;
-    margin-top: -2px;
-    -moz-box-sizing: content-box;
-    -webkit-box-sizing: content-box;
-    box-sizing: content-box;
-}
-
-/* Inline controls */
-.minicolors-inline {
-    display: inline-block;
-}
-
-.minicolors-inline .minicolors-input {
-    display: none !important;
-}
-
-.minicolors-inline .minicolors-panel {
-    position: relative;
-    top: auto;
-    left: auto;
-    box-shadow: none;
-    z-index: auto;
-    display: inline-block;
-}
-
-/* Default theme */
-.minicolors-theme-default .minicolors-swatch {
-    top: 5px;
-    left: 5px;
-    width: 18px;
-    height: 18px;
-}
-.minicolors-theme-default.minicolors-position-right .minicolors-swatch {
-    left: auto;
-    right: 5px;
-}
-.minicolors-theme-default.minicolors {
-    width: auto;
-    display: inline-block;
-}
-.minicolors-theme-default .minicolors-input {
-    height: 20px;
-    width: auto;
-    display: inline-block;
-    padding-left: 26px;
-}
-.minicolors-theme-default.minicolors-position-right .minicolors-input {
-    padding-right: 26px;
-    padding-left: inherit;
-}
-
-/* Bootstrap theme */
-.minicolors-theme-bootstrap .minicolors-swatch {
-    z-index: 2;
-    top: 3px;
-    left: 3px;
-    width: 28px;
-    height: 28px;
-    border-radius: 3px;
-}
-.minicolors-theme-bootstrap .minicolors-swatch-color {
-    border-radius: inherit;
-}
-.minicolors-theme-bootstrap.minicolors-position-right .minicolors-swatch {
-    left: auto;
-    right: 3px;
-}
-.minicolors-theme-bootstrap .minicolors-input {
-    float: none;
-    padding-left: 44px;
-}
-.minicolors-theme-bootstrap.minicolors-position-right .minicolors-input {
-    padding-right: 44px;
-    padding-left: 12px;
-}
-.minicolors-theme-bootstrap .minicolors-input.input-lg + .minicolors-swatch {
-    top: 4px;
-    left: 4px;
-    width: 37px;
-    height: 37px;
-    border-radius: 5px;
-}
-.minicolors-theme-bootstrap .minicolors-input.input-sm + .minicolors-swatch {
-    width: 24px;
-    height: 24px;
-}
-.input-group .minicolors-theme-bootstrap:not(:first-child) .minicolors-input {
-    border-top-left-radius: 0;
-    border-bottom-left-radius: 0;
-}
diff --git a/packages/rocketchat-theme/client/minicolors/jquery.minicolors.js b/packages/rocketchat-theme/client/minicolors/jquery.minicolors.js
deleted file mode 100644
index 671eb78e2e8f8b695956e5af2cdb1ca1a9bd9d44..0000000000000000000000000000000000000000
--- a/packages/rocketchat-theme/client/minicolors/jquery.minicolors.js
+++ /dev/null
@@ -1,1019 +0,0 @@
-/*
- * jQuery MiniColors: A tiny color picker built on jQuery
- *
- * Copyright: Cory LaViska for A Beautiful Site, LLC: http://www.abeautifulsite.net/
- *
- * Contribute: https://github.com/claviska/jquery-minicolors
- *
- * @license: http://opensource.org/licenses/MIT
- *
- */
-(function (factory) {
-    /* jshint ignore:start */
-        // Browser globals
-    factory(jQuery);
-    /* jshint ignore:end */
-}(function ($) {
-
-    // Defaults
-    $.minicolors = {
-        defaults: {
-            animationSpeed: 50,
-            animationEasing: 'swing',
-            change: null,
-            changeDelay: 0,
-            control: 'hue',
-            dataUris: true,
-            defaultValue: '',
-            format: 'hex',
-            hide: null,
-            hideSpeed: 100,
-            inline: false,
-            keywords: '',
-            letterCase: 'lowercase',
-            opacity: false,
-            position: 'bottom left',
-            show: null,
-            showSpeed: 100,
-            theme: 'default'
-        }
-    };
-
-    // Public methods
-    $.extend($.fn, {
-        minicolors: function(method, data) {
-
-            switch(method) {
-
-                // Destroy the control
-                case 'destroy':
-                    $(this).each( function() {
-                        destroy($(this));
-                    });
-                    return $(this);
-
-                // Hide the color picker
-                case 'hide':
-                    hide();
-                    return $(this);
-
-                // Get/set opacity
-                case 'opacity':
-                    // Getter
-                    if( data === undefined ) {
-                        // Getter
-                        return $(this).attr('data-opacity');
-                    } else {
-                        // Setter
-                        $(this).each( function() {
-                            updateFromInput($(this).attr('data-opacity', data));
-                        });
-                    }
-                    return $(this);
-
-                // Get an RGB(A) object based on the current color/opacity
-                case 'rgbObject':
-                    return rgbObject($(this), method === 'rgbaObject');
-
-                // Get an RGB(A) string based on the current color/opacity
-                case 'rgbString':
-                case 'rgbaString':
-                    return rgbString($(this), method === 'rgbaString');
-
-                // Get/set settings on the fly
-                case 'settings':
-                    if( data === undefined ) {
-                        return $(this).data('minicolors-settings');
-                    } else {
-                        // Setter
-                        $(this).each( function() {
-                            var settings = $(this).data('minicolors-settings') || {};
-                            destroy($(this));
-                            $(this).minicolors($.extend(true, settings, data));
-                        });
-                    }
-                    return $(this);
-
-                // Show the color picker
-                case 'show':
-                    show( $(this).eq(0) );
-                    return $(this);
-
-                // Get/set the hex color value
-                case 'value':
-                    if( data === undefined ) {
-                        // Getter
-                        return $(this).val();
-                    } else {
-                        // Setter
-                        $(this).each( function() {
-                            updateFromInput($(this).val(data));
-                        });
-                    }
-                    return $(this);
-
-                // Initializes the control
-                default:
-                    if( method !== 'create' ) data = method;
-                    $(this).each( function() {
-                        init($(this), data);
-                    });
-                    return $(this);
-
-            }
-
-        }
-    });
-
-    // Initialize input elements
-    function init(input, settings) {
-
-        var minicolors = $('<div class="minicolors" />'),
-            defaults = $.minicolors.defaults,
-            format = input.attr('data-format'),
-            keywords = input.attr('data-keywords'),
-            opacity = input.attr('data-opacity');
-
-        // Do nothing if already initialized
-        if( input.data('minicolors-initialized') ) return;
-
-        // Handle settings
-        settings = $.extend(true, {}, defaults, settings);
-
-        // The wrapper
-        minicolors
-            .addClass('minicolors-theme-' + settings.theme)
-            .toggleClass('minicolors-with-opacity', settings.opacity)
-            .toggleClass('minicolors-no-data-uris', settings.dataUris !== true);
-
-        // Custom positioning
-        if( settings.position !== undefined ) {
-            $.each(settings.position.split(' '), function() {
-                minicolors.addClass('minicolors-position-' + this);
-            });
-        }
-
-        // Input size
-        if( format === 'rgb' ) {
-            $input_size = opacity ? '25' : '20';
-        } else {
-            $input_size = keywords ? '11' : '7';
-        }
-
-        // The input
-        input
-            .addClass('minicolors-input')
-            .data('minicolors-initialized', false)
-            .data('minicolors-settings', settings)
-            .prop('size', $input_size)
-            .wrap(minicolors)
-            .after(
-                '<div class="minicolors-panel minicolors-slider-' + settings.control + '">' +
-                    '<div class="minicolors-slider minicolors-sprite">' +
-                        '<div class="minicolors-picker"></div>' +
-                    '</div>' +
-                    '<div class="minicolors-opacity-slider minicolors-sprite">' +
-                        '<div class="minicolors-picker"></div>' +
-                    '</div>' +
-                    '<div class="minicolors-grid minicolors-sprite">' +
-                        '<div class="minicolors-grid-inner"></div>' +
-                        '<div class="minicolors-picker"><div></div></div>' +
-                    '</div>' +
-                '</div>'
-            );
-
-        // The swatch
-        if( !settings.inline ) {
-            input.after('<span class="minicolors-swatch minicolors-sprite"><span class="minicolors-swatch-color"></span></span>');
-            input.next('.minicolors-swatch').on('click', function(event) {
-                event.preventDefault();
-                input.focus();
-            });
-        }
-
-        // Prevent text selection in IE
-        input.parent().find('.minicolors-panel').on('selectstart', function() { return false; }).end();
-
-        // Inline controls
-        if( settings.inline ) input.parent().addClass('minicolors-inline');
-
-        updateFromInput(input, false);
-
-        input.data('minicolors-initialized', true);
-
-    }
-
-    // Returns the input back to its original state
-    function destroy(input) {
-
-        var minicolors = input.parent();
-
-        // Revert the input element
-        input
-            .removeData('minicolors-initialized')
-            .removeData('minicolors-settings')
-            .removeProp('size')
-            .removeClass('minicolors-input');
-
-        // Remove the wrap and destroy whatever remains
-        minicolors.before(input).remove();
-
-    }
-
-    // Shows the specified dropdown panel
-    function show(input) {
-
-        var minicolors = input.parent(),
-            panel = minicolors.find('.minicolors-panel'),
-            settings = input.data('minicolors-settings');
-
-        // Do nothing if uninitialized, disabled, inline, or already open
-        if( !input.data('minicolors-initialized') ||
-            input.prop('disabled') ||
-            minicolors.hasClass('minicolors-inline') ||
-            minicolors.hasClass('minicolors-focus')
-        ) return;
-
-        hide();
-
-        minicolors.addClass('minicolors-focus');
-        panel
-            .stop(true, true)
-            .fadeIn(settings.showSpeed, function() {
-                if( settings.show ) settings.show.call(input.get(0));
-            });
-
-    }
-
-    // Hides all dropdown panels
-    function hide() {
-
-        $('.minicolors-focus').each( function() {
-
-            var minicolors = $(this),
-                input = minicolors.find('.minicolors-input'),
-                panel = minicolors.find('.minicolors-panel'),
-                settings = input.data('minicolors-settings');
-
-            panel.fadeOut(settings.hideSpeed, function() {
-                if( settings.hide ) settings.hide.call(input.get(0));
-                minicolors.removeClass('minicolors-focus');
-            });
-
-        });
-    }
-
-    // Moves the selected picker
-    function move(target, event, animate) {
-
-        var input = target.parents('.minicolors').find('.minicolors-input'),
-            settings = input.data('minicolors-settings'),
-            picker = target.find('[class$=-picker]'),
-            offsetX = target.offset().left,
-            offsetY = target.offset().top,
-            x = Math.round(event.pageX - offsetX),
-            y = Math.round(event.pageY - offsetY),
-            duration = animate ? settings.animationSpeed : 0,
-            wx, wy, r, phi;
-
-        // Touch support
-        if( event.originalEvent.changedTouches ) {
-            x = event.originalEvent.changedTouches[0].pageX - offsetX;
-            y = event.originalEvent.changedTouches[0].pageY - offsetY;
-        }
-
-        // Constrain picker to its container
-        if( x < 0 ) x = 0;
-        if( y < 0 ) y = 0;
-        if( x > target.width() ) x = target.width();
-        if( y > target.height() ) y = target.height();
-
-        // Constrain color wheel values to the wheel
-        if( target.parent().is('.minicolors-slider-wheel') && picker.parent().is('.minicolors-grid') ) {
-            wx = 75 - x;
-            wy = 75 - y;
-            r = Math.sqrt(wx * wx + wy * wy);
-            phi = Math.atan2(wy, wx);
-            if( phi < 0 ) phi += Math.PI * 2;
-            if( r > 75 ) {
-                r = 75;
-                x = 75 - (75 * Math.cos(phi));
-                y = 75 - (75 * Math.sin(phi));
-            }
-            x = Math.round(x);
-            y = Math.round(y);
-        }
-
-        // Move the picker
-        if( target.is('.minicolors-grid') ) {
-            picker
-                .stop(true)
-                .animate({
-                    top: y + 'px',
-                    left: x + 'px'
-                }, duration, settings.animationEasing, function() {
-                    updateFromControl(input, target);
-                });
-        } else {
-            picker
-                .stop(true)
-                .animate({
-                    top: y + 'px'
-                }, duration, settings.animationEasing, function() {
-                    updateFromControl(input, target);
-                });
-        }
-
-    }
-
-    // Sets the input based on the color picker values
-    function updateFromControl(input, target) {
-
-        function getCoords(picker, container) {
-
-            var left, top;
-            if( !picker.length || !container ) return null;
-            left = picker.offset().left;
-            top = picker.offset().top;
-
-            return {
-                x: left - container.offset().left + (picker.outerWidth() / 2),
-                y: top - container.offset().top + (picker.outerHeight() / 2)
-            };
-
-        }
-
-        var hue, saturation, brightness, x, y, r, phi,
-
-            hex = input.val(),
-            format = input.attr('data-format'),
-            keywords = input.attr('data-keywords'),
-            opacity = input.attr('data-opacity'),
-
-            // Helpful references
-            minicolors = input.parent(),
-            settings = input.data('minicolors-settings'),
-            swatch = minicolors.find('.minicolors-swatch'),
-
-            // Panel objects
-            grid = minicolors.find('.minicolors-grid'),
-            slider = minicolors.find('.minicolors-slider'),
-            opacitySlider = minicolors.find('.minicolors-opacity-slider'),
-
-            // Picker objects
-            gridPicker = grid.find('[class$=-picker]'),
-            sliderPicker = slider.find('[class$=-picker]'),
-            opacityPicker = opacitySlider.find('[class$=-picker]'),
-
-            // Picker positions
-            gridPos = getCoords(gridPicker, grid),
-            sliderPos = getCoords(sliderPicker, slider),
-            opacityPos = getCoords(opacityPicker, opacitySlider);
-
-        // Handle colors
-        if( target.is('.minicolors-grid, .minicolors-slider, .minicolors-opacity-slider') ) {
-
-            // Determine HSB values
-            switch(settings.control) {
-
-                case 'wheel':
-                    // Calculate hue, saturation, and brightness
-                    x = (grid.width() / 2) - gridPos.x;
-                    y = (grid.height() / 2) - gridPos.y;
-                    r = Math.sqrt(x * x + y * y);
-                    phi = Math.atan2(y, x);
-                    if( phi < 0 ) phi += Math.PI * 2;
-                    if( r > 75 ) {
-                        r = 75;
-                        gridPos.x = 69 - (75 * Math.cos(phi));
-                        gridPos.y = 69 - (75 * Math.sin(phi));
-                    }
-                    saturation = keepWithin(r / 0.75, 0, 100);
-                    hue = keepWithin(phi * 180 / Math.PI, 0, 360);
-                    brightness = keepWithin(100 - Math.floor(sliderPos.y * (100 / slider.height())), 0, 100);
-                    hex = hsb2hex({
-                        h: hue,
-                        s: saturation,
-                        b: brightness
-                    });
-
-                    // Update UI
-                    slider.css('backgroundColor', hsb2hex({ h: hue, s: saturation, b: 100 }));
-                    break;
-
-                case 'saturation':
-                    // Calculate hue, saturation, and brightness
-                    hue = keepWithin(parseInt(gridPos.x * (360 / grid.width()), 10), 0, 360);
-                    saturation = keepWithin(100 - Math.floor(sliderPos.y * (100 / slider.height())), 0, 100);
-                    brightness = keepWithin(100 - Math.floor(gridPos.y * (100 / grid.height())), 0, 100);
-                    hex = hsb2hex({
-                        h: hue,
-                        s: saturation,
-                        b: brightness
-                    });
-
-                    // Update UI
-                    slider.css('backgroundColor', hsb2hex({ h: hue, s: 100, b: brightness }));
-                    minicolors.find('.minicolors-grid-inner').css('opacity', saturation / 100);
-                    break;
-
-                case 'brightness':
-                    // Calculate hue, saturation, and brightness
-                    hue = keepWithin(parseInt(gridPos.x * (360 / grid.width()), 10), 0, 360);
-                    saturation = keepWithin(100 - Math.floor(gridPos.y * (100 / grid.height())), 0, 100);
-                    brightness = keepWithin(100 - Math.floor(sliderPos.y * (100 / slider.height())), 0, 100);
-                    hex = hsb2hex({
-                        h: hue,
-                        s: saturation,
-                        b: brightness
-                    });
-
-                    // Update UI
-                    slider.css('backgroundColor', hsb2hex({ h: hue, s: saturation, b: 100 }));
-                    minicolors.find('.minicolors-grid-inner').css('opacity', 1 - (brightness / 100));
-                    break;
-
-                default:
-                    // Calculate hue, saturation, and brightness
-                    hue = keepWithin(360 - parseInt(sliderPos.y * (360 / slider.height()), 10), 0, 360);
-                    saturation = keepWithin(Math.floor(gridPos.x * (100 / grid.width())), 0, 100);
-                    brightness = keepWithin(100 - Math.floor(gridPos.y * (100 / grid.height())), 0, 100);
-                    hex = hsb2hex({
-                        h: hue,
-                        s: saturation,
-                        b: brightness
-                    });
-
-                    // Update UI
-                    grid.css('backgroundColor', hsb2hex({ h: hue, s: 100, b: 100 }));
-                    break;
-
-            }
-
-            // Handle opacity
-            if( settings.opacity ) {
-                opacity = parseFloat(1 - (opacityPos.y / opacitySlider.height())).toFixed(2);
-            } else {
-                opacity = 1;
-            }
-            if( settings.opacity ) input.attr('data-opacity', opacity);
-
-            // Set color string
-            if( format === 'rgb' ) {
-                // Returns RGB(A) string
-                var rgb = hex2rgb(hex),
-                    opacity = input.attr('data-opacity') === '' ? 1 : keepWithin( parseFloat( input.attr('data-opacity') ).toFixed(2), 0, 1 );
-                if( isNaN( opacity ) ) opacity = 1;
-
-                if( input.minicolors('rgbObject').a < 1 && rgb ) {
-                    // Set RGBA string if alpha
-                    value = 'rgba(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ', ' + parseFloat( opacity ) + ')';
-                } else {
-                    // Set RGB string (alpha = 1)
-                    value = 'rgb(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ')';
-                }
-            } else {
-                // Returns hex color
-                value = convertCase( hex, settings.letterCase );
-            }
-
-            // Update value from picker
-            input.val( value );
-        }
-
-        // Set swatch color
-        swatch.find('span').css({
-            backgroundColor: hex,
-            opacity: opacity
-        });
-
-        // Handle change event
-        doChange(input, value, opacity);
-
-    }
-
-    // Sets the color picker values from the input
-    function updateFromInput(input, preserveInputValue) {
-
-        var hex,
-            hsb,
-            format = input.attr('data-format'),
-            keywords = input.attr('data-keywords'),
-            opacity,
-            x, y, r, phi,
-
-            // Helpful references
-            minicolors = input.parent(),
-            settings = input.data('minicolors-settings'),
-            swatch = minicolors.find('.minicolors-swatch'),
-
-            // Panel objects
-            grid = minicolors.find('.minicolors-grid'),
-            slider = minicolors.find('.minicolors-slider'),
-            opacitySlider = minicolors.find('.minicolors-opacity-slider'),
-
-            // Picker objects
-            gridPicker = grid.find('[class$=-picker]'),
-            sliderPicker = slider.find('[class$=-picker]'),
-            opacityPicker = opacitySlider.find('[class$=-picker]');
-
-        // Determine hex/HSB values
-        if( isRgb(input.val()) ) {
-            // If input value is a rgb(a) string, convert it to hex color and update opacity
-            hex = rgbString2hex(input.val());
-            alpha = keepWithin(parseFloat(getAlpha(input.val())).toFixed(2), 0, 1);
-            if( alpha ) {
-                input.attr('data-opacity', alpha);
-            }
-        } else {
-            hex = convertCase(parseHex(input.val(), true), settings.letterCase);
-        }
-
-        if( !hex ){
-            hex = convertCase(parseInput(settings.defaultValue, true), settings.letterCase);
-        }
-        hsb = hex2hsb(hex);
-
-        // Get array of lowercase keywords
-        keywords = !keywords ? [] : $.map(keywords.split(','), function(a) {
-            return $.trim(a.toLowerCase());
-        });
-
-        // Set color string
-        if( input.val() !== '' && $.inArray(input.val().toLowerCase(), keywords) > -1 ) {
-            value = convertCase(input.val());
-        } else {
-            value = isRgb(input.val()) ? parseRgb(input.val()) : hex;
-        }
-
-        // Update input value
-        if( !preserveInputValue ) input.val(value);
-
-        // Determine opacity value
-        if( settings.opacity ) {
-            // Get from data-opacity attribute and keep within 0-1 range
-            opacity = input.attr('data-opacity') === '' ? 1 : keepWithin(parseFloat(input.attr('data-opacity')).toFixed(2), 0, 1);
-            if( isNaN(opacity) ) opacity = 1;
-            input.attr('data-opacity', opacity);
-            swatch.find('span').css('opacity', opacity);
-
-            // Set opacity picker position
-            y = keepWithin(opacitySlider.height() - (opacitySlider.height() * opacity), 0, opacitySlider.height());
-            opacityPicker.css('top', y + 'px');
-        }
-
-        // Set opacity to zero if input value is transparent
-        if( input.val().toLowerCase() === 'transparent' ) {
-            swatch.find('span').css('opacity', 0);
-        }
-
-        // Update swatch
-        swatch.find('span').css('backgroundColor', hex);
-
-        // Determine picker locations
-        switch(settings.control) {
-
-            case 'wheel':
-                // Set grid position
-                r = keepWithin(Math.ceil(hsb.s * 0.75), 0, grid.height() / 2);
-                phi = hsb.h * Math.PI / 180;
-                x = keepWithin(75 - Math.cos(phi) * r, 0, grid.width());
-                y = keepWithin(75 - Math.sin(phi) * r, 0, grid.height());
-                gridPicker.css({
-                    top: y + 'px',
-                    left: x + 'px'
-                });
-
-                // Set slider position
-                y = 150 - (hsb.b / (100 / grid.height()));
-                if( hex === '' ) y = 0;
-                sliderPicker.css('top', y + 'px');
-
-                // Update panel color
-                slider.css('backgroundColor', hsb2hex({ h: hsb.h, s: hsb.s, b: 100 }));
-                break;
-
-            case 'saturation':
-                // Set grid position
-                x = keepWithin((5 * hsb.h) / 12, 0, 150);
-                y = keepWithin(grid.height() - Math.ceil(hsb.b / (100 / grid.height())), 0, grid.height());
-                gridPicker.css({
-                    top: y + 'px',
-                    left: x + 'px'
-                });
-
-                // Set slider position
-                y = keepWithin(slider.height() - (hsb.s * (slider.height() / 100)), 0, slider.height());
-                sliderPicker.css('top', y + 'px');
-
-                // Update UI
-                slider.css('backgroundColor', hsb2hex({ h: hsb.h, s: 100, b: hsb.b }));
-                minicolors.find('.minicolors-grid-inner').css('opacity', hsb.s / 100);
-                break;
-
-            case 'brightness':
-                // Set grid position
-                x = keepWithin((5 * hsb.h) / 12, 0, 150);
-                y = keepWithin(grid.height() - Math.ceil(hsb.s / (100 / grid.height())), 0, grid.height());
-                gridPicker.css({
-                    top: y + 'px',
-                    left: x + 'px'
-                });
-
-                // Set slider position
-                y = keepWithin(slider.height() - (hsb.b * (slider.height() / 100)), 0, slider.height());
-                sliderPicker.css('top', y + 'px');
-
-                // Update UI
-                slider.css('backgroundColor', hsb2hex({ h: hsb.h, s: hsb.s, b: 100 }));
-                minicolors.find('.minicolors-grid-inner').css('opacity', 1 - (hsb.b / 100));
-                break;
-
-            default:
-                // Set grid position
-                x = keepWithin(Math.ceil(hsb.s / (100 / grid.width())), 0, grid.width());
-                y = keepWithin(grid.height() - Math.ceil(hsb.b / (100 / grid.height())), 0, grid.height());
-                gridPicker.css({
-                    top: y + 'px',
-                    left: x + 'px'
-                });
-
-                // Set slider position
-                y = keepWithin(slider.height() - (hsb.h / (360 / slider.height())), 0, slider.height());
-                sliderPicker.css('top', y + 'px');
-
-                // Update panel color
-                grid.css('backgroundColor', hsb2hex({ h: hsb.h, s: 100, b: 100 }));
-                break;
-
-        }
-
-        // Fire change event, but only if minicolors is fully initialized
-        if( input.data('minicolors-initialized') ) {
-            doChange(input, value, opacity);
-        }
-
-    }
-
-    // Runs the change and changeDelay callbacks
-    function doChange(input, value, opacity) {
-
-        var settings = input.data('minicolors-settings'),
-            lastChange = input.data('minicolors-lastChange');
-
-        // Only run if it actually changed
-        if( !lastChange || lastChange.value !== value || lastChange.opacity !== opacity ) {
-
-            // Remember last-changed value
-            input.data('minicolors-lastChange', {
-                value: value,
-                opacity: opacity
-            });
-
-            // Fire change event
-            if( settings.change ) {
-                if( settings.changeDelay ) {
-                    // Call after a delay
-                    clearTimeout(input.data('minicolors-changeTimeout'));
-                    input.data('minicolors-changeTimeout', setTimeout( function() {
-                        settings.change.call(input.get(0), value, opacity);
-                    }, settings.changeDelay));
-                } else {
-                    // Call immediately
-                    settings.change.call(input.get(0), value, opacity);
-                }
-            }
-            input.trigger('change').trigger('input');
-        }
-
-    }
-
-    // Generates an RGB(A) object based on the input's value
-    function rgbObject(input) {
-        var hex = parseHex($(input).val(), true),
-            rgb = hex2rgb(hex),
-            opacity = $(input).attr('data-opacity');
-        if( !rgb ) return null;
-        if( opacity !== undefined ) $.extend(rgb, { a: parseFloat(opacity) });
-        return rgb;
-    }
-
-    // Generates an RGB(A) string based on the input's value
-    function rgbString(input, alpha) {
-        var hex = parseHex($(input).val(), true),
-            rgb = hex2rgb(hex),
-            opacity = $(input).attr('data-opacity');
-        if( !rgb ) return null;
-        if( opacity === undefined ) opacity = 1;
-        if( alpha ) {
-            return 'rgba(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ', ' + parseFloat(opacity) + ')';
-        } else {
-            return 'rgb(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ')';
-        }
-    }
-
-    // Converts to the letter case specified in settings
-    function convertCase(string, letterCase) {
-        return letterCase === 'uppercase' ? string.toUpperCase() : string.toLowerCase();
-    }
-
-    // Parses a string and returns a valid hex string when possible
-    function parseHex(string, expand) {
-        string = string.replace(/^#/g, '');
-        if( !string.match(/^[A-F0-9]{3,6}/ig) ) return '';
-        if( string.length !== 3 && string.length !== 6 ) return '';
-        if( string.length === 3 && expand ) {
-            string = string[0] + string[0] + string[1] + string[1] + string[2] + string[2];
-        }
-        return '#' + string;
-    }
-
-    // Parses a string and returns a valid RGB(A) string when possible
-    function parseRgb(string, obj) {
-
-        var values = string.replace(/[^\d,.]/g, ''),
-            rgba = values.split(','),
-            output;
-
-        rgba[0] = keepWithin(parseInt(rgba[0], 10), 0, 255);
-        rgba[1] = keepWithin(parseInt(rgba[1], 10), 0, 255);
-        rgba[2] = keepWithin(parseInt(rgba[2], 10), 0, 255);
-        if( rgba[3] ) {
-            rgba[3] = keepWithin(parseFloat(rgba[3], 10), 0, 1);
-        }
-
-        // Return RGBA object
-        if( obj ) {
-            return {
-                r: rgba[0],
-                g: rgba[1],
-                b: rgba[2],
-                a: rgba[3] ? rgba[3] : null
-            };
-        }
-
-        // Return RGBA string
-        if( rgba[3] ) {
-            return 'rgba(' + rgba[0] + ', ' + rgba[1] + ', ' + rgba[2] + ', ' + rgba[3] + ')';
-        } else {
-            return 'rgb(' + rgba[0] + ', ' + rgba[1] + ', ' + rgba[2] + ')';
-        }
-
-    }
-
-    // Parses a string and returns a valid color string when possible
-    function parseInput(string, expand) {
-        if( isRgb(string) ) {
-            // Returns a valid rgb(a) string
-            return parseRgb(string);
-        } else {
-            return parseHex(string, expand);
-        }
-    }
-
-    // Keeps value within min and max
-    function keepWithin(value, min, max) {
-        if( value < min ) value = min;
-        if( value > max ) value = max;
-        return value;
-    }
-
-    // Checks if a string is a valid RGB(A) string
-    function isRgb(string) {
-        rgb = string.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);
-        return (rgb && rgb.length === 4) ? true : false;
-    }
-
-    // Function to get alpha from a RGB(A) string
-    function getAlpha(rgba) {
-        rgba = rgba.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+(\.\d{1,2})?|\.\d{1,2})[\s+]?/i);
-        return (rgba && rgba.length === 6) ? rgba[4] : '1';
-    }
-
-   // Converts an HSB object to an RGB object
-    function hsb2rgb(hsb) {
-        var rgb = {};
-        var h = Math.round(hsb.h);
-        var s = Math.round(hsb.s * 255 / 100);
-        var v = Math.round(hsb.b * 255 / 100);
-        if(s === 0) {
-            rgb.r = rgb.g = rgb.b = v;
-        } else {
-            var t1 = v;
-            var t2 = (255 - s) * v / 255;
-            var t3 = (t1 - t2) * (h % 60) / 60;
-            if( h === 360 ) h = 0;
-            if( h < 60 ) { rgb.r = t1; rgb.b = t2; rgb.g = t2 + t3; }
-            else if( h < 120 ) {rgb.g = t1; rgb.b = t2; rgb.r = t1 - t3; }
-            else if( h < 180 ) {rgb.g = t1; rgb.r = t2; rgb.b = t2 + t3; }
-            else if( h < 240 ) {rgb.b = t1; rgb.r = t2; rgb.g = t1 - t3; }
-            else if( h < 300 ) {rgb.b = t1; rgb.g = t2; rgb.r = t2 + t3; }
-            else if( h < 360 ) {rgb.r = t1; rgb.g = t2; rgb.b = t1 - t3; }
-            else { rgb.r = 0; rgb.g = 0; rgb.b = 0; }
-        }
-        return {
-            r: Math.round(rgb.r),
-            g: Math.round(rgb.g),
-            b: Math.round(rgb.b)
-        };
-    }
-
-    // Converts an RGB string to a hex string
-    function rgbString2hex(rgb){
-        rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);
-        return (rgb && rgb.length === 4) ? '#' +
-        ('0' + parseInt(rgb[1],10).toString(16)).slice(-2) +
-        ('0' + parseInt(rgb[2],10).toString(16)).slice(-2) +
-        ('0' + parseInt(rgb[3],10).toString(16)).slice(-2) : '';
-    }
-
-    // Converts an RGB object to a hex string
-    function rgb2hex(rgb) {
-        var hex = [
-            rgb.r.toString(16),
-            rgb.g.toString(16),
-            rgb.b.toString(16)
-        ];
-        $.each(hex, function(nr, val) {
-            if (val.length === 1) hex[nr] = '0' + val;
-        });
-        return '#' + hex.join('');
-    }
-
-    // Converts an HSB object to a hex string
-    function hsb2hex(hsb) {
-        return rgb2hex(hsb2rgb(hsb));
-    }
-
-    // Converts a hex string to an HSB object
-    function hex2hsb(hex) {
-        var hsb = rgb2hsb(hex2rgb(hex));
-        if( hsb.s === 0 ) hsb.h = 360;
-        return hsb;
-    }
-
-    // Converts an RGB object to an HSB object
-    function rgb2hsb(rgb) {
-        var hsb = { h: 0, s: 0, b: 0 };
-        var min = Math.min(rgb.r, rgb.g, rgb.b);
-        var max = Math.max(rgb.r, rgb.g, rgb.b);
-        var delta = max - min;
-        hsb.b = max;
-        hsb.s = max !== 0 ? 255 * delta / max : 0;
-        if( hsb.s !== 0 ) {
-            if( rgb.r === max ) {
-                hsb.h = (rgb.g - rgb.b) / delta;
-            } else if( rgb.g === max ) {
-                hsb.h = 2 + (rgb.b - rgb.r) / delta;
-            } else {
-                hsb.h = 4 + (rgb.r - rgb.g) / delta;
-            }
-        } else {
-            hsb.h = -1;
-        }
-        hsb.h *= 60;
-        if( hsb.h < 0 ) {
-            hsb.h += 360;
-        }
-        hsb.s *= 100/255;
-        hsb.b *= 100/255;
-        return hsb;
-    }
-
-    // Converts a hex string to an RGB object
-    function hex2rgb(hex) {
-        hex = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16);
-        return {
-            /* jshint ignore:start */
-            r: hex >> 16,
-            g: (hex & 0x00FF00) >> 8,
-            b: (hex & 0x0000FF)
-            /* jshint ignore:end */
-        };
-    }
-
-    // Handle events
-    $(document)
-        // Hide on clicks outside of the control
-        .on('mousedown.minicolors touchstart.minicolors', function(event) {
-            if( !$(event.target).parents().add(event.target).hasClass('minicolors') ) {
-                hide();
-            }
-        })
-        // Start moving
-        .on('mousedown.minicolors touchstart.minicolors', '.minicolors-grid, .minicolors-slider, .minicolors-opacity-slider', function(event) {
-            var target = $(this);
-            event.preventDefault();
-            $(document).data('minicolors-target', target);
-            move(target, event, true);
-        })
-        // Move pickers
-        .on('mousemove.minicolors touchmove.minicolors', function(event) {
-            var target = $(document).data('minicolors-target');
-            if( target ) move(target, event);
-        })
-        // Stop moving
-        .on('mouseup.minicolors touchend.minicolors', function() {
-            $(this).removeData('minicolors-target');
-        })
-        // Show panel when swatch is clicked
-        .on('mousedown.minicolors touchstart.minicolors', '.minicolors-swatch', function(event) {
-            var input = $(this).parent().find('.minicolors-input');
-            event.preventDefault();
-            show(input);
-        })
-        // Show on focus
-        .on('focus.minicolors', '.minicolors-input', function() {
-            var input = $(this);
-            if( !input.data('minicolors-initialized') ) return;
-            show(input);
-        })
-        // Update value on blur
-        .on('blur.minicolors', '.minicolors-input', function() {
-            var input = $(this),
-                keywords = input.attr('data-keywords'),
-                settings = input.data('minicolors-settings'),
-                hex,
-                rgba,
-                swatchOpacity;
-
-            if( !input.data('minicolors-initialized') ) return;
-
-            // Get array of lowercase keywords
-            keywords = !keywords ? [] : $.map(keywords.split(','), function(a) {
-                return $.trim(a.toLowerCase());
-            });
-
-            // Set color string
-            if( input.val() !== '' && $.inArray(input.val().toLowerCase(), keywords) > -1 ) {
-                value = input.val();
-            } else {
-                // Get RGBA values for easy conversion
-                if( isRgb(input.val()) ) {
-                    rgba = parseRgb(input.val(), true);
-                } else {
-                    hex = parseHex(input.val(), true);
-                    rgba = hex ? hex2rgb(hex) : null;
-                }
-
-                // Convert to format
-                if( rgba === null ) {
-                    value = settings.defaultValue;
-                } else if( settings.format === 'rgb' ) {
-                    value = settings.opacity ?
-                        parseRgb('rgba(' + rgba.r + ',' + rgba.g + ',' + rgba.b + ',' + input.attr('data-opacity') + ')') :
-                        parseRgb('rgb(' + rgba.r + ',' + rgba.g + ',' + rgba.b + ')');
-                } else {
-                    value = rgb2hex(rgba);
-                }
-            }
-
-            // Update swatch opacity
-            swatchOpacity = settings.opacity ? input.attr('data-opacity') : 1;
-            if( value.toLowerCase() === 'transparent' ) swatchOpacity = 0;
-            input
-                .closest('.minicolors')
-                .find('.minicolors-swatch > span')
-                .css('opacity', swatchOpacity);
-
-            // Set input value
-            input.val(value);
-
-            // Is it blank?
-            if( input.val() === '' ) input.val(parseInput(settings.defaultValue, true));
-
-            // Adjust case
-            input.val( convertCase(input.val(), settings.letterCase) );
-
-        })
-        // Handle keypresses
-        .on('keydown.minicolors', '.minicolors-input', function(event) {
-            var input = $(this);
-            if( !input.data('minicolors-initialized') ) return;
-            switch(event.keyCode) {
-                case 9: // tab
-                    hide();
-                    break;
-                case 13: // enter
-                case 27: // esc
-                    hide();
-                    input.blur();
-                    break;
-            }
-        })
-        // Update on keyup
-        .on('keyup.minicolors', '.minicolors-input', function() {
-            var input = $(this);
-            if( !input.data('minicolors-initialized') ) return;
-            updateFromInput(input, true);
-        })
-        // Update on paste
-        .on('paste.minicolors', '.minicolors-input', function() {
-            var input = $(this);
-            if( !input.data('minicolors-initialized') ) return;
-            setTimeout( function() {
-                updateFromInput(input, true);
-            }, 1);
-        });
-
-}));
diff --git a/packages/rocketchat-theme/assets/stylesheets/fontello.css b/packages/rocketchat-theme/client/vendor/fontello/css/fontello.css
old mode 100644
new mode 100755
similarity index 98%
rename from packages/rocketchat-theme/assets/stylesheets/fontello.css
rename to packages/rocketchat-theme/client/vendor/fontello/css/fontello.css
index a9ca191f95793fb2994bbb7fa7aa8c2d98d5879a..3da0e897da43fcca68192399ef4963f9f2690015
--- a/packages/rocketchat-theme/assets/stylesheets/fontello.css
+++ b/packages/rocketchat-theme/client/vendor/fontello/css/fontello.css
@@ -1,10 +1,11 @@
 @font-face {
   font-family: 'fontello';
-  src: url('fonts/fontello.eot?80104145');
-  src: url('fonts/fontello.eot?80104145#iefix') format('embedded-opentype'),
-       url('fonts/fontello.woff2?80104145') format('woff2'),
-       url('fonts/fontello.woff?80104145') format('woff'),
-       url('fonts/fontello.ttf?80104145') format('truetype');
+  src: url('../font/fontello.eot?90843248');
+  src: url('../font/fontello.eot?90843248#iefix') format('embedded-opentype'),
+       url('../font/fontello.woff2?90843248') format('woff2'),
+       url('../font/fontello.woff?90843248') format('woff'),
+       url('../font/fontello.ttf?90843248') format('truetype'),
+       url('../font/fontello.svg?90843248#fontello') format('svg');
   font-weight: normal;
   font-style: normal;
 }
@@ -14,7 +15,7 @@
 @media screen and (-webkit-min-device-pixel-ratio:0) {
   @font-face {
     font-family: 'fontello';
-    src: url('/fonts/fontello.svg?80104145#fontello') format('svg');
+    src: url('../font/fontello.svg?90843248#fontello') format('svg');
   }
 }
 */
diff --git a/public/fonts/fontello.html b/packages/rocketchat-theme/client/vendor/fontello/demo.html
similarity index 99%
rename from public/fonts/fontello.html
rename to packages/rocketchat-theme/client/vendor/fontello/demo.html
index 1d698b3978c2ebfb09d1ddf8c0803fe9224c73a0..1247bdf23e335b47fe7f355a6628331bb1e43ff1 100644
--- a/public/fonts/fontello.html
+++ b/packages/rocketchat-theme/client/vendor/fontello/demo.html
@@ -229,10 +229,10 @@ body {
 }
 @font-face {
       font-family: 'fontello';
-      src: url('./fontello.eot?87518418');
-      src: url('./fontello.eot?87518418#iefix') format('embedded-opentype'),
-           url('./fontello.woff?87518418') format('woff'),
-           url('./fontello.ttf?87518418') format('truetype');
+      src: url('./font/fontello.eot?87518418');
+      src: url('./font/fontello.eot?87518418#iefix') format('embedded-opentype'),
+           url('./font/fontello.woff?87518418') format('woff'),
+           url('./font/fontello.ttf?87518418') format('truetype');
       font-weight: normal;
       font-style: normal;
     }
diff --git a/public/fonts/fontello.eot b/packages/rocketchat-theme/client/vendor/fontello/font/fontello.eot
similarity index 100%
rename from public/fonts/fontello.eot
rename to packages/rocketchat-theme/client/vendor/fontello/font/fontello.eot
diff --git a/packages/rocketchat-theme/client/vendor/fontello/font/fontello.svg b/packages/rocketchat-theme/client/vendor/fontello/font/fontello.svg
new file mode 100755
index 0000000000000000000000000000000000000000..ba07cafa1d7b87cb2b56ad55d3dd46ccbee55b8b
--- /dev/null
+++ b/packages/rocketchat-theme/client/vendor/fontello/font/fontello.svg
@@ -0,0 +1,980 @@
+<?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="parking" unicode="&#x21;" d="M1096 504l-99 255c-19 49-59 91-135 91h-140-238-141c-76 0-117-42-136-91l-98-255c-40-5-109-51-109-138v-325h96v-104c0-127 181-126 181 0v104h325 325v-104c1-126 181-127 181 0v104h97v325c0 87-70 133-109 138z m-906-267c-47 0-84 39-84 86 0 48 37 86 84 86 46 0 83-38 83-86 0-47-37-86-83-86z m412 270h0-391l75 201c9 28 23 48 56 49h260 0 261c33-1 47-21 56-49l75-201h-392z m413-270c-46 0-84 39-84 86 0 48 38 86 84 86 46 0 83-38 84-86 0-47-38-86-84-86z" horiz-adv-x="1205" />
+
+<glyph glyph-name="bedroom" unicode="&#x22;" d="M292 361c0 75 61 135 135 135 75 0 135-60 135-135 0-74-60-135-135-135-74 0-135 61-135 135z m1123-135h-791v174c0 53 40 96 89 96h612c49 0 90-43 90-96v-174z m220 263v-559c0-32-26-58-58-58-16 0-31 6-41 17-10 10-17 25-17 41v96h-1300v-101c0-29-23-53-53-53-14 0-28 6-37 15-10 10-16 23-16 38v805c0 30 24 53 53 53 15 0 28-6 38-15 9-10 15-23 15-38v-607h1300v366c0 32 26 58 58 58 16 0 30-6 41-17s17-25 17-41z" horiz-adv-x="1644" />
+
+<glyph glyph-name="elevator" unicode="&#x23;" d="M974 850h-948c-14 0-26-12-26-26v-948c0-14 12-26 26-26h948c14 0 26 12 26 26v948c0 14-12 26-26 26z m-53-573c0 0 0 0 0 0h-92c-7 0-13 4-15 10-3 6-1 13 3 18l46 46c7 7 17 7 24 0l45-45c3-3 6-7 6-13 0-9-8-16-17-16z m12-79l-46-46c-4-4-8-5-12-5-4 0-8 1-12 5l-46 46c-4 4-6 11-3 18 2 6 8 10 15 10h92c7 0 13-4 15-10 3-7 1-14-3-18z m-683 402h224v-697h-224v697z m276-697v697h224v-697h-224z m-188 947c0 90 72 163 162 163 90 0 163-73 163-163" horiz-adv-x="1000" />
+
+<glyph glyph-name="kettle" unicode="&#x24;" d="M732 550c0 0 0 0 0 0-5 114-98 205-214 205-118 0-213-96-213-214v-61l-146 85h-99l245-245v-470h427v279h0c116 0 211 95 211 210 0 116-95 211-211 211z m0-354l0 0 0 287h0c79 0 144-65 144-144 0-79-65-143-144-143z m-214 654c27 0 48-21 48-47 0-27-21-48-48-48-26 0-47 21-47 48 0 26 21 47 47 47z" horiz-adv-x="1000" />
+
+<glyph glyph-name="pan" unicode="&#x25;" d="M106 587h792c18 0 33 15 33 33 0 19-15 33-33 33h-17c-47 44-182 76-345 80 6 8 10 17 10 28 0 24-20 44-44 44-25 0-45-20-45-44 0-11 4-20 10-28-163-4-298-36-344-80h-17c-18 0-33-14-33-33 0-18 15-33 33-33z m845-43h-898c-25 0-44-19-44-44 0-24 19-44 44-44h53v-443c0-61 49-110 110-110h572c60 0 110 49 110 110v443h53c24 0 44 20 44 44 0 25-20 44-44 44z" horiz-adv-x="1000" />
+
+<glyph glyph-name="tap" unicode="&#x26;" d="M870 224v-59h-270v59h32v138c0 22-18 39-39 39h-150v-38h-165v38h-148v207h148v37h53v121h-89c-20 0-37 16-37 36s16 36 37 36h237c20 0 36-16 36-36s-16-36-36-36h-89v-121h53v-37h189c114 0 206-93 206-207v-177h32z m-54-281c0-45-36-81-81-81-45 0-82 36-82 81 0 13 3 25 9 36 5 10 6 10 13 21 9 13 20 30 30 47 18 30 30 59 30 59s12-29 30-60c9-16 21-33 30-46 7-11 8-11 13-21 6-11 8-23 8-36z" horiz-adv-x="1000" />
+
+<glyph glyph-name="foxter" unicode="&#x27;" d="M500-140c-270 0-490 220-490 490 0 270 220 490 490 490 270 0 490-220 490-490 0-270-220-490-490-490l0 0z m0 917l0 0c-235 0-427-192-427-427 0-235 192-427 427-427 235 0 427 192 427 427 0 235-192 427-427 427z m-225-411c1 68-30 87-70 82-36-3-64-8-79-14-3-16-6-32-7-48 0-12-1-24-1-36 0-4 0-9 0-13 7-1 22-2 45-2 0-47 2-93 6-137-9 2-17 5-23 7 32-78 89-143 161-185-23 77-33 213-32 346z m498-273c5 1 10 2 14 4 15 16 28 34 40 54 4 37-13 43-42 38-56-8-129-14-206-16 2 49 2 104 3 159 142 0 269 2 297 4 1 1 2 1 3 1 0 4 0 9 0 13 0 12 0 24-1 36-1 16-4 32-7 48-45 17-200 26-359 26-57 0-94-22-94-93-1-177 6-358 21-396 7-1 15-2 23-2 11-1 23-1 35-1 12 0 24 0 35 1 9 0 17 1 25 3 6 15 11 51 14 100 73 3 142 10 199 21z m-263 482c125-1 249-12 321-32-25 42-58 80-96 110-51 7-108 12-167 14-3 30-7 52-11 62-7 1-14 2-21 2-12 1-24 1-36 1-12 0-24 0-36-1-9 0-18-2-26-3-6-13-10-43-13-83-4-50 30-71 85-70z m-218 59c3 16 6 31 10 44-55-33-101-80-133-135 13 4 27 7 42 10 39 6 72 31 81 81z" horiz-adv-x="1000" />
+
+<glyph glyph-name="left-circled2" unicode="&#x28;" d="M643 404v-108q0-7-5-12t-13-5h-196v-108q0-7-5-12t-13-5q-7 0-14 5l-178 178q-5 5-5 13t5 13l179 178q5 5 13 5 7 0 12-5t6-12v-108h196q7 0 13-5t5-12z m89-54q0 83-41 152t-110 111-152 41-153-41-110-111-41-152 41-152 110-111 153-41 152 41 110 111 41 152z m125 0q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="right-circled2" unicode="&#x29;" d="M643 350q0-8-5-13l-179-178q-5-5-13-5-7 0-12 5t-5 12v108h-197q-7 0-12 5t-6 12v108q0 7 6 12t12 5h197v108q0 7 5 12t12 5q7 0 14-5l178-178q5-5 5-13z m89 0q0 83-41 152t-110 111-152 41-153-41-110-111-41-152 41-152 110-111 153-41 152 41 110 111 41 152z m125 0q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="football" unicode="&#x2a;" d="M505 850c-278 0-505-225-505-501 0-276 227-501 505-501s506 225 506 501c0 276-227 501-506 501z m156-72c73-27 137-72 186-131 35-61 41-91 39-107l-139-51-150 95c-10 54-35 142-42 170 37 23 99 24 106 24z m-139-24l0 0c0-1 30-107 43-170l-135-111-217 32c0 0-13 58-13 104l0 0c1 1 77 122 203 161 0 0 74-3 119-16z m-216 5c-67-45-114-106-128-126-18-8-37-23-52-38 43 70 106 127 180 164z m-248-400c0 8 1 15 1 23 12-21 30-37 43-47 11-41 42-147 93-231-2-33 2-56 5-71-87 82-142 197-142 326z m165-240c-52 86-84 200-92 232 33 69 75 122 75 122l212-31c24-69 58-141 74-175-24-35-90-133-129-181-38-1-103 20-140 33z m282-207c-39 0-76 5-112 15 37 1 59 10 72 18 11-2 44-8 88-8 44 0 100 6 155 30 3-1 6-2 9-2-63-34-135-53-212-53z m200 88c-113-53-235-23-237-23l-9 5c-33 30-62 77-67 87 0 0 0 1-1 1 41 51 103 143 126 178 127 6 177 16 177 16 1-1 65-85 96-160-16-37-60-80-85-104z m205 184c-51-40-96-56-96-56-20 40-91 154-91 154 23 59 33 139 37 178l134 49c33-32 51-87 56-109 2-13 3-27 3-41 0-66-15-128-41-185 0 7-2 10-2 10z" horiz-adv-x="1008" />
+
+<glyph glyph-name="tennis" unicode="&#x2b;" d="M275 480c-41-71-106-119-178-140-2 72 15 145 53 212 39 67 94 118 157 152 18-73 9-153-32-224z m363-209c-57-99-68-211-39-312-98-25-206-13-301 41-94 55-159 142-186 240 102 26 194 91 250 189 57 99 68 211 39 312 98 25 206 13 301-41 95-55 159-142 186-240-102-26-194-91-250-189z m212-123c-39-66-94-118-157-152-18 73-9 153 32 224 41 71 106 119 179 140 1-72-16-145-54-212z" horiz-adv-x="1000" />
+
+<glyph glyph-name="chrome" unicode="&#x2c;" d="M498 850c-147-1-291-67-387-186l154-237c39 111 150 182 267 170l414-22c-42 84-108 157-196 208-79 46-166 67-252 67z m-416-226c-52-79-82-173-82-274 0-250 183-457 423-494l128 252c-116-22-233 39-281 146l-188 370z m885-94l-282-15c76-89 82-221 13-317l-226-347c94-6 190 15 278 66 216 125 304 387 217 613z m-467-11c-93 0-169-76-169-169s76-169 169-169 169 76 169 169-76 169-169 169z" horiz-adv-x="1000" />
+
+<glyph glyph-name="opera" unicode="&#x2d;" d="M426-150c-568 0-568 1000 0 1000s567-1000 0-1000z m0 92c237 0 237 816 0 816s-238-816 0-816z" horiz-adv-x="851" />
+
+<glyph glyph-name="crown" unicode="&#x2e;" d="M419 822c-39 0-71-32-71-72 0-40 32-72 71-72 39 0 74 32 74 72 0 40-35 72-74 72z m-48-222c-40-119-101-151-101-151s-52 145-109 231c-23-52-47-86-96-100-1-44 51-208 55-290l601 0c2 79 55 256 55 288-38 16-85 51-96 102-63-86-109-231-109-231s-61 32-101 151c-27-13-77-13-99 0z m-297 222c-40 0-74-32-74-72 0-40 34-72 74-72 39 0 70 32 70 72 0 40-31 72-70 72z m47-603l0-119 600 0c0 43 0 81 0 119z m644 603c-40 0-72-32-72-72 0-40 32-72 72-72 40 0 72 32 72 72 0 40-32 72-72 72z" horiz-adv-x="837" />
+
+<glyph glyph-name="ie" unicode="&#x2f;" d="M844 850c-81-1-181-46-281-106-239 35-498-103-509-386 60 93 224 257 367 301l0-13c-179-90-571-612-360-773 90-69 310 37 344 76 29-5 59-8 89-8 201 0 371 124 424 292l-301 0c-13-56-56-92-121-92-102 0-126 68-126 151l561 0c29 204-114 385-306 439 174 115 363 161 299-104l20 0c35 109 21 191-38 213-18 7-37 10-58 10-1 0-3 0-4 0z m-352-303c79 0 128-48 128-129l-252 0c0 77 46 129 124 129z m-367-422c58-83 149-145 256-171-77-58-226-84-266-52-48 40-36 124 10 223z" horiz-adv-x="944" />
+
+<glyph glyph-name="glass" unicode="&#x30;" d="M948 746q0-19-24-43l-353-353v-429h179q15 0 25-10t11-25-11-25-25-11h-500q-14 0-25 11t-11 25 11 25 25 10h179v429l-353 353q-24 24-24 43 0 13 10 21t21 9 24 3h786q13 0 24-3t21-9 10-21z" horiz-adv-x="1000" />
+
+<glyph glyph-name="music" unicode="&#x31;" d="M857 725v-625q0-28-19-50t-48-33-58-18-53-6-54 6-58 18-48 33-19 50 19 50 48 33 58 18 54 6q58 0 107-22v300l-429-132v-396q0-28-19-50t-48-33-58-18-53-6-54 6-58 18-48 33-19 50 19 50 48 34 58 17 54 6q58 0 107-21v539q0 17 10 32t28 20l464 142q7 3 16 3 22 0 38-16t15-38z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="search" unicode="&#x32;" d="M643 386q0 103-73 176t-177 74-177-74-73-176 73-177 177-73 177 73 73 177z m286-465q0-29-22-50t-50-21q-30 0-50 21l-191 191q-100-69-223-69-80 0-153 31t-125 84-84 125-31 153 31 152 84 126 125 84 153 31 153-31 125-84 84-126 31-152q0-123-69-223l191-191q21-21 21-51z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="360" unicode="&#x33;" d="M1068 458v-19c85-25 134-57 134-92 0-59-137-109-337-130v-88c255 26 436 98 436 182 0 59-88 112-233 147z m-703-76c-35 0-62 28-62 28l-36-58c0 0 36-40 104-40 76 0 112 52 112 104 0 42-28 78-73 88l63 71v45h-193v-62h72c20 0 31 2 31 2v-1c0 0-13-11-27-29l-41-48 16-37h21c33 0 57-9 57-33 0-17-16-30-44-30z m282-70c66 0 104 51 104 103 0 52-37 104-100 104-14 0-34-6-42-11h0c9 27 29 50 65 50 22 0 42-9 42-9l20 64c0 0-25 13-68 13-94 0-145-86-145-168 0-100 63-146 124-146z m-16 147c33 0 46-23 46-45 0-18-12-34-30-34-21 0-47 24-47 61 0 14 14 18 31 18z m387 11c0 87-28 156-115 156s-114-69-114-156c0-87 28-158 114-158s115 71 115 158z m-153 0c0 49 9 88 38 88s38-39 38-88c0-50-8-90-38-90s-38 40-38 90z m-235-264c-294 2-532 64-532 141 0 39 65 74 165 100v18c-158-35-264-91-264-154 0-105 282-189 631-192v-45l155 89-155 89v-46z" horiz-adv-x="1300" />
+
+<glyph glyph-name="mail" unicode="&#x34;" d="M929 11v428q-18-20-39-36-149-115-238-189-28-24-46-37t-48-28-57-13h-2q-26 0-57 13t-48 28-46 37q-88 74-238 189-21 16-39 36v-428q0-7 6-13t12-5h822q7 0 12 5t6 13z m0 586v14t-1 7-1 7-3 5-5 4-8 2h-822q-7 0-12-6t-6-12q0-94 83-159 107-84 223-176 4-3 20-17t25-21 25-17 28-16 24-5h2q11 0 24 5t28 16 25 17 25 21 20 17q116 92 224 176 30 24 56 65t26 73z m71 21v-607q0-37-26-63t-63-27h-822q-36 0-63 27t-26 63v607q0 37 26 63t63 26h822q37 0 63-26t26-63z" horiz-adv-x="1000" />
+
+<glyph glyph-name="mail-alt" unicode="&#x35;" d="M1000 454v-443q0-37-26-63t-63-27h-822q-36 0-63 27t-26 63v443q25-27 56-49 202-137 278-192 32-24 51-37t53-27 61-13h2q28 0 61 13t53 27 51 37q95 68 278 192 32 22 56 49z m0 164q0-44-27-84t-68-69q-210-146-262-181-5-4-23-17t-30-22-29-18-32-15-28-5h-2q-12 0-27 5t-32 15-30 18-30 22-23 17q-51 35-147 101t-114 80q-35 23-65 64t-31 77q0 43 23 72t66 29h822q36 0 63-26t26-63z" horiz-adv-x="1000" />
+
+<glyph glyph-name="heart" unicode="&#x36;" d="M500-79q-14 0-25 10l-348 336q-5 5-15 15t-31 37-38 54-30 67-13 77q0 123 71 192t196 70q34 0 70-12t67-33 54-38 42-38q20 20 42 38t54 38 67 33 70 12q125 0 196-70t71-192q0-123-128-251l-347-335q-10-10-25-10z" horiz-adv-x="1000" />
+
+<glyph glyph-name="heart-empty" unicode="&#x37;" d="M929 517q0 46-12 80t-31 55-46 33-52 18-55 4-62-14-62-36-48-40-34-34q-10-13-27-13t-27 13q-14 15-34 34t-48 40-62 36-62 14-55-4-52-18-46-33-31-55-12-80q0-93 105-198l324-312 324 312q105 105 105 198z m71 0q0-123-128-251l-347-335q-10-10-25-10t-25 10l-348 336q-5 5-15 15t-31 37-38 54-30 67-13 77q0 123 71 192t196 70q34 0 70-12t67-33 54-38 42-38q20 20 42 38t54 38 67 33 70 12q125 0 196-70t71-192z" horiz-adv-x="1000" />
+
+<glyph glyph-name="camera-tour" unicode="&#x38;" d="M583 571c20-20 30-45 30-74 0-29-10-54-30-74-21-21-46-31-75-31-29 0-53 10-74 31-21 20-31 45-31 74 0 29 10 54 31 74 21 21 45 31 74 31 29 0 54-10 75-31z m61-555c0 8-3 14-8 20l-139 139c-9 9-19 10-31 6-12-5-18-14-17-26v-80c-209 17-368 99-368 197 0 30 16 60 45 86v38c-78-48-126-109-126-176 0-135 195-248 449-269v-74c-1-13 5-22 17-27 11-4 22-2 31 7l139 139c3 4 5 8 7 13l1 2-1 1c0 1 1 3 1 4z m215 318c0-93-88-94-155-94-78 0-157 0-235 0-68 0-135 0-202 0-31 0-59 5-82 28-33 33-27 78-27 120 0 82 0 163 0 244 0 62 23 122 96 122 26 0 51 0 76 0 8 0 17 38 20 46 21 56 79 47 126 47 44 0 92 7 135 0 37-7 51-37 63-68 9-25 7-25 33-25 25 0 54 3 79-2 42-9 73-49 73-91m-235-279c63 63 63 167 0 231-64 63-168 63-231 0-64-64-64-168 0-231 63-64 167-64 231 0 32 32-32-32 0 0z m383-162c0 65-43 124-117 171v-41c23-24 35-51 35-78 0-66-70-124-181-161-3 0-5-1-8-2-29-10-44-43-33-75 10-31 43-49 72-39 3 1 5 2 8 3 136 50 224 131 224 222z" horiz-adv-x="1005" />
+
+<glyph glyph-name="hubot" unicode="&#x39;" d="M188 475c-35 0-63-28-63-62v-125c0-35 28-63 63-63h500c34 0 62 28 62 63v125c0 34-28 62-62 62h-500z m500-109l-79-78h-93l-78 78-79-78h-93l-78 78v47h46l79-79 78 79h93l79-79 78 79h47v-47z m-375-203h250v-63h-250v63z m125 562c-242 0-438-182-438-406v-281c0-35 28-63 63-63h750c34 0 62 28 62 63v281c0 224-196 406-437 406z m375-687h-750v281c0 193 165 349 375 349s375-156 375-349v-281z" horiz-adv-x="875" />
+
+<glyph glyph-name="squirrel" unicode="&#x3a;" d="M750 788c-138 0-250-82-250-183 0-121 31-190 0-380 0 281-173 396-250 396 3 32-30 42-30 42s-14-7-19-22c-17 20-35 18-35 18l-9-37c0 0-114-40-116-201 14-21 97-38 156-27 56-3 42-50 30-62-53-53-102 18-164 18s-63-62 0-62 62-63 187-63c-193-75 0-250 0-250h-62c-63 0-63-63-63-63s250 0 375 0c188 0 313 63 313 218 0 53-27 111-63 158-69 91 14 167 63 125s187-63 187 125c0 138-112 250-250 250z m-594-313c-17 0-31 14-31 31 0 18 14 32 31 32 18 0 32-14 32-32 0-17-14-31-32-31z" horiz-adv-x="1000" />
+
+<glyph glyph-name="clippy" unicode="&#x3b;" d="M125 100h250v-62h-250v62z m313 375h-313v-62h313v62z m125-187v125l-188-188 188-187v125h312v125h-312z m-282 62h-156v-62h156v62z m-156-187h156v62h-156v-62z m563-63h62v-125c-1-18-7-32-19-44s-26-18-43-19h-625c-35 0-63 29-63 63v688c0 34 28 62 63 62h187c0 69 56 125 125 125s125-56 125-125h188c34 0 62-28 62-62v-313h-62v188h-625v-563h625v125z m-563 500h500c0 34-28 63-62 63h-63c-34 0-62 28-62 62s-29 63-63 63-62-29-62-63-29-62-63-62h-62c-35 0-63-29-63-63z" horiz-adv-x="875" />
+
+<glyph glyph-name="left-dir" unicode="&#x3c;" d="M357 600v-500q0-14-10-25t-26-11-25 11l-250 250q-10 11-10 25t10 25l250 250q11 11 25 11t26-11 10-25z" horiz-adv-x="357.1" />
+
+<glyph glyph-name="right-dir" unicode="&#x3e;" d="M321 350q0-14-10-25l-250-250q-11-11-25-11t-25 11-11 25v500q0 15 11 25t25 11 25-11l250-250q10-10 10-25z" horiz-adv-x="357.1" />
+
+<glyph glyph-name="star-half" unicode="&#x3f;" d="M464 832v-747l-250-132q-12-7-23-7-11 0-17 9t-6 19q0 4 1 12l48 279-203 197q-14 15-14 27 0 21 31 26l280 40 126 254q11 23 27 23z" horiz-adv-x="500" />
+
+<glyph glyph-name="star-half-alt" unicode="&#x40;" d="M662 316l143 140-198 29-37 5-17 34-89 179v-537l33-17 178-94-34 198-6 37z m252 146l-202-197 48-279q2-19-4-29t-19-11q-9 0-22 7l-251 132-250-132q-13-7-23-7-12 0-19 11t-3 29l48 279-203 197q-18 18-13 33t30 20l280 40 126 254q11 23 27 23 16 0 28-23l125-254 280-40q25-4 31-20t-14-33z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="marquee" unicode="&#x41;" d="M0 850l0-143 143 0 0 143-143 0z m286 0l0-143 143 0 0 143-143 0z m285 0l0-143 143 0 0 143-143 0z m286 0l0-143 143 0 0 143-143 0z m-857-286l0-143 143 0 0 143-143 0z m857 0l0-143 143 0 0 143-143 0z m-857-285l0-143 143 0 0 143-143 0z m857 0l0-143 143 0 0 143-143 0z m-857-286l0-143 143 0 0 143-143 0z m286 0l0-143 143 0 0 143-143 0z m285 0l0-143 143 0 0 143-143 0z m286 0l0-143 143 0 0 143-143 0z" horiz-adv-x="1000" />
+
+<glyph glyph-name="user" unicode="&#x42;" d="M714 69q0-60-35-104t-84-44h-476q-49 0-84 44t-35 104q0 48 5 90t17 85 33 73 52 50 76 19q73-72 174-72t175 72q42 0 75-19t52-50 33-73 18-85 4-90z m-143 495q0-88-62-151t-152-63-151 63-63 151 63 152 151 63 152-63 62-152z" horiz-adv-x="714.3" />
+
+<glyph glyph-name="users" unicode="&#x43;" d="M331 350q-90-3-148-71h-75q-45 0-77 22t-31 66q0 197 69 197 4 0 25-11t54-24 66-12q38 0 75 13-3-21-3-37 0-78 45-143z m598-356q0-66-41-105t-108-39h-488q-68 0-108 39t-41 105q0 30 2 58t8 61 14 61 24 54 35 45 48 30 62 11q6 0 24-12t41-26 59-27 76-12 75 12 60 27 41 26 24 12q34 0 62-11t47-30 35-45 24-54 15-61 8-61 2-58z m-572 713q0-59-42-101t-101-42-101 42-42 101 42 101 101 42 101-42 42-101z m393-214q0-89-63-152t-151-62-152 62-63 152 63 151 152 63 151-63 63-151z m321-126q0-43-31-66t-77-22h-75q-57 68-147 71 45 65 45 143 0 16-3 37 37-13 74-13 33 0 67 12t54 24 24 11q69 0 69-197z m-71 340q0-59-42-101t-101-42-101 42-42 101 42 101 101 42 101-42 42-101z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="shower" unicode="&#x44;" d="M834 393h-668c0 113 92 205 205 205h57v254h144v-254h57c113 0 205-92 205-205z m-300-82v1c0 18-15 33-34 33-19 0-34-15-34-34 0-19 15-34 34-34s34 15 34 34z m0-283v0c0 19-15 34-34 34-19 0-34-15-34-34 0-19 15-35 34-35s34 16 34 35z m0 141v1c0 19-15 34-34 34-19 0-34-16-34-35 0-18 15-34 34-34s34 16 34 34z m0-283v1c0 18-15 33-34 33-19 0-34-15-34-34 0-19 15-34 34-34 19 0 34 15 34 34z m367 7c17 7 26 27 19 44l-1 1c-6 17-26 26-44 18-17-7-26-27-19-44 6-14 19-22 32-22 4 0 9 1 13 3z m-47 129c17 7 26 27 19 44l-1 1c-7 17-26 26-44 18-17-7-26-27-19-44 6-14 18-22 32-22 4 0 9 1 13 3z m-50 127c18 6 28 25 23 43l-1 1c-5 18-24 27-42 22-18-5-28-25-23-43 5-14 18-24 33-24 3 0 6 0 10 1z m-45 130c18 7 26 27 19 45l0 0c-7 18-27 26-44 19-17-7-26-27-19-45 6-13 18-21 32-21 4 0 8 1 12 2z m-59-408c18 4 30 22 27 40l-1 1c-3 18-21 30-40 26-18-3-30-22-26-40 3-17 17-28 33-28 2 0 5 0 7 1z m-25 135c19 2 33 19 31 37l0 1c-2 19-19 32-37 30-19-2-33-19-31-38 2-17 17-30 34-30 1 0 2 0 3 0z m-17 136c18 4 30 22 26 40l0 1c-3 18-21 30-40 26-18-4-30-22-27-40 4-17 18-28 34-28 2 0 4 0 7 1z m-21 135c18 4 30 22 26 41l0 0c-4 19-22 30-40 27-18-4-30-22-27-41 4-16 18-27 34-27 2 0 4 0 7 0z m-493-365l0 0c7 18-2 37-19 44-17 7-38-1-44-19-7-17 1-37 19-44 4-2 8-3 12-3 14 0 26 8 32 22z m47 129l0 0c7 18-1 37-19 44-17 7-37-1-44-19-7-18 1-37 19-44 4-2 8-3 12-3 14 0 27 8 32 22z m48 131l0 1c6 18-5 37-23 42-18 6-37-5-42-23-6-18 4-37 23-43 3-1 6-1 9-1 15 0 29 10 33 24z m46 126l0 1c7 17-1 37-19 44-17 7-37-2-44-20-7-17 1-37 19-44 4-1 8-2 12-2 14 0 27 8 32 21z m56-400l0 0c3 19-9 36-27 40-19 4-37-8-40-27-4-18 8-36 26-40 3-1 5-1 7-1 16 0 30 11 34 28z m21 138l0 1c2 19-12 35-30 37-19 2-36-12-38-31-2-18 12-35 31-37 1 0 2 0 3 0 18 0 32 13 34 30z m21 133l0 0c4 19-8 36-27 40-18 4-36-8-40-27-4-18 8-36 27-40 2-1 4-1 6-1 16 0 30 11 34 28z m21 135l0 1c4 18-8 36-27 40-18 3-36-9-40-27-4-19 8-37 27-41 2 0 4 0 6 0 16 0 31 11 34 27z" horiz-adv-x="1000" />
+
+<glyph glyph-name="male" unicode="&#x45;" d="M571 457v-232q0-22-15-38t-38-16-38 16-16 38v196h-35v-509q0-25-19-44t-44-18-44 18-18 44v259h-36v-259q0-25-19-44t-44-18-44 18-18 44v509h-36v-196q0-22-15-38t-38-16-38 16-16 38v232q0 45 31 76t76 31h357q45 0 76-31t31-76z m-160 250q0-52-37-88t-88-37-89 37-36 88 36 89 89 36 88-36 37-89z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="female" unicode="&#x46;" d="M714 261q0-23-15-38t-38-16q-29 0-45 24l-127 190h-25v-73l138-230q5-8 5-18 0-14-10-25t-26-11h-107v-152q0-25-18-44t-44-18h-89q-26 0-45 18t-18 44v152h-107q-15 0-25 11t-11 25q0 10 5 18l138 230v73h-25l-127-190q-16-24-44-24-23 0-38 16t-16 38q0 16 9 29l143 215q41 59 98 59h214q58 0 99-59l142-215q9-13 9-29z m-232 446q0-52-36-88t-89-37-88 37-37 88 37 89 88 36 89-36 36-89z" horiz-adv-x="714.3" />
+
+<glyph glyph-name="video" unicode="&#x47;" d="M214-43v72q0 14-10 25t-25 10h-72q-14 0-25-10t-11-25v-72q0-14 11-25t25-11h72q14 0 25 11t10 25z m0 214v72q0 14-10 25t-25 11h-72q-14 0-25-11t-11-25v-72q0-14 11-25t25-10h72q14 0 25 10t10 25z m0 215v71q0 15-10 25t-25 11h-72q-14 0-25-11t-11-25v-71q0-15 11-25t25-11h72q14 0 25 11t10 25z m572-429v286q0 14-11 25t-25 11h-429q-14 0-25-11t-10-25v-286q0-14 10-25t25-11h429q15 0 25 11t11 25z m-572 643v71q0 15-10 26t-25 10h-72q-14 0-25-10t-11-26v-71q0-14 11-25t25-11h72q14 0 25 11t10 25z m786-643v72q0 14-11 25t-25 10h-71q-15 0-25-10t-11-25v-72q0-14 11-25t25-11h71q15 0 25 11t11 25z m-214 429v285q0 15-11 26t-25 10h-429q-14 0-25-10t-10-26v-285q0-15 10-25t25-11h429q15 0 25 11t11 25z m214-215v72q0 14-11 25t-25 11h-71q-15 0-25-11t-11-25v-72q0-14 11-25t25-10h71q15 0 25 10t11 25z m0 215v71q0 15-11 25t-25 11h-71q-15 0-25-11t-11-25v-71q0-15 11-25t25-11h71q15 0 25 11t11 25z m0 214v71q0 15-11 26t-25 10h-71q-15 0-25-10t-11-26v-71q0-14 11-25t25-11h71q15 0 25 11t11 25z m71 89v-750q0-37-26-63t-63-26h-893q-36 0-63 26t-26 63v750q0 37 26 63t63 27h893q37 0 63-27t26-63z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="videocam" unicode="&#x48;" d="M1000 654v-608q0-23-22-32-7-3-14-3-15 0-25 10l-225 225v-92q0-67-47-114t-113-47h-393q-67 0-114 47t-47 114v392q0 67 47 114t114 47h393q66 0 113-47t47-114v-92l225 225q10 10 25 10 7 0 14-2 22-10 22-33z" horiz-adv-x="1000" />
+
+<glyph glyph-name="picture" unicode="&#x49;" d="M357 529q0-45-31-76t-76-32-76 32-31 76 31 76 76 31 76-31 31-76z m572-215v-250h-786v107l178 179 90-89 285 285z m53 393h-893q-7 0-12-5t-6-13v-678q0-7 6-13t12-5h893q7 0 13 5t5 13v678q0 8-5 13t-13 5z m89-18v-678q0-37-26-63t-63-27h-893q-36 0-63 27t-26 63v678q0 37 26 63t63 27h893q37 0 63-27t26-63z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="camera" unicode="&#x4a;" d="M536 475q66 0 113-47t47-114-47-113-113-47-114 47-47 113 47 114 114 47z m393 232q59 0 101-42t41-101v-500q0-59-41-101t-101-42h-786q-59 0-101 42t-42 101v500q0 59 42 101t101 42h125l28 76q11 27 39 47t58 20h286q29 0 57-20t39-47l29-76h125z m-393-643q103 0 176 74t74 176-74 177-176 73-177-73-73-177 73-176 177-74z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="th-large" unicode="&#x4b;" d="M429 279v-215q0-29-22-50t-50-21h-286q-29 0-50 21t-21 50v215q0 29 21 50t50 21h286q29 0 50-21t22-50z m0 428v-214q0-29-22-50t-50-22h-286q-29 0-50 22t-21 50v214q0 29 21 50t50 22h286q29 0 50-22t22-50z m500-428v-215q0-29-22-50t-50-21h-286q-29 0-50 21t-21 50v215q0 29 21 50t50 21h286q29 0 50-21t22-50z m0 428v-214q0-29-22-50t-50-22h-286q-29 0-50 22t-21 50v214q0 29 21 50t50 22h286q29 0 50-22t22-50z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="th" unicode="&#x4c;" d="M286 154v-108q0-22-16-37t-38-16h-178q-23 0-38 16t-16 37v108q0 22 16 38t38 15h178q23 0 38-15t16-38z m0 285v-107q0-22-16-38t-38-15h-178q-23 0-38 15t-16 38v107q0 23 16 38t38 16h178q23 0 38-16t16-38z m357-285v-108q0-22-16-37t-38-16h-178q-23 0-38 16t-16 37v108q0 22 16 38t38 15h178q23 0 38-15t16-38z m-357 571v-107q0-22-16-38t-38-16h-178q-23 0-38 16t-16 38v107q0 22 16 38t38 16h178q23 0 38-16t16-38z m357-286v-107q0-22-16-38t-38-15h-178q-23 0-38 15t-16 38v107q0 23 16 38t38 16h178q23 0 38-16t16-38z m357-285v-108q0-22-16-37t-38-16h-178q-22 0-38 16t-16 37v108q0 22 16 38t38 15h178q23 0 38-15t16-38z m-357 571v-107q0-22-16-38t-38-16h-178q-23 0-38 16t-16 38v107q0 22 16 38t38 16h178q23 0 38-16t16-38z m357-286v-107q0-22-16-38t-38-15h-178q-22 0-38 15t-16 38v107q0 23 16 38t38 16h178q23 0 38-16t16-38z m0 286v-107q0-22-16-38t-38-16h-178q-22 0-38 16t-16 38v107q0 22 16 38t38 16h178q23 0 38-16t16-38z" horiz-adv-x="1000" />
+
+<glyph glyph-name="th-list" unicode="&#x4d;" d="M286 154v-108q0-22-16-37t-38-16h-178q-23 0-38 16t-16 37v108q0 22 16 38t38 15h178q23 0 38-15t16-38z m0 285v-107q0-22-16-38t-38-15h-178q-23 0-38 15t-16 38v107q0 23 16 38t38 16h178q23 0 38-16t16-38z m714-285v-108q0-22-16-37t-38-16h-535q-23 0-38 16t-16 37v108q0 22 16 38t38 15h535q23 0 38-15t16-38z m-714 571v-107q0-22-16-38t-38-16h-178q-23 0-38 16t-16 38v107q0 22 16 38t38 16h178q23 0 38-16t16-38z m714-286v-107q0-22-16-38t-38-15h-535q-23 0-38 15t-16 38v107q0 23 16 38t38 16h535q23 0 38-16t16-38z m0 286v-107q0-22-16-38t-38-16h-535q-23 0-38 16t-16 38v107q0 22 16 38t38 16h535q23 0 38-16t16-38z" horiz-adv-x="1000" />
+
+<glyph glyph-name="child" unicode="&#x4e;" d="M663 544l-163-163v-460q0-25-18-44t-44-18-45 18-18 44v215h-36v-215q0-25-18-44t-44-18-44 18-19 44v460l-163 163q-15 16-15 38t15 38q17 16 39 16t37-16l128-127h205l127 127q16 16 38 16t38-16q16-16 16-38t-16-38z m-181 92q0-52-36-89t-89-36-88 36-37 89 37 88 88 37 89-37 36-88z" horiz-adv-x="714.3" />
+
+<glyph glyph-name="ok" unicode="&#x4f;" d="M933 534q0-22-16-38l-404-404-76-76q-16-15-38-15t-38 15l-76 76-202 202q-15 16-15 38t15 38l76 76q16 16 38 16t38-16l164-165 366 367q16 16 38 16t38-16l76-76q16-15 16-38z" horiz-adv-x="1000" />
+
+<glyph glyph-name="ok-circled" unicode="&#x50;" d="M717 440q0 16-10 26l-51 50q-11 11-25 11t-25-11l-228-227-126 126q-11 11-25 11t-25-11l-51-50q-10-10-10-26 0-15 10-25l202-202q10-10 25-10 15 0 26 10l303 303q10 10 10 25z m140-90q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="ok-squared" unicode="&#x51;" d="M382 125l343 343q11 10 11 25t-11 25l-57 57q-11 11-25 11t-25-11l-261-261-118 118q-10 11-25 11t-25-11l-57-57q-10-10-10-25t10-25l200-200q11-10 25-10t25 10z m475 493v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="cancel" unicode="&#x52;" d="M724 112q0-22-15-38l-76-76q-16-15-38-15t-38 15l-164 165-164-165q-16-15-38-15t-38 15l-76 76q-16 16-16 38t16 38l164 164-164 164q-16 16-16 38t16 38l76 76q16 16 38 16t38-16l164-164 164 164q16 16 38 16t38-16l76-76q15-15 15-38t-15-38l-164-164 164-164q15-15 15-38z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="plus" unicode="&#x53;" d="M786 439v-107q0-22-16-38t-38-15h-232v-233q0-22-16-37t-38-16h-107q-22 0-38 16t-15 37v233h-232q-23 0-38 15t-16 38v107q0 23 16 38t38 16h232v232q0 22 15 38t38 16h107q23 0 38-16t16-38v-232h232q23 0 38-16t16-38z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="plus-circled" unicode="&#x54;" d="M679 314v72q0 14-11 25t-25 10h-143v143q0 15-11 25t-25 11h-71q-15 0-25-11t-11-25v-143h-143q-14 0-25-10t-10-25v-72q0-14 10-25t25-10h143v-143q0-15 11-25t25-11h71q15 0 25 11t11 25v143h143q14 0 25 10t11 25z m178 36q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="plus-squared" unicode="&#x55;" d="M714 314v72q0 14-10 25t-25 10h-179v179q0 15-11 25t-25 11h-71q-15 0-25-11t-11-25v-179h-178q-15 0-25-10t-11-25v-72q0-14 11-25t25-10h178v-179q0-14 11-25t25-11h71q15 0 25 11t11 25v179h179q14 0 25 10t10 25z m143 304v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="plus-squared-alt" unicode="&#x56;" d="M643 404v-36q0-8-5-13t-13-5h-196v-196q0-8-5-13t-13-5h-36q-8 0-13 5t-5 13v196h-196q-8 0-13 5t-5 13v36q0 7 5 12t13 5h196v197q0 8 5 13t13 5h36q8 0 13-5t5-13v-197h196q8 0 13-5t5-12z m71-250v464q0 37-26 63t-63 26h-464q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63z m72 464v-464q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h464q66 0 114-48t47-113z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="minus" unicode="&#x57;" d="M786 439v-107q0-22-16-38t-38-15h-678q-23 0-38 15t-16 38v107q0 23 16 38t38 16h678q23 0 38-16t16-38z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="minus-circled" unicode="&#x58;" d="M679 314v72q0 14-11 25t-25 10h-429q-14 0-25-10t-10-25v-72q0-14 10-25t25-10h429q14 0 25 10t11 25z m178 36q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="minus-squared" unicode="&#x59;" d="M714 314v72q0 14-10 25t-25 10h-500q-15 0-25-10t-11-25v-72q0-14 11-25t25-10h500q14 0 25 10t10 25z m143 304v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="minus-squared-alt" unicode="&#x5a;" d="M643 404v-36q0-8-5-13t-13-5h-464q-8 0-13 5t-5 13v36q0 7 5 12t13 5h464q8 0 13-5t5-12z m71-250v464q0 37-26 63t-63 26h-464q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63z m72 464v-464q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h464q66 0 114-48t47-113z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="left-open" unicode="&#x5b;" d="M654 682l-297-296 297-297q10-10 10-25t-10-25l-93-93q-11-10-25-10t-25 10l-414 415q-11 10-11 25t11 25l414 414q10 11 25 11t25-11l93-93q10-10 10-25t-10-25z" horiz-adv-x="714.3" />
+
+<glyph glyph-name="help-circled" unicode="&#x5c;" d="M500 82v107q0 8-5 13t-13 5h-107q-8 0-13-5t-5-13v-107q0-8 5-13t13-5h107q8 0 13 5t5 13z m143 375q0 49-31 91t-77 65-95 23q-136 0-207-119-9-13 4-24l74-55q4-4 10-4 9 0 14 7 30 38 48 51 19 14 48 14 27 0 48-15t21-33q0-21-11-34t-38-25q-35-15-65-48t-29-70v-20q0-8 5-13t13-5h107q8 0 13 5t5 13q0 10 12 27t30 28q18 10 28 16t25 19 25 27 16 34 7 45z m214-107q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="right-open" unicode="&#x5d;" d="M618 361l-414-415q-11-10-25-10t-25 10l-93 93q-11 11-11 25t11 25l296 297-296 296q-11 11-11 25t11 25l93 93q10 11 25 11t25-11l414-414q10-11 10-25t-10-25z" horiz-adv-x="714.3" />
+
+<glyph glyph-name="info" unicode="&#x5e;" d="M357 100v-71q0-15-10-25t-26-11h-285q-15 0-25 11t-11 25v71q0 15 11 25t25 11h35v214h-35q-15 0-25 11t-11 25v71q0 15 11 25t25 11h214q15 0 25-11t11-25v-321h35q15 0 26-11t10-25z m-71 643v-107q0-15-11-25t-25-11h-143q-14 0-25 11t-11 25v107q0 14 11 25t25 11h143q15 0 25-11t11-25z" horiz-adv-x="357.1" />
+
+<glyph glyph-name="home" unicode="&#x5f;" d="M786 296v-267q0-15-11-25t-25-11h-214v214h-143v-214h-214q-15 0-25 11t-11 25v267q0 1 0 2t0 2l321 264 321-264q1-1 1-4z m124 39l-34-41q-5-5-12-6h-2q-7 0-12 3l-386 322-386-322q-7-4-13-3-7 1-12 6l-35 41q-4 6-3 13t6 12l401 334q18 15 42 15t43-15l136-113v108q0 8 5 13t13 5h107q8 0 13-5t5-13v-227l122-102q6-4 6-12t-4-13z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="link" unicode="&#x60;" d="M813 171q0 23-16 38l-116 116q-16 16-38 16-24 0-40-18 1-1 10-10t12-12 9-11 7-14 2-15q0-23-16-38t-38-16q-8 0-15 2t-14 7-11 9-12 12-10 10q-19-17-19-40 0-23 16-38l115-116q15-15 38-15 22 0 38 15l82 81q16 16 16 37z m-393 394q0 22-15 38l-115 115q-16 16-38 16-22 0-38-15l-82-82q-16-15-16-37 0-22 16-38l116-116q15-15 38-15 23 0 40 17-2 2-11 11t-12 12-8 10-7 14-2 16q0 22 15 38t38 15q9 0 16-2t14-7 11-8 12-12 10-11q18 17 18 41z m500-394q0-66-48-113l-82-81q-46-47-113-47-68 0-114 48l-115 115q-46 47-46 114 0 68 49 116l-49 49q-48-49-116-49-67 0-114 47l-116 116q-47 47-47 114t47 113l82 82q47 46 114 46 67 0 114-47l115-116q46-46 46-113 0-69-49-117l49-49q48 49 116 49 67 0 114-47l116-116q47-47 47-114z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="unlink" unicode="&#x61;" d="M245 141l-143-143q-6-5-13-5t-12 5q-6 6-6 13t6 13l142 142q6 5 13 5t13-5q5-5 5-12t-5-13z m94-23v-179q0-8-5-13t-13-5-12 5-5 13v179q0 8 5 13t12 5 13-5 5-13z m-125 125q0-8-5-13t-13-5h-178q-8 0-13 5t-5 13 5 13 13 5h178q8 0 13-5t5-13z m706-72q0-66-48-113l-82-81q-46-47-113-47-68 0-114 48l-186 187q-12 12-24 31l134 10 152-153q15-15 38-15t38 15l82 81q16 16 16 37 0 23-16 38l-153 154 10 133q20-11 31-23l188-188q47-48 47-114z m-345 404l-133-10-152 153q-16 16-38 16-22 0-38-15l-82-82q-16-15-16-37 0-22 16-38l153-153-10-134q-20 12-32 24l-187 187q-47 48-47 114 0 67 47 113l82 82q47 46 114 46 67 0 114-47l186-187q12-12 23-32z m354-46q0-8-5-13t-13-5h-179q-8 0-13 5t-5 13 5 12 13 5h179q8 0 13-5t5-12z m-304 303v-178q0-8-5-13t-13-5-13 5-5 13v178q0 8 5 13t13 5 13-5 5-13z m227-84l-143-143q-6-5-13-5t-12 5q-5 6-5 13t5 13l143 143q5 5 12 5t13-5q5-6 5-13t-5-13z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="link-ext" unicode="&#x62;" d="M786 332v-178q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h393q7 0 12-5t5-13v-36q0-8-5-13t-12-5h-393q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63v178q0 8 5 13t13 5h36q8 0 13-5t5-13z m214 482v-285q0-15-11-25t-25-11-25 11l-98 98-364-364q-5-6-13-6t-12 6l-64 64q-6 5-6 12t6 13l364 364-98 98q-11 11-11 25t11 25 25 11h285q15 0 25-11t11-25z" horiz-adv-x="1000" />
+
+<glyph glyph-name="link-ext-alt" unicode="&#x63;" d="M714 332v268q0 15-10 25t-25 11h-268q-24 0-33-22-10-23 8-39l80-80-298-298q-11-11-11-26t11-25l57-57q11-10 25-10t25 10l298 298 81-80q10-11 25-11 6 0 14 3 21 10 21 33z m143 286v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="lock" unicode="&#x65;" d="M179 421h285v108q0 59-42 101t-101 41-101-41-41-101v-108z m464-53v-322q0-22-16-37t-38-16h-535q-23 0-38 16t-16 37v322q0 22 16 38t38 15h17v108q0 102 74 176t176 74 177-74 73-176v-108h18q23 0 38-15t16-38z" horiz-adv-x="642.9" />
+
+<glyph glyph-name="lock-open" unicode="&#x66;" d="M929 529v-143q0-15-11-25t-25-11h-36q-14 0-25 11t-11 25v143q0 59-41 101t-101 41-101-41-42-101v-108h53q23 0 38-15t16-38v-322q0-22-16-37t-38-16h-535q-23 0-38 16t-16 37v322q0 22 16 38t38 15h375v108q0 103 73 176t177 74 176-74 74-176z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="cancel-circled" unicode="&#x67;" d="M641 224q0 14-10 25l-101 101 101 101q10 11 10 25 0 15-10 26l-51 50q-10 11-25 11-15 0-25-11l-101-101-101 101q-11 11-25 11-16 0-26-11l-50-50q-11-11-11-26 0-14 11-25l101-101-101-101q-11-11-11-25 0-15 11-26l50-50q10-11 26-11 14 0 25 11l101 101 101-101q10-11 25-11 15 0 25 11l51 50q10 11 10 26z m216 126q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="lock-open-alt" unicode="&#x68;" d="M589 421q23 0 38-15t16-38v-322q0-22-16-37t-38-16h-535q-23 0-38 16t-16 37v322q0 22 16 38t38 15h17v179q0 103 74 177t176 73 177-73 73-177q0-14-10-25t-25-11h-36q-14 0-25 11t-11 25q0 59-42 101t-101 42-101-42-41-101v-179h410z" horiz-adv-x="642.9" />
+
+<glyph glyph-name="meteor" unicode="&#x69;" d="M2 848l872-923c0 0 29-21 52 3 23 25 5 49 5 49l-929 871 0 0z m276-87l664-716c0 0 30-21 52 4 23 24 6 49 6 49l-722 663 0 0z m-194-187l664-716c0 0 30-21 52 4 23 24 6 49 6 49l-722 663 0 0z m427 112l464-500c0 0 21-15 37 2 16 17 3 34 3 34l-504 464 0 0z m-363-328l464-501c0 0 20-14 36 3 16 17 4 34 4 34l-504 464 0 0z m602 220l210-228c0 0 10-7 18 1 8 8 2 16 2 16l-230 211 0 0z m-486-451l210-227c0 0 10-7 18 1 8 8 2 16 2 16l-230 210 0 0z" horiz-adv-x="1020" />
+
+<glyph glyph-name="pin" unicode="&#x6a;" d="M268 368v250q0 8-5 13t-13 5-13-5-5-13v-250q0-8 5-13t13-5 13 5 5 13z m375-197q0-14-11-25t-25-10h-239l-29-270q-1-7-6-11t-11-5h-1q-15 0-17 15l-43 271h-225q-15 0-25 10t-11 25q0 69 44 124t99 55v286q-29 0-50 21t-22 50 22 50 50 22h357q29 0 50-22t21-50-21-50-50-21v-286q55 0 99-55t44-124z" horiz-adv-x="642.9" />
+
+<glyph glyph-name="eye" unicode="&#x6b;" d="M929 314q-85 132-213 197 34-58 34-125 0-103-73-177t-177-73-177 73-73 177q0 67 34 125-128-65-213-197 75-114 187-182t242-68 243 68 186 182z m-402 215q0 11-8 19t-19 7q-70 0-120-50t-50-119q0-11 8-19t19-8 19 8 8 19q0 48 34 82t82 34q11 0 19 8t8 19z m473-215q0-19-11-38-78-129-210-206t-279-77-279 77-210 206q-11 19-11 38t11 39q78 128 210 205t279 78 279-78 210-205q11-20 11-39z" horiz-adv-x="1000" />
+
+<glyph glyph-name="eye-off" unicode="&#x6c;" d="M310 105l43 79q-48 35-76 88t-27 114q0 67 34 125-128-65-213-197 94-144 239-209z m217 424q0 11-8 19t-19 7q-70 0-120-50t-50-119q0-11 8-19t19-8 19 8 8 19q0 48 34 82t82 34q11 0 19 8t8 19z m202 106q0-4 0-5-59-105-176-316t-176-316l-28-50q-5-9-15-9-7 0-75 39-9 6-9 16 0 7 25 49-80 36-147 96t-117 137q-11 17-11 38t11 39q86 131 212 207t277 76q50 0 100-10l31 54q5 9 15 9 3 0 10-3t18-9 18-10 18-10 10-7q9-5 9-15z m21-249q0-78-44-142t-117-91l157 280q4-25 4-47z m250-72q0-19-11-38-22-36-61-81-84-96-194-149t-234-53l41 74q119 10 219 76t169 171q-65 100-158 164l35 63q53-36 102-85t81-103q11-19 11-39z" horiz-adv-x="1000" />
+
+<glyph glyph-name="gitlab" unicode="&#x6d;" d="M962 288c-42 131-85 262-127 393-9 28-18 55-27 83-6 16-29 18-34 0-3-9-6-18-9-26-27-84-55-168-82-252-4-11-5-38-19-38-34 0-68 0-102 0-78 0-155 0-232 0-6 0-21 59-23 65-14 45-29 90-43 134-8 23-15 46-22 68-5 15-8 37-17 50-6 21-30 11-35-5-44-137-89-274-133-411-10-28-38-79-7-101 11-11 26-19 39-28 71-52 143-104 215-157 61-44 123-89 184-134 16-11 15-6 31 7 36 25 71 51 106 76 108 79 216 157 324 236 12 9 18 24 13 40z" horiz-adv-x="1000" />
+
+<glyph glyph-name="rocketchat" unicode="&#x6e;" d="M969 351c0 47-14 93-41 135-25 37-60 71-104 99-85 54-197 84-315 84-39 0-78-4-115-10-24 22-51 41-80 57-154 75-282 2-282 2s119-98 100-184c-54-53-83-116-83-183 0 0 0 0 0 0 0-1 0-1 0-1 0-66 29-130 83-183 19-85-100-183-100-183s128-73 282 1c29 16 56 36 80 58 37-7 76-10 115-10 118 0 230 30 315 84 44 28 79 61 104 99 27 42 41 87 41 134 0 0 0 0 0 1 0 0 0 0 0 0z m-459-258c-50 0-97 5-141 16-45-54-143-128-238-104 31 33 77 89 67 182-57 44-91 101-91 163 0 142 180 257 403 257 222 0 402-115 402-257 0-142-180-257-402-257z m53 257c0-29-24-53-53-53-30 0-54 24-54 53s24 54 54 54c29 0 53-24 53-54z m133 54c-30 0-54-24-54-54s24-53 54-53c29 0 53 24 53 53s-24 54-53 54z m-373 0c-29 0-53-24-53-54s24-53 53-53c30 0 54 24 54 53s-24 54-54 54z" horiz-adv-x="1000" />
+
+<glyph glyph-name="repo" unicode="&#x6f;" d="M250 288h-62v62h62v-62z m0 187h-62v-62h62v62z m0 125h-62v-62h62v62z m0 125h-62v-62h62v62z m500 63v-750c0-35-28-63-62-63h-313v-125l-94 94-93-94v125h-125c-35 0-63 28-63 63v750c0 34 28 62 63 62h625c34 0 62-28 62-62z m-62-625h-625v-125h125v62h187v-62h313v125z m0 625h-563v-563h563v563z" horiz-adv-x="750" />
+
+<glyph glyph-name="tag" unicode="&#x70;" d="M250 600q0 30-21 51t-50 20-51-20-21-51 21-50 51-21 50 21 21 50z m595-321q0-30-20-51l-274-274q-22-21-51-21-30 0-50 21l-399 399q-21 21-36 57t-15 65v232q0 29 21 50t50 22h233q29 0 65-15t57-36l399-399q20-21 20-50z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="spin" unicode="&#x71;" d="M855 9c-189-190-520-172-705 13-190 190-200 494-28 695 11 13 21 26 35 34 36 23 85 18 117-13 30-31 35-76 16-112-5-9-9-15-16-22-140-151-145-379-8-516 153-153 407-121 542 34 106 122 142 297 77 451-83 198-305 291-510 222l0 1c236 82 492-24 588-252 71-167 37-355-72-493-11-15-23-29-36-42z" horiz-adv-x="1000" />
+
+<glyph glyph-name="firefox" unicode="&#x72;" d="M504-137c-216 0-387 126-466 306-87 200-17 521 139 663l-6-156c8 9 68 12 78-1 32 62 136 109 220 110-32-26-106-124-99-174 40-13 103-13 136-15 10-6 8-40-12-68-27-36-97-49-97-49l8-106-77 38c-26-64 35-120 97-110 69 12 94 57 142 54 49-2 68-29 61-54-7-30-59-25-59-25-44-70-103-100-198-92 144-119 338-11 387 86 50 97 7 242-43 283 59-25 99-51 120-107 11 124-46 266-149 349 193-56 311-205 314-444 3-239-211-488-496-488z" horiz-adv-x="1000" />
+
+<glyph glyph-name="tags" unicode="&#x73;" d="M250 600q0 30-21 51t-50 20-51-20-21-51 21-50 51-21 50 21 21 50z m595-321q0-30-20-51l-274-274q-22-21-51-21-30 0-50 21l-399 399q-21 21-36 57t-15 65v232q0 29 21 50t50 22h233q29 0 65-15t57-36l399-399q20-21 20-50z m215 0q0-30-21-51l-274-274q-22-21-51-21-20 0-33 8t-29 25l262 262q21 21 21 51 0 29-21 50l-399 399q-21 21-57 36t-65 15h125q29 0 65-15t57-36l399-399q21-21 21-50z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="bookmark" unicode="&#x74;" d="M650 779q12 0 24-5 19-8 29-23t11-35v-719q0-19-11-35t-29-23q-10-4-24-4-27 0-47 18l-246 236-246-236q-20-19-46-19-13 0-25 5-18 7-29 23t-11 35v719q0 19 11 35t29 23q12 5 25 5h585z" horiz-adv-x="714.3" />
+
+<glyph glyph-name="bookmark-empty" unicode="&#x75;" d="M643 707h-572v-693l237 227 49 47 50-47 236-227v693z m7 72q12 0 24-5 19-8 29-23t11-35v-719q0-19-11-35t-29-23q-10-4-24-4-27 0-47 18l-246 236-246-236q-20-19-46-19-13 0-25 5-18 7-29 23t-11 35v719q0 19 11 35t29 23q12 5 25 5h585z" horiz-adv-x="714.3" />
+
+<glyph glyph-name="flag" unicode="&#x76;" d="M179 707q0-40-36-61v-707q0-7-5-12t-13-6h-36q-7 0-12 6t-6 12v707q-35 21-35 61 0 30 21 51t50 21 51-21 21-51z m821-36v-425q0-14-7-22t-22-15q-120-65-206-65-34 0-69 12t-60 27-65 27-79 12q-107 0-259-81-10-5-19-5-14 0-25 10t-10 25v415q0 17 17 30 12 8 44 24 132 67 235 67 60 0 112-16t122-49q21-11 49-11 30 0 65 12t62 26 49 26 30 12q15 0 25-10t11-26z" horiz-adv-x="1000" />
+
+<glyph glyph-name="flag-empty" unicode="&#x77;" d="M929 267v344q-95-51-171-51-46 0-81 18-56 27-103 42t-99 16q-97 0-225-71v-334q137 63 242 63 30 0 57-4t55-15 43-17 46-22l16-8q24-12 56-12 67 0 164 51z m-750 440q0-19-10-36t-26-25v-707q0-8-5-13t-13-5h-36q-7 0-12 5t-6 13v707q-16 9-25 25t-10 36q0 30 21 51t50 21 51-21 21-51z m821-36v-425q0-22-19-32-6-3-10-5-122-65-206-65-49 0-88 20l-16 7q-35 19-55 27t-51 16-63 8q-57 0-132-24t-127-57q-9-5-19-5-9 0-18 4-17 11-17 31v415q0 19 17 30 19 12 44 24t63 29 85 28 87 10q62 0 117-17t116-48q21-11 50-11 68 0 173 63 12 6 17 9 17 9 35-1 17-11 17-31z" horiz-adv-x="1000" />
+
+<glyph glyph-name="flag-checkered" unicode="&#x78;" d="M464 292v107q-101-9-214-65v-103q114 53 214 61z m0 233v110q-96-4-214-70v-106q120 62 214 66z m465-258v103q-132-65-215-40v125q-11 3-21 8-3 2-19 10t-19 9-18 9-19 8-18 8-20 7-20 4-22 4-22 3-24 1q-13 0-28-2v-124h11q57 0 107-16t111-46q10-5 21-8v-105q24-9 51-9 67 0 164 51z m0 238v106q-95-51-171-51-25 0-44 4v-109q83-23 215 50z m-750 202q0-19-10-36t-26-25v-707q0-8-5-13t-13-5h-36q-7 0-12 5t-6 13v707q-16 9-25 25t-10 36q0 30 21 51t50 21 51-21 21-51z m821-36v-425q0-22-19-32-6-3-10-5-122-65-206-65-49 0-88 20l-16 7q-35 19-55 27t-51 16-63 8q-57 0-132-24t-127-57q-9-5-19-5-9 0-18 4-17 11-17 31v415q0 19 17 30 19 12 44 24t63 29 85 28 87 10q62 0 117-17t116-48q21-11 50-11 68 0 173 63 12 6 17 9 17 9 35-1 17-11 17-31z" horiz-adv-x="1000" />
+
+<glyph glyph-name="thumbs-up" unicode="&#x79;" d="M143 100q0 15-11 25t-25 11-25-11-11-25 11-25 25-11 25 11 11 25z m643 321q0 29-22 50t-50 22h-196q0 32 27 89t26 89q0 55-17 81t-72 27q-14-15-21-48t-17-70-33-61q-13-13-43-51-2-3-13-16t-18-23-19-24-22-25-22-19-22-15-20-6h-18v-357h18q7 0 18-1t18-4 21-6 20-7 20-6 16-6q118-41 191-41h67q107 0 107 93 0 15-2 31 16 9 26 30t10 41-10 38q29 28 29 67 0 14-5 31t-14 26q18 1 30 26t12 45z m71 1q0-50-27-91 5-18 5-38 0-43-21-81 1-12 1-24 0-56-33-99 0-78-48-123t-126-45h-72q-54 0-106 13t-121 36q-65 23-77 23h-161q-29 0-50 21t-21 50v357q0 30 21 51t50 21h153q20 13 77 86 32 42 60 72 13 14 19 48t17 70 35 60q22 21 50 21 47 0 84-18t57-57 20-104q0-51-27-107h98q58 0 101-42t42-100z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="thumbs-down" unicode="&#x7a;" d="M143 600q0 15-11 25t-25 11-25-11-11-25 11-25 25-11 25 11 11 25z m643-321q0 19-12 45t-30 26q8 10 14 27t5 31q0 38-29 66 10 17 10 38 0 21-10 41t-26 30q2 16 2 31 0 47-27 70t-76 23h-71q-73 0-191-41-3-1-16-5t-20-7-20-7-21-6-18-4-18-1h-18v-357h18q9 0 20-5t22-15 22-20 22-25 19-24 18-22 13-17q30-38 43-51 23-24 33-61t17-70 21-48q54 0 72 27t17 81q0 33-26 89t-27 89h196q28 0 50 22t22 50z m71-1q0-57-42-100t-101-42h-98q27-55 27-107 0-66-20-104-19-39-57-57t-84-18q-28 0-50 21-19 18-30 45t-14 51-10 47-17 36q-27 28-60 71-57 73-77 86h-153q-29 0-50 21t-21 51v357q0 29 21 50t50 21h161q12 0 77 23 72 24 125 36t111 13h63q78 0 126-44t48-121v-3q33-43 33-99 0-12-1-24 21-38 21-80 0-21-5-39 27-41 27-91z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="angle-left" unicode="&#x7b;" d="M350 546q0-7-6-12l-219-220 219-219q6-6 6-13t-6-13l-28-28q-5-5-12-5t-13 5l-260 261q-6 5-6 12t6 13l260 260q5 6 13 6t12-6l28-28q6-5 6-13z" horiz-adv-x="357.1" />
+
+<glyph glyph-name="checklist" unicode="&#x7c;" d="M1000 319l-375-375-187 187 93 94 94-94 281 282 94-94z m-644-232l50-49h-281c-34 0-62 28-62 62v563c0 34 28 62 62 62h438c34 0 62-28 62-62v-407l-50 50c-24 25-64 25-89 0l-130-131c-24-24-24-63 0-88z m-106 513h313v63h-313v-63z m0-125h313v63h-313v-63z m0-125h188v63h-188v-63z m-62-62h-63v-63h63v63z m0 125h-63v-63h63v63z m0 125h-63v-63h63v63z m0 125h-63v-63h63v63z" horiz-adv-x="1000" />
+
+<glyph glyph-name="angle-right" unicode="&#x7d;" d="M332 314q0-7-5-12l-261-261q-5-5-12-5t-13 5l-28 28q-6 6-6 13t6 13l219 219-219 220q-6 5-6 12t6 13l28 28q5 6 13 6t12-6l261-260q5-5 5-13z" horiz-adv-x="357.1" />
+
+<glyph glyph-name="upload" unicode="&#x7e;" d="M714 29q0 14-10 25t-25 10-25-10-11-25 11-25 25-11 25 11 10 25z m143 0q0 14-10 25t-26 10-25-10-10-25 10-25 25-11 26 11 10 25z m72 125v-179q0-22-16-38t-38-16h-821q-23 0-38 16t-16 38v179q0 22 16 38t38 15h238q12-31 39-51t62-20h143q34 0 61 20t40 51h238q22 0 38-15t16-38z m-182 361q-9-22-33-22h-143v-250q0-15-10-25t-25-11h-143q-15 0-25 11t-11 25v250h-143q-23 0-33 22-9 22 8 39l250 250q10 10 25 10t25-10l250-250q18-17 8-39z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="angle-circled-left" unicode="&#xab;" d="M507 72l57 57q11 10 11 25t-11 25l-171 171 171 171q11 11 11 25t-11 26l-57 57q-10 10-25 10t-25-10l-253-254q-11-10-11-25t11-25l253-253q11-11 25-11t25 11z m350 278q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="angle-circled-right" unicode="&#xbb;" d="M400 72l254 253q10 11 10 25t-10 25l-254 254q-10 10-25 10t-25-10l-57-57q-11-11-11-26t11-25l171-171-171-171q-11-11-11-25t11-25l57-57q11-11 25-11t25 11z m457 278q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="angle-double-left" unicode="&#x2039;" d="M350 82q0-7-6-13l-28-28q-5-5-12-5t-13 5l-260 261q-6 5-6 12t6 13l260 260q5 6 13 6t12-6l28-28q6-5 6-13t-6-12l-219-220 219-219q6-6 6-13z m214 0q0-7-5-13l-28-28q-6-5-13-5t-13 5l-260 261q-6 5-6 12t6 13l260 260q6 6 13 6t13-6l28-28q5-5 5-13t-5-12l-220-220 220-219q5-6 5-13z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="angle-double-right" unicode="&#x203a;" d="M332 314q0-7-5-12l-261-261q-5-5-12-5t-13 5l-28 28q-6 6-6 13t6 13l219 219-219 220q-6 5-6 12t6 13l28 28q5 6 13 6t12-6l261-260q5-5 5-13z m214 0q0-7-5-12l-260-261q-6-5-13-5t-13 5l-28 28q-5 6-5 13t5 13l219 219-219 220q-5 5-5 12t5 13l28 28q6 6 13 6t13-6l260-260q5-5 5-13z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="right" unicode="&#x2264;" d="M1000 404v-108q0-7-5-12t-13-5h-696v-125q0-12-11-17t-19 3l-215 196q-5 5-5 12 0 8 5 14l215 197q9 8 19 4 11-5 11-17v-125h696q8 0 13-5t5-12z" horiz-adv-x="1000" />
+
+<glyph glyph-name="left" unicode="&#x2265;" d="M964 352q0-8-5-14l-215-197q-8-8-19-4-11 5-11 17v125h-696q-8 0-13 5t-5 12v108q0 7 5 12t13 5h696v125q0 12 11 17t19-3l215-195q5-6 5-13z" horiz-adv-x="1000" />
+
+<glyph glyph-name="left-big" unicode="&#x2266;" d="M857 350v-71q0-30-18-51t-47-21h-393l164-164q21-20 21-50t-21-50l-42-43q-21-20-51-20-29 0-50 20l-364 364q-20 21-20 50 0 29 20 51l364 363q21 21 50 21 29 0 51-21l42-41q21-22 21-51t-21-51l-164-164h393q29 0 47-20t18-51z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="right-big" unicode="&#x2267;" d="M821 314q0-30-20-50l-363-364q-22-20-51-20-29 0-50 20l-42 42q-22 21-22 51t22 51l163 163h-393q-29 0-47 21t-18 51v71q0 30 18 51t47 20h393l-163 165q-22 20-22 50t22 50l42 42q21 21 50 21 29 0 51-21l363-363q20-20 20-51z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="right-hand" unicode="&#x2268;" d="M143 100q0 15-11 25t-25 11-25-11-11-25 11-25 25-11 25 11 11 25z m786 321q0 29-22 50t-50 22h-321q0 11 8 27t19 31 18 38 8 47q0 37-24 54t-65 17q-13 0-50-77-14-25-21-37-22-35-62-81-40-45-57-59-38-32-78-32h-18v-357h18q40 0 93-18t108-35 101-18q105 0 105 93 0 15-3 31 17 9 27 30t9 41-10 38q30 28 30 67 0 14-6 31t-14 26h185q29 0 50 21t22 50z m71 1q0-59-42-101t-101-42h-94q-2-35-21-67 2-12 2-24 0-56-34-99 1-78-47-123t-127-45q-74 0-179 39-92 33-125 33h-161q-29 0-50 21t-21 50v357q0 30 21 51t50 21h161q6 0 12 2t13 8 13 10 13 13 12 12 10 12 8 9q36 42 56 72 7 12 18 35t21 40 23 35 30 28 39 10q70 0 115-38t46-105q0-38-13-72h209q58 0 101-42t42-100z" horiz-adv-x="1000" />
+
+<glyph glyph-name="left-hand" unicode="&#x2269;" d="M768 64h18v357h-18q-20 0-38 7t-35 21-28 25-27 31q-4 5-7 7-40 46-62 81-8 13-21 38-1 2-6 13t-10 20-12 20-12 17-10 6q-40 0-64-17t-25-54q0-24 8-47t19-38 18-31 8-27h-321q-28 0-50-22t-22-50q0-29 22-50t50-21h185q-9-9-14-26t-6-31q0-39 30-67-10-18-10-38t9-41 27-30q-2-13-2-31 0-47 27-70t75-23q47 0 102 18t109 35 93 18z m161 36q0 15-11 25t-25 11-25-11-11-25 11-25 25-11 25 11 11 25z m71 321v-357q0-29-21-50t-50-21h-161q-33 0-125-33-106-39-176-39-80 0-129 44t-48 121l0 3q-34 42-34 99 0 12 2 24-19 32-21 67h-94q-59 0-101 42t-42 101q0 58 42 100t101 42h209q-13 34-13 72 0 68 46 105t115 38q21 0 39-10t31-28 22-35 21-40 18-35q20-30 56-72 1-1 8-9t10-12 12-12 13-13 13-10 13-8 12-2h161q29 0 50-21t21-51z" horiz-adv-x="1000" />
+
+<glyph glyph-name="left-circled" unicode="&#x226a;" d="M714 314v72q0 14-10 25t-25 10h-281l106 106q11 11 11 25t-11 25l-51 51q-10 10-25 10t-25-10l-202-202-51-51q-10-10-10-25t10-25l51-51 202-202q10-10 25-10t25 10l51 51q10 10 10 25t-10 25l-106 106h281q14 0 25 10t10 25z m143 36q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="right-circled" unicode="&#x226b;" d="M717 350q0 15-10 25l-51 51-202 202q-10 10-25 10t-25-10l-51-51q-10-10-10-25t10-25l106-106h-280q-15 0-25-10t-11-25v-72q0-14 11-25t25-10h280l-106-106q-10-10-10-25t10-25l51-51q10-10 25-10t25 10l202 202 51 51q10 10 10 25z m140 0q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="expand-right" unicode="&#x2276;" d="M607 350q0-18-15-29l-250-179q-17-12-37-2-19 9-19 31v358q0 22 19 31 20 10 37-2l250-179q15-11 15-29z m107-268v536q0 8-5 13t-13 5h-535q-8 0-13-5t-5-13v-536q0-8 5-13t13-5h535q8 0 13 5t5 13z m143 536v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="collapse-left" unicode="&#x2277;" d="M571 529v-358q0-14-10-25t-25-10q-11 0-21 6l-250 179q-15 11-15 29t15 29l250 179q10 6 21 6 14 0 25-10t10-25z m143-447v536q0 7-5 12t-13 6h-535q-7 0-13-6t-5-12v-536q0-7 5-12t13-6h535q8 0 13 6t5 12z m143 536v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="right-open-small" unicode="&#x22a2;" 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="left-open-small" unicode="&#x22a3;" 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="download-cloud" unicode="&#xe800;" d="M714 332q0 8-5 13t-13 5h-125v196q0 8-5 13t-12 5h-108q-7 0-12-5t-5-13v-196h-125q-8 0-13-5t-5-13q0-8 5-13l196-196q5-5 13-5t13 5l196 196q5 6 5 13z m357-125q0-89-62-151t-152-63h-607q-103 0-177 73t-73 177q0 72 39 134t105 92q-1 17-1 24 0 118 84 202t202 84q87 0 159-49t105-129q40 35 93 35 59 0 101-42t42-101q0-43-23-77 72-17 119-76t46-133z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="upload-cloud" unicode="&#xe801;" d="M714 368q0 8-5 13l-196 196q-5 5-13 5t-13-5l-196-196q-5-6-5-13 0-8 5-13t13-5h125v-196q0-8 5-13t12-5h108q7 0 12 5t5 13v196h125q8 0 13 5t5 13z m357-161q0-89-62-151t-152-63h-607q-103 0-177 73t-73 177q0 72 39 134t105 92q-1 17-1 24 0 118 84 202t202 84q87 0 159-49t105-129q40 35 93 35 59 0 101-42t42-101q0-43-23-77 72-17 119-76t46-133z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="reply" unicode="&#xe802;" d="M1000 225q0-93-71-252-1-4-6-13t-7-17-7-12q-7-10-16-10-8 0-13 6t-5 14q0 5 1 15t2 13q3 38 3 69 0 56-10 101t-27 77-45 56-59 39-74 24-86 12-98 3h-125v-143q0-14-10-25t-26-11-25 11l-285 286q-11 10-11 25t11 25l285 286q11 10 25 10t26-10 10-25v-143h125q398 0 488-225 30-75 30-186z" horiz-adv-x="1000" />
+
+<glyph glyph-name="reply-all" unicode="&#xe803;" d="M357 246v-39q0-23-22-33-7-3-14-3-15 0-25 11l-285 286q-11 10-11 25t11 25l285 286q17 17 39 8 22-10 22-33v-39l-221-222q-11-11-11-25t11-25z m643-21q0-32-9-74t-22-77-27-70-22-51l-11-22q-5-10-16-10-3 0-5 1-14 4-13 19 24 223-59 315-36 40-95 62t-150 29v-140q0-23-21-33-8-3-14-3-15 0-25 11l-286 286q-11 10-11 25t11 25l286 286q16 17 39 8 21-10 21-33v-147q230-15 335-123 94-96 94-284z" horiz-adv-x="1000" />
+
+<glyph glyph-name="forward" unicode="&#xe804;" d="M1000 493q0-15-11-25l-285-286q-11-11-25-11t-25 11-11 25v143h-125q-55 0-98-3t-86-12-74-24-59-39-45-56-27-77-10-101q0-31 3-69 0-4 2-13t1-15q0-8-5-14t-13-6q-9 0-15 10-4 5-8 12t-7 17-6 13q-71 159-71 252 0 111 30 186 90 225 488 225h125v143q0 14 11 25t25 10 25-10l285-286q11-11 11-25z" horiz-adv-x="1000" />
+
+<glyph glyph-name="quote-left" unicode="&#xe805;" d="M429 314v-214q0-45-32-76t-76-31h-214q-44 0-76 31t-31 76v393q0 58 23 111t61 91 91 61 111 23h35q15 0 26-11t10-25v-72q0-14-10-25t-26-10h-35q-59 0-101-42t-42-101v-18q0-22 16-38t37-16h125q45 0 76-31t32-76z m500 0v-214q0-45-32-76t-76-31h-214q-44 0-76 31t-31 76v393q0 58 23 111t61 91 91 61 111 23h35q15 0 26-11t10-25v-72q0-14-10-25t-26-10h-35q-59 0-101-42t-42-101v-18q0-22 16-38t37-16h125q45 0 76-31t32-76z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="quote-right" unicode="&#xe806;" d="M429 671v-392q0-58-23-111t-61-91-91-61-111-23h-36q-14 0-25 11t-11 25v71q0 15 11 25t25 11h36q59 0 101 42t42 101v17q0 23-16 38t-38 16h-125q-44 0-76 31t-31 76v214q0 45 31 76t76 32h214q45 0 76-32t32-76z m500 0v-392q0-58-23-111t-61-91-91-61-111-23h-36q-14 0-25 11t-11 25v71q0 15 11 25t25 11h36q59 0 101 42t42 101v17q0 23-16 38t-38 16h-125q-44 0-76 31t-31 76v214q0 45 31 76t76 32h214q45 0 76-32t32-76z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="code" unicode="&#xe807;" d="M344 69l-28-28q-5-5-12-5t-13 5l-260 261q-6 5-6 12t6 13l260 260q5 6 13 6t12-6l28-28q6-5 6-13t-6-12l-219-220 219-219q6-6 6-13t-6-13z m330 596l-208-721q-2-7-9-11t-13-1l-34 9q-8 3-11 9t-2 14l209 720q2 8 8 11t13 2l35-10q7-2 11-9t1-13z m367-363l-260-261q-6-5-13-5t-13 5l-28 28q-5 6-5 13t5 13l219 219-219 220q-5 5-5 12t5 13l28 28q6 6 13 6t13-6l260-260q5-5 5-13t-5-12z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="export" unicode="&#xe808;" d="M786 298v-144q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h142q7 0 13-6t5-12q0-15-15-18-43-15-74-34-5-2-9-2h-62q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63v119q0 11 10 16 16 7 31 21 8 9 19 4 12-5 12-16z m132 277l-214-214q-10-11-25-11-7 0-14 3-22 9-22 33v107h-89q-181 0-245-73-66-77-41-264 2-13-11-19-5-1-7-1-9 0-14 7-6 8-12 17t-22 39-28 55-21 64-10 68q0 27 2 51t8 50 15 49 27 45 38 42 52 34 70 27 89 17 110 6h89v107q0 24 22 33 7 3 14 3 14 0 25-11l214-214q11-10 11-25t-11-25z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="export-alt" unicode="&#xe809;" d="M561 236l196 196q11 11 11 25t-11 25l-196 197q-17 17-39 8-22-10-22-33v-90q-66 0-120-11t-91-28-64-44-42-53-25-61-12-62-3-62q0-101 93-226 6-6 14-6 4 0 7 1 13 5 11 19-25 197 35 264 25 29 72 42t125 13v-89q0-24 22-33 7-3 14-3 14 0 25 11z m296 382v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="share" unicode="&#xe80a;" d="M679 279q74 0 126-53t52-126-52-126-126-53-127 53-52 126q0 7 1 19l-201 100q-51-48-121-48-75 0-127 53t-52 126 52 126 127 53q70 0 121-48l201 100q-1 12-1 19 0 74 52 126t127 53 126-53 52-126-52-126-126-53q-71 0-122 48l-201-100q1-12 1-19t-1-19l201-100q51 48 122 48z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="share-squared" unicode="&#xe80b;" d="M714 183q0 49-35 84t-84 36q-46 0-80-33l-135 67q1 9 1 13t-1 13l135 67q34-33 80-33 50 0 84 36t35 84-35 84-84 35-84-35-35-84q0-4 1-13l-134-67q-35 32-81 32-49 0-84-35t-35-84 35-84 84-35q46 0 81 32l134-67q-1-9-1-13 0-49 35-84t84-35 84 35 35 84z m143 435v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="pencil" unicode="&#xe80c;" d="M203-7l50 51-131 131-51-51v-60h72v-71h60z m291 518q0 12-12 12-5 0-9-4l-303-302q-4-4-4-10 0-12 13-12 5 0 9 4l303 302q3 4 3 10z m-30 107l232-232-464-465h-232v233z m381-54q0-29-20-50l-93-93-232 233 93 92q20 21 50 21 29 0 51-21l131-131q20-22 20-51z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="pencil-squared" unicode="&#xe80d;" d="M225 232l85-85-29-29h-31v53h-54v32z m232 217q7-7-2-16l-163-163q-9-9-16-1-8 7 1 16l163 163q9 9 17 1z m-153-385l303 304-161 161-303-304v-161h161z m339 340l51 51q16 16 16 38t-16 38l-85 85q-15 15-38 15t-37-15l-52-52z m214 214v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="edit" unicode="&#xe80e;" d="M496 189l64 65-85 85-64-65v-31h53v-54h32z m245 402q-9 9-18 0l-196-196q-9-9 0-18t18 0l196 196q9 9 0 18z m45-331v-106q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h464q35 0 65-14 9-4 10-13 2-10-5-16l-27-28q-8-8-18-4-13 3-25 3h-464q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63v70q0 7 5 12l36 36q8 8 20 4t11-16z m-54 411l161-160-375-375h-161v160z m248-73l-51-52-161 161 51 52q16 15 38 15t38-15l85-85q16-16 16-38t-16-38z" horiz-adv-x="1000" />
+
+<glyph glyph-name="print" unicode="&#xe80f;" d="M214-7h500v143h-500v-143z m0 357h500v214h-89q-22 0-38 16t-16 38v89h-357v-357z m643-36q0 15-10 25t-26 11-25-11-10-25 10-25 25-10 26 10 10 25z m72 0v-232q0-7-6-12t-12-6h-125v-89q0-22-16-38t-38-16h-536q-22 0-37 16t-16 38v89h-125q-7 0-13 6t-5 12v232q0 44 32 76t75 31h36v304q0 22 16 38t37 16h375q23 0 50-12t42-26l85-85q15-16 27-43t11-49v-143h35q45 0 76-31t32-76z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="retweet" unicode="&#xe810;" d="M714 11q0-7-5-13t-13-5h-535q-5 0-8 1t-5 4-3 4-2 7 0 6v335h-107q-15 0-25 11t-11 25q0 13 8 23l179 214q11 12 27 12t28-12l178-214q9-10 9-23 0-15-11-25t-25-11h-107v-214h321q9 0 14-6l89-108q4-5 4-11z m357 232q0-13-8-23l-178-214q-12-13-28-13t-27 13l-179 214q-8 10-8 23 0 14 11 25t25 11h107v214h-322q-9 0-14 7l-89 107q-4 5-4 11 0 7 5 12t13 6h536q4 0 7-1t5-4 3-5 2-6 1-7v-334h107q14 0 25-11t10-25z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="keyboard" unicode="&#xe811;" d="M214 198v-53q0-9-9-9h-53q-9 0-9 9v53q0 9 9 9h53q9 0 9-9z m72 143v-53q0-9-9-9h-125q-9 0-9 9v53q0 9 9 9h125q9 0 9-9z m-72 143v-54q0-9-9-9h-53q-9 0-9 9v54q0 9 9 9h53q9 0 9-9z m572-286v-53q0-9-9-9h-482q-9 0-9 9v53q0 9 9 9h482q9 0 9-9z m-357 143v-53q0-9-9-9h-54q-9 0-9 9v53q0 9 9 9h54q9 0 9-9z m-72 143v-54q0-9-9-9h-53q-9 0-9 9v54q0 9 9 9h53q9 0 9-9z m214-143v-53q0-9-8-9h-54q-9 0-9 9v53q0 9 9 9h54q8 0 8-9z m-71 143v-54q0-9-9-9h-53q-9 0-9 9v54q0 9 9 9h53q9 0 9-9z m214-143v-53q0-9-9-9h-53q-9 0-9 9v53q0 9 9 9h53q9 0 9-9z m215-143v-53q0-9-9-9h-54q-9 0-9 9v53q0 9 9 9h54q9 0 9-9z m-286 286v-54q0-9-9-9h-54q-9 0-9 9v54q0 9 9 9h54q9 0 9-9z m143 0v-54q0-9-9-9h-54q-9 0-9 9v54q0 9 9 9h54q9 0 9-9z m143 0v-196q0-9-9-9h-125q-9 0-9 9v53q0 9 9 9h62v134q0 9 9 9h54q9 0 9-9z m71-420v500h-929v-500h929z m71 500v-500q0-29-20-50t-51-21h-929q-29 0-50 21t-21 50v500q0 30 21 51t50 21h929q30 0 51-21t20-51z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="gamepad" unicode="&#xe812;" d="M464 243v71q0 8-5 13t-13 5h-107v107q0 8-5 13t-13 5h-71q-8 0-13-5t-5-13v-107h-107q-8 0-13-5t-5-13v-71q0-8 5-13t13-5h107v-107q0-8 5-13t13-5h71q8 0 13 5t5 13v107h107q8 0 13 5t5 13z m322-36q0 30-21 51t-51 21-50-21-21-51 21-50 50-21 51 21 21 50z m143 143q0 30-21 51t-51 20-50-20-21-51 21-50 50-21 51 21 21 50z m142-71q0-119-83-202t-202-84q-107 0-189 71h-123q-81-71-188-71-119 0-202 84t-84 202 84 202 202 83h500q118 0 202-83t83-202z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="comment" unicode="&#xe813;" d="M1000 350q0-97-67-179t-182-130-251-48q-39 0-81 4-110-97-257-135-27-8-63-12-10-1-17 5t-10 16v1q-2 2 0 6t1 6 2 5l4 5t4 5 4 5q4 5 17 19t20 22 17 22 18 28 15 33 15 42q-88 50-138 123t-51 157q0 73 40 139t106 114 160 76 194 28q136 0 251-48t182-130 67-179z" horiz-adv-x="1000" />
+
+<glyph glyph-name="chat" unicode="&#xe814;" d="M786 421q0-77-53-143t-143-104-197-38q-48 0-98 9-70-49-155-72-21-5-48-9h-2q-6 0-12 5t-6 12q-1 1-1 3t1 4 1 3l1 3t2 3 2 3 3 3 2 2q3 3 13 14t15 16 12 17 14 21 11 25q-69 40-108 98t-40 125q0 78 53 144t143 104 197 38 197-38 143-104 53-144z m214-142q0-67-40-126t-108-98q5-14 11-25t14-21 13-16 14-17 13-14q0 0 2-2t3-3 2-3 2-3l1-3t1-3 1-4-1-3q-2-8-7-13t-12-4q-28 4-48 9-86 23-156 72-50-9-98-9-151 0-263 74 32-3 49-3 90 0 172 25t148 72q69 52 107 119t37 141q0 43-13 85 72-39 114-99t42-128z" horiz-adv-x="1000" />
+
+<glyph glyph-name="comment-empty" unicode="&#xe815;" d="M500 636q-114 0-213-39t-157-105-59-142q0-62 40-119t113-98l48-28-15-53q-13-51-39-97 85 36 154 96l24 21 32-3q38-5 72-5 114 0 213 39t157 105 59 142-59 142-157 105-213 39z m500-286q0-97-67-179t-182-130-251-48q-39 0-81 4-110-97-257-135-27-8-63-12h-3q-8 0-15 6t-9 15v1q-2 2 0 6t1 6 2 5l4 5t4 5 4 5q4 5 17 19t20 22 17 22 18 28 15 33 15 42q-88 50-138 123t-51 157q0 97 67 179t182 130 251 48 251-48 182-130 67-179z" horiz-adv-x="1000" />
+
+<glyph glyph-name="chat-empty" unicode="&#xe816;" d="M393 636q-85 0-160-29t-118-79-44-107q0-45 30-88t83-73l54-32-19-46q19 11 34 21l25 18 30-6q43-8 85-8 85 0 160 29t118 79 43 106-43 107-118 79-160 29z m0 71q106 0 197-38t143-104 53-144-53-143-143-104-197-38q-48 0-98 9-70-49-155-72-21-5-48-9h-2q-6 0-12 5t-6 12q-1 1-1 3t1 4 1 3l1 3t2 3 2 3 3 3 2 2q3 3 13 14t15 16 12 17 14 21 11 25q-69 40-108 98t-40 125q0 78 53 144t143 104 197 38z m459-652q5-14 11-25t14-21 13-16 14-17 13-14q0 0 2-2t3-3 2-3 2-3l1-3t1-3 1-4-1-3q-2-8-7-13t-12-4q-28 4-48 9-86 23-156 72-50-9-98-9-151 0-263 74 32-3 49-3 90 0 172 25t148 72q69 52 107 119t37 141q0 43-13 85 72-39 114-99t42-128q0-67-40-126t-108-98z" horiz-adv-x="1000" />
+
+<glyph glyph-name="bell" unicode="&#xe817;" d="M509-96q0 8-9 8-33 0-57 24t-23 57q0 9-9 9t-9-9q0-41 29-70t69-28q9 0 9 9z m-372 160h726q-149 168-149 465 0 28-13 58t-39 58-67 45-95 17-95-17-67-45-39-58-13-58q0-297-149-465z m827 0q0-29-21-50t-50-21h-250q0-59-42-101t-101-42-101 42-42 101h-250q-29 0-50 21t-21 50q28 24 51 49t47 67 42 89 27 115 11 145q0 84 66 157t171 89q-5 10-5 21 0 23 16 38t38 16 38-16 16-38q0-11-5-21 106-16 171-89t66-157q0-78 11-145t28-115 41-89 48-67 50-49z" horiz-adv-x="1000" />
+
+<glyph glyph-name="bell-alt" unicode="&#xe818;" d="M509-96q0 8-9 8-33 0-57 24t-23 57q0 9-9 9t-9-9q0-41 29-70t69-28q9 0 9 9z m455 160q0-29-21-50t-50-21h-250q0-59-42-101t-101-42-101 42-42 101h-250q-29 0-50 21t-21 50q28 24 51 49t47 67 42 89 27 115 11 145q0 84 66 157t171 89q-5 10-5 21 0 23 16 38t38 16 38-16 16-38q0-11-5-21 106-16 171-89t66-157q0-78 11-145t28-115 41-89 48-67 50-49z" horiz-adv-x="1000" />
+
+<glyph glyph-name="bell-off" unicode="&#xe819;" d="M869 375q35-199 167-311 0-29-21-50t-51-21h-250q0-59-42-101t-101-42-100 42-42 100z m-298-480q9 0 9 9t-9 8q-32 0-56 24t-24 57q0 9-9 9t-9-9q0-41 29-70t69-28z m560 893q4-6 4-14t-6-12l-1045-905q-5-5-13-4t-12 6l-47 53q-4 6-4 14t6 12l104 90q-11 17-11 36 28 24 51 49t47 67 42 89 28 115 11 145q0 84 65 157t171 89q-4 10-4 21 0 23 16 38t37 16 38-16 16-38q0-11-4-21 69-10 122-46t82-88l234 202q5 5 13 4t12-6z" horiz-adv-x="1142.9" />
+
+<glyph glyph-name="bell-off-empty" unicode="&#xe81a;" d="M580-96q0 8-9 8-32 0-56 24t-24 57q0 9-9 9t-9-9q0-41 29-70t69-28q9 0 9 9z m-299 265l489 424q-23 49-74 82t-125 32q-51 0-94-17t-68-45-38-58-14-58q0-215-76-360z m755-105q0-29-21-50t-51-21h-250q0-59-42-101t-101-42-100 42-42 100l83 72h422q-92 105-126 256l61 55q35-199 167-311z m48 777l47-53q4-6 4-14t-6-12l-1045-905q-5-5-13-4t-12 6l-47 53q-4 6-4 14t6 12l104 90q-11 17-11 36 28 24 51 49t47 67 42 89 28 115 11 145q0 84 65 157t171 89q-4 10-4 21 0 23 16 38t37 16 38-16 16-38q0-11-4-21 69-10 122-46t82-88l234 202q5 5 13 4t12-6z" horiz-adv-x="1142.9" />
+
+<glyph glyph-name="attention-alt" unicode="&#xe81b;" d="M286 154v-125q0-15-11-25t-25-11h-143q-14 0-25 11t-11 25v125q0 14 11 25t25 10h143q15 0 25-10t11-25z m17 589l-16-429q-1-14-12-25t-25-10h-143q-14 0-25 10t-12 25l-15 429q-1 14 10 25t24 11h179q14 0 25-11t10-25z" horiz-adv-x="357.1" />
+
+<glyph glyph-name="attention" unicode="&#xe81c;" d="M571 83v106q0 8-5 13t-12 5h-108q-7 0-12-5t-5-13v-106q0-8 5-13t12-6h108q7 0 12 6t5 13z m-1 208l10 257q0 6-5 10-7 6-14 6h-122q-6 0-14-6-5-4-5-12l9-255q0-5 6-9t13-3h103q8 0 14 3t5 9z m-7 522l428-786q20-35-1-70-9-17-26-26t-35-10h-858q-18 0-35 10t-26 26q-21 35-1 70l429 786q9 17 26 27t36 10 36-10 27-27z" horiz-adv-x="1000" />
+
+<glyph glyph-name="attention-circled" unicode="&#xe81d;" d="M429 779q116 0 215-58t156-156 57-215-57-215-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58z m71-696v106q0 8-5 13t-12 5h-107q-8 0-13-5t-6-13v-106q0-8 6-13t13-6h107q7 0 12 6t5 13z m-1 192l10 346q0 7-6 10-5 5-13 5h-123q-8 0-13-5-6-3-6-10l10-346q0-6 5-10t14-4h103q8 0 13 4t6 10z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="location" unicode="&#xe81e;" d="M429 493q0 59-42 101t-101 42-101-42-42-101 42-101 101-42 101 42 42 101z m142 0q0-61-18-100l-203-432q-9-18-27-29t-37-11-38 11-26 29l-204 432q-18 39-18 100 0 118 84 202t202 84 202-84 83-202z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="direction" unicode="&#xe81f;" d="M782 655l-357-714q-10-20-32-20-3 0-8 1-13 3-20 13t-8 22v322h-321q-13 0-22 7t-13 20 2 23 17 17l714 357q7 4 16 4 15 0 25-10 9-8 10-20t-3-22z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="compass" unicode="&#xe820;" d="M357 243l143 71-143 72v-143z m214 330v-303l-285-143v303z m161-223q0 83-41 152t-110 111-152 41-153-41-110-111-41-152 41-152 110-111 153-41 152 41 110 111 41 152z m125 0q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="trash-alt" unicode="&#xe821;" d="M286 82v393q0 8-5 13t-13 5h-36q-8 0-13-5t-5-13v-393q0-8 5-13t13-5h36q8 0 13 5t5 13z m143 0v393q0 8-5 13t-13 5h-36q-8 0-13-5t-5-13v-393q0-8 5-13t13-5h36q8 0 13 5t5 13z m142 0v393q0 8-5 13t-12 5h-36q-8 0-13-5t-5-13v-393q0-8 5-13t13-5h36q7 0 12 5t5 13z m-303 554h250l-27 65q-4 5-9 6h-177q-6-1-10-6z m518-18v-36q0-8-5-13t-13-5h-54v-529q0-46-26-80t-63-34h-464q-37 0-63 33t-27 79v531h-53q-8 0-13 5t-5 13v36q0 8 5 13t13 5h172l39 93q9 21 31 35t44 15h178q23 0 44-15t30-35l39-93h173q8 0 13-5t5-13z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="trash" unicode="&#xe822;" d="M286 439v-321q0-8-5-13t-13-5h-36q-8 0-13 5t-5 13v321q0 8 5 13t13 5h36q8 0 13-5t5-13z m143 0v-321q0-8-5-13t-13-5h-36q-8 0-13 5t-5 13v321q0 8 5 13t13 5h36q8 0 13-5t5-13z m142 0v-321q0-8-5-13t-12-5h-36q-8 0-13 5t-5 13v321q0 8 5 13t13 5h36q7 0 12-5t5-13z m72-404v529h-500v-529q0-12 4-22t8-15 6-5h464q2 0 6 5t8 15 4 22z m-375 601h250l-27 65q-4 5-9 6h-177q-6-1-10-6z m518-18v-36q0-8-5-13t-13-5h-54v-529q0-46-26-80t-63-34h-464q-37 0-63 33t-27 79v531h-53q-8 0-13 5t-5 13v36q0 8 5 13t13 5h172l39 93q9 21 31 35t44 15h178q23 0 44-15t30-35l39-93h173q8 0 13-5t5-13z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="doc" unicode="&#xe823;" d="M819 638q16-16 27-42t11-50v-642q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h500q22 0 49-11t42-27z m-248 136v-210h210q-5 17-12 23l-175 175q-6 7-23 12z m215-853v572h-232q-23 0-38 16t-16 37v233h-429v-858h715z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="docs" unicode="&#xe824;" d="M946 636q23 0 38-16t16-38v-678q0-23-16-38t-38-16h-535q-23 0-38 16t-16 38v160h-303q-23 0-38 16t-16 38v375q0 22 11 49t27 42l228 228q15 16 42 27t49 11h232q23 0 38-16t16-38v-183q38 23 71 23h232z m-303-119l-167-167h167v167z m-357 214l-167-167h167v167z m109-361l176 176v233h-214v-233q0-22-15-37t-38-16h-233v-357h286v143q0 22 11 49t27 42z m534-449v643h-215v-232q0-22-15-38t-38-15h-232v-358h500z" horiz-adv-x="1000" />
+
+<glyph glyph-name="doc-text" unicode="&#xe825;" d="M819 638q16-16 27-42t11-50v-642q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h500q22 0 49-11t42-27z m-248 136v-210h210q-5 17-12 23l-175 175q-6 7-23 12z m215-853v572h-232q-23 0-38 16t-16 37v233h-429v-858h715z m-572 483q0 7 5 12t13 5h393q8 0 13-5t5-12v-36q0-8-5-13t-13-5h-393q-8 0-13 5t-5 13v36z m411-125q8 0 13-5t5-13v-36q0-8-5-13t-13-5h-393q-8 0-13 5t-5 13v36q0 8 5 13t13 5h393z m0-143q8 0 13-5t5-13v-36q0-8-5-13t-13-5h-393q-8 0-13 5t-5 13v36q0 8 5 13t13 5h393z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="doc-inv" unicode="&#xe826;" d="M571 564v264q13-8 21-16l227-228q8-7 16-20h-264z m-71-18q0-22 16-37t38-16h303v-589q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h446v-304z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="doc-text-inv" unicode="&#xe827;" d="M819 584q8-7 16-20h-264v264q13-8 21-16z m-265-91h303v-589q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h446v-304q0-22 16-37t38-16z m89-411v36q0 8-5 13t-13 5h-393q-8 0-13-5t-5-13v-36q0-8 5-13t13-5h393q8 0 13 5t5 13z m0 143v36q0 8-5 13t-13 5h-393q-8 0-13-5t-5-13v-36q0-8 5-13t13-5h393q8 0 13 5t5 13z m0 143v36q0 7-5 12t-13 5h-393q-8 0-13-5t-5-12v-36q0-8 5-13t13-5h393q8 0 13 5t5 13z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="folder" unicode="&#xe828;" d="M929 511v-393q0-51-37-88t-88-37h-679q-51 0-88 37t-37 88v536q0 51 37 88t88 37h179q51 0 88-37t37-88v-18h375q51 0 88-37t37-88z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="folder-open" unicode="&#xe829;" d="M1049 319q0-17-18-37l-187-221q-24-28-67-48t-81-20h-607q-19 0-33 7t-15 24q0 17 17 37l188 221q24 28 67 48t80 20h607q19 0 34-7t15-24z m-192 192v-90h-464q-53 0-110-26t-92-67l-188-221-2-3q0 2-1 7t0 7v536q0 51 37 88t88 37h179q51 0 88-37t37-88v-18h303q52 0 88-37t37-88z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="folder-empty" unicode="&#xe82a;" d="M857 118v393q0 22-15 38t-38 15h-393q-23 0-38 16t-16 38v36q0 22-15 38t-38 15h-179q-22 0-38-15t-16-38v-536q0-22 16-38t38-16h679q22 0 38 16t15 38z m72 393v-393q0-51-37-88t-88-37h-679q-51 0-88 37t-37 88v536q0 51 37 88t88 37h179q51 0 88-37t37-88v-18h375q51 0 88-37t37-88z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="folder-open-empty" unicode="&#xe82b;" d="M994 331q0 19-30 19h-607q-22 0-48-12t-39-29l-164-203q-11-13-11-22 0-20 30-20h607q23 0 48 13t40 29l164 203q10 12 10 22z m-637 90h429v90q0 22-16 38t-38 15h-321q-23 0-38 16t-16 38v36q0 22-15 38t-38 15h-179q-22 0-38-15t-16-38v-476l143 175q25 30 65 49t78 19z m708-90q0-35-25-67l-165-203q-24-30-65-49t-78-19h-607q-51 0-88 37t-37 88v536q0 51 37 88t88 37h179q51 0 88-37t37-88v-18h303q52 0 88-37t37-88v-90h107q30 0 56-13t37-40q8-17 8-37z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="box" unicode="&#xe82c;" d="M607 386q0 14-10 25t-26 10h-142q-15 0-25-10t-11-25 11-25 25-11h142q15 0 26 11t10 25z m322 107v-536q0-14-11-25t-25-11h-786q-14 0-25 11t-11 25v536q0 14 11 25t25 11h786q14 0 25-11t11-25z m35 250v-143q0-14-10-25t-25-11h-858q-14 0-25 11t-10 25v143q0 14 10 25t25 11h858q14 0 25-11t10-25z" horiz-adv-x="1000" />
+
+<glyph glyph-name="rss" unicode="&#xe82d;" d="M214 100q0-45-31-76t-76-31-76 31-31 76 31 76 76 31 76-31 31-76z m286-69q1-15-9-26-10-12-27-12h-75q-14 0-24 9t-11 23q-12 128-103 219t-219 103q-14 1-23 11t-9 24v75q0 16 12 26 9 10 24 10h3q89-7 170-45t145-101q63-63 101-145t45-171z m286-1q1-15-10-26-10-11-26-11h-80q-14 0-25 10t-10 23q-7 120-57 228t-129 188-188 129-227 57q-14 1-24 11t-10 24v80q0 16 11 26 10 10 25 10h1q147-8 280-67t238-164q104-104 164-238t67-280z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="rss-squared" unicode="&#xe82e;" d="M286 136q0 29-21 50t-51 21-50-21-21-50 21-51 50-21 51 21 21 51z m196-53q-8 130-99 222t-221 98q-8 1-14-5t-5-13v-71q0-7 5-12t12-6q86-6 147-68t67-147q1-7 6-12t12-5h72q7 0 13 6t5 13z m214 0q-3 86-31 166t-78 145-115 114-145 78-166 31q-7 1-13-5-5-5-5-13v-71q0-7 5-12t12-6q114-4 211-62t156-155 62-211q0-8 5-13t13-5h71q7 0 13 6 6 5 5 13z m161 535v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="phone" unicode="&#xe82f;" d="M786 158q0-15-6-39t-12-38q-11-28-68-60-52-28-103-28-15 0-30 2t-32 7-26 8-31 11-28 10q-54 20-97 47-71 44-148 120t-120 148q-27 43-46 97-2 5-10 28t-12 31-8 26-7 32-2 29q0 52 29 104 31 57 59 68 14 6 38 12t39 6q8 0 12-2 10-3 30-42 6-11 16-31t20-35 17-30q2-2 10-14t12-20 4-16q0-11-16-27t-35-31-34-30-16-25q0-5 3-13t4-11 8-14 7-10q42-77 97-132t131-97q1 0 10-6t14-8 11-5 13-2q10 0 25 16t30 34 31 35 28 16q7 0 15-4t20-12 14-10q14-8 30-17t36-20 30-17q39-19 42-29 2-4 2-12z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="phone-squared" unicode="&#xe830;" d="M714 184q0 6-1 9t-10 9-22 14-27 15-25 14-16 9q-3 1-11 7t-14 8-11 3q-9 0-21-12t-22-25-21-25-19-11q-4 0-9 2t-9 3-9 6-8 4q-55 31-95 71t-71 95q-1 2-5 8t-5 9-4 9-2 9q0 8 12 19t25 22 25 22 11 20q0 6-2 12t-9 14-7 10q-2 4-8 16t-14 25-15 27-14 23-9 10-9 1q-27 0-56-13-26-11-45-52t-19-73q0-9 1-19t3-17 5-18 6-17 7-18 6-17q33-92 121-179t178-121q4-1 17-6t19-7 16-5 19-5 17-3 19-2q31 0 72 19t53 45q12 30 12 56z m143 434v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="fax" unicode="&#xe831;" d="M161 636q37 0 63-26t26-64v-607q0-37-26-63t-63-26h-72q-36 0-63 26t-26 63v607q0 37 26 64t63 26h72z m768-91q32-19 52-52t19-72v-428q0-59-42-101t-101-42h-482q-37 0-63 26t-26 63v857q0 23 15 38t38 16h375q23 0 49-11t43-27l85-85q15-15 26-42t12-49v-91z m-411-552v71q0 8-5 13t-13 5h-71q-8 0-13-5t-5-13v-71q0-8 5-13t13-5h71q8 0 13 5t5 13z m0 143v71q0 8-5 13t-13 5h-71q-8 0-13-5t-5-13v-71q0-8 5-13t13-5h71q8 0 13 5t5 13z m0 143v71q0 8-5 13t-13 5h-71q-8 0-13-5t-5-13v-71q0-8 5-13t13-5h71q8 0 13 5t5 13z m143-286v71q0 8-5 13t-13 5h-72q-7 0-12-5t-5-13v-71q0-8 5-13t12-5h72q8 0 13 5t5 13z m0 143v71q0 8-5 13t-13 5h-72q-7 0-12-5t-5-13v-71q0-8 5-13t12-5h72q8 0 13 5t5 13z m0 143v71q0 8-5 13t-13 5h-72q-7 0-12-5t-5-13v-71q0-8 5-13t12-5h72q8 0 13 5t5 13z m143-286v71q0 8-5 13t-13 5h-72q-7 0-12-5t-6-13v-71q0-8 6-13t12-5h72q8 0 13 5t5 13z m0 143v71q0 8-5 13t-13 5h-72q-7 0-12-5t-6-13v-71q0-8 6-13t12-5h72q8 0 13 5t5 13z m0 143v71q0 8-5 13t-13 5h-72q-7 0-12-5t-6-13v-71q0-8 6-13t12-5h72q8 0 13 5t5 13z m53 214v143h-89q-22 0-38 15t-16 38v90h-357v-286h500z" horiz-adv-x="1000" />
+
+<glyph glyph-name="menu" unicode="&#xe832;" d="M857 100v-71q0-15-10-25t-26-11h-785q-15 0-25 11t-11 25v71q0 15 11 25t25 11h785q15 0 26-11t10-25z m0 286v-72q0-14-10-25t-26-10h-785q-15 0-25 10t-11 25v72q0 14 11 25t25 10h785q15 0 26-10t10-25z m0 285v-71q0-14-10-25t-26-11h-785q-15 0-25 11t-11 25v71q0 15 11 26t25 10h785q15 0 26-10t10-26z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="cog" unicode="&#xe833;" d="M571 350q0 59-41 101t-101 42-101-42-42-101 42-101 101-42 101 42 41 101z m286 61v-124q0-7-4-13t-11-7l-104-16q-10-30-21-51 19-27 59-77 6-6 6-13t-5-13q-15-21-55-61t-53-39q-7 0-14 5l-77 60q-25-13-51-21-9-76-16-104-4-16-20-16h-124q-8 0-14 5t-6 12l-16 103q-27 9-50 21l-79-60q-6-5-14-5-8 0-14 6-70 64-92 94-4 5-4 13 0 6 5 12 8 12 28 37t30 40q-15 28-23 55l-102 15q-7 1-11 7t-5 13v124q0 7 5 13t10 7l104 16q8 25 22 51-23 32-60 77-6 7-6 14 0 5 5 12 15 20 55 60t53 40q7 0 15-5l77-60q24 13 50 21 9 76 17 104 3 16 20 16h124q7 0 13-5t7-12l15-103q28-9 51-20l79 59q5 5 13 5 7 0 14-5 72-67 92-95 4-5 4-12 0-7-4-13-9-12-29-37t-30-40q15-28 23-54l102-16q7-1 12-7t4-13z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="cog-alt" unicode="&#xe834;" d="M500 350q0 59-42 101t-101 42-101-42-42-101 42-101 101-42 101 42 42 101z m429-286q0 29-22 51t-50 21-50-21-21-51q0-29 21-50t50-21 51 21 21 50z m0 572q0 29-22 50t-50 21-50-21-21-50q0-30 21-51t50-21 51 21 21 51z m-215-235v-103q0-6-4-11t-8-6l-87-14q-6-19-18-42 19-27 50-64 4-6 4-11 0-7-4-11-12-17-46-50t-43-33q-7 0-12 4l-64 50q-21-11-43-17-6-60-13-87-4-13-17-13h-104q-6 0-11 4t-5 10l-13 85q-19 6-42 18l-66-50q-4-4-11-4-6 0-12 4-80 75-80 90 0 5 4 10 5 8 23 30t26 34q-13 24-20 46l-85 13q-5 1-9 5t-4 11v104q0 5 4 10t9 6l86 14q7 19 18 42-19 27-50 64-4 6-4 11 0 7 4 12 12 16 46 49t44 33q6 0 12-4l64-50q19 10 43 18 6 60 13 86 3 13 16 13h104q6 0 11-4t6-10l13-85q19-6 42-17l65 49q5 4 12 4 6 0 11-4 81-75 81-90 0-4-4-10-7-9-24-30t-25-34q13-27 19-46l85-12q6-2 9-6t4-11z m357-298v-78q0-9-83-17-6-15-16-29 28-63 28-77 0-2-2-4-68-40-69-40-5 0-26 27t-29 37q-11-1-17-1t-17 1q-7-11-29-37t-25-27q-1 0-69 40-3 2-3 4 0 14 29 77-10 14-17 29-83 8-83 17v78q0 9 83 18 7 16 17 29-29 63-29 77 0 2 3 4 2 1 19 11t33 19 17 9q4 0 25-26t29-38q12 1 17 1t17-1q28 40 51 63l4 1q2 0 69-39 2-2 2-4 0-14-28-77 9-13 16-29 83-9 83-18z m0 572v-78q0-9-83-18-6-15-16-29 28-63 28-77 0-2-2-4-68-39-69-39-5 0-26 26t-29 38q-11-1-17-1t-17 1q-7-12-29-38t-25-26q-1 0-69 39-3 2-3 4 0 14 29 77-10 14-17 29-83 9-83 18v78q0 9 83 17 7 16 17 29-29 63-29 77 0 2 3 4 2 1 19 11t33 19 17 9q4 0 25-26t29-37q12 1 17 1t17-1q28 39 51 62l4 1q2 0 69-39 2-2 2-4 0-14-28-77 9-13 16-29 83-8 83-17z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="wrench" unicode="&#xe835;" d="M214 29q0 14-10 25t-25 10-25-10-11-25 11-25 25-11 25 11 10 25z m360 234l-381-381q-21-20-50-20-29 0-51 20l-59 61q-21 20-21 50 0 29 21 51l380 380q22-55 64-97t97-64z m354 243q0-22-13-59-27-75-92-122t-144-46q-104 0-177 73t-73 177 73 176 177 74q32 0 67-10t60-26q9-6 9-15t-9-16l-163-94v-125l108-60q2 2 44 27t75 45 40 20q8 0 13-5t5-14z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="sliders" unicode="&#xe836;" d="M196 64v-71h-196v71h196z m197 72q14 0 25-11t11-25v-143q0-14-11-25t-25-11h-143q-14 0-25 11t-11 25v143q0 15 11 25t25 11h143z m89 214v-71h-482v71h482z m-357 286v-72h-125v72h125z m732-572v-71h-411v71h411z m-536 643q15 0 26-10t10-26v-142q0-15-10-25t-26-11h-142q-15 0-25 11t-11 25v142q0 15 11 26t25 10h142z m358-286q14 0 25-10t10-25v-143q0-15-10-25t-25-11h-143q-15 0-25 11t-11 25v143q0 14 11 25t25 10h143z m178-71v-71h-125v71h125z m0 286v-72h-482v72h482z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="basket" unicode="&#xe837;" d="M357-7q0-29-21-50t-50-22-50 22-22 50 22 50 50 21 50-21 21-50z m500 0q0-29-21-50t-50-22-50 22-22 50 22 50 50 21 50-21 21-50z m72 607v-286q0-13-10-23t-22-12l-583-68q7-34 7-40 0-8-13-35h513q15 0 26-11t10-25-10-25-26-11h-571q-14 0-25 11t-11 25q0 6 5 18t9 20 12 22 8 17l-98 459h-114q-15 0-25 10t-11 25 11 26 25 10h143q9 0 16-3t10-9 8-14 4-14 3-17 3-14h670q14 0 25-11t11-25z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="calendar" unicode="&#xe838;" d="M71-79h161v161h-161v-161z m197 0h178v161h-178v-161z m-197 197h161v178h-161v-178z m197 0h178v178h-178v-178z m-197 214h161v161h-161v-161z m411-411h179v161h-179v-161z m-214 411h178v161h-178v-161z m428-411h161v161h-161v-161z m-214 197h179v178h-179v-178z m-196 482v161q0 7-6 12t-12 6h-36q-7 0-12-6t-6-12v-161q0-7 6-13t12-5h36q7 0 12 5t6 13z m410-482h161v178h-161v-178z m-214 214h179v161h-179v-161z m214 0h161v161h-161v-161z m18 268v161q0 7-5 12t-13 6h-35q-7 0-13-6t-5-12v-161q0-7 5-13t13-5h35q8 0 13 5t5 13z m215 36v-715q0-29-22-50t-50-21h-786q-29 0-50 21t-21 50v715q0 29 21 50t50 21h72v54q0 37 26 63t63 26h36q37 0 63-26t26-63v-54h214v54q0 37 27 63t63 26h35q37 0 64-26t26-63v-54h71q29 0 50-21t22-50z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="calendar-empty" unicode="&#xe839;" d="M71-79h786v572h-786v-572z m215 679v161q0 8-5 13t-13 5h-36q-8 0-13-5t-5-13v-161q0-8 5-13t13-5h36q8 0 13 5t5 13z m428 0v161q0 8-5 13t-13 5h-35q-8 0-13-5t-5-13v-161q0-8 5-13t13-5h35q8 0 13 5t5 13z m215 36v-715q0-29-22-50t-50-21h-786q-29 0-50 21t-21 50v715q0 29 21 50t50 21h72v54q0 37 26 63t63 26h36q37 0 63-26t26-63v-54h214v54q0 37 27 63t63 26h35q37 0 64-26t26-63v-54h71q29 0 50-21t22-50z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="login" unicode="&#xe83a;" d="M661 350q0-14-11-25l-303-304q-11-10-26-10t-25 10-10 25v161h-250q-15 0-25 11t-11 25v214q0 15 11 25t25 11h250v161q0 14 10 25t25 10 26-10l303-304q11-10 11-25z m196 196v-392q0-67-47-114t-114-47h-178q-7 0-13 5t-5 13q0 2-1 11t0 15 2 13 5 11 12 3h178q37 0 64 27t26 63v392q0 37-26 64t-64 26h-174t-6 0-6 2-5 3-4 5-1 8q0 2-1 11t0 15 2 13 5 11 12 3h178q67 0 114-47t47-114z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="logout" unicode="&#xe83b;" d="M357 46q0-2 1-11t0-14-2-14-5-11-12-3h-178q-67 0-114 47t-47 114v392q0 67 47 114t114 47h178q8 0 13-5t5-13q0-2 1-11t0-15-2-13-5-11-12-3h-178q-37 0-63-26t-27-64v-392q0-37 27-63t63-27h174t6 0 7-2 4-3 4-5 1-8z m518 304q0-14-11-25l-303-304q-11-10-25-10t-25 10-11 25v161h-250q-14 0-25 11t-11 25v214q0 15 11 25t25 11h250v161q0 14 11 25t25 10 25-10l303-304q11-10 11-25z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="mic" unicode="&#xe83c;" d="M643 457v-71q0-124-82-215t-204-104v-74h143q15 0 25-11t11-25-11-25-25-11h-357q-15 0-25 11t-11 25 11 25 25 11h143v74q-121 13-204 104t-82 215v71q0 15 11 25t25 11 25-11 10-25v-71q0-103 74-177t176-73 177 73 73 177v71q0 15 11 25t25 11 25-11 11-25z m-143 214v-285q0-74-52-126t-127-53-126 53-52 126v285q0 74 52 127t126 52 127-52 52-127z" horiz-adv-x="642.9" />
+
+<glyph glyph-name="mute" unicode="&#xe83d;" d="M151 323l-56-57q-24 58-24 120v71q0 15 11 25t25 11 25-11 11-25v-71q0-30 8-63z m622 336l-202-202v-71q0-74-52-126t-126-53q-31 0-61 11l-53-54q54-28 114-28 103 0 177 73t73 177v71q0 15 11 25t25 11 25-11 10-25v-71q0-124-82-215t-203-104v-74h142q15 0 26-11t10-25-10-25-26-11h-357q-14 0-25 11t-10 25 10 25 25 11h143v74q-70 7-131 45l-142-142q-5-6-13-6t-12 6l-46 46q-6 5-6 13t6 12l689 689q5 6 12 6t13-6l46-46q6-5 6-13t-6-12z m-212 73l-347-346v285q0 74 53 127t126 52q57 0 103-33t65-85z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="volume-off" unicode="&#xe83e;" d="M429 654v-608q0-14-11-25t-25-10-25 10l-186 186h-146q-15 0-25 11t-11 25v214q0 15 11 25t25 11h146l186 186q10 10 25 10t25-10 11-25z" horiz-adv-x="428.6" />
+
+<glyph glyph-name="volume-down" unicode="&#xe83f;" d="M429 654v-608q0-14-11-25t-25-10-25 10l-186 186h-146q-15 0-25 11t-11 25v214q0 15 11 25t25 11h146l186 186q10 10 25 10t25-10 11-25z m214-304q0-42-24-79t-63-52q-5-3-14-3-14 0-25 10t-10 26q0 12 6 20t17 14 19 12 16 21 6 31-6 32-16 20-19 13-17 13-6 20q0 15 10 26t25 10q9 0 14-3 39-15 63-52t24-79z" horiz-adv-x="642.9" />
+
+<glyph glyph-name="volume-up" unicode="&#xe840;" d="M429 654v-608q0-14-11-25t-25-10-25 10l-186 186h-146q-15 0-25 11t-11 25v214q0 15 11 25t25 11h146l186 186q10 10 25 10t25-10 11-25z m214-304q0-42-24-79t-63-52q-5-3-14-3-14 0-25 10t-10 26q0 12 6 20t17 14 19 12 16 21 6 31-6 32-16 20-19 13-17 13-6 20q0 15 10 26t25 10q9 0 14-3 39-15 63-52t24-79z m143 0q0-85-48-158t-125-105q-7-3-14-3-15 0-26 11t-10 25q0 22 21 33 32 16 43 25 41 30 64 75t23 97-23 97-64 75q-11 9-43 25-21 11-21 33 0 14 10 25t25 11q8 0 15-3 78-33 125-105t48-158z m143 0q0-128-71-236t-189-158q-7-3-14-3-15 0-25 11t-11 25q0 20 22 33 4 2 12 6t13 6q25 14 46 28 68 51 107 127t38 161-38 161-107 127q-21 15-46 28-4 3-13 6t-12 6q-22 13-22 33 0 15 11 25t25 11q7 0 14-3 118-51 189-158t71-236z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="headphones" unicode="&#xe841;" d="M929 356q0-93-34-176l-11-27-103-18q-13-47-51-77t-87-29v-18q0-8-5-13t-13-5h-36q-7 0-12 5t-6 13v321q0 8 6 13t12 5h36q8 0 13-5t5-13v-18q40 0 72-19t52-54l38 7q16 53 16 108 0 82-49 155t-132 117-176 43-176-43-132-117-49-155q0-55 16-108l38-7q19 34 52 54t73 19v18q0 8 5 13t13 5h35q8 0 13-5t5-13v-321q0-8-5-13t-13-5h-35q-8 0-13 5t-5 13v18q-49 0-88 29t-50 77l-103 18-11 27q-34 83-34 176 0 84 37 162t100 135 149 92 178 34 179-34 148-92 100-135 38-162z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="clock" unicode="&#xe842;" d="M500 546v-250q0-7-5-12t-13-5h-178q-8 0-13 5t-5 12v36q0 8 5 13t13 5h125v196q0 8 5 13t12 5h36q8 0 13-5t5-13z m232-196q0 83-41 152t-110 111-152 41-153-41-110-111-41-152 41-152 110-111 153-41 152 41 110 111 41 152z m125 0q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="lightbulb" unicode="&#xe843;" d="M411 529q0-8-6-13t-12-5-13 5-5 13q0 25-30 39t-59 14q-7 0-13 5t-5 13 5 13 13 5q28 0 55-9t49-30 21-50z m89 0q0 40-19 74t-50 57-69 35-76 12-76-12-69-35-50-57-20-74q0-57 38-101 6-6 17-18t17-19q72-85 79-166h127q8 81 79 166 6 6 17 19t17 18q38 44 38 101z m71 0q0-87-57-150-25-27-42-48t-33-54-19-60q26-15 26-46 0-20-13-35 13-15 13-36 0-29-25-45 8-13 8-26 0-26-18-40t-43-14q-11-25-34-39t-48-15-49 15-33 39q-26 0-44 14t-17 40q0 13 7 26-25 16-25 45 0 21 14 36-14 15-14 35 0 31 26 46-2 28-19 60t-33 54-41 48q-58 63-58 150 0 55 25 103t65 79 92 49 104 19 104-19 91-49 66-79 24-103z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="block" unicode="&#xe844;" d="M732 352q0 90-48 164l-421-420q76-50 166-50 62 0 118 25t96 65 65 97 24 119z m-557-167l421 421q-75 50-167 50-83 0-153-40t-110-111-41-153q0-91 50-167z m682 167q0-88-34-168t-91-137-137-92-166-34-167 34-137 92-91 137-34 168 34 167 91 137 137 91 167 34 166-34 137-91 91-137 34-167z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="resize-full" unicode="&#xe845;" d="M421 261q0-7-5-13l-185-185 80-81q10-10 10-25t-10-25-25-11h-250q-15 0-25 11t-11 25v250q0 15 11 25t25 11 25-11l80-80 186 185q5 6 12 6t13-6l64-63q5-6 5-13z m436 482v-250q0-15-10-25t-26-11-25 11l-80 80-185-185q-6-6-13-6t-13 6l-64 64q-5 5-5 12t5 13l186 185-81 81q-10 10-10 25t10 25 25 11h250q15 0 26-11t10-25z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="resize-full-alt" unicode="&#xe846;" d="M716 548l-198-198 198-198 80 80q17 18 39 8 22-9 22-33v-250q0-14-10-25t-26-11h-250q-23 0-32 23-10 21 7 38l81 81-198 198-198-198 80-81q17-17 8-38-10-23-33-23h-250q-15 0-25 11t-11 25v250q0 24 22 33 22 10 39-8l80-80 198 198-198 198-80-80q-11-11-25-11-7 0-14 3-22 9-22 33v250q0 14 11 25t25 11h250q23 0 33-23 9-21-8-38l-80-81 198-198 198 198-81 81q-17 17-7 38 9 23 32 23h250q15 0 26-11t10-25v-250q0-24-22-33-7-3-14-3-14 0-25 11z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="resize-small" unicode="&#xe847;" d="M429 314v-250q0-14-11-25t-25-10-25 10l-81 81-185-186q-5-5-13-5t-12 5l-64 64q-6 6-6 13t6 13l185 185-80 80q-11 11-11 25t11 25 25 11h250q14 0 25-11t11-25z m421 375q0-7-6-12l-185-186 80-80q11-11 11-25t-11-25-25-11h-250q-14 0-25 11t-10 25v250q0 14 10 25t25 10 25-10l81-80 185 185q6 5 13 5t13-5l63-64q6-5 6-13z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="resize-vertical" unicode="&#xe848;" d="M393 671q0-14-11-25t-25-10h-71v-572h71q15 0 25-10t11-25-11-25l-143-143q-10-11-25-11t-25 11l-143 143q-10 10-10 25t10 25 25 10h72v572h-72q-14 0-25 10t-10 25 10 26l143 142q11 11 25 11t25-11l143-142q11-11 11-26z" horiz-adv-x="428.6" />
+
+<glyph glyph-name="resize-horizontal" unicode="&#xe849;" d="M1000 350q0-14-11-25l-142-143q-11-11-26-11t-25 11-10 25v72h-572v-72q0-14-10-25t-25-11-25 11l-143 143q-11 11-11 25t11 25l143 143q10 11 25 11t25-11 10-25v-72h572v72q0 14 10 25t25 11 26-11l142-143q11-10 11-25z" horiz-adv-x="1000" />
+
+<glyph glyph-name="move" unicode="&#xe84a;" d="M1000 350q0-14-11-25l-142-143q-11-11-26-11t-25 11-10 25v72h-215v-215h72q14 0 25-10t11-25-11-25l-143-143q-10-11-25-11t-25 11l-143 143q-11 10-11 25t11 25 25 10h72v215h-215v-72q0-14-10-25t-25-11-25 11l-143 143q-11 11-11 25t11 25l143 143q10 11 25 11t25-11 10-25v-72h215v215h-72q-14 0-25 10t-11 25 11 26l143 142q11 11 25 11t25-11l143-142q11-11 11-26t-11-25-25-10h-72v-215h215v72q0 14 10 25t25 11 26-11l142-143q11-10 11-25z" horiz-adv-x="1000" />
+
+<glyph glyph-name="zoom-in" unicode="&#xe84b;" d="M571 404v-36q0-7-5-13t-12-5h-125v-125q0-7-6-13t-12-5h-36q-7 0-13 5t-5 13v125h-125q-7 0-12 5t-6 13v36q0 7 6 12t12 5h125v125q0 8 5 13t13 5h36q7 0 12-5t6-13v-125h125q7 0 12-5t5-12z m72-18q0 103-73 176t-177 74-177-74-73-176 73-177 177-73 177 73 73 177z m286-465q0-29-21-50t-51-21q-30 0-50 21l-191 191q-100-69-223-69-80 0-153 31t-125 84-84 125-31 153 31 152 84 126 125 84 153 31 153-31 125-84 84-126 31-152q0-123-69-223l191-191q21-21 21-51z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="zoom-out" unicode="&#xe84c;" d="M571 404v-36q0-7-5-13t-12-5h-322q-7 0-12 5t-6 13v36q0 7 6 12t12 5h322q7 0 12-5t5-12z m72-18q0 103-73 176t-177 74-177-74-73-176 73-177 177-73 177 73 73 177z m286-465q0-29-21-50t-51-21q-30 0-50 21l-191 191q-100-69-223-69-80 0-153 31t-125 84-84 125-31 153 31 152 84 126 125 84 153 31 153-31 125-84 84-126 31-152q0-123-69-223l191-191q21-21 21-51z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="down-circled2" unicode="&#xe84d;" d="M625 332q0-7-6-13l-178-178q-6-5-12-5t-13 5l-179 178q-8 9-4 20 5 11 17 11h107v196q0 8 5 13t13 5h107q8 0 13-5t5-13v-196h107q8 0 13-5t5-13z m-196 322q-83 0-153-41t-110-111-41-152 41-152 110-111 153-41 152 41 110 111 41 152-41 152-110 111-152 41z m428-304q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="up-circled2" unicode="&#xe84e;" d="M624 361q-5-11-17-11h-107v-196q0-8-5-13t-13-5h-107q-8 0-13 5t-5 13v196h-107q-8 0-13 5t-5 13q0 7 6 13l178 178q6 5 13 5t12-5l179-178q8-9 4-20z m-195 293q-83 0-153-41t-110-111-41-152 41-152 110-111 153-41 152 41 110 111 41 152-41 152-110 111-152 41z m428-304q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="help" unicode="&#xe84f;" d="M393 149v-134q0-9-7-15t-15-7h-134q-9 0-16 7t-7 15v134q0 9 7 16t16 6h134q9 0 15-6t7-16z m176 335q0-30-8-56t-20-43-31-33-32-25-34-19q-23-13-38-37t-15-37q0-10-7-18t-16-9h-134q-8 0-14 11t-6 20v26q0 46 37 87t79 60q33 16 47 32t14 42q0 24-26 41t-60 18q-36 0-60-16-20-14-60-64-7-9-17-9-7 0-14 4l-91 70q-8 6-9 14t3 16q89 148 259 148 45 0 90-17t81-46 59-72 23-88z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="info-circled" unicode="&#xe850;" d="M571 82v89q0 8-5 13t-12 5h-54v286q0 8-5 13t-13 5h-178q-8 0-13-5t-5-13v-89q0-8 5-13t13-5h53v-179h-53q-8 0-13-5t-5-13v-89q0-8 5-13t13-5h250q7 0 12 5t5 13z m-71 500v89q0 8-5 13t-13 5h-107q-8 0-13-5t-5-13v-89q0-8 5-13t13-5h107q8 0 13 5t5 13z m357-232q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="down-dir" unicode="&#xe851;" d="M571 457q0-14-10-25l-250-250q-11-11-25-11t-25 11l-250 250q-11 11-11 25t11 25 25 11h500q14 0 25-11t10-25z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="up-dir" unicode="&#xe852;" d="M571 171q0-14-10-25t-25-10h-500q-15 0-25 10t-11 25 11 26l250 250q10 10 25 10t25-10l250-250q10-11 10-26z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="star" unicode="&#xe853;" d="M929 489q0-12-15-27l-202-197 48-279q0-4 0-12 0-11-6-19t-17-9q-10 0-22 7l-251 132-250-132q-12-7-23-7-11 0-17 9t-6 19q0 4 1 12l48 279-203 197q-14 15-14 27 0 21 31 26l280 40 126 254q11 23 27 23t28-23l125-254 280-40q32-5 32-26z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="star-empty" unicode="&#xe854;" d="M635 290l170 166-235 34-106 213-105-213-236-34 171-166-41-235 211 111 211-111z m294 199q0-12-15-27l-202-197 48-279q0-4 0-12 0-28-23-28-10 0-22 7l-251 132-250-132q-12-7-23-7-11 0-17 9t-6 19q0 4 1 12l48 279-203 197q-14 15-14 27 0 21 31 26l280 40 126 254q11 23 27 23t28-23l125-254 280-40q32-5 32-26z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="down-open" unicode="&#xe855;" d="M939 399l-414-413q-10-11-25-11t-25 11l-414 413q-11 11-11 26t11 25l93 92q10 11 25 11t25-11l296-296 296 296q11 11 25 11t26-11l92-92q11-11 11-25t-11-26z" horiz-adv-x="1000" />
+
+<glyph glyph-name="gym" unicode="&#xe856;" d="M790 172v356c0 11 7 20 16 22 1 0 2 0 3 0h31c10 0 19-10 19-22v-97h24c10 0 19-10 19-22v-116c0-13-9-23-19-23h-24v-98c0-12-9-22-19-22h-31c-1 0-2 0-3 0-9 2-16 11-16 22z m-674 98h15v-98c0-12 7-22 17-22h28c1 0 2 0 3 0 8 2 14 11 14 22v356c0 11-6 20-14 22-1 0-2 0-3 0h-28c-10 0-17-10-17-22v-97h-15c-10 0-18-10-18-22v-116c0-13 8-23 18-23z m99-197h68c13 0 23 10 23 23v202h21 20 289 21 20v-202c0-13 11-23 23-23h68c12 0 22 10 22 23v508c0 13-10 23-22 23h-68c-12 0-23-10-23-23v-200h-20-21-289-20-21v200c0 13-10 23-23 23h-68c-12 0-22-10-22-23v-508c0-13 10-23 22-23z" horiz-adv-x="1000" />
+
+<glyph glyph-name="sports" unicode="&#xe857;" d="M624 655c46 0 83 37 83 82 0 46-37 83-83 83-45 0-82-37-82-83 0-45 37-82 82-82z m189-171l-38 35-105 104c-9 9-23 15-37 15l-157 1-289 4c-12 2-23-1-33-9-17-15-19-41-4-59 8-10 20-15 32-14l196-1 105 0-156-186 0 0-85-99c-3-4-6-7-8-11-14-26-9-59 17-73 23-12 56-5 71 14l107 127 7 9 12-9-5-5-294-356c-3-3-6-7-8-11-15-26-6-58 20-73 22-13 50-7 66 11l338 397 0 0 140 173 23-19-95-119c-6-8-9-18-9-28 2-24 22-42 45-41 11 0 20 4 27 11l114 142c37 40 3 70 3 70z" horiz-adv-x="1000" />
+
+<glyph glyph-name="up-open" unicode="&#xe858;" d="M939 107l-92-92q-11-10-26-10t-25 10l-296 297-296-297q-11-10-25-10t-25 10l-93 92q-11 11-11 26t11 25l414 414q11 10 25 10t25-10l414-414q11-11 11-25t-11-26z" horiz-adv-x="1000" />
+
+<glyph glyph-name="browser" unicode="&#xe859;" d="M313 663h62v-63h-62v63z m-125 0h62v-63h-62v63z m-125 0h62v-63h-62v63z m750-625h-750v500h750v-500z m0 562h-375v63h375v-63z m62 63c0 34-28 62-62 62h-750c-35 0-63-28-63-62v-625c0-35 28-63 63-63h750c34 0 62 28 62 63v625z" horiz-adv-x="875" />
+
+<glyph glyph-name="download" unicode="&#xe85a;" d="M714 100q0 15-10 25t-25 11-25-11-11-25 11-25 25-11 25 11 10 25z m143 0q0 15-10 25t-26 11-25-11-10-25 10-25 25-11 26 11 10 25z m72 125v-179q0-22-16-37t-38-16h-821q-23 0-38 16t-16 37v179q0 22 16 38t38 16h259l75-76q33-32 76-32t76 32l76 76h259q22 0 38-16t16-38z m-182 318q10-23-8-39l-250-250q-10-11-25-11t-25 11l-250 250q-17 16-8 39 10 21 33 21h143v250q0 15 11 25t25 11h143q14 0 25-11t10-25v-250h143q24 0 33-21z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="angle-up" unicode="&#xe85b;" d="M600 189q0-7-6-12l-28-28q-5-6-12-6t-13 6l-220 219-219-219q-5-6-13-6t-12 6l-28 28q-6 5-6 12t6 13l260 260q5 6 12 6t13-6l260-260q6-5 6-13z" horiz-adv-x="642.9" />
+
+<glyph glyph-name="angle-down" unicode="&#xe85c;" d="M600 439q0-7-6-12l-260-261q-5-5-13-5t-12 5l-260 261q-6 5-6 12t6 13l28 28q5 6 12 6t13-6l219-219 220 219q5 6 13 6t12-6l28-28q6-5 6-13z" horiz-adv-x="642.9" />
+
+<glyph glyph-name="angle-circled-up" unicode="&#xe85f;" d="M650 214l57 57q11 11 11 25t-11 26l-253 253q-11 11-25 11t-25-11l-254-253q-10-11-10-26t10-25l57-57q11-10 25-10t25 10l172 172 171-172q11-10 25-10t25 10z m207 136q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="angle-circled-down" unicode="&#xe860;" d="M454 125l253 254q11 10 11 25t-11 25l-57 57q-10 10-25 10t-25-10l-171-172-172 172q-10 10-25 10t-25-10l-57-57q-10-11-10-25t10-25l254-254q10-10 25-10t25 10z m403 225q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="angle-double-up" unicode="&#xe863;" d="M600 118q0-7-6-13l-28-28q-5-5-12-5t-13 5l-220 219-219-219q-5-5-13-5t-12 5l-28 28q-6 6-6 13t6 13l260 260q5 5 12 5t13-5l260-260q6-6 6-13z m0 214q0-7-6-13l-28-28q-5-5-12-5t-13 5l-220 220-219-220q-5-5-13-5t-12 5l-28 28q-6 6-6 13t6 13l260 260q5 6 12 6t13-6l260-260q6-6 6-13z" horiz-adv-x="642.9" />
+
+<glyph glyph-name="angle-double-down" unicode="&#xe864;" d="M600 368q0-7-6-13l-260-260q-5-6-13-6t-12 6l-260 260q-6 6-6 13t6 13l28 28q5 5 12 5t13-5l219-220 220 220q5 5 13 5t12-5l28-28q6-6 6-13z m0 214q0-7-6-13l-260-260q-5-5-13-5t-12 5l-260 260q-6 6-6 13t6 13l28 28q5 6 12 6t13-6l219-219 220 219q5 6 13 6t12-6l28-28q6-6 6-13z" horiz-adv-x="642.9" />
+
+<glyph glyph-name="down" unicode="&#xe865;" d="M427 125q4-10-3-19l-195-215q-6-5-13-5-8 0-13 5l-198 215q-8 9-3 19 5 11 16 11h125v696q0 8 5 13t13 5h107q8 0 13-5t5-13v-696h125q11 0 16-11z" horiz-adv-x="428.6" />
+
+<glyph glyph-name="up" unicode="&#xe868;" d="M427 575q-5-11-16-11h-125v-696q0-8-5-13t-13-5h-107q-8 0-13 5t-5 13v696h-125q-12 0-16 11t3 19l195 215q5 5 13 5 7 0 13-5l198-215q7-8 3-19z" horiz-adv-x="428.6" />
+
+<glyph glyph-name="down-big" unicode="&#xe869;" d="M899 386q0-30-21-50l-363-364q-22-21-51-21-29 0-50 21l-363 364q-21 20-21 50 0 29 21 51l41 41q22 21 51 21 29 0 50-21l164-164v393q0 29 21 50t51 22h71q29 0 50-22t21-50v-393l165 164q20 21 50 21 29 0 51-21l41-41q21-22 21-51z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="up-big" unicode="&#xe86c;" d="M899 308q0-28-21-50l-41-42q-22-21-51-21-30 0-50 21l-165 164v-393q0-29-20-47t-51-19h-71q-30 0-51 19t-21 47v393l-164-164q-20-21-50-21t-50 21l-42 42q-21 21-21 50 0 30 21 51l363 363q20 21 50 21 30 0 51-21l363-363q21-22 21-51z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="up-hand" unicode="&#xe86f;" d="M714-43q0 15-10 25t-25 11-25-11-11-25 11-25 25-11 25 11 10 25z m72 427q0 105-93 105-15 0-32-3-9 17-29 27t-41 9-38-10q-28 30-67 30-14 0-31-6t-26-14v185q0 29-22 50t-50 22q-28 0-50-22t-21-50v-321q-11 0-27 8t-31 19-38 18-47 8q-37 0-55-24t-17-65q0-13 78-50 25-14 36-21 36-22 81-62 45-40 59-57 32-38 32-78v-18h357v18q0 40 18 93t36 108 18 101z m71 2q0-74-38-179-33-92-33-125v-161q0-29-21-50t-51-21h-357q-29 0-50 21t-21 50v161q0 6-3 12t-8 13-10 13-12 13-12 12-12 10-10 8q-41 36-72 56-11 7-34 18t-40 21-36 23-27 30-10 39q0 70 37 115t106 46q38 0 71-13v209q0 58 43 101t100 42q58 0 101-42t42-101v-94q35-2 66-21 12 2 24 2 57 0 100-34 77 1 122-47t45-127z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="down-hand" unicode="&#xe870;" d="M786 314q0 47-18 102t-36 109-18 93v18h-357v-18q0-20-7-38t-20-35-26-28-30-27q-5-4-8-7-45-40-81-62-12-8-38-21-1-1-12-6t-20-10-20-12-17-12-7-10q0-40 17-64t55-25q24 0 47 8t38 19 31 18 27 8v-321q0-28 21-50t50-22q29 0 50 22t22 50v185q25-20 57-20 39 0 67 30 17-10 38-10t41 9 29 27q14-2 32-2 47 0 70 27t23 75z m-72 429q0 14-10 25t-25 11-25-11-11-25 11-25 25-11 25 11 10 25z m143-426q0-80-43-129t-121-48l-3 0q-43-34-100-34-12 0-24 2-30-17-66-21v-94q0-59-42-101t-101-42q-58 0-100 42t-43 101v209q-30-13-71-13-68 0-105 46t-38 115q0 21 10 39t27 31 36 22 40 21 34 18q31 20 72 56 2 1 10 8t12 10 12 12 12 13 10 13 8 13 3 12v161q0 29 21 50t50 21h357q30 0 51-21t21-50v-161q0-33 33-125 38-106 38-176z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="up-circled" unicode="&#xe873;" d="M717 351q0 15-10 25l-202 202-51 51q-10 10-25 10t-25-10l-51-51-202-202q-10-10-10-25t10-26l51-50q10-10 25-10t25 10l105 105v-280q0-14 11-25t25-11h71q15 0 25 11t11 25v280l106-105q10-11 25-11t25 11l51 50q10 11 10 26z m140-1q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="down-circled" unicode="&#xe874;" d="M717 349q0 16-10 26l-51 50q-10 10-25 10t-25-10l-106-105v280q0 15-11 25t-25 11h-71q-15 0-25-11t-11-25v-280l-105 105q-11 11-25 11t-25-11l-51-50q-10-10-10-26t10-25l202-202 51-50q10-10 25-10t25 10l51 50 202 202q10 10 10 25z m140 1q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="cw" unicode="&#xe875;" d="M857 707v-250q0-14-10-25t-26-11h-250q-23 0-32 23-10 22 7 38l77 77q-82 77-194 77-58 0-111-23t-91-61-61-91-23-111 23-111 61-91 91-61 111-23q66 0 125 29t100 82q4 6 13 7 8 0 14-5l76-77q5-4 6-11t-5-13q-60-74-147-114t-182-41q-87 0-167 34t-136 92-92 137-34 166 34 166 92 137 136 92 167 34q82 0 158-31t137-88l72 72q17 18 39 8 22-9 22-33z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="ccw" unicode="&#xe876;" d="M857 350q0-87-34-166t-91-137-137-92-166-34q-96 0-183 41t-147 114q-4 6-4 13t5 11l76 77q6 5 14 5 9-1 13-7 41-53 100-82t126-29q58 0 110 23t92 61 61 91 22 111-22 111-61 91-92 61-110 23q-55 0-105-20t-90-57l77-77q17-16 8-38-10-23-33-23h-250q-15 0-25 11t-11 25v250q0 24 22 33 22 10 39-8l72-72q60 57 137 88t159 31q87 0 166-34t137-92 91-137 34-166z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="arrows-cw" unicode="&#xe877;" d="M843 261q0-3 0-4-36-150-150-243t-267-93q-81 0-157 31t-136 88l-72-72q-11-11-25-11t-25 11-11 25v250q0 14 11 25t25 11h250q14 0 25-11t10-25-10-25l-77-77q40-36 90-57t105-20q74 0 139 37t104 99q6 10 30 66 4 13 16 13h107q8 0 13-6t5-12z m14 446v-250q0-14-10-25t-26-11h-250q-14 0-25 11t-10 25 10 25l77 77q-82 77-194 77-75 0-140-37t-104-99q-6-10-29-66-5-13-17-13h-111q-7 0-13 6t-5 12v4q36 150 151 243t268 93q81 0 158-31t137-88l72 72q11 11 25 11t26-11 10-25z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="level-up" unicode="&#xe878;" d="M568 514q-10-21-32-21h-107v-482q0-8-5-13t-13-5h-393q-12 0-16 10-5 11 2 19l89 108q5 6 14 6h179v357h-107q-23 0-33 21-9 20 5 38l179 214q10 12 27 12t28-12l178-214q15-18 5-38z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="level-down" unicode="&#xe879;" d="M18 707h393q7 0 12-5t6-13v-482h107q22 0 32-20t-5-39l-178-214q-11-13-28-13t-27 13l-179 214q-14 17-5 39 10 20 33 20h107v357h-179q-8 0-14 6l-89 108q-7 7-2 19 5 10 16 10z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="shuffle" unicode="&#xe87a;" d="M372 582q-34-52-77-153-12 25-20 41t-23 35-28 32-36 19-45 8h-125q-8 0-13 5t-5 13v107q0 8 5 13t13 5h125q139 0 229-125z m628-446q0-8-5-13l-179-179q-5-5-12-5-8 0-13 6t-5 12v107q-18 0-48 0t-45-1-41 1-39 3-36 6-35 10-32 16-33 22-31 30-31 39q33 52 76 152 12-25 20-40t23-36 28-31 35-20 46-8h143v107q0 8 5 13t13 5q6 0 13-5l178-178q5-5 5-13z m0 500q0-8-5-13l-179-179q-5-5-12-5-8 0-13 6t-5 12v107h-143q-27 0-49-8t-38-25-29-34-25-44q-18-34-43-95-16-37-28-62t-30-59-36-55-41-47-50-38-60-23-71-10h-125q-8 0-13 5t-5 13v107q0 8 5 13t13 5h125q27 0 48 9t39 25 28 34 26 43q17 35 43 96 16 36 28 62t30 58 36 56 41 46 50 39 59 23 72 9h143v107q0 8 5 13t13 5q6 0 13-5l178-178q5-5 5-13z" horiz-adv-x="1000" />
+
+<glyph glyph-name="exchange" unicode="&#xe87b;" d="M1000 189v-107q0-7-5-12t-13-6h-768v-107q0-7-5-12t-13-6q-6 0-13 6l-178 178q-5 6-5 13 0 8 5 13l179 178q5 5 12 5 8 0 13-5t5-13v-107h768q7 0 13-5t5-13z m0 304q0-8-5-13l-179-178q-5-6-12-6-8 0-13 6t-5 12v107h-768q-7 0-13 6t-5 12v107q0 8 5 13t13 5h768v107q0 8 5 13t13 5q6 0 13-5l178-178q5-5 5-13z" horiz-adv-x="1000" />
+
+<glyph glyph-name="history" unicode="&#xe87c;" d="M857 350q0-87-34-166t-91-137-137-92-166-34q-96 0-183 41t-147 114q-4 6-4 13t5 11l76 77q6 5 14 5 9-1 13-7 41-53 100-82t126-29q58 0 110 23t92 61 61 91 22 111-22 111-61 91-92 61-110 23q-55 0-105-20t-90-57l77-77q17-16 8-38-10-23-33-23h-250q-15 0-25 11t-11 25v250q0 24 22 33 22 10 39-8l72-72q60 57 137 88t159 31q87 0 166-34t137-92 91-137 34-166z m-357 161v-250q0-8-5-13t-13-5h-178q-8 0-13 5t-5 13v35q0 8 5 13t13 5h125v197q0 8 5 13t12 5h36q8 0 13-5t5-13z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="expand" unicode="&#xe87d;" d="M639 473q10-19-3-36l-178-250q-11-16-29-16t-29 16l-179 250q-13 17-3 36 10 20 32 20h357q23 0 32-20z m75-391v536q0 7-5 12t-13 6h-535q-7 0-13-6t-5-12v-536q0-7 5-12t13-6h535q8 0 13 6t5 12z m143 536v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="collapse" unicode="&#xe87e;" d="M639 227q-9-20-32-20h-357q-22 0-32 20-10 19 3 37l179 250q10 15 29 15t29-15l178-250q13-18 3-37z m75-145v536q0 7-5 12t-13 6h-535q-7 0-13-6t-5-12v-536q0-7 5-12t13-6h535q8 0 13 6t5 12z m143 536v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="play" unicode="&#xe881;" d="M772 333l-741-412q-13-7-22-2t-9 20v822q0 14 9 20t22-2l741-412q13-7 13-17t-13-17z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="play-circled" unicode="&#xe882;" d="M429 779q116 0 215-58t156-156 57-215-57-215-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58z m214-460q18 10 18 31t-18 31l-304 178q-17 11-35 1-18-11-18-31v-358q0-20 18-31 9-4 17-4 10 0 18 5z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="play-circled2" unicode="&#xe883;" d="M661 350q0-21-18-31l-304-178q-8-5-18-5-8 0-17 4-18 11-18 31v358q0 20 18 31 18 10 35-1l304-178q18-10 18-31z m71 0q0 83-41 152t-110 111-152 41-153-41-110-111-41-152 41-152 110-111 153-41 152 41 110 111 41 152z m125 0q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="stop" unicode="&#xe884;" d="M857 743v-786q0-14-10-25t-26-11h-785q-15 0-25 11t-11 25v786q0 14 11 25t25 11h785q15 0 26-11t10-25z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="pause" unicode="&#xe885;" d="M857 743v-786q0-14-10-25t-26-11h-285q-15 0-25 11t-11 25v786q0 14 11 25t25 11h285q15 0 26-11t10-25z m-500 0v-786q0-14-10-25t-26-11h-285q-15 0-25 11t-11 25v786q0 14 11 25t25 11h285q15 0 26-11t10-25z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="to-end" unicode="&#xe886;" d="M25-71q-10-11-18-8t-7 18v822q0 14 7 18t18-8l396-396q5-5 8-10v378q0 14 10 25t25 11h72q14 0 25-11t10-25v-786q0-14-10-25t-25-11h-72q-14 0-25 11t-10 25v379q-3-6-8-11z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="to-end-alt" unicode="&#xe887;" d="M25-71q-10-11-18-8t-7 18v822q0 14 7 18t18-8l396-396q5-5 8-10v396q0 14 7 18t18-8l396-396q5-5 7-10v378q0 14 11 25t25 11h71q15 0 25-11t11-25v-786q0-14-11-25t-25-11h-71q-15 0-25 11t-11 25v379q-2-6-7-11l-396-396q-11-11-18-8t-7 18v397q-3-6-8-11z" horiz-adv-x="1000" />
+
+<glyph glyph-name="to-start" unicode="&#xe888;" d="M546 771q11 11 18 8t7-18v-822q0-14-7-18t-18 8l-396 396q-5 5-7 11v-379q0-14-11-25t-25-11h-71q-15 0-25 11t-11 25v786q0 14 11 25t25 11h71q15 0 25-11t11-25v-378q2 5 7 10z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="to-start-alt" unicode="&#xe889;" d="M975 771q11 11 18 8t7-18v-822q0-14-7-18t-18 8l-396 396q-5 5-8 11v-397q0-14-7-18t-18 8l-396 396q-5 5-7 11v-379q0-14-11-25t-25-11h-71q-15 0-25 11t-11 25v786q0 14 11 25t25 11h71q15 0 25-11t11-25v-378q2 5 7 10l396 396q11 11 18 8t7-18v-396q3 5 8 10z" horiz-adv-x="1000" />
+
+<glyph glyph-name="fast-fw" unicode="&#xe88a;" d="M25-71q-10-11-18-8t-7 18v822q0 14 7 18t18-8l396-396q5-5 8-10v396q0 14 7 18t18-8l396-396q11-10 11-25t-11-25l-396-396q-11-11-18-8t-7 18v397q-3-6-8-11z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="fast-bw" unicode="&#xe88b;" d="M904 771q10 11 17 8t8-18v-822q0-14-8-18t-17 8l-397 396q-5 5-7 11v-397q0-14-7-18t-18 8l-396 396q-11 11-11 25t11 25l396 396q11 11 18 8t7-18v-396q2 5 7 10z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="eject" unicode="&#xe88c;" d="M8 304l396 396q11 11 25 11t25-11l396-396q11-11 8-18t-18-7h-822q-14 0-17 7t7 18z m814-311h-786q-14 0-25 11t-10 25v142q0 15 10 26t25 10h786q15 0 25-10t11-26v-142q0-15-11-25t-25-11z" horiz-adv-x="858.3" />
+
+<glyph glyph-name="target" unicode="&#xe88d;" d="M668 279h-61q-14 0-25 10t-11 25v72q0 14 11 25t25 10h61q-18 61-63 106t-105 62v-60q0-15-11-25t-25-11h-71q-15 0-25 11t-11 25v60q-60-17-105-62t-63-106h61q15 0 25-10t11-25v-72q0-14-11-25t-25-10h-61q18-61 63-106t105-62v60q0 15 11 26t25 10h71q15 0 25-10t11-26v-60q60 18 105 62t63 106z m189 107v-72q0-14-10-25t-26-10h-79q-21-90-87-156t-155-86v-80q0-14-11-25t-25-11h-71q-15 0-25 11t-11 25v80q-90 21-155 86t-86 156h-80q-15 0-25 10t-11 25v72q0 14 11 25t25 10h80q20 90 86 156t155 86v80q0 14 11 25t25 11h71q15 0 25-11t11-25v-80q90-21 155-86t87-156h79q15 0 26-10t10-25z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="signal" unicode="&#xe88e;" d="M143 46v-107q0-8-5-13t-13-5h-107q-8 0-13 5t-5 13v107q0 8 5 13t13 5h107q8 0 13-5t5-13z m214 72v-179q0-8-5-13t-13-5h-107q-8 0-13 5t-5 13v179q0 8 5 13t13 5h107q8 0 13-5t5-13z m214 143v-322q0-8-5-13t-12-5h-108q-7 0-12 5t-5 13v322q0 8 5 13t12 5h108q7 0 12-5t5-13z m215 214v-536q0-8-5-13t-13-5h-107q-8 0-13 5t-5 13v536q0 8 5 13t13 5h107q8 0 13-5t5-13z m214 286v-822q0-8-5-13t-13-5h-107q-8 0-13 5t-5 13v822q0 8 5 13t13 5h107q8 0 13-5t5-13z" horiz-adv-x="1000" />
+
+<glyph glyph-name="award" unicode="&#xe88f;" d="M256 357q-42 91-42 207h-143v-53q0-44 53-91t132-63z m601 154v53h-143q0-116-41-207 79 16 131 63t53 91z m72 71v-71q0-40-24-80t-62-73-97-54-120-25q-23-30-53-53-21-19-29-40t-8-50q0-30 17-51t54-21q42 0 75-25t32-64v-36q0-8-5-13t-13-5h-464q-8 0-13 5t-5 13v36q0 39 33 64t74 25q38 0 55 21t17 51q0 28-8 50t-29 40q-30 23-53 53-64 3-121 25t-96 54-63 73-23 80v71q0 23 16 38t38 16h160v53q0 37 27 63t63 27h321q37 0 63-27t26-63v-53h161q22 0 38-16t16-38z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="desktop" unicode="&#xe890;" d="M1000 296v465q0 7-5 12t-13 6h-893q-7 0-12-6t-6-12v-465q0-7 6-12t12-5h893q7 0 13 5t5 12z m71 465v-607q0-37-26-63t-63-27h-303q0-20 9-43t17-40 9-24q0-14-10-25t-25-11h-286q-15 0-25 11t-11 25q0 8 9 25t18 39 9 43h-304q-36 0-63 27t-26 63v607q0 37 26 63t63 26h893q37 0 63-26t26-63z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="laptop" unicode="&#xe891;" d="M232 136q-37 0-63 26t-26 63v393q0 37 26 63t63 26h607q37 0 63-26t27-63v-393q0-37-27-63t-63-26h-607z m-18 482v-393q0-7 6-13t12-5h607q8 0 13 5t5 13v393q0 7-5 12t-13 6h-607q-7 0-12-6t-6-12z m768-518h89v-54q0-22-26-37t-63-16h-893q-36 0-63 16t-26 37v54h982z m-402-54q9 0 9 9t-9 9h-89q-9 0-9-9t9-9h89z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="tablet" unicode="&#xe892;" d="M357 64q0 15-10 25t-26 11-25-11-10-25 10-25 25-10 26 10 10 25z m214 90v535q0 8-5 13t-12 5h-465q-7 0-12-5t-6-13v-535q0-8 6-13t12-5h465q7 0 12 5t5 13z m72 535v-607q0-37-26-63t-63-26h-465q-36 0-63 26t-26 63v607q0 37 26 63t63 27h465q36 0 63-27t26-63z" horiz-adv-x="642.9" />
+
+<glyph glyph-name="mobile" unicode="&#xe893;" d="M259 64q0 19-13 32t-32 13-31-13-13-32 13-31 31-13 32 13 13 31z m116 90v392q0 8-5 13t-13 5h-286q-7 0-12-5t-5-13v-392q0-8 5-13t12-5h286q7 0 13 5t5 13z m-107 473q0 9-9 9h-89q-9 0-9-9t9-9h89q9 0 9 9z m161 9v-572q0-29-22-50t-50-21h-286q-29 0-50 21t-21 50v572q0 29 21 50t50 21h286q29 0 50-21t22-50z" horiz-adv-x="428.6" />
+
+<glyph glyph-name="inbox" unicode="&#xe894;" d="M571 314h176q0 2-1 5t-2 4l-118 277h-395l-118-277q-1-1-2-4t-1-5h176l53-107h179z m286-16v-269q0-15-10-25t-26-11h-785q-15 0-25 11t-11 25v269q0 34 14 68l133 308q5 14 20 24t29 9h465q14 0 29-9t20-24l133-308q14-34 14-68z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="globe" unicode="&#xe895;" d="M429 779q116 0 215-58t156-156 57-215-57-215-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58z m153-291q-2-1-6-5t-7-6q1 0 2 3t3 6 2 4q3 4 12 8 8 4 29 7 19 5 29-6-1 1 5 7t8 7q2 1 8 3t9 4l1 12q-7-1-10 4t-3 12q0-2-4-5 0 4-2 5t-7-1-5-1q-5 2-8 5t-5 9-2 8q-1 3-5 6t-5 6q-1 1-2 3t-1 4-3 3-3 1-4-3-4-5-2-3q-2 1-4 1t-2-1-3-1-3-2q-1-2-4-2t-5-1q8 3-1 6-5 2-9 2 6 2 5 6t-5 8h3q-1 2-5 5t-10 5-7 3q-5 3-19 5t-18 1q-3-4-3-6t2-8 2-7q1-3-3-7t-3-7q0-4 7-9t6-12q-2-4-9-9t-9-6q-3-5-1-11t6-9q1-1 1-2t-2-3-3-2-4-2l-1-1q-7-3-12 3t-7 15q-4 14-9 17-13 4-16-1-3 7-23 15-14 5-33 2 4 0 0 8-4 9-10 7 1 3 2 10t0 7q2 8 7 13 1 1 4 5t5 7 1 4q19-3 28 6 2 3 6 9t6 10q5 3 8 3t8-3 8-3q8-1 8 6t-4 11q7 0 2 10-2 4-5 5-6 2-15-3-4-2 2-4-1 0-6-6t-9-10-9 3q0 0-3 7t-5 8q-5 0-9-9 1 5-6 9t-14 4q11 7-4 15-4 3-12 3t-11-2q-2-4-3-7t3-4 6-3 6-2 5-2q8-6 5-8-1 0-5-2t-6-2-4-2q-1-3 0-8t-1-8q-3 3-5 10t-4 9q4-5-14-3l-5 0q-3 0-9-1t-12-1-7 5q-3 4 0 11 0 2 2 1-2 2-6 5t-6 5q-25-8-52-23 3 0 6 1 3 1 8 4t5 3q19 7 24 4l3 2q7-9 11-14-4 3-17 1-11-3-12-7 4-6 2-10-2 2-6 6t-8 6-8 3q-9 0-13-1-81-45-131-124 4-4 7-4 2-1 3-5t1-6 6 1q5-4 2-10 1 0 25-15 10-10 11-12 2-6-5-10-1 1-5 5t-5 2q-2-3 0-10t6-7q-4 0-5-9t-2-20 0-13l1-1q-2-6 3-19t12-11q-7-1 11-24 3-4 4-5 2-1 7-4t9-6 5-5q2-3 6-13t8-13q-2-3 5-11t6-13q-1 0-2-1t-1 0q2-4 9-8t8-7q1-2 1-6t2-6 4-1q2 11-13 35-8 13-9 16-2 2-4 8t-2 8q1 0 3 0t5-2 4-3 1-1q-1-4 1-10t7-10 10-11 6-7q4-4 8-11t0-8q5 0 11-5t10-11q3-5 4-15t3-13q1-4 5-8t7-5l9-5t7-3q3-2 10-6t12-7q6-2 9-2t8 1 8 2q8 1 16-8t12-12q20-10 30-6-1 0 1-4t4-9 5-8 3-5q3-3 10-8t10-8q4 2 4 5-1-5 4-11t10-6q8 2 8 18-17-8-27 10 0 0-2 3t-2 5-1 4 0 5 2 1q5 0 6 2t-1 7-2 8q-1 4-6 11t-7 8q-3-5-9-4t-9 5q0-1-1-3t-1-4q-7 0-8 0 1 2 1 10t2 13q1 2 3 6t5 9 2 7-3 5-9 1q-11 0-15-11-1-2-2-6t-2-6-5-4q-4-2-14-1t-13 3q-8 4-13 16t-5 20q0 6 1 15t2 14-3 14q2 1 5 5t5 6q2 1 3 1t3 0 2 1 1 3q0 1-2 2-1 1-2 1 4-1 16 1t15-1q9-6 12 1 0 1-1 6t0 7q3-15 16-5 2-1 9-3t9-2q2-1 4-3t3-3 3 0 5 4q5-8 7-13 6-23 10-25 4-2 6-1t3 5 0 8-1 7l-1 5v10l0 4q-8 2-10 7t0 10 9 10q0 1 4 2t9 4 7 4q12 11 8 20 4 0 6 5 0 0-2 2t-5 2-2 2q5 2 1 8 3 2 4 7t4 5q5-6 12-1 5 5 1 9 2 4 11 6t10 5q4-1 5 1t0 7 2 7q2 2 9 5t7 2l9 7q2 2 0 2 10-1 18 6 5 6-4 11 2 4-1 5t-9 4q2 0 7 0t5 1q9 5-3 9-10 2-24-7z m-91-490q115 21 195 106-1 2-7 2t-7 2q-10 4-13 5 1 4-1 7t-5 5-7 5-6 4q-1 1-4 3t-4 3-4 2-5 2-5-1l-2-1q-2 0-3-1t-3-2-2-1 0-2q-12 10-20 13-3 0-6 3t-6 4-6 0-6-3q-3-3-4-9t-1-7q-4 3 0 10t1 10q-1 3-6 2t-6-2-7-5-5-3-4-3-5-5q-2-2-4-6t-2-6q-1 2-7 3t-5 3q1-5 2-19t3-22q4-17-7-26-15-14-16-23-2-12 7-14 0-4-5-12t-4-12q0-3 2-9z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="sun" unicode="&#xe896;" d="M821 350q0 65-25 125t-69 102-102 69-125 25-125-25-102-69-69-102-25-125 25-125 69-102 102-69 125-25 125 25 102 69 69 102 25 125z m154-155q-2-8-11-11l-163-53v-171q0-9-7-15-8-5-16-2l-163 53-100-139q-6-7-15-7t-14 7l-101 139-163-53q-8-3-16 2-7 6-7 15v171l-163 53q-9 3-11 11-3 10 2 17l100 138-100 138q-5 8-2 17 2 8 11 11l163 53v171q0 9 7 15 8 5 16 2l163-53 101 139q5 6 14 6t15-6l100-139 163 53q8 3 16-2 7-6 7-15v-171l163-53q9-3 11-11 3-9-2-17l-100-138 100-138q5-7 2-17z" horiz-adv-x="1000" />
+
+<glyph glyph-name="cloud" unicode="&#xe897;" d="M1071 207q0-89-62-151t-152-63h-607q-103 0-177 73t-73 177q0 74 40 135t104 91q-1 16-1 24 0 118 84 202t202 84q88 0 159-49t105-129q39 35 93 35 59 0 101-42t42-101q0-42-23-77 72-17 119-75t46-134z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="flash" unicode="&#xe898;" d="M494 534q10-11 4-24l-302-646q-7-14-23-14-2 0-8 1-9 3-14 11t-3 16l110 451-226-56q-2-1-7-1-10 0-17 7-10 8-7 21l112 461q2 8 9 13t15 5h183q11 0 18-7t7-17q0-4-2-10l-96-258 221 54q5 2 7 2 11 0 19-9z" horiz-adv-x="500" />
+
+<glyph glyph-name="moon" unicode="&#xe899;" d="M704 123q-30-5-61-5-102 0-188 50t-137 137-50 188q0 107 58 199-112-33-183-128t-72-214q0-72 29-139t76-113 114-77 139-28q80 0 152 34t123 96z m114 47q-53-113-159-181t-230-68q-87 0-167 34t-136 92-92 137-34 166q0 85 32 163t87 135 132 92 161 38q25 1 34-22 11-23-8-40-48-43-73-101t-26-122q0-83 41-152t111-111 152-41q66 0 127 29 23 10 40-7 8-8 10-19t-2-22z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="umbrella" unicode="&#xe89a;" d="M500 388v-324q0-58-42-100t-101-43-100 43-43 100q0 15 11 25t25 11 25-11 11-25q0-28 22-49t49-22 50 22 22 49v324q18 6 35 6t36-6z m429-15q0-7-6-13t-12-5q-6 0-13 6-27 25-52 38t-57 13q-38 0-71-21t-58-54q-4-5-10-15t-8-14q-6-9-15-9-10 0-16 9-3 4-9 14t-9 15q-24 34-58 54t-71 21-71-21-57-54q-4-5-10-15t-8-14q-6-9-16-9-10 0-16 9-2 4-8 14t-10 15q-24 34-57 54t-71 21q-33 0-57-13t-52-38q-7-6-13-6-7 0-13 5t-5 13q0 3 1 4 25 102 96 178t166 114 201 38q78 0 154-22t137-63 109-105 64-140q1-1 1-4z m-429 406v-55q-23 1-36 1t-35-1v55q0 14 10 25t25 10 25-10 11-25z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="flight" unicode="&#xe89b;" d="M768 761q24-29 7-83t-61-96l-90-90 90-388q3-11-7-18l-71-54q-4-3-11-3-2 0-4 0-8 2-12 9l-155 284-145-145 30-108q3-10-5-17l-53-54q-5-5-13-5h-1q-9 1-14 7l-105 141-141 105q-6 4-7 13-1 7 5 14l54 54q5 5 12 5 4 0 5 0l108-30 145 145-284 155q-8 5-9 14-1 9 5 15l71 71q8 7 17 5l371-89 89 89q43 43 96 60t83-6z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="tasklist" unicode="&#xe89c;" d="M963 288h-488c-37 0-37 25-37 62s0 63 37 63h488c37 0 37-26 37-63s0-62-37-62z m-363 312c-37 0-37 25-37 63s0 62 37 62h363c37 0 37-25 37-62s0-63-37-63h-363z m-600 6l88 81 100-100 255 263 88-88-343-344-188 188z m475-506h488c37 0 37-25 37-62s0-63-37-63h-488c-37 0-37 25-37 63s0 62 37 62z" horiz-adv-x="1000" />
+
+<glyph glyph-name="paper-plane" unicode="&#xe89d;" d="M984 844q19-13 15-36l-142-857q-3-16-18-25-8-5-18-5-6 0-13 3l-253 104-135-165q-10-13-27-13-7 0-12 2-11 4-17 13t-7 21v195l482 590-596-516-221 91q-20 8-22 30-1 23 18 33l928 536q9 5 18 5 11 0 20-6z" horiz-adv-x="1000" />
+
+<glyph glyph-name="leaf" unicode="&#xe89e;" d="M714 457q0 15-10 25t-25 11q-96 0-178-28t-145-74-131-123q-11-12-11-25 0-15 11-25t25-11q13 0 25 11 15 13 41 39t38 37q76 69 150 98t175 29q14 0 25 11t10 25z m286 111q0-53-11-108-26-125-103-214t-200-149q-119-61-244-61-83 0-160 27-8 2-49 23t-53 21q-9 0-22-18t-25-39-30-39-33-18q-24 0-36 10t-25 33q-1 2-3 6t-3 6-2 5-1 7q0 20 17 41t38 37 38 31 18 27q0 2-8 21t-9 25q-5 28-5 58 0 64 24 123t66 103 96 77 113 53q31 10 81 15t101 5 99 3 91 13 64 32l16 16t17 16 15 11 20 9 24 3q22 0 40-26t26-63 14-69 4-53z" horiz-adv-x="1000" />
+
+<glyph glyph-name="font" unicode="&#xe89f;" d="M405 538l-95-251q18 0 76-1t89-1q11 0 32 1-48 141-102 252z m-405-617l1 44q13 4 31 7t32 6 28 8 25 17 17 28l132 344 156 404h72q4-8 6-12l114-268q19-43 60-144t63-153q9-19 33-80t40-94q11-26 19-32 11-9 49-17t47-11q4-22 4-32 0-3-1-8t0-7q-35 0-106 5t-107 4q-42 0-120-4t-99-4q0 24 2 43l73 16q1 0 7 1t9 2 8 3 9 4 6 4 5 6 1 8q0 9-17 54t-40 99-24 56l-251 1q-14-32-43-109t-28-91q0-12 8-21t24-14 27-7 32-5 23-2q1-11 1-32 0-5-1-16-33 0-98 6t-97 6q-5 0-15-3t-12-2q-45-8-105-8z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="bold" unicode="&#xe8a0;" d="M310 1q41-18 78-18 210 0 210 187 0 64-23 101-15 24-34 41t-38 26-45 14-47 6-53 1q-40 0-56-6 0-29 0-88t-1-88q0-5 0-38t0-54 2-47 7-37z m-8 417q23-4 61-4 46 0 80 7t61 25 42 50 14 79q0 39-16 68t-45 46-60 24-69 8q-28 0-73-7 0-28 3-84t2-85q0-15 0-45t-1-44q0-26 1-38z m-302-497l1 53q9 2 48 9t59 15q4 7 7 15t4 19 4 18 1 21 0 19v36q0 548-12 572-2 5-12 8t-25 6-28 4-27 3-17 2l-2 46q55 1 190 6t208 6q13 0 38-1t38 0q39 0 76-7t72-24 60-39 41-59 16-76q0-29-9-54t-22-40-36-32-41-25-47-22q86-20 144-75t57-138q0-56-20-101t-52-72-77-48-91-27-98-8q-25 0-74 2t-74 1q-59 0-171-6t-129-7z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="italic" unicode="&#xe8a1;" d="M0-78l10 48q12 4 34 9t40 11 33 13q16 19 23 56 1 4 35 162t63 303 29 165v14q-13 8-30 11t-39 4-32 3l10 58q19-1 67-4t84-4 67-1q27 0 55 1t68 4 54 4q-2-22-10-50-17-6-57-16t-60-19q-5-10-8-23t-5-23-4-25-4-24q-15-82-49-234t-43-198q-1-5-7-32t-11-51-9-46-4-32l1-10q9-3 103-18-2-24-9-55-6 0-18-1t-18-1q-16 0-49 6t-48 6q-77 1-115 1-28 0-79-5t-68-7z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="paragraph" unicode="&#xe8a2;" d="M713 745v-41q0-16-10-34t-24-18q-28 0-30-1-14-3-18-17-1-6-1-36v-643q0-14-11-24t-24-10h-60q-14 0-24 10t-10 24v680h-80v-680q0-14-9-24t-25-10h-60q-14 0-24 10t-10 24v277q-82 7-137 33-70 33-107 100-36 65-36 145 0 92 50 159 49 66 116 89 62 21 233 21h267q14 0 24-10t10-24z" horiz-adv-x="714.3" />
+
+<glyph glyph-name="text-height" unicode="&#xe8a3;" d="M973 64q19 0 24-10t-6-25l-71-90q-11-15-27-15t-27 15l-71 90q-11 15-6 25t24 10h44v572h-44q-19 0-24 10t6 25l71 90q11 15 27 15t27-15l71-90q11-15 6-25t-24-10h-44v-572h44z m-928 714l30-15q7-3 118-3 25 0 74 1t73 1q21 0 60 0t60 0h164q3 0 12 0t11 0 9 1 10 5 8 10l24 1q2 0 7-1t8 0q1-62 1-187 0-45-2-61-22-8-38-10-14 24-31 71-1 5-6 27t-8 41-4 20q-3 4-7 7t-8 3-8 1-10 1-9-1q-9 0-37 1t-41 0-36-1-40-3q-5-46-4-76 0-53 1-217t1-254q0-9-1-40t0-51 7-38q22-12 69-24t67-21q2-22 2-28 0-8-1-16l-19-1q-43-1-122 5t-115 5q-28 0-85-5t-84-5q-2 29-2 29v5q9 15 34 24t55 17 44 15q10 23 10 213 0 57-1 170t-2 169v65q0 1 0 9t1 14-1 14-2 13-2 8q-7 7-91 7-18 0-52-7t-44-15q-11-7-19-40t-18-62-24-30q-23 15-31 25v214z" horiz-adv-x="1000" />
+
+<glyph glyph-name="text-width" unicode="&#xe8a4;" d="M45 778l30-15q7-3 118-3 25 0 74 1t73 1q40 0 138 1t170 0 138-2q18-1 31 17l23 1q3 0 8-1t8 0q1-62 1-187 0-45-3-61-21-8-38-10-13 24-30 71-1 5-6 27t-8 41-4 20q-6 7-15 10-3 1-37 1-17 0-52 1t-57 1-53-2-53-3q-5-46-5-76l1-85v29q0-31 0-86t1-101 0-85q0-9-1-40t0-51 7-38q22-12 69-24t67-21q3-22 3-28 0-8-2-16l-19-1q-42-1-121 5t-116 5q-28 0-84-5t-85-5q-2 29-2 29v5q10 15 35 24t55 17 43 15q4 9 7 41t3 81 1 87-1 85 0 50q0 4-1 12t-2 12q0 4 1 25t0 41 0 42-1 38-4 18q-6 7-90 7-23 0-91-8t-77-14q-11-6-19-39t-18-63-24-30q-23 15-31 25v214z m686-715q7 0 24-11t32-23 33-28 20-17q14-11 14-27t-14-27q-2-2-20-17t-33-27-32-23-24-11q-7 0-11 5t-6 16-1 19 0 18 1 11h-571q0-1 1-11t1-18-2-19-5-16-12-5q-7 0-23 11t-32 23-34 27-20 17q-14 11-14 27t14 27q3 2 20 17t34 28 32 23 23 11q7 0 12-6t5-16 2-19-1-18-1-11h571q0 1-1 11t0 18 1 19 6 16 11 6z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="align-left" unicode="&#xe8a5;" d="M1000 100v-71q0-15-11-25t-25-11h-928q-15 0-25 11t-11 25v71q0 15 11 25t25 11h928q15 0 25-11t11-25z m-214 214v-71q0-15-11-25t-25-11h-714q-15 0-25 11t-11 25v71q0 15 11 25t25 11h714q15 0 25-11t11-25z m143 215v-72q0-14-11-25t-25-11h-857q-15 0-25 11t-11 25v72q0 14 11 25t25 10h857q14 0 25-10t11-25z m-215 214v-72q0-14-10-25t-25-10h-643q-15 0-25 10t-11 25v72q0 14 11 25t25 11h643q14 0 25-11t10-25z" horiz-adv-x="1000" />
+
+<glyph glyph-name="align-center" unicode="&#xe8a6;" d="M1000 100v-71q0-15-11-25t-25-11h-928q-15 0-25 11t-11 25v71q0 15 11 25t25 11h928q15 0 25-11t11-25z m-214 214v-71q0-15-11-25t-25-11h-500q-14 0-25 11t-11 25v71q0 15 11 25t25 11h500q15 0 25-11t11-25z m143 215v-72q0-14-11-25t-25-11h-786q-14 0-25 11t-11 25v72q0 14 11 25t25 10h786q14 0 25-10t11-25z m-215 214v-72q0-14-10-25t-25-10h-358q-14 0-25 10t-10 25v72q0 14 10 25t25 11h358q14 0 25-11t10-25z" horiz-adv-x="1000" />
+
+<glyph glyph-name="align-right" unicode="&#xe8a7;" d="M1000 100v-71q0-15-11-25t-25-11h-928q-15 0-25 11t-11 25v71q0 15 11 25t25 11h928q15 0 25-11t11-25z m0 214v-71q0-15-11-25t-25-11h-714q-14 0-25 11t-11 25v71q0 15 11 25t25 11h714q15 0 25-11t11-25z m0 215v-72q0-14-11-25t-25-11h-857q-14 0-25 11t-11 25v72q0 14 11 25t25 10h857q15 0 25-10t11-25z m0 214v-72q0-14-11-25t-25-10h-643q-14 0-25 10t-10 25v72q0 14 10 25t25 11h643q15 0 25-11t11-25z" horiz-adv-x="1000" />
+
+<glyph glyph-name="align-justify" unicode="&#xe8a8;" d="M1000 100v-71q0-15-11-25t-25-11h-928q-15 0-25 11t-11 25v71q0 15 11 25t25 11h928q15 0 25-11t11-25z m0 214v-71q0-15-11-25t-25-11h-928q-15 0-25 11t-11 25v71q0 15 11 25t25 11h928q15 0 25-11t11-25z m0 215v-72q0-14-11-25t-25-11h-928q-15 0-25 11t-11 25v72q0 14 11 25t25 10h928q15 0 25-10t11-25z m0 214v-72q0-14-11-25t-25-10h-928q-15 0-25 10t-11 25v72q0 14 11 25t25 11h928q15 0 25-11t11-25z" horiz-adv-x="1000" />
+
+<glyph glyph-name="list" unicode="&#xe8a9;" d="M143 118v-107q0-7-5-13t-13-5h-107q-7 0-13 5t-5 13v107q0 7 5 12t13 6h107q7 0 13-6t5-12z m0 214v-107q0-7-5-13t-13-5h-107q-7 0-13 5t-5 13v107q0 7 5 13t13 5h107q7 0 13-5t5-13z m0 214v-107q0-7-5-12t-13-6h-107q-7 0-13 6t-5 12v107q0 8 5 13t13 5h107q7 0 13-5t5-13z m857-428v-107q0-7-5-13t-13-5h-750q-7 0-12 5t-6 13v107q0 7 6 12t12 6h750q7 0 13-6t5-12z m-857 643v-107q0-8-5-13t-13-5h-107q-7 0-13 5t-5 13v107q0 7 5 12t13 6h107q7 0 13-6t5-12z m857-429v-107q0-7-5-13t-13-5h-750q-7 0-12 5t-6 13v107q0 7 6 13t12 5h750q7 0 13-5t5-13z m0 214v-107q0-7-5-12t-13-6h-750q-7 0-12 6t-6 12v107q0 8 6 13t12 5h750q7 0 13-5t5-13z m0 215v-107q0-8-5-13t-13-5h-750q-7 0-12 5t-6 13v107q0 7 6 12t12 6h750q7 0 13-6t5-12z" horiz-adv-x="1000" />
+
+<glyph glyph-name="indent-left" unicode="&#xe8aa;" d="M214 546v-321q0-7-5-13t-13-5q-7 0-12 5l-161 161q-5 5-5 13t5 13l161 160q5 5 12 5 8 0 13-5t5-13z m786-428v-107q0-7-5-13t-13-5h-964q-7 0-13 5t-5 13v107q0 7 5 12t13 6h964q7 0 13-6t5-12z m0 214v-107q0-7-5-13t-13-5h-607q-7 0-13 5t-5 13v107q0 7 5 13t13 5h607q7 0 13-5t5-13z m0 214v-107q0-7-5-12t-13-6h-607q-7 0-13 6t-5 12v107q0 8 5 13t13 5h607q7 0 13-5t5-13z m0 215v-107q0-8-5-13t-13-5h-964q-7 0-13 5t-5 13v107q0 7 5 12t13 6h964q7 0 13-6t5-12z" horiz-adv-x="1000" />
+
+<glyph glyph-name="indent-right" unicode="&#xe8ab;" d="M196 386q0-8-5-13l-160-161q-5-5-13-5-7 0-13 5t-5 13v321q0 8 5 13t13 5q8 0 13-5l160-160q5-5 5-13z m804-268v-107q0-7-5-13t-13-5h-964q-7 0-13 5t-5 13v107q0 7 5 12t13 6h964q7 0 13-6t5-12z m0 214v-107q0-7-5-13t-13-5h-607q-7 0-13 5t-5 13v107q0 7 5 13t13 5h607q7 0 13-5t5-13z m0 214v-107q0-7-5-12t-13-6h-607q-7 0-13 6t-5 12v107q0 8 5 13t13 5h607q7 0 13-5t5-13z m0 215v-107q0-8-5-13t-13-5h-964q-7 0-13 5t-5 13v107q0 7 5 12t13 6h964q7 0 13-6t5-12z" horiz-adv-x="1000" />
+
+<glyph glyph-name="list-bullet" unicode="&#xe8ac;" d="M214 64q0-44-31-76t-76-31-76 31-31 76 31 76 76 31 76-31 31-76z m0 286q0-45-31-76t-76-31-76 31-31 76 31 76 76 31 76-31 31-76z m786-232v-107q0-7-5-13t-13-5h-678q-8 0-13 5t-5 13v107q0 7 5 12t13 6h678q7 0 13-6t5-12z m-786 518q0-45-31-76t-76-31-76 31-31 76 31 76 76 31 76-31 31-76z m786-232v-108q0-7-5-12t-13-5h-678q-8 0-13 5t-5 12v108q0 7 5 12t13 5h678q7 0 13-5t5-12z m0 285v-107q0-7-5-12t-13-6h-678q-8 0-13 6t-5 12v107q0 8 5 13t13 5h678q7 0 13-5t5-13z" horiz-adv-x="1000" />
+
+<glyph glyph-name="list-numbered" unicode="&#xe8ad;" d="M213-54q0-45-31-70t-75-26q-60 0-96 37l31 49q28-25 60-25 16 0 28 8t12 24q0 35-59 31l-14 31q4 6 18 24t24 31 20 21v1q-9 0-27-1t-27 0v-30h-59v85h186v-49l-53-65q28-6 45-27t17-49z m1 350v-89h-202q-4 20-4 30 0 29 14 52t31 38 37 27 31 24 14 25q0 14-9 22t-22 7q-25 0-45-32l-47 33q13 28 40 44t59 16q40 0 68-23t28-63q0-28-19-51t-42-36-42-28-20-30h71v34h59z m786-178v-107q0-7-5-13t-13-5h-678q-8 0-13 5t-5 13v107q0 8 5 13t13 5h678q7 0 13-6t5-12z m-786 502v-56h-187v56h60q0 22 0 67t1 68v7h-1q-5-10-28-30l-40 42 76 71h59v-225h60z m786-216v-108q0-7-5-12t-13-5h-678q-8 0-13 5t-5 12v108q0 7 5 12t13 5h678q7 0 13-5t5-12z m0 285v-107q0-7-5-12t-13-6h-678q-8 0-13 6t-5 12v107q0 8 5 13t13 5h678q7 0 13-5t5-13z" horiz-adv-x="1000" />
+
+<glyph glyph-name="strike" unicode="&#xe8ae;" d="M982 350q8 0 13-5t5-13v-36q0-7-5-12t-13-5h-964q-8 0-13 5t-5 12v36q0 8 5 13t13 5h964z m-712 36q-16 19-29 44-27 55-27 105 0 101 75 173 74 71 219 71 28 0 94-11 36-7 98-27 6-21 12-66 8-68 8-102 0-10-3-25l-7-2-46 4-8 1q-28 83-58 114-49 51-117 51-64 0-101-33-38-32-38-81 0-41 37-78t156-72q38-12 96-37 33-16 53-29h-414z m283-143h229q4-22 4-51 0-62-23-119-13-31-40-58-20-19-61-45-44-27-85-37-45-12-113-12-64 0-109 13l-78 23q-32 8-40 15-5 5-5 12v8q0 60-1 87 0 17 0 38l1 20v25l57 1q8-19 17-40t12-31 7-15q20-32 45-52 24-20 59-32 33-12 73-12 36 0 78 15 43 14 68 48 26 34 26 72 0 47-45 87-19 16-76 40z" horiz-adv-x="1000" />
+
+<glyph glyph-name="underline" unicode="&#xe8af;" d="M27 726q-21 1-25 2l-2 49q7 1 22 1 34 0 63-3 74-4 93-4 47 0 93 2 65 2 82 3 31 0 48 1l-1-8 1-36v-5q-33-5-69-5-33 0-44-14-7-7-7-73 0-7 0-18t0-15l1-127 8-157q3-69 28-112 20-33 54-52 49-26 98-26 59 0 107 16 31 10 55 28 27 20 37 36 20 31 29 63 12 41 12 128 0 44-2 72t-6 68-8 89l-2 33q-3 37-13 49-19 20-43 19l-56-1-8 2 1 48h47l114-6q43-2 110 6l10-1q3-22 3-29 0-4-2-17-25-7-47-8-41-6-44-9-8-8-8-23 0-4 0-15t1-17q5-11 13-221 3-109-9-170-8-42-23-68-21-36-62-69-42-31-102-49-61-19-142-19-93 0-159 26-66 26-99 68-34 42-47 109-9 45-9 132v186q0 105-9 119-14 20-82 22z m830-787v36q0 8-5 13t-13 5h-821q-8 0-13-5t-5-13v-36q0-8 5-13t13-5h821q8 0 13 5t5 13z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="superscript" unicode="&#xe8b0;" d="M501 86v-93h-139l-89 141-13 23q-4 5-6 12h-2q0-2-1-4t-2-4-2-4q-5-11-14-25l-86-139h-144v93h71l110 162-103 152h-76v94h154l77-127q1-2 13-24 4-5 6-11h2q1 5 6 11l14 24 78 127h143v-94h-69l-103-149 114-165h61z m355 379v-115h-287l-1 15q-3 16-3 26 0 36 15 65t36 48 47 37 47 30 36 30 15 36q0 21-17 35t-39 13q-29 0-54-21-8-6-20-22l-59 52q15 20 35 37 47 36 105 36 61 0 99-33t38-89q0-31-13-57t-35-43-45-33-46-28-37-28-17-36h130v45h70z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="subscript" unicode="&#xe8b1;" d="M501 86v-93h-139l-89 141-13 23q-4 5-6 12h-2q0-2-1-4t-2-4-2-4q-5-11-14-25l-86-139h-144v93h71l110 162-103 152h-76v94h154l77-127q1-2 13-24 4-5 6-11h2q1 5 6 11l14 24 78 127h143v-94h-69l-103-149 114-165h61z m356-121v-115h-287l-2 15q-2 25-2 26 0 35 15 65t36 48 47 37 47 30 36 30 15 36q0 21-17 35t-39 13q-28 0-54-21-8-6-20-22l-59 52q15 20 35 37 45 36 105 36 62 0 100-33t37-89q0-37-19-66t-47-48-55-35-49-35-23-41h130v45h70z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="table" unicode="&#xe8b2;" d="M286 82v107q0 8-5 13t-13 5h-179q-7 0-12-5t-6-13v-107q0-8 6-13t12-5h179q8 0 13 5t5 13z m0 214v108q0 7-5 12t-13 5h-179q-7 0-12-5t-6-12v-108q0-7 6-12t12-5h179q8 0 13 5t5 12z m285-214v107q0 8-5 13t-12 5h-179q-8 0-13-5t-5-13v-107q0-8 5-13t13-5h179q7 0 12 5t5 13z m-285 429v107q0 8-5 13t-13 5h-179q-7 0-12-5t-6-13v-107q0-8 6-13t12-5h179q8 0 13 5t5 13z m285-215v108q0 7-5 12t-12 5h-179q-8 0-13-5t-5-12v-108q0-7 5-12t13-5h179q7 0 12 5t5 12z m286-214v107q0 8-5 13t-13 5h-178q-8 0-13-5t-5-13v-107q0-8 5-13t13-5h178q8 0 13 5t5 13z m-286 429v107q0 8-5 13t-12 5h-179q-8 0-13-5t-5-13v-107q0-8 5-13t13-5h179q7 0 12 5t5 13z m286-215v108q0 7-5 12t-13 5h-178q-8 0-13-5t-5-12v-108q0-7 5-12t13-5h178q8 0 13 5t5 12z m0 215v107q0 8-5 13t-13 5h-178q-8 0-13-5t-5-13v-107q0-8 5-13t13-5h178q8 0 13 5t5 13z m72 178v-607q0-37-27-63t-63-26h-750q-36 0-63 26t-26 63v607q0 37 26 63t63 27h750q37 0 63-27t27-63z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="columns" unicode="&#xe8b3;" d="M89-7h340v643h-358v-625q0-7 6-13t12-5z m768 18v625h-357v-643h339q8 0 13 5t5 13z m72 678v-678q0-37-27-63t-63-27h-750q-36 0-63 27t-26 63v678q0 37 26 63t63 27h750q37 0 63-27t27-63z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="crop" unicode="&#xe8b4;" d="M311 136h332v332z m-25 25l332 332h-332v-332z m643-43v-107q0-8-5-13t-13-5h-125v-125q0-8-5-13t-13-5h-107q-8 0-13 5t-5 13v125h-482q-8 0-13 5t-5 13v482h-125q-8 0-13 5t-5 13v107q0 8 5 13t13 5h125v125q0 8 5 13t13 5h107q8 0 13-5t5-13v-125h475l137 138q6 5 13 5t13-5q5-6 5-13t-5-13l-138-137v-475h125q8 0 13-5t5-13z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="scissors" unicode="&#xe8b5;" d="M536 350q14 0 25-11t10-25-10-25-25-10-25 10-11 25 11 25 25 11z m167-36l283-222q16-11 14-31-3-20-19-28l-72-36q-7-4-16-4-10 0-17 4l-385 216-62-36q-4-3-7-3 8-28 6-54-4-43-31-83t-74-69q-74-47-154-47-76 0-124 44-51 47-44 116 4 42 31 82t73 69q74 47 155 47 46 0 84-18 5 8 13 13l68 40-68 41q-8 5-13 12-38-17-84-17-81 0-155 47-46 30-73 69t-31 82q-3 33 8 63t36 52q47 44 124 44 80 0 154-47 46-29 74-68t31-83q2-27-6-54 3-1 7-3l62-37 385 216q7 5 17 5 9 0 16-4l72-36q16-9 19-28 2-20-14-32z m-380 145q26 24 12 61t-59 65q-52 33-107 33-42 0-63-20-26-24-12-60t59-66q51-33 107-33 41 0 63 20z m-47-415q45 28 59 65t-12 60q-22 20-63 20-56 0-107-33-45-28-59-65t12-60q21-20 63-20 55 0 107 33z m99 342l54-33v7q0 20 18 31l8 4-44 26-15-14q-1-2-5-6t-7-7q-1-1-2-2t-2-1z m125-125l54-18 410 321-71 36-429-240v-64l-89-53 5-5q1-1 4-3 2-2 6-7t6-6l15-15z m393-232l71 35-290 228-99-77q-1-2-7-4z" horiz-adv-x="1000" />
+
+<glyph glyph-name="paste" unicode="&#xe8b6;" d="M429-79h500v358h-233q-22 0-37 15t-16 38v232h-214v-643z m142 804v36q0 7-5 12t-12 6h-393q-7 0-13-6t-5-12v-36q0-7 5-13t13-5h393q7 0 12 5t5 13z m143-375h167l-167 167v-167z m286-71v-375q0-23-16-38t-38-16h-535q-23 0-38 16t-16 38v89h-303q-23 0-38 16t-16 37v750q0 23 16 38t38 16h607q22 0 38-16t15-38v-183q12-7 20-15l228-228q16-15 27-42t11-49z" horiz-adv-x="1000" />
+
+<glyph glyph-name="briefcase" unicode="&#xe8b7;" d="M357 707h286v72h-286v-72z m643-357v-268q0-37-26-63t-63-26h-822q-36 0-63 26t-26 63v268h375v-89q0-15 11-25t25-11h178q15 0 25 11t11 25v89h375z m-429 0v-71h-142v71h142z m429 268v-214h-1000v214q0 37 26 63t63 26h197v89q0 23 15 38t38 16h322q22 0 38-16t15-38v-89h197q37 0 63-26t26-63z" horiz-adv-x="1000" />
+
+<glyph glyph-name="suitcase" unicode="&#xe8b8;" d="M357 636h286v71h-286v-71z m-196 0v-715h-36q-51 0-88 37t-37 88v465q0 51 37 88t88 37h36z m625 0v-715h-572v715h72v89q0 22 15 38t38 16h322q22 0 38-16t15-38v-89h72z m214-125v-465q0-51-37-88t-88-37h-36v715h36q51 0 88-37t37-88z" horiz-adv-x="1000" />
+
+<glyph glyph-name="ellipsis" unicode="&#xe8b9;" d="M214 439v-107q0-22-15-38t-38-15h-107q-23 0-38 15t-16 38v107q0 23 16 38t38 16h107q22 0 38-16t15-38z m286 0v-107q0-22-16-38t-38-15h-107q-22 0-38 15t-15 38v107q0 23 15 38t38 16h107q23 0 38-16t16-38z m286 0v-107q0-22-16-38t-38-15h-107q-22 0-38 15t-16 38v107q0 23 16 38t38 16h107q23 0 38-16t16-38z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="ellipsis-vert" unicode="&#xe8ba;" d="M214 154v-108q0-22-15-37t-38-16h-107q-23 0-38 16t-16 37v108q0 22 16 38t38 15h107q22 0 38-15t15-38z m0 285v-107q0-22-15-38t-38-15h-107q-23 0-38 15t-16 38v107q0 23 16 38t38 16h107q22 0 38-16t15-38z m0 286v-107q0-22-15-38t-38-16h-107q-23 0-38 16t-16 38v107q0 22 16 38t38 16h107q22 0 38-16t15-38z" horiz-adv-x="214.3" />
+
+<glyph glyph-name="off" unicode="&#xe8bb;" d="M857 350q0-87-34-166t-91-137-137-92-166-34-167 34-136 92-92 137-34 166q0 102 45 191t126 151q24 18 54 14t46-28q18-23 14-53t-28-47q-54-41-84-101t-30-127q0-58 23-111t61-91 91-61 111-23 110 23 92 61 61 91 22 111q0 68-30 127t-84 101q-23 18-28 47t14 53q17 24 47 28t53-14q81-61 126-151t45-191z m-357 429v-358q0-29-21-50t-50-21-51 21-21 50v358q0 29 21 50t51 21 50-21 21-50z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="road" unicode="&#xe8bc;" d="M620 294v2l-13 179q-1 7-7 13t-12 5h-104q-7 0-13-5t-6-13l-13-179v-2q-1-6 4-11t12-4h136q7 0 12 4t4 11z m424-260q0-41-26-41h-393q7 0 12 5t5 13l-11 143q-1 7-7 12t-12 5h-152q-7 0-13-5t-6-12l-11-143q-1-7 4-13t12-5h-392q-26 0-26 41 0 30 14 64l233 583q5 11 15 18t21 8h189q-7 0-13-5t-6-13l-8-107q-1-8 4-13t12-5h93q7 0 12 5t5 13l-9 107q0 8-6 13t-13 5h190q11 0 21-8t14-18l233-583q15-34 15-64z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="list-alt" unicode="&#xe8bd;" d="M214 189v-35q0-8-5-13t-13-5h-35q-7 0-13 5t-5 13v35q0 8 5 13t13 5h35q8 0 13-5t5-13z m0 143v-36q0-7-5-12t-13-5h-35q-7 0-13 5t-5 12v36q0 7 5 13t13 5h35q8 0 13-5t5-13z m0 143v-36q0-7-5-12t-13-6h-35q-7 0-13 6t-5 12v36q0 7 5 13t13 5h35q8 0 13-5t5-13z m643-286v-35q0-8-5-13t-13-5h-535q-8 0-13 5t-5 13v35q0 8 5 13t13 5h535q8 0 13-5t5-13z m0 143v-36q0-7-5-12t-13-5h-535q-8 0-13 5t-5 12v36q0 7 5 13t13 5h535q8 0 13-5t5-13z m0 143v-36q0-7-5-12t-13-6h-535q-8 0-13 6t-5 12v36q0 7 5 13t13 5h535q8 0 13-5t5-13z m72-393v464q0 8-6 13t-12 5h-822q-7 0-12-5t-6-13v-464q0-7 6-12t12-6h822q7 0 12 6t6 12z m71 607v-607q0-37-26-63t-63-26h-822q-36 0-63 26t-26 63v607q0 37 26 63t63 27h822q37 0 63-27t26-63z" horiz-adv-x="1000" />
+
+<glyph glyph-name="qrcode" unicode="&#xe8be;" d="M214 207v-71h-71v71h71z m0 429v-72h-71v72h71z m429 0v-72h-72v72h72z m-572-571h215v214h-215v-214z m0 428h215v214h-215v-214z m429 0h214v214h-214v-214z m-143-143v-357h-357v357h357z m286-286v-71h-72v71h72z m143 0v-71h-72v71h72z m0 286v-214h-215v71h-71v-214h-71v357h214v-71h71v71h72z m-429 429v-358h-357v358h357z m429 0v-358h-357v358h357z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="barcode" unicode="&#xe8bf;" d="M35-7h-35v786h35v-786z m35 0h-17v786h17v-786z m53 0h-17v786h17v-786z m87 0h-17v786h17v-786z m88 0h-35v786h35v-786z m70 0h-17v786h17v-786z m36 0h-18v786h18v-786z m35 0h-18v786h18v-786z m87 0h-35v786h35v-786z m88 0h-35v786h35v-786z m70 0h-35v786h35v-786z m71 0h-36v786h36v-786z m52 0h-35v786h35v-786z m105 0h-52v786h52v-786z m36 0h-18v786h18v-786z m52 0h-35v786h35v-786z" horiz-adv-x="1000" />
+
+<glyph glyph-name="book" unicode="&#xe8c0;" d="M915 583q22-31 10-72l-154-505q-10-36-42-60t-69-25h-515q-43 0-83 30t-55 74q-14 37-1 71 0 2 1 15t3 20q0 5-2 12t-2 11q1 6 5 12t9 13 9 13q13 21 25 51t17 51q2 6 0 17t0 16q2 6 9 15t10 13q12 20 23 51t14 51q1 5-1 17t0 16q2 7 12 17t13 13q10 14 23 47t16 54q0 4-2 14t-1 15q1 4 5 10t10 13 10 11q4 7 9 17t8 20 9 20 11 18 15 13 20 6 26-3l0-1q21 5 28 5h425q41 0 64-32t10-72l-153-506q-20-66-40-85t-72-20h-485q-15 0-21-8-6-9-1-24 14-39 81-39h515q16 0 31 9t20 23l167 550q4 13 3 32 21-8 33-24z m-594-1q-2-7 1-12t11-6h339q8 0 15 6t9 12l12 36q2 7-1 12t-12 6h-339q-7 0-14-6t-9-12z m-46-143q-3-7 1-12t11-6h339q7 0 14 6t10 12l11 36q3 7-1 13t-11 5h-339q-7 0-14-5t-10-13z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="ajust" unicode="&#xe8c1;" d="M429 46v608q-83 0-153-41t-110-111-41-152 41-152 110-111 153-41z m428 304q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="tint" unicode="&#xe8c2;" d="M286 207q0 20-11 39-1 0-9 12t-14 21-14 25-12 28q-2 9-12 9t-11-9q-4-13-12-28t-14-25-14-21-9-12q-11-19-11-39 0-29 21-50t50-21 51 21 21 50z m285 72q0-119-83-202t-202-84-202 84-84 202q0 81 45 153 4 5 35 51t56 84 56 99 46 113q5 16 19 26t29 9 29-9 18-26q16-52 47-113t55-99 56-84 35-51q45-71 45-153z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="toggle-off" unicode="&#xe8c3;" d="M643 350q0 58-23 111t-61 91-91 61-111 23-111-23-91-61-61-91-23-111 23-111 61-91 91-61 111-23 111 23 91 61 61 91 23 111z m428 0q0 58-22 111t-61 91-91 61-111 23h-216q67-50 106-125t38-161-38-161-106-125h216q58 0 111 23t91 61 61 91 22 111z m72 0q0-72-29-139t-76-113-114-77-138-28h-429q-72 0-138 28t-114 77-76 113-29 139 29 139 76 114 114 76 138 28h429q72 0 138-28t114-76 76-114 29-139z" horiz-adv-x="1142.9" />
+
+<glyph glyph-name="toggle-on" unicode="&#xe8c4;" d="M0 350q0 73 29 139t76 114 114 76 138 28h429q72 0 138-28t114-76 76-114 29-139-29-139-76-113-114-77-138-28h-429q-72 0-138 28t-114 77-76 113-29 139z m786-286q58 0 111 23t91 61 61 91 22 111-22 111-61 91-91 61-111 23-111-23-91-61-61-91-23-111 23-111 61-91 91-61 111-23z" horiz-adv-x="1142.9" />
+
+<glyph glyph-name="check" unicode="&#xe8c5;" d="M786 331v-177q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h464q35 0 65-14 9-4 10-13 2-10-5-16l-27-28q-6-5-13-5-1 0-5 1-13 3-25 3h-464q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63v141q0 8 5 13l36 35q6 6 13 6 3 0 7-2 11-4 11-16z m129 273l-455-454q-13-14-31-14t-32 14l-240 240q-14 13-14 31t14 32l61 62q14 13 32 13t32-13l147-147 361 361q13 13 31 13t32-13l62-61q13-14 13-32t-13-32z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="check-empty" unicode="&#xe8c6;" d="M625 707h-464q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63v464q0 37-26 63t-63 26z m161-89v-464q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h464q66 0 114-48t47-113z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="circle" unicode="&#xe8c7;" d="M857 350q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="circle-empty" unicode="&#xe8c8;" d="M429 654q-83 0-153-41t-110-111-41-152 41-152 110-111 153-41 152 41 110 111 41 152-41 152-110 111-152 41z m428-304q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="circle-notch" unicode="&#xe8c9;" d="M982 350q0-98-38-187t-103-154-153-103-188-38-187 38-154 103-103 154-38 187q0 119 54 222t148 171 209 84v-127q-124-25-205-123t-81-227q0-72 28-139t77-113 113-77 139-28 139 28 114 77 76 113 28 139q0 128-81 227t-205 123v127q115-17 209-84t148-171 54-222z" horiz-adv-x="1000" />
+
+<glyph glyph-name="dot-circled" unicode="&#xe8ca;" d="M571 350q0-59-41-101t-101-42-101 42-42 101 42 101 101 42 101-42 41-101z m-142 304q-83 0-153-41t-110-111-41-152 41-152 110-111 153-41 152 41 110 111 41 152-41 152-110 111-152 41z m428-304q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="asterisk" unicode="&#xe8cb;" d="M827 264q26-14 33-43t-7-55l-35-61q-15-26-44-33t-54 7l-149 85v-171q0-29-21-50t-50-22h-71q-29 0-51 22t-21 50v171l-148-85q-26-15-55-7t-43 33l-36 61q-14 26-7 55t34 43l148 86-148 86q-26 14-34 43t7 55l36 61q15 26 43 33t55-7l148-85v171q0 29 21 50t51 22h71q29 0 50-22t21-50v-171l149 85q26 15 54 7t44-33l35-61q15-26 7-55t-33-43l-148-86z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="gift" unicode="&#xe8cc;" d="M518 93v400h-179v-400q0-14 10-21t26-8h107q16 0 26 8t10 21z m-255 471h109l-70 90q-15 17-39 17-22 0-38-15t-15-38 15-38 38-16z m384 54q0 22-15 38t-38 15q-24 0-39-17l-69-90h108q22 0 38 16t15 38z m210-143v-179q0-7-5-12t-13-5h-53v-233q0-22-16-37t-38-16h-607q-22 0-38 16t-16 37v233h-53q-8 0-13 5t-5 12v179q0 8 5 13t13 5h245q-51 0-88 36t-37 89 37 88 88 37q60 0 94-43l72-92 71 92q34 43 94 43 52 0 88-37t37-88-37-89-88-36h245q8 0 13-5t5-13z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="fire" unicode="&#xe8cd;" d="M786-96v-36q0-7-6-13t-12-5h-750q-7 0-13 5t-5 13v36q0 7 5 12t13 5h750q7 0 12-5t6-12z m-143 589q0-44-14-80t-35-63-49-49-54-44-49-40-35-45-14-54q0-54 37-125l-2 0 1 0q-51 23-90 46t-77 56-63 68-41 84-15 103q0 44 14 80t35 63 49 49 54 44 49 40 35 45 14 54q0 53-37 125l2-1-1 1q50-23 89-46t78-56 63-68 41-84 15-103z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="magnet" unicode="&#xe8ce;" d="M857 386v-72q0-112-55-202t-153-140-220-51-221 51-153 140-55 202v72q0 14 11 25t25 10h214q15 0 25-10t11-25v-72q0-29 13-50t30-32 39-16 36-8 25-1 24 1 36 8 40 16 29 32 13 50v72q0 14 11 25t25 10h214q15 0 26-10t10-25z m-571 357v-214q0-15-11-25t-25-11h-214q-15 0-25 11t-11 25v214q0 14 11 25t25 11h214q15 0 25-11t11-25z m571 0v-214q0-15-10-25t-26-11h-214q-14 0-25 11t-11 25v214q0 14 11 25t25 11h214q15 0 26-11t10-25z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="chart-bar" unicode="&#xe8cf;" d="M357 350v-286h-143v286h143z m214 286v-572h-142v572h142z m572-643v-72h-1143v858h71v-786h1072z m-357 500v-429h-143v429h143z m214 214v-643h-143v643h143z" horiz-adv-x="1142.9" />
+
+<glyph glyph-name="chart-area" unicode="&#xe8d0;" d="M1143-7v-72h-1143v858h71v-786h1072z m-214 571l142-500h-928v322l250 321 321-321z" horiz-adv-x="1142.9" />
+
+<glyph glyph-name="chart-pie" unicode="&#xe8d1;" d="M429 353l304-304q-59-61-138-94t-166-34q-117 0-216 58t-155 156-58 215 58 215 155 156 216 58v-426z m104-3h431q0-88-33-167t-94-138z m396 71h-429v429q117 0 215-57t156-156 58-216z" horiz-adv-x="1000" />
+
+<glyph glyph-name="chart-line" unicode="&#xe8d2;" d="M1143-7v-72h-1143v858h71v-786h1072z m-72 696v-242q0-12-10-17t-20 4l-68 68-353-353q-6-6-13-6t-13 6l-130 130-232-233-107 108 327 326q5 6 12 6t13-6l130-130 259 259-67 68q-9 8-5 19t17 11h243q7 0 12-5t5-13z" horiz-adv-x="1142.9" />
+
+<glyph glyph-name="ticket" unicode="&#xe8d3;" d="M571 598l177-177-319-319-177 177z m-117-546l345 344q10 11 10 25t-10 26l-202 202q-10 10-26 10t-25-10l-344-345q-11-11-11-25t11-25l202-202q10-11 25-11t25 11z m496 355l-506-507q-21-20-51-20t-50 20l-71 70q32 32 32 76t-32 76-76 32-75-32l-70 71q-21 20-21 50t21 51l506 505q21 21 50 21t51-21l70-69q-32-32-32-76t32-76 76-32 76 32l70-70q20-21 20-51t-20-50z" horiz-adv-x="1000" />
+
+<glyph glyph-name="credit-card" unicode="&#xe8d4;" d="M982 779q37 0 63-27t26-63v-678q0-37-26-63t-63-27h-893q-36 0-63 27t-26 63v678q0 37 26 63t63 27h893z m-893-72q-7 0-12-5t-6-13v-125h929v125q0 8-5 13t-13 5h-893z m893-714q7 0 13 5t5 13v339h-929v-339q0-7 6-13t12-5h893z m-839 71v72h143v-72h-143z m214 0v72h214v-72h-214z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="floppy" unicode="&#xe8d5;" d="M214-7h429v214h-429v-214z m500 0h72v500q0 8-6 21t-11 20l-157 156q-5 6-19 12t-22 5v-232q0-22-15-38t-38-16h-322q-22 0-37 16t-16 38v232h-72v-714h72v232q0 22 16 38t37 16h465q22 0 38-16t15-38v-232z m-214 518v178q0 8-5 13t-13 5h-107q-7 0-13-5t-5-13v-178q0-7 5-13t13-5h107q7 0 13 5t5 13z m357-18v-518q0-22-15-38t-38-16h-750q-23 0-38 16t-16 38v750q0 22 16 38t38 16h517q23 0 50-12t42-26l156-157q16-15 27-42t11-49z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="megaphone" unicode="&#xe8d6;" d="M929 493q29 0 50-21t21-51-21-50-50-21v-214q0-29-22-50t-50-22q-233 194-453 212-32-10-51-36t-17-57 22-51q-11-19-13-37t4-32 19-31 26-28 35-28q-17-32-63-46t-94-7-73 31q-4 13-17 49t-18 53-12 50-9 56 2 55 12 62h-68q-36 0-63 26t-26 63v107q0 37 26 63t63 26h268q243 0 500 215 29 0 50-22t22-50v-214z m-72-337v532q-220-168-428-191v-151q210-23 428-190z" horiz-adv-x="1000" />
+
+<glyph glyph-name="hdd" unicode="&#xe8d7;" d="M580 171q0-18-13-31t-31-13-32 13-13 31 13 32 32 13 31-13 13-32z m143 0q0-18-13-31t-31-13-32 13-13 31 13 32 32 13 31-13 13-32z m63-89v179q0 7-6 12t-12 6h-679q-7 0-12-6t-6-12v-179q0-7 6-12t12-6h679q7 0 12 6t6 12z m-687 268h659l-88 269q-2 7-9 12t-14 5h-437q-7 0-14-5t-9-12z m758-89v-179q0-37-26-63t-63-26h-679q-36 0-63 26t-26 63v179q0 14 9 42l110 338q9 29 35 48t56 18h437q31 0 56-18t35-48l110-338q9-28 9-42z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="fork" unicode="&#xe8d9;" d="M161 29q0 22-16 38t-38 15-38-15-15-38 15-38 38-16 38 16 16 38z m0 642q0 23-16 38t-38 16-38-16-15-38 15-37 38-16 38 16 16 37z m357-71q0 22-16 38t-38 16-38-16-15-38 15-38 38-16 38 16 16 38z m53 0q0-29-14-54t-39-39q-1-160-126-231-38-21-113-45-72-22-95-39t-23-56v-15q24-14 39-39t14-53q0-45-31-76t-76-32-76 32-31 76q0 29 15 53t39 39v458q-25 14-39 39t-15 53q0 45 31 76t76 32 76-32 31-76q0-29-14-53t-39-39v-277q30 14 86 31 30 10 49 17t39 17 33 22 22 29 16 38 5 51q-25 14-39 39t-15 54q0 45 31 76t76 31 76-31 31-76z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="rocket" unicode="&#xe8da;" d="M804 600q0 22-16 38t-38 16-38-16-16-38 16-38 38-16 38 16 16 38z m125 161q0-139-43-240t-141-202q-45-44-109-98l-11-211q-1-9-9-15l-214-125q-4-2-9-2-7 0-13 5l-36 36q-7 7-4 17l47 155-156 156-154-47q-2-1-6-1-7 0-12 5l-36 36q-10 11-3 22l125 214q6 8 15 9l211 11q54 64 98 109 105 104 200 144t241 40q7 0 13-6t6-12z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="bug" unicode="&#xe8db;" d="M911 314q0-14-11-25t-25-10h-125q0-96-37-162l116-117q10-11 10-25t-10-25q-10-11-25-11t-25 11l-111 110q-3-3-8-7t-24-16-36-21-46-16-54-7v500h-71v-500q-29 0-57 7t-49 19-36 22-25 18l-8 8-102-116q-11-12-27-12-13 0-24 9-11 10-11 25t8 26l113 127q-32 63-32 153h-125q-15 0-25 10t-11 25 11 25 25 11h125v164l-97 97q-11 10-11 25t11 25 25 10 25-10l97-97h471l96 97q11 10 25 10t26-10 10-25-10-25l-97-97v-164h125q15 0 25-11t11-25z m-268 322h-357q0 74 52 126t126 52 127-52 52-126z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="certificate" unicode="&#xe8dc;" d="M768 350l77-75q17-16 11-39-7-23-29-29l-105-27 30-103q6-23-11-39-16-18-39-11l-104 30-27-105q-5-23-28-30-7-1-11-1-17 0-28 13l-75 77-76-77q-15-17-39-12-23 7-28 30l-27 105-104-30q-23-7-39 11-17 16-10 39l29 103-105 27q-22 6-29 29-6 23 11 39l77 75-77 75q-17 16-11 39 7 23 29 29l105 27-29 103q-7 23 10 40 16 17 39 10l104-29 27 104q5 23 28 29 23 7 39-11l76-77 75 77q16 17 39 11 23-6 28-29l27-104 104 29q23 7 39-10 17-17 11-40l-30-103 105-27q22-6 29-29 6-23-11-39z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="tasks" unicode="&#xe8dd;" d="M571 64h358v72h-358v-72z m-214 286h572v71h-572v-71z m357 286h215v71h-215v-71z m286-465v-142q0-15-11-25t-25-11h-928q-15 0-25 11t-11 25v142q0 15 11 26t25 10h928q15 0 25-10t11-26z m0 286v-143q0-14-11-25t-25-10h-928q-15 0-25 10t-11 25v143q0 15 11 25t25 11h928q15 0 25-11t11-25z m0 286v-143q0-14-11-25t-25-11h-928q-15 0-25 11t-11 25v143q0 14 11 25t25 11h928q15 0 25-11t11-25z" horiz-adv-x="1000" />
+
+<glyph glyph-name="filter" unicode="&#xe8de;" d="M783 685q9-22-8-39l-275-275v-414q0-23-22-33-7-3-14-3-15 0-25 11l-143 143q-10 11-10 25v271l-275 275q-18 17-8 39 9 22 33 22h714q23 0 33-22z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="beaker" unicode="&#xe8df;" d="M852 42q31-50 12-85t-78-36h-643q-59 0-78 36t12 85l280 443v222h-36q-14 0-25 11t-10 25 10 25 25 11h286q15 0 25-11t11-25-11-25-25-11h-36v-222z m-435 405l-151-240h397l-152 240-11 17v243h-71v-243z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="magic" unicode="&#xe8e0;" d="M664 526l164 163-60 60-164-163z m250 163q0-15-10-25l-718-718q-10-10-25-10t-25 10l-111 111q-10 10-10 25t10 25l718 718q10 10 25 10t25-10l111-111q10-10 10-25z m-754 106l54-16-54-17-17-55-17 55-55 17 55 16 17 55z m195-90l109-34-109-33-34-109-33 109-109 33 109 34 33 109z m519-267l55-17-55-16-17-55-17 55-54 16 54 17 17 55z m-357 357l54-16-54-17-17-55-17 55-54 17 54 16 17 55z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="cab" unicode="&#xe8e1;" d="M268 243q0 37-26 63t-63 26-63-26-27-63 27-63 63-26 63 26 26 63z m20 178h567l-50 200q-1 4-8 9t-11 6h-429q-5 0-12-6t-7-9z m766-178q0 37-27 63t-63 26-63-26-26-63 26-63 63-26 63 26 27 63z m89 53v-214q0-8-5-13t-13-5h-54v-71q0-45-31-76t-76-31-76 31-31 76v71h-571v-71q0-45-31-76t-76-31-76 31-32 76v71h-53q-8 0-13 5t-5 13v214q0 52 37 89t88 36h16l58 234q13 53 58 88t100 36h429q54 0 100-36t58-88l58-234h16q52 0 88-36t37-89z" horiz-adv-x="1142.9" />
+
+<glyph glyph-name="taxi" unicode="&#xe8e2;" d="M1018 350q52 0 88-37t37-88v-214q0-8-5-13t-13-5h-54v-36q0-45-31-76t-76-31-76 31-31 76v36h-571v-36q0-45-31-76t-76-31-76 31-32 76v36h-53q-8 0-13 5t-5 13v214q0 52 37 88t88 37h16l58 234q13 52 58 88t100 35h72v125q0 8 5 13t12 5h250q8 0 13-5t5-13v-125h72q54 0 100-35t58-88l58-234h16z m-839-268q36 0 63 26t26 63-26 64-63 26-63-26-27-64 27-63 63-26z m109 268h567l-50 199q-1 5-8 10t-11 5h-429q-5 0-12-5t-7-10z m676-268q37 0 63 26t27 63-27 64-63 26-63-26-26-64 26-63 63-26z" horiz-adv-x="1142.9" />
+
+<glyph glyph-name="truck" unicode="&#xe8e3;" d="M357 64q0 29-21 51t-50 21-50-21-22-51 22-50 50-21 50 21 21 50z m-214 286h214v143h-88q-7 0-12-5l-109-109q-5-5-5-12v-17z m714-286q0 29-21 51t-50 21-50-21-22-51 22-50 50-21 50 21 21 50z m143 607v-571q0-8-2-15t-8-10-9-6-13-4-13-1-14 0-12 0q0-59-42-101t-101-42-101 42-42 101h-214q0-59-42-101t-101-42-101 42-42 101h-36q-1 0-12 0t-15 0-12 1-13 4-9 6-8 10-2 15q0 15 10 25t25 11v178q0 5 0 20t0 21 2 19 3 21 8 17 13 17l110 110q11 11 28 18t33 7h89v107q0 15 11 26t25 10h571q15 0 25-10t11-26z" horiz-adv-x="1000" />
+
+<glyph glyph-name="bus" unicode="&#xe8e4;" d="M214 171q0 30-21 51t-50 21-51-21-21-51 21-50 51-21 50 21 21 50z m572 0q0 30-21 51t-51 21-50-21-21-51 21-50 50-21 51 21 21 50z m-26 221l-40 215q-3 13-13 21t-22 8h-513q-12 0-22-8t-13-21l-40-215q-3-16 8-29t27-13h593q17 0 27 13t8 29z m-126 342q0 11-8 19t-19 8h-357q-11 0-19-8t-8-19 8-19 19-8h357q11 0 19 8t8 19z m223-405v-336h-71v-72q0-29-21-50t-51-21-50 21-21 50v72h-429v-72q0-29-21-50t-50-21-51 21-21 50v72h-71v336q0 63 14 125l57 253q6 44 55 77t128 49 175 17 174-17 128-49 55-77l58-253q13-57 13-125z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="bicycle" unicode="&#xe8e5;" d="M425 207h-175q-22 0-32 20t4 37l105 140q-37 17-77 17-74 0-126-52t-53-126 53-126 126-53q64 0 113 41t62 102z m-104 72h104q-10 47-42 82z m268 0l161 214h-268l-55-74q59-57 70-140h92z m625-36q0 74-52 126t-126 52q-34 0-68-13l97-145q9-13 6-27t-15-23q-9-6-20-6-20 0-30 16l-97 145q-52-53-52-125 0-74 53-126t126-53 126 53 52 126z m72 0q0-103-74-177t-176-73-177 73-73 177q0 54 22 102t61 84l-36 54-197-261q-10-15-29-15h-110q-13-91-83-153t-164-61q-103 0-177 73t-73 177 73 177 177 73q64 0 120-31l76 102h-125q-14 0-25 11t-10 25 10 25 25 11h215v-72h243l-48 72h-124q-14 0-25 10t-11 25 11 26 25 10h143q18 0 30-15l149-224q50 25 107 25 103 0 176-73t74-177z" horiz-adv-x="1285.7" />
+
+<glyph glyph-name="money" unicode="&#xe8e6;" d="M429 207h214v54h-72v250h-63l-83-77 43-44q24 20 31 31h1v-160h-71v-54z m285 143q0-39-11-79t-34-75-56-56-77-22-77 22-57 56-33 75-12 79 12 79 33 75 57 56 77 22 77-22 56-56 34-75 11-79z m286-143v286q-59 0-101 42t-42 101h-643q0-59-42-101t-101-42v-286q60 0 101-42t42-101h643q0 59 42 101t101 42z m71 464v-642q0-15-10-25t-25-11h-1000q-15 0-25 11t-11 25v642q0 15 11 26t25 10h1000q14 0 25-10t10-26z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="euro" unicode="&#xe8e7;" d="M545 121l19-89q2-7-1-13t-10-8l-3 0q-2-1-6-2t-9-3-12-3-14-3-16-2-19-3-21-2-21 0q-131 0-228 73t-133 196h-53q-7 0-13 5t-5 13v63q0 7 5 12t13 6h37q-1 31 0 58h-37q-8 0-13 5t-5 13v64q0 8 5 13t13 5h55q37 117 135 188t224 72q57 0 108-13 6-2 11-9 4-6 2-13l-24-89q-2-7-8-11t-13-1l-2 1q-3 0-7 1l-10 2t-12 2-15 2-16 1-16 1q-71 0-126-36t-84-98h261q9 0 14-7 6-7 4-15l-13-63q-3-15-18-15h-273q-1-20 0-58h257q8 0 13-7 5-7 4-15l-14-63q-1-6-6-10t-11-4h-216q27-65 84-104t127-38q10 0 20 1t19 2 16 2 14 3 10 3l7 1 3 2q7 2 14-2 7-3 9-11z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="pound" unicode="&#xe8e8;" d="M569 216v-205q0-8-5-13t-13-5h-533q-8 0-13 5t-5 13v83q0 8 5 13t13 5h54v214h-53q-8 0-13 5t-5 13v73q0 8 5 13t13 5h53v124q0 96 69 158t175 62q104 0 187-70 5-5 6-12t-4-12l-57-71q-5-6-13-7-7-1-13 4-2 3-14 11t-39 18-51 10q-48 0-77-27t-29-68v-120h170q8 0 13-5t5-13v-73q0-7-5-13t-13-5h-170v-211h231v101q0 7 5 12t13 5h90q8 0 13-5t5-12z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="dollar" unicode="&#xe8e9;" d="M546 189q0-86-56-147t-144-77v-97q0-8-5-13t-13-5h-75q-7 0-13 5t-5 13v97q-37 5-71 18t-57 25-41 26-26 21-10 10q-9 12-1 23l58 76q3 5 12 6 9 1 14-5l1-1q63-55 135-70 21-4 42-4 45 0 79 24t35 68q0 16-9 30t-18 23-33 21-37 18-45 18q-21 9-34 14t-34 15-35 17-32 20-29 24-25 27-20 32-11 37-5 44q0 77 55 135t142 75v100q0 7 5 13t13 5h75q8 0 13-5t5-13v-98q32-3 62-13t48-19 36-20 21-17 9-7q9-11 3-22l-46-81q-4-9-12-9-8-2-15 4-2 2-9 7t-21 14-33 18-42 15-47 6q-53 0-87-24t-33-62q0-14 4-27t17-23 22-18 31-18 34-15 39-15q30-11 45-17t43-20 42-24 34-28 30-35 18-43 7-52z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="sort" unicode="&#xe8ea;" d="M571 243q0-15-10-25l-250-250q-11-11-25-11t-25 11l-250 250q-11 10-11 25t11 25 25 11h500q14 0 25-11t10-25z m0 214q0-14-10-25t-25-11h-500q-15 0-25 11t-11 25 11 25l250 250q10 11 25 11t25-11l250-250q10-10 10-25z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="sort-down" unicode="&#xe8eb;" d="M571 243q0-15-10-25l-250-250q-11-11-25-11t-25 11l-250 250q-11 10-11 25t11 25 25 11h500q14 0 25-11t10-25z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="sort-up" unicode="&#xe8ec;" d="M571 457q0-14-10-25t-25-11h-500q-15 0-25 11t-11 25 11 25l250 250q10 11 25 11t25-11l250-250q10-10 10-25z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="sort-alt-up" unicode="&#xe8ed;" d="M411 46q0-6-6-13l-178-178q-5-5-13-5-6 0-12 5l-179 179q-8 9-4 19 4 11 17 11h107v768q0 8 5 13t13 5h107q8 0 13-5t5-13v-768h107q8 0 13-5t5-13z m589-71v-107q0-8-5-13t-13-5h-464q-8 0-13 5t-5 13v107q0 8 5 13t13 5h464q8 0 13-5t5-13z m-107 286v-107q0-8-5-13t-13-5h-357q-8 0-13 5t-5 13v107q0 8 5 13t13 5h357q8 0 13-5t5-13z m-107 285v-107q0-7-5-12t-13-6h-250q-8 0-13 6t-5 12v107q0 8 5 13t13 5h250q8 0 13-5t5-13z m-107 286v-107q0-8-5-13t-13-5h-143q-8 0-13 5t-5 13v107q0 8 5 13t13 5h143q8 0 13-5t5-13z" horiz-adv-x="1000" />
+
+<glyph glyph-name="sort-alt-down" unicode="&#xe8ee;" d="M679-25v-107q0-8-5-13t-13-5h-143q-8 0-13 5t-5 13v107q0 8 5 13t13 5h143q8 0 13-5t5-13z m-268 71q0-6-6-13l-178-178q-5-5-13-5-6 0-12 5l-179 179q-8 9-4 19 4 11 17 11h107v768q0 8 5 13t13 5h107q8 0 13-5t5-13v-768h107q8 0 13-5t5-13z m375 215v-107q0-8-5-13t-13-5h-250q-8 0-13 5t-5 13v107q0 8 5 13t13 5h250q8 0 13-5t5-13z m107 285v-107q0-7-5-12t-13-6h-357q-8 0-13 6t-5 12v107q0 8 5 13t13 5h357q8 0 13-5t5-13z m107 286v-107q0-8-5-13t-13-5h-464q-8 0-13 5t-5 13v107q0 8 5 13t13 5h464q8 0 13-5t5-13z" horiz-adv-x="1000" />
+
+<glyph glyph-name="sort-name-up" unicode="&#xe8ef;" d="M665 622h98l-40 122-6 26q-2 9-2 11h-2l-1-11q0 0-2-10t-5-16z m-254-576q0-6-6-13l-178-178q-5-5-13-5-6 0-12 5l-179 179q-8 9-4 19 4 11 17 11h107v768q0 8 5 13t13 5h107q8 0 13-5t5-13v-768h107q8 0 13-5t5-13z m466-66v-130h-326v50l206 295q7 11 12 16l6 5v1q-1 0-3 0t-5 0q-6-2-16-2h-130v-64h-67v128h317v-50l-206-296q-4-4-12-14l-6-7v-1l8 1q5 2 16 2h139v66h67z m50 501v-60h-161v60h42l-26 80h-136l-26-80h42v-60h-160v60h39l128 369h91l128-369h39z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="sort-name-down" unicode="&#xe8f0;" d="M665 51h98l-40 122-6 26q-2 9-2 11h-2l-1-11q0-1-2-10t-5-16z m-254-5q0-6-6-13l-178-178q-5-5-13-5-6 0-12 5l-179 179q-8 9-4 19 4 11 17 11h107v768q0 8 5 13t13 5h107q8 0 13-5t5-13v-768h107q8 0 13-5t5-13z m516-137v-59h-161v59h42l-26 80h-136l-26-80h42v-59h-160v59h39l128 370h91l128-370h39z m-50 643v-131h-326v51l206 295q7 10 12 15l6 5v2q-1 0-3-1t-5 0q-6-2-16-2h-130v-64h-67v128h317v-50l-206-295q-4-5-12-15l-6-5v-2l8 2q5 0 16 0h139v67h67z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="sort-number-up" unicode="&#xe8f1;" d="M751 117q0 36-24 65t-58 30q-29 0-46-21t-17-52 20-53 58-22q28 0 48 15t19 38z m-340-71q0-6-6-13l-178-178q-5-5-13-5-6 0-12 5l-179 179q-8 9-4 19 4 11 17 11h107v768q0 8 5 13t13 5h107q8 0 13-5t5-13v-768h107q8 0 13-5t5-13z m418 39q0-35-7-68t-23-64-38-53-55-36-71-14q-35 0-60 9-14 4-24 8l22 63q9-4 17-6 21-7 42-7 47 0 75 33t37 81h-1q-11-13-34-21t-47-8q-59 0-97 40t-37 97q0 58 40 99t101 41q69 0 115-53t45-141z m-16 400v-64h-262v64h93v241q0 4 0 11t1 9v9h-2l-3-7q-5-7-15-17l-35-32-45 48 107 103h68v-365h93z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="sort-number-down" unicode="&#xe8f2;" d="M751 689q0 35-24 65t-58 29q-29 0-46-21t-17-52 20-53 58-21q28 0 48 15t19 38z m-340-643q0-6-6-13l-178-178q-5-5-13-5-6 0-12 5l-179 179q-8 9-4 19 4 11 17 11h107v768q0 8 5 13t13 5h107q8 0 13-5t5-13v-768h107q8 0 13-5t5-13z m402-132v-64h-262v64h93v241q0 4 0 10t1 10v9h-2l-3-7q-5-7-15-17l-35-33-45 48 107 104h68v-365h93z m16 742q0-34-7-67t-23-64-38-53-55-37-71-14q-35 0-60 9-14 5-24 9l22 63q9-4 17-6 21-8 42-8 47 0 75 33t37 81h-1q-11-13-34-20t-47-8q-59 0-97 40t-37 96q0 59 40 99t101 41q69 0 115-53t45-141z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="hammer" unicode="&#xe8f3;" d="M988-7q0-30-20-50l-60-61q-22-20-51-20-29 0-50 20l-203 204q-21 20-21 50 0 29 24 53l-143 143-70-70q-8-8-19-8t-19 8q1-1 7-7t7-7 6-6 5-8 4-8 3-9 0-10q0-21-15-38-2-1-9-10t-11-11-10-9-13-9-12-5-14-3q-23 0-38 16l-228 228q-16 15-16 38 0 7 3 14t5 12 9 13 9 10 11 11 10 9q17 15 38 15 6 0 10 0t9-3 8-4 8-5 6-6 7-7 7-7q-8 8-8 19t8 19l194 194q8 8 19 8t19-8q-1 1-7 7t-7 7-6 7-5 7-3 8-4 9 0 10q0 21 15 38 2 2 9 10t11 11 10 10 13 8 12 5 14 3q23 0 38-16l228-228q16-15 16-38 0-7-3-14t-5-12-8-13-10-10-11-11-10-9q-17-15-38-15-6 0-10 0t-9 4-8 3-7 5-7 6-7 7-7 7q8-8 8-19t-8-19l-70-70 143-143q24 24 53 24 29 0 51-21l203-202q20-22 20-51z" horiz-adv-x="1000" />
+
+<glyph glyph-name="gauge" unicode="&#xe8f4;" d="M214 207q0 30-21 51t-50 21-51-21-21-51 21-50 51-21 50 21 21 50z m107 250q0 30-20 51t-51 21-50-21-21-51 21-50 50-21 51 21 20 50z m239-268l57 213q3 14-5 27t-21 16-27-3-17-22l-56-213q-33-3-60-25t-35-55q-11-43 11-81t66-50 81 11 50 66q9 33-4 65t-40 51z m369 18q0 30-21 51t-51 21-50-21-21-51 21-50 50-21 51 21 21 50z m-358 357q0 30-20 51t-51 21-50-21-21-51 21-50 50-21 51 21 20 50z m250-107q0 30-20 51t-51 21-50-21-21-51 21-50 50-21 51 21 20 50z m179-250q0-145-79-269-10-17-30-17h-782q-20 0-30 17-79 123-79 269 0 102 40 194t106 160 160 107 194 39 194-39 160-107 106-160 40-194z" horiz-adv-x="1000" />
+
+<glyph glyph-name="sitemap" unicode="&#xe8f5;" d="M1000 154v-179q0-22-16-38t-38-16h-178q-22 0-38 16t-16 38v179q0 22 16 38t38 15h53v107h-285v-107h53q23 0 38-15t16-38v-179q0-22-16-38t-38-16h-178q-23 0-38 16t-16 38v179q0 22 16 38t38 15h53v107h-285v-107h53q23 0 38-15t16-38v-179q0-22-16-38t-38-16h-178q-23 0-38 16t-16 38v179q0 22 16 38t38 15h53v107q0 29 21 51t51 21h285v107h-53q-23 0-38 16t-16 37v179q0 22 16 38t38 16h178q23 0 38-16t16-38v-179q0-22-16-37t-38-16h-53v-107h285q29 0 51-21t21-51v-107h53q23 0 38-15t16-38z" horiz-adv-x="1000" />
+
+<glyph glyph-name="spinner" unicode="&#xe8f6;" d="M294 72q0-29-21-50t-51-21q-29 0-50 21t-21 50q0 30 21 51t50 21 51-21 21-51z m277-115q0-29-20-50t-51-21-50 21-21 50 21 51 50 21 51-21 20-51z m-392 393q0-30-21-50t-51-21-50 21-21 50 21 51 50 20 51-20 21-51z m670-278q0-29-21-50t-50-21q-30 0-51 21t-20 50 20 51 51 21 50-21 21-51z m-538 556q0-37-26-63t-63-26-63 26-26 63 26 63 63 26 63-26 26-63z m653-278q0-30-21-50t-50-21-51 21-21 50 21 51 51 20 50-20 21-51z m-357 393q0-45-31-76t-76-31-76 31-31 76 31 76 76 31 76-31 31-76z m296-115q0-52-37-88t-88-37q-52 0-88 37t-37 88q0 51 37 88t88 37q51 0 88-37t37-88z" horiz-adv-x="1000" />
+
+<glyph glyph-name="coffee" unicode="&#xe8f7;" d="M929 493q0 45-32 76t-76 31h-35v-214h35q45 0 76 31t32 76z m-929-429h1000q0-59-42-101t-101-42h-714q-59 0-101 42t-42 101z m1036 429q0-89-63-152t-152-62h-35v-18q0-52-37-88t-88-37h-393q-51 0-88 37t-37 88v410q0 15 11 26t25 10h642q89 0 152-63t63-151z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="food" unicode="&#xe8f8;" d="M357 814v-357q0-34-20-62t-51-39v-435q0-29-21-50t-51-21h-71q-29 0-50 21t-22 50v435q-31 11-51 39t-20 62v357q0 15 11 25t25 11 25-11 10-25v-232q0-14 11-25t25-11 25 11 11 25v232q0 15 11 25t25 11 25-11 10-25v-232q0-14 11-25t25-11 25 11 11 25v232q0 15 10 25t25 11 26-11 10-25z m429 0v-893q0-29-21-50t-51-21h-71q-29 0-50 21t-22 50v286h-125q-7 0-12 5t-5 13v446q0 74 52 127t126 52h143q15 0 25-11t11-25z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="beer" unicode="&#xe8f9;" d="M357 350v214h-143v-143q0-29 21-50t51-21h71z m572-250v-107h-643v107l71 107h-71q-89 0-152 63t-63 151v179l-35 36 18 71h267l18 72h536l18-108-36-17v-447z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="user-md" unicode="&#xe8fa;" d="M214 100q0-14-10-25t-25-11-25 11-11 25 11 25 25 11 25-11 10-25z m572-34q0-68-41-106t-108-39h-488q-67 0-108 39t-41 106q0 38 3 73t14 77 26 74 45 58 67 33q-12-29-12-67v-113q-32-11-52-39t-20-62q0-45 32-76t76-31 76 31 31 76q0 34-20 62t-52 39v113q0 35 14 52 74-58 165-58t165 58q13-17 13-52v-35q-59 0-101-42t-41-101v-50q-18-16-18-40 0-22 15-37t38-16 38 16 16 37q0 24-18 40v50q0 29 21 50t50 21 51-21 21-50v-50q-18-16-18-40 0-22 16-37t38-16 38 16 15 37q0 24-18 40v50q0 38-19 71t-52 52q0 6 0 24t0 27-1 23-4 26-7 22q38-8 67-33t45-58 26-74 14-77 3-73z m-179 498q0-88-63-151t-151-63-152 63-62 151 62 152 152 63 151-63 63-152z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="stethoscope" unicode="&#xe8fb;" d="M714 457q0 15-10 25t-25 11-25-11-11-25 11-25 25-11 25 11 10 25z m72 0q0-34-20-62t-52-39v-220q0-89-73-152t-177-63-176 63-74 152v73q-91 12-153 72t-61 140v286q0 15 11 25t25 11q3 0 9-1 9 17 26 27t36 10q30 0 51-21t21-51-21-50-51-21q-18 0-36 10v-225q0-59 53-101t126-41 126 41 53 101v225q-18-10-36-10-30 0-51 21t-21 50 21 51 51 21q19 0 36-10t26-27q6 1 9 1 15 0 25-11t11-25v-286q0-80-61-140t-153-72v-73q0-59 52-101t126-42 126 42 53 101v220q-32 12-52 39t-20 62q0 45 32 76t76 31 76-31 31-76z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="ambulance" unicode="&#xe8fc;" d="M357 64q0 30-21 51t-50 21-51-21-21-51 21-50 51-21 50 21 21 50z m-214 286h214v143h-88q-8-1-12-5l-109-109q-4-7-5-12v-17z m714-286q0 30-21 51t-50 21-51-21-21-51 21-50 51-21 50 21 21 50z m72 375v107q0 8-5 13t-13 5h-125v125q0 8-5 13t-13 5h-107q-8 0-13-5t-5-13v-125h-125q-8 0-13-5t-5-13v-107q0-7 5-12t13-6h125v-125q0-7 5-12t13-5h107q8 0 13 5t5 12v125h125q8 0 13 6t5 12z m142 304v-643q0-14-10-25t-25-11h-107q0-59-42-101t-101-42-101 42-42 101h-214q0-59-42-101t-101-42-101 42-42 101h-72q-14 0-25 11t-10 25 10 25 25 11v232q0 14 8 32t18 29l110 110q11 11 29 18t32 7h89v179q0 14 11 25t25 11h643q14 0 25-11t10-25z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="medkit" unicode="&#xe8fd;" d="M714 225v107q0 8-5 13t-13 5h-125v125q0 8-5 13t-12 5h-108q-7 0-12-5t-5-13v-125h-125q-8 0-13-5t-5-13v-107q0-8 5-13t13-5h125v-125q0-8 5-13t12-5h108q7 0 12 5t5 13v125h125q8 0 13 5t5 13z m-357 411h286v71h-286v-71z m-214 0v-715h-18q-51 0-88 37t-37 88v465q0 51 37 88t88 37h18z m661 0v-715h-608v715h90v89q0 22 15 38t38 16h322q22 0 38-16t15-38v-89h90z m196-125v-465q0-51-37-88t-88-37h-18v715h18q51 0 88-37t37-88z" horiz-adv-x="1000" />
+
+<glyph glyph-name="h-sigh" unicode="&#xe8fe;" d="M714 100v500q0 15-10 25t-25 11h-72q-14 0-25-11t-11-25v-179h-285v179q0 15-11 25t-25 11h-71q-15 0-25-11t-11-25v-500q0-14 11-25t25-11h71q15 0 25 11t11 25v179h285v-179q0-14 11-25t25-11h72q14 0 25 11t10 25z m143 518v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="hospital" unicode="&#xe8ff;" d="M214 118v-36q0-7-5-12t-13-6h-35q-7 0-13 6t-5 12v36q0 7 5 12t13 6h35q8 0 13-6t5-12z m0 143v-36q0-7-5-13t-13-5h-35q-7 0-13 5t-5 13v36q0 7 5 12t13 6h35q8 0 13-6t5-12z m143 0v-36q0-7-5-13t-13-5h-35q-8 0-13 5t-5 13v36q0 7 5 12t13 6h35q8 0 13-6t5-12z m-143 143v-36q0-7-5-13t-13-5h-35q-7 0-13 5t-5 13v36q0 7 5 12t13 5h35q8 0 13-5t5-12z m429-286v-36q0-7-5-12t-13-6h-36q-7 0-12 6t-6 12v36q0 7 6 12t12 6h36q7 0 13-6t5-12z m-143 143v-36q0-7-5-13t-13-5h-36q-7 0-12 5t-5 13v36q0 7 5 12t12 6h36q7 0 13-6t5-12z m-143 143v-36q0-7-5-13t-13-5h-35q-8 0-13 5t-5 13v36q0 7 5 12t13 5h35q8 0 13-5t5-12z m286-143v-36q0-7-5-13t-13-5h-36q-7 0-12 5t-6 13v36q0 7 6 12t12 6h36q7 0 13-6t5-12z m-143 143v-36q0-7-5-13t-13-5h-36q-7 0-12 5t-5 13v36q0 7 5 12t12 5h36q7 0 13-5t5-12z m143 0v-36q0-7-5-13t-13-5h-36q-7 0-12 5t-6 13v36q0 7 6 12t12 5h36q7 0 13-5t5-12z m-143-483h214v643h-143v-18q0-22-15-37t-38-16h-250q-22 0-38 16t-16 37v18h-143v-643h215v125q0 8 5 13t13 5h178q7 0 13-5t5-13v-125z m0 661v179q0 7-5 12t-13 6h-36q-7 0-12-6t-5-12v-54h-72v54q0 7-5 12t-13 6h-35q-8 0-13-6t-5-12v-179q0-7 5-12t13-6h35q8 0 13 6t5 12v54h72v-54q0-7 5-12t12-6h36q7 0 13 6t5 12z m286 18v-714q0-15-11-25t-25-11h-714q-15 0-25 11t-11 25v714q0 15 11 25t25 11h178v160q0 23 16 38t38 16h250q22 0 38-16t15-38v-160h179q15 0 25-11t11-25z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="building" unicode="&#xe900;" d="M214 118v-36q0-7-5-12t-13-6h-35q-7 0-13 6t-5 12v36q0 7 5 12t13 6h35q8 0 13-6t5-12z m0 143v-36q0-7-5-13t-13-5h-35q-7 0-13 5t-5 13v36q0 7 5 12t13 6h35q8 0 13-6t5-12z m143 0v-36q0-7-5-13t-13-5h-35q-8 0-13 5t-5 13v36q0 7 5 12t13 6h35q8 0 13-6t5-12z m-143 143v-36q0-7-5-13t-13-5h-35q-7 0-13 5t-5 13v36q0 7 5 12t13 5h35q8 0 13-5t5-12z m429-286v-36q0-7-5-12t-13-6h-36q-7 0-12 6t-6 12v36q0 7 6 12t12 6h36q7 0 13-6t5-12z m-143 143v-36q0-7-5-13t-13-5h-36q-7 0-12 5t-5 13v36q0 7 5 12t12 6h36q7 0 13-6t5-12z m-143 143v-36q0-7-5-13t-13-5h-35q-8 0-13 5t-5 13v36q0 7 5 12t13 5h35q8 0 13-5t5-12z m-143 142v-35q0-7-5-13t-13-5h-35q-7 0-13 5t-5 13v35q0 8 5 13t13 5h35q8 0 13-5t5-13z m429-285v-36q0-7-5-13t-13-5h-36q-7 0-12 5t-6 13v36q0 7 6 12t12 6h36q7 0 13-6t5-12z m-143 143v-36q0-7-5-13t-13-5h-36q-7 0-12 5t-5 13v36q0 7 5 12t12 5h36q7 0 13-5t5-12z m-143 142v-35q0-7-5-13t-13-5h-35q-8 0-13 5t-5 13v35q0 8 5 13t13 5h35q8 0 13-5t5-13z m-143 143v-35q0-8-5-13t-13-5h-35q-7 0-13 5t-5 13v35q0 8 5 13t13 5h35q8 0 13-5t5-13z m429-285v-36q0-7-5-13t-13-5h-36q-7 0-12 5t-6 13v36q0 7 6 12t12 5h36q7 0 13-5t5-12z m-143 142v-35q0-7-5-13t-13-5h-36q-7 0-12 5t-5 13v35q0 8 5 13t12 5h36q7 0 13-5t5-13z m-143 143v-35q0-8-5-13t-13-5h-35q-8 0-13 5t-5 13v35q0 8 5 13t13 5h35q8 0 13-5t5-13z m286-143v-35q0-7-5-13t-13-5h-36q-7 0-12 5t-6 13v35q0 8 6 13t12 5h36q7 0 13-5t5-13z m-143 143v-35q0-8-5-13t-13-5h-36q-7 0-12 5t-5 13v35q0 8 5 13t12 5h36q7 0 13-5t5-13z m143 0v-35q0-8-5-13t-13-5h-36q-7 0-12 5t-6 13v35q0 8 6 13t12 5h36q7 0 13-5t5-13z m-143-768h214v858h-643v-858h215v125q0 8 5 13t13 5h178q7 0 13-5t5-13v-125z m286 893v-928q0-15-11-25t-25-11h-714q-15 0-25 11t-11 25v928q0 15 11 25t25 11h714q15 0 25-11t11-25z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="building-filled" unicode="&#xe901;" d="M750 850q15 0 25-11t11-25v-928q0-15-11-25t-25-11h-714q-15 0-25 11t-11 25v928q0 15 11 25t25 11h714z m-464-161v-35q0-8 5-13t13-5h35q8 0 13 5t5 13v35q0 8-5 13t-13 5h-35q-8 0-13-5t-5-13z m0-143v-35q0-8 5-13t13-5h35q8 0 13 5t5 13v35q0 8-5 13t-13 5h-35q-8 0-13-5t-5-13z m0-142v-36q0-8 5-13t13-5h35q8 0 13 5t5 13v36q0 7-5 12t-13 5h-35q-8 0-13-5t-5-12z m0-143v-36q0-8 5-13t13-5h35q8 0 13 5t5 13v36q0 8-5 13t-13 5h-35q-8 0-13-5t-5-13z m-72-179v36q0 8-5 13t-13 5h-35q-8 0-13-5t-5-13v-36q0-8 5-13t13-5h35q8 0 13 5t5 13z m0 143v36q0 8-5 13t-13 5h-35q-8 0-13-5t-5-13v-36q0-8 5-13t13-5h35q8 0 13 5t5 13z m0 143v36q0 7-5 12t-13 5h-35q-8 0-13-5t-5-12v-36q0-8 5-13t13-5h35q8 0 13 5t5 13z m0 143v35q0 8-5 13t-13 5h-35q-8 0-13-5t-5-13v-35q0-8 5-13t13-5h35q8 0 13 5t5 13z m0 143v35q0 8-5 13t-13 5h-35q-8 0-13-5t-5-13v-35q0-8 5-13t13-5h35q8 0 13 5t5 13z m286-715v107q0 8-5 13t-13 5h-178q-8 0-13-5t-5-13v-107q0-8 5-13t13-5h178q8 0 13 5t5 13z m0 286v36q0 8-5 13t-13 5h-36q-7 0-12-5t-5-13v-36q0-8 5-13t12-5h36q8 0 13 5t5 13z m0 143v36q0 7-5 12t-13 5h-36q-7 0-12-5t-5-12v-36q0-8 5-13t12-5h36q8 0 13 5t5 13z m0 143v35q0 8-5 13t-13 5h-36q-7 0-12-5t-5-13v-35q0-8 5-13t12-5h36q8 0 13 5t5 13z m0 143v35q0 8-5 13t-13 5h-36q-7 0-12-5t-5-13v-35q0-8 5-13t12-5h36q8 0 13 5t5 13z m143-572v36q0 8-5 13t-13 5h-36q-7 0-12-5t-6-13v-36q0-8 6-13t12-5h36q8 0 13 5t5 13z m0 143v36q0 8-5 13t-13 5h-36q-7 0-12-5t-6-13v-36q0-8 6-13t12-5h36q8 0 13 5t5 13z m0 143v36q0 7-5 12t-13 5h-36q-7 0-12-5t-6-12v-36q0-8 6-13t12-5h36q8 0 13 5t5 13z m0 143v35q0 8-5 13t-13 5h-36q-7 0-12-5t-6-13v-35q0-8 6-13t12-5h36q8 0 13 5t5 13z m0 143v35q0 8-5 13t-13 5h-36q-7 0-12-5t-6-13v-35q0-8 6-13t12-5h36q8 0 13 5t5 13z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="bank" unicode="&#xe902;" d="M536 850l535-214v-72h-71q0-14-11-25t-27-10h-852q-16 0-27 10t-12 25h-71v72z m-393-357h143v-429h71v429h143v-429h71v429h143v-429h72v429h143v-429h33q15 0 27-10t11-25v-36h-929v36q0 14 12 25t27 10h33v429z m890-536q16 0 27-11t11-25v-71h-1071v71q0 15 11 25t28 11h994z" horiz-adv-x="1142.9" />
+
+<glyph glyph-name="smile" unicode="&#xe903;" d="M633 250q-21-67-77-109t-127-41-128 41-77 109q-4 14 3 27t21 18q14 4 27-2t17-22q14-44 52-72t85-28 84 28 52 72q4 15 18 22t27 2 21-18 2-27z m-276 243q0-30-21-51t-50-21-51 21-21 51 21 50 51 21 50-21 21-50z m286 0q0-30-21-51t-51-21-50 21-21 51 21 50 50 21 51-21 21-50z m143-143q0 73-29 139t-76 114-114 76-138 28-139-28-114-76-76-114-29-139 29-139 76-113 114-77 139-28 138 28 114 77 76 113 29 139z m71 0q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="frown" unicode="&#xe904;" d="M633 164q4-14-2-27t-21-17-27 2-18 21q-14 45-52 72t-84 28-85-28-52-72q-4-14-17-21t-27-2q-15 4-21 17t-3 27q21 68 77 109t128 41 127-41 77-109z m-276 329q0-30-21-51t-50-21-51 21-21 51 21 50 51 21 50-21 21-50z m286 0q0-30-21-51t-51-21-50 21-21 51 21 50 50 21 51-21 21-50z m143-143q0 73-29 139t-76 114-114 76-138 28-139-28-114-76-76-114-29-139 29-139 76-113 114-77 139-28 138 28 114 77 76 113 29 139z m71 0q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="meh" unicode="&#xe905;" d="M643 243q0-15-11-25t-25-11h-357q-14 0-25 11t-11 25 11 25 25 11h357q15 0 25-11t11-25z m-286 250q0-30-21-51t-50-21-51 21-21 51 21 50 51 21 50-21 21-50z m286 0q0-30-21-51t-51-21-50 21-21 51 21 50 50 21 51-21 21-50z m143-143q0 73-29 139t-76 114-114 76-138 28-139-28-114-76-76-114-29-139 29-139 76-113 114-77 139-28 138 28 114 77 76 113 29 139z m71 0q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="anchor" unicode="&#xe906;" d="M536 707q0 15-11 25t-25 11-25-11-11-25 11-25 25-11 25 11 11 25z m464-518v-196q0-12-11-17-5-1-7-1-7 0-13 5l-52 52q-66-80-177-127t-240-46-240 46-177 127l-52-52q-5-5-13-5-2 0-7 1-11 5-11 17v196q0 8 5 13t13 5h196q13 0 17-11 5-11-4-19l-56-56q38-51 106-86t152-46v361h-108q-14 0-25 11t-10 25v71q0 15 10 25t25 11h108v91q-33 19-52 51t-20 72q0 59 42 101t101 42 101-42 42-101q0-39-20-72t-52-51v-91h108q14 0 25-11t10-25v-71q0-15-10-25t-25-11h-108v-361q84 11 152 46t106 86l-56 56q-8 8-4 19 4 11 17 11h196q8 0 13-5t5-13z" horiz-adv-x="1000" />
+
+<glyph glyph-name="terminal" unicode="&#xe907;" d="M438 225h250v-62h-250v62z m-188-62l188 187-188 188-47-47 141-141-141-141 47-46z m625 500v-625c0-35-28-63-62-63h-750c-35 0-63 28-63 63v625c0 34 28 62 63 62h750c34 0 62-28 62-62z m-62 0h-750v-625h750v625z" horiz-adv-x="875" />
+
+<glyph glyph-name="eraser" unicode="&#xe908;" d="M500 64l188 215h-429l-188-215h429z m565 601q9-19 6-40t-17-36l-500-572q-22-24-54-24h-429q-21 0-38 11t-27 31q-8 19-5 40t17 36l500 572q21 24 53 24h429q21 0 39-11t26-31z" horiz-adv-x="1071.4" />
+
+<glyph glyph-name="puzzle" unicode="&#xe909;" d="M929 237q0-45-25-75t-69-30q-23 0-43 10t-33 21-32 21-39 10q-62 0-62-69 0-22 9-65t8-64v-3q-12 0-18 0-19-2-54-7t-65-7-54-3q-35 0-58 15t-23 47q0 20 9 39t22 32 21 33 10 43q0 44-31 69t-75 25q-47 0-80-26t-33-71q0-24 9-46t18-36 19-30 8-28q0-25-25-50-21-19-65-19-54 0-137 13-5 1-16 2t-15 3l-7 1q-1 0-2 0-1 0-1 1v571q1 0 10-2t19-2 12-2q83-14 137-14 44 0 65 20 25 24 25 49 0 13-8 29t-19 29-18 36-9 47q0 45 33 71t81 25q44 0 74-25t31-69q0-23-10-43t-21-33-22-31-9-40q0-32 23-47t58-14q35 0 100 8t91 9v-1q-1-1-2-9t-3-19-2-12q-13-84-13-137 0-45 19-65 25-26 50-26 12 0 28 8t30 19 36 19 46 8q46 0 71-33t26-80z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="shield" unicode="&#xe90a;" d="M607 314v357h-250v-634q67 35 119 76 131 103 131 201z m107 429v-429q0-48-18-95t-47-84-66-71-70-57-68-43-50-28-23-11q-7-4-15-4t-14 4q-9 4-24 11t-50 28-67 43-71 57-66 71-46 84-19 95v429q0 14 11 25t25 11h643q14 0 25-11t10-25z" horiz-adv-x="714.3" />
+
+<glyph glyph-name="extinguisher" unicode="&#xe90b;" d="M286 743q0 14-11 25t-25 11-25-11-11-25 11-25 25-11 25 11 11 25z m500 18v-179q0-9-7-14-4-4-11-4-2 0-4 1l-250 53q-6 2-10 7t-4 11h-143v-57q62-13 103-62t40-113v-447q0-14-11-25t-25-11h-285q-15 0-25 11t-11 25v447q0 59 35 106t90 64v62h-18q-33 0-64-13t-51-30-37-37-23-30-7-14q-10-19-32-19-9 0-16 4-13 7-18 20t2 28q3 5 8 14t21 30 34 39 47 38 61 29q-14 23-14 48 0 37 26 63t63 26 63-26 26-63q0-19-7-36h168q0 6 4 11t10 6l250 54q2 1 4 1 7 0 11-4 7-5 7-14z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="bullseye" unicode="&#xe90c;" d="M571 350q0-59-41-101t-101-42-101 42-42 101 42 101 101 42 101-42 41-101z m72 0q0 89-63 152t-151 62-152-62-63-152 63-151 152-63 151 63 63 151z m71 0q0-118-83-202t-202-84-202 84-84 202 84 202 202 84 202-84 83-202z m72 0q0 73-29 139t-76 114-114 76-138 28-139-28-114-76-76-114-29-139 29-139 76-113 114-77 139-28 138 28 114 77 76 113 29 139z m71 0q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="wheelchair" unicode="&#xe90d;" d="M571 188l57-114q-33-100-117-162t-190-62q-87 0-161 43t-117 117-43 161q0 101 58 185t154 117l9-73q-68-30-109-92t-41-137q0-103 74-176t176-74q71 0 130 37t92 98 28 132z m306-56l32-64-143-71q-7-4-16-4-22 0-32 19l-133 267h-264q-13 0-23 9t-12 22l-54 435q-1 10 4 24 7 28 31 46t54 17q37 0 64-26t26-63q0-39-29-66t-67-23l20-161h236v-72h-227l9-71h254q23 0 32-19l127-254z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="attach" unicode="&#xe90e;" d="M0 65q8 68 67 127l383 383q117 115 211 33 84-86-36-209l-353-351-66 70 349 349q2 0 8 6l8 8t7 9 6 10 6 9 4 11l0 10t-2 12q-19 17-74-37l-381-381q-37-35-41-69-4-39 35-78 41-33 70-28t71 46q82 80 218 215t194 195q2 2 18 17t17 17 15 16 15 17 12 17 13 19 11 20 10 25q16 57-33 123t-115 75q-68 7-152-73l-418-418-69 67 418 420q98 95 199 100t190-83q105-107 74-236-19-74-94-150-86-84-246-245l-209-209q-70-70-150-72-68 0-125 57-70 70-64 156z" horiz-adv-x="896" />
+
+<glyph glyph-name="paw" unicode="&#xe90f;" d="M435 587q0-34-10-64t-35-51-59-22q-42 0-77 32t-51 76-17 84q0 33 10 63t36 52 58 22q43 0 78-32t51-76 16-84z m-191-270q0-45-23-77t-66-33q-43 0-79 31t-56 74-20 85q0 45 23 78t67 33q42 0 79-31t56-75 19-85z m220 15q66 0 143-54t127-132 52-142q0-26-10-43t-27-25-36-12-42-3q-38 0-105 25t-102 26q-36 0-107-25t-112-25q-102 0-102 82 0 48 31 106t78 108 105 81 107 33z m134 118q-34 0-59 22t-35 51-11 64q0 41 17 84t51 76 77 32q34 0 59-22t35-52 11-63q0-41-17-84t-51-76-77-32z m241 58q43 0 66-33t24-78q0-41-20-85t-56-74-79-31q-43 0-66 33t-24 77q0 41 20 85t56 75 79 31z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="spoon" unicode="&#xe910;" d="M393 555q0-81-32-135t-85-76l25-458q2-15-9-25t-24-11h-107q-15 0-25 11t-9 25l25 458q-53 21-84 76t-32 135q0 72 23 140t66 111 89 44 90-44 65-111 24-140z" horiz-adv-x="428.6" />
+
+<glyph glyph-name="cube" unicode="&#xe911;" d="M500-59l357 195v355l-357-130v-420z m-36 483l390 141-390 142-389-142z m465 140v-428q0-20-10-37t-28-26l-393-214q-15-9-34-9t-34 9l-393 214q-17 10-27 26t-10 37v428q0 23 13 41t34 26l393 143q12 5 24 5t25-5l393-143q21-8 34-26t13-41z" horiz-adv-x="1000" />
+
+<glyph glyph-name="cubes" unicode="&#xe912;" d="M357-61l214 107v176l-214-92v-191z m-36 254l226 96-226 97-225-97z m608-254l214 107v176l-214-92v-191z m-36 254l225 96-225 97-226-97z m-250 163l214 92v149l-214-92v-149z m-36 212l246 105-246 106-246-106z m607-289v-233q0-20-10-37t-29-26l-250-125q-14-8-32-8t-32 8l-250 125q-2 1-4 2-1-1-4-2l-250-125q-14-8-32-8t-31 8l-250 125q-19 9-29 26t-11 37v233q0 21 12 39t32 26l242 104v223q0 22 12 40t31 26l250 107q13 6 28 6t28-6l250-107q20-9 32-26t12-40v-223l242-104q20-8 32-26t11-39z" horiz-adv-x="1285.7" />
+
+<glyph glyph-name="recycle" unicode="&#xe913;" d="M467 198l-9-206-1-12-234 16q-20 2-38 18t-26 36q-6 15-8 31t2 36 7 31 12 36 11 29q43-6 284-15z m-216 327l100-212-82 52q-35-41-62-81t-41-70-22-53-10-35l-2-11-106 199q-10 14-10 31t3 26l4 10q20 35 64 105l-78 48z m687-289l-105-200q-7-16-21-26t-24-12l-10-2q-40-4-122-7l4-91-128 205 118 202 4-97q94-9 157-2t95 18z m-439 516q-26-35-147-243l-177 104-11 7 126 199q11 17 33 25t45 5q13-1 27-6t23-12 23-18 21-20 20-22 17-19z m366-171l118-203q10-21 7-42t-15-42q-7-11-18-20t-22-16-27-12-26-9-29-8-25-7q-19 40-148 244l174 108z m-80 126l79 46-122-208-234 11 84 48q-19 50-42 93t-42 69-36 44-26 26l-10 7 226 0q18 1 33-6t22-16l6-8q21-34 62-106z" horiz-adv-x="1000" />
+
+<glyph glyph-name="tree" unicode="&#xe914;" d="M839 29q0-15-10-25t-25-11h-258q0-10 3-49t3-61q0-14-10-23t-24-10h-179q-14 0-24 10t-10 23q0 22 3 61t3 49h-257q-15 0-25 11t-11 25 11 25l224 225h-128q-14 0-25 10t-11 25 11 25l224 225h-110q-14 0-25 11t-10 25 10 25l215 214q10 11 25 11t25-11l214-214q11-10 11-25t-11-25-25-11h-110l224-225q11-10 11-25t-11-25-25-10h-128l225-225q10-11 10-25z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="database" unicode="&#xe915;" d="M429 421q132 0 247 24t181 71v-95q0-38-57-71t-157-52-214-19-215 19-156 52-58 71v95q66-47 181-71t248-24z m0-428q132 0 247 24t181 71v-95q0-39-57-72t-157-52-214-19-215 19-156 52-58 72v95q66-47 181-71t248-24z m0 214q132 0 247 24t181 71v-95q0-38-57-71t-157-52-214-20-215 20-156 52-58 71v95q66-47 181-71t248-24z m0 643q116 0 214-19t157-52 57-72v-71q0-39-57-72t-157-52-214-19-215 19-156 52-58 72v71q0 39 58 72t156 52 215 19z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="lifebuoy" unicode="&#xe916;" d="M500 850q102 0 194-40t160-106 106-160 40-194-40-194-106-160-160-106-194-40-194 40-160 106-106 160-40 194 40 194 106 160 160 106 194 40z m0-71q-106 0-201-51l108-108q46 16 93 16t93-16l109 108q-96 51-202 51z m-378-630l108 108q-16 46-16 93t16 93l-108 109q-51-96-51-202t51-201z m378-228q106 0 202 51l-109 108q-46-16-93-16t-93 16l-108-108q95-51 201-51z m0 215q89 0 152 63t62 151-62 152-152 62-151-62-63-152 63-151 151-63z m270 121l108-108q51 95 51 201t-51 202l-108-109q16-46 16-93t-16-93z" horiz-adv-x="1000" />
+
+<glyph glyph-name="birthday" unicode="&#xe917;" d="M1000 64v-214h-1000v214q25 0 47 8t33 15 27 21q16 15 28 22t32 6q13 0 24-4t18-9 18-15q16-14 26-21t33-15 48-8q25 0 47 8t33 15 26 21q12 11 18 15t18 9 24 4q20 0 32-6t28-22q16-13 27-21t32-15 48-8 47 8 33 15 26 21q17 15 29 22t32 6q19 0 31-6t28-22q16-13 27-21t33-15 47-8z m0 179v-107q-13 0-25 4t-17 8-18 15q-16 14-26 21t-33 15-47 8q-26 0-48-8t-33-15-26-21q-12-10-18-15t-18-8-24-4q-20 0-32 6t-28 21q-17 14-27 21t-32 15-48 8q-25 0-47-8t-33-15-27-21q-11-10-18-15t-17-8-24-4q-20 0-32 6t-29 21q-15 14-26 21t-33 15-47 8q-26 0-48-8t-32-15-27-21q-16-15-28-21t-32-6v107q0 45 31 76t76 31h36v250h143v-250h143v250h142v-250h143v250h143v-250h36q45 0 76-31t31-76z m-714 482q0-43-20-66t-52-23q-29 0-50 21t-21 50q0 16 5 29t13 19 18 15 17 18 13 25 5 37q22 0 47-41t25-84z m285 0q0-43-20-66t-51-23q-30 0-50 21t-21 50q0 16 5 29t13 19 17 15 18 18 13 25 5 37q21 0 46-41t25-84z m286 0q0-43-20-66t-51-23q-30 0-51 21t-21 50q0 16 6 29t13 19 17 15 17 18 13 25 6 37q21 0 46-41t25-84z" horiz-adv-x="1000" />
+
+<glyph glyph-name="adn" unicode="&#xe918;" d="M429 503l112-171h-225z m203-296h53l-256 386-257-386h53l58 89h291z m225 143q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="android" unicode="&#xe919;" d="M275 581q9 0 16 6t6 15-6 16-16 6-15-6-6-16 6-15 15-6z m236 0q9 0 15 6t6 15-6 16-15 6-16-6-6-16 6-15 16-6z m-453-103q23 0 40-17t16-40v-240q0-24-16-41t-40-17-41 17-17 41v240q0 23 17 40t41 17z m591-11v-371q0-26-18-44t-43-18h-42v-127q0-24-16-40t-41-17-41 17-17 40v127h-77v-127q0-24-16-40t-41-17q-24 0-40 17t-17 40l-1 127h-41q-26 0-43 18t-18 44v371h512z m-129 226q59-30 95-85t36-121h-516q0 66 35 121t96 85l-39 73q-4 8 2 12 8 3 12-4l40-74q53 24 112 24t112-24l40 74q4 7 11 4 7-4 3-12z m266-272v-240q0-24-17-41t-41-17q-23 0-40 17t-17 41v240q0 24 17 40t40 17q24 0 41-17t17-40z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="angellist" unicode="&#xe91a;" d="M532 639l-64-183 66-12q92 252 92 289 0 32-22 32-31 0-72-126z m-167-383l18-49q21 23 40 37l-18 3t-22 4-18 5z m-163 500q0-55 89-291 9 6 27 6 9 0 42-3l-68 196q-41 122-68 122-11 0-16-9t-6-21z m-44-424q0-20 29-66t65-86 56-39q8 0 14 8t7 15q0 13-18 57-7 17-18 40t-26 49-35 46-34 17q-12 0-26-15t-14-26z m-88-187q0-23 14-58 33-81 102-127t157-45q127 0 213 95 85 94 85 238 0 24 0 37t-7 35-17 31q-31 28-118 42t-151 15q-20 0-27-6-7-3-7-20 0-19 12-33t31-22 43-14 49-6 48-2 39 0h13q13 0 22-11 8-10 11-30-16-16-54-31-34-12-52-25-36-26-60-64t-25-76q0-18 10-50t10-49l-1-6q-3-7-3-8-76 5-81 120-5-1-23-1 1-4 1-11 0-30-22-50t-53-21q-46 0-93 44t-47 89q0 19 18 37 29-36 34-42 43-58 74-58 7 0 15 4t8 12q0 19-49 81t-65 62q-24 0-39-25t-15-51z m-64-5q0 57 24 91t76 49q-16 42-16 58 0 35 34 69t69 34q16 0 39-8-91 257-91 316 0 45 23 73t66 28q73 0 181-324 4-10 5-13 3 9 16 44t24 66 30 72 36 68 40 49 42 20q40 0 63-28t23-68q0-60-89-307 34-8 56-25t33-44 14-52 4-62q0-83-26-156t-74-126-117-83-156-31q-62 0-124 23-83 32-144 107t-61 160z" horiz-adv-x="714.3" />
+
+<glyph glyph-name="apple" unicode="&#xe91b;" d="M777 172q-21-70-68-139-72-110-144-110-27 0-78 18-48 18-84 18-34 0-79-19-45-19-74-19-85 0-168 145-82 146-82 281 0 127 63 208 63 81 159 81 40 0 98-17 58-17 77-17 25 0 80 19 57 19 97 19 66 0 119-36 29-20 58-56-44-37-64-66-36-52-36-115 0-69 38-125t88-70z m-209 655q0-34-17-76-16-42-52-77-30-30-60-40-20-7-58-10 2 83 44 143 41 60 139 83 1-2 2-6t1-6q0-2 0-6t1-5z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="behance" unicode="&#xe91c;" d="M1031 661h-285v-69h285v69z m-140-238q-51 0-82-29t-34-80h227q-10 109-111 109z m9-326q35 0 68 18t42 48h123q-55-171-238-171-119 0-190 73t-70 194q0 116 72 193t188 77q77 0 134-38t86-100 28-139q0-9-1-26h-367q0-62 32-96t93-33z m-745 28h165q114 0 114 93 0 100-111 100h-168v-193z m0 299h156q44 0 69 21t26 63q0 80-106 80h-145v-164z m-155 284h332q48 0 86-8t71-26 50-54 17-86q0-101-96-147 64-17 96-64t33-114q0-41-14-76t-37-58-55-39-67-24-75-7h-341v703z" horiz-adv-x="1142.9" />
+
+<glyph glyph-name="bitbucket" unicode="&#xe91d;" d="M455 371q4-35-28-57t-63-3q-21 9-29 32t-1 46 29 32q20 11 41 7t36-20 15-37z m62 11q-8 60-63 92t-110 7q-35-15-56-49t-20-72q3-51 44-87t92-31q51 4 85 47t28 93z m133 303q-11 15-31 25t-32 12-40 7q-162 26-316-1-24-4-37-7t-30-12-28-24q16-16 42-26t41-12 49-6q127-16 250-1 35 5 50 7t40 12 42 26z m32-578q-4-14-9-42t-7-47-16-39-33-32q-48-27-106-40t-112-12-113 10q-25 5-45 10t-43 15-41 25-29 34q-14 54-31 163l3 9 10 5q124-83 283-83t283 83q12-3 13-13t-3-25-4-21z m101 537q-15-94-62-366-3-17-15-31t-24-23-31-17q-140-70-340-49-139 15-220 78-8 6-14 14t-10 20-5 19-3 22-3 20q-5 27-15 83t-16 90-13 83-12 88q2 14 10 27t17 21 26 17 25 12 27 10q70 26 175 36 211 21 377-28 86-25 120-68 9-11 9-28t-3-30z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="bitbucket-squared" unicode="&#xe91e;" d="M473 365q0 24-23 36t-43 1q-24-11-23-41t24-39q22-13 45 2t20 41z m45 8q4-36-20-67t-62-34-66 22-31 63q-1 28 14 52t40 36q40 17 79-6t46-66z m96 219q-11-12-30-19t-30-9-35-5q-86-11-181 0-24 4-35 6t-29 9-31 18q8 10 20 17t23 9 26 4q110 20 228 1 18-3 28-5t24-9 22-17z m23-417q0 4 3 15t2 18-10 9q-90-59-203-59t-205 59l-6-3-3-7q14-86 23-117 26-45 114-60 139-26 238 29 19 11 28 29t12 48 7 39z m73 387q5 30-5 42-24 31-86 49-121 35-272 20-74-7-126-26-21-8-33-13t-26-19-17-31q5-38 11-77t16-95 13-76q1-3 3-18t4-20 7-15 12-16q59-44 158-55 145-16 246 35 13 7 22 13t17 16 11 22q27 149 45 264z m147 56v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="css3" unicode="&#xe91f;" d="M154 779h839l-148-744-449-149-389 149 39 198h166l-16-82 235-89 272 89 38 190h-675l33 165h674l22 107h-674z" horiz-adv-x="1000" />
+
+<glyph glyph-name="delicious" unicode="&#xe920;" d="M821 82v268h-392v393h-268q-52 0-89-37t-36-88v-268h393v-393h267q52 0 89 37t36 88z m36 536v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="digg" unicode="&#xe921;" d="M183 693h114v-549h-297v389h183v160z m0-457v206h-69v-206h69z m160 297v-389h114v389h-114z m0 160v-114h114v114h-114z m160-160h297v-526h-297v91h183v46h-183v389z m183-297v206h-69v-206h69z m160 297h297v-526h-297v91h183v46h-183v389z m183-297v206h-69v-206h69z" horiz-adv-x="1142.9" />
+
+<glyph glyph-name="dribbble" unicode="&#xe922;" d="M571 13q-23 134-78 278h-1l-1-1q-9-3-24-9t-56-27-77-46-73-64-57-82l-9 6q103-84 234-84 73 0 142 29z m-103 339q-11 27-29 62-174-52-376-52 0-4 0-12 0-69 24-132t69-112q28 49 69 93t80 69 73 45 55 27l21 7q2 1 7 2t7 3z m-59 118q-67 119-137 211-77-36-130-104t-72-152q169 0 339 45z m381-178q-117 33-228 16 49-133 71-262 62 42 104 106t53 140z m-449 414q-1 0-1-1 0 1 1 1z m329-81q-103 91-241 91-43 0-87-10 73-95 137-214 39 15 73 34t54 34 36 32 21 23z m125-271q-2 129-83 229l-1-1q-5-7-11-13t-24-25-40-34-55-36-74-36q14-30 25-53 1-3 3-10t5-9q20 2 41 4t41 1 39-1 35-2 32-3 27-4 20-3 14-3z m62-4q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="dropbox" unicode="&#xe923;" d="M224 456l276-171-191-159-273 178z m551-310v-60l-274-164v-1l0 1-1-1v1l-273 164v60l82-54 191 159v1l1-1 0 1v-1l192-159z m-466 638l191-159-276-169-188 150z m467-328l188-152-273-178-191 159z m-85 328l273-178-188-150-276 169z" horiz-adv-x="1000" />
+
+<glyph glyph-name="facebook" unicode="&#xe924;" d="M535 843v-147h-87q-48 0-65-20t-17-60v-106h164l-22-165h-142v-424h-171v424h-142v165h142v122q0 104 58 161t155 57q82 0 127-7z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="facebook-squared" unicode="&#xe925;" d="M696 779q67 0 114-48t47-113v-536q0-66-47-113t-114-48h-104v333h111l16 129h-127v83q0 31 13 46t51 16l68 1v115q-35 5-100 5-75 0-121-44t-45-127v-95h-112v-129h112v-333h-297q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="flickr" unicode="&#xe926;" d="M696 779q67 0 114-48t47-113v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535z m-306-429q0 49-35 84t-84 34-83-34-35-84 35-84 83-34 84 34 35 84z m314 0q0 49-34 84t-84 34-84-34-34-84 34-84 84-34 84 34 34 84z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="foursquare" unicode="&#xe927;" d="M558 608l21 108q3 13-5 22t-20 10h-397q-13 0-22-10t-8-20v-615q0-4 3 0l162 196q13 15 22 19t26 4h134q12 0 20 8t11 17q13 72 20 106 2 12-6 23t-21 10h-164q-16 0-26 11t-11 27v23q0 16 11 27t26 10h193q10 0 20 7t11 17z m127 124q-9-41-30-149t-39-195-19-97q-4-12-5-18t-8-18-14-19-21-12-33-5h-151q-7 0-12-6-5-5-238-275-12-14-33-16t-27 3q-30 12-30 54v787q0 31 21 58t67 26h495q53 0 71-30t6-88z m0 0l-88-441q2 9 19 97t39 195 30 149z" horiz-adv-x="714.3" />
+
+<glyph glyph-name="git-squared" unicode="&#xe928;" d="M325 120q0-37-52-37-60 0-60 35 0 36 55 36 57 0 57-34z m-20 260q0-47-42-47-43 0-43 47 0 50 43 50 21 0 31-14t11-36z m92 42v70q-43-16-75-16-28 16-61 16-48 0-81-32t-33-80q0-28 16-57t41-37v-2q-21-9-21-47 0-30 23-43v-2q-63-21-63-77 0-26 11-44t30-29 40-14 46-4q125 0 125 105 0 37-27 55t-71 25q-15 3-28 12t-14 22q0 24 27 29 43 8 68 39t26 75q0 13-6 29 21 5 27 7z m33-234h77q-1 15-1 46v216q0 26 1 38h-77q2-12 2-39v-219q0-28-2-42z m284 9v68q-16-12-38-12-29 0-29 46v125h29q5 0 15 0t14-1v65h-58q0 46 1 57h-78q3-13 3-30v-27h-34v-65q20 2 21 2 1 0 6 0t7-1v-1h-2v-121q0-21 2-36t6-31 14-27 24-18 37-6q36 0 60 13z m-198 394q0 20-14 36t-33 15-34-15-14-36q0-20 14-35t34-15 33 16 14 34z m341 27v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="github-circled" unicode="&#xe929;" d="M429 779q116 0 215-58t156-156 57-215q0-140-82-252t-211-155q-15-3-22 4t-7 17q0 1 0 43t0 75q0 54-29 79 32 3 57 10t53 22 45 37 30 58 11 84q0 67-44 115 21 51-4 114-16 5-46-6t-51-25l-21-13q-52 15-107 15t-108-15q-8 6-23 15t-47 22-47 7q-25-63-5-114-44-48-44-115 0-47 12-83t29-59 45-37 52-22 57-10q-21-20-27-58-12-5-25-8t-32-3-36 12-31 35q-11 18-27 29t-28 14l-11 1q-12 0-16-2t-3-7 5-8 7-6l4-3q12-6 24-21t18-29l6-13q7-21 24-34t37-17 39-3 31 1l13 3q0-22 0-50t1-30q0-10-8-17t-22-4q-129 43-211 155t-82 252q0 117 58 215t155 156 216 58z m-267-616q2 4-3 7-6 1-8-1-1-4 4-7 5-3 7 1z m18-19q4 3-1 9-6 5-9 2-4-3 1-9 5-6 9-2z m16-25q6 4 0 11-4 7-9 3-5-3 0-10t9-4z m24-23q4 4-2 10-7 7-11 2-5-5 2-11 6-6 11-1z m32-14q1 6-8 9-8 2-10-4t7-9q8-3 11 4z m35-3q0 7-10 6-9 0-9-6 0-7 10-6 9 0 9 6z m32 5q-1 7-10 5-9-1-8-8t10-4 8 7z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="gittip" unicode="&#xe92a;" d="M431 123l196 264q9 13 13 33t-3 48-34 44q-23 14-47 14t-41-10-30-25q-20-22-54-22-33 0-53 22-13 16-30 25t-41 10-47-14q-26-17-34-44t-3-48 14-33z m426 227q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="google" unicode="&#xe92b;" d="M429 411h404q7-37 7-71 0-121-51-216t-145-149-215-54q-88 0-167 34t-137 91-91 137-34 167 34 167 91 137 137 91 167 34q167 0 287-113l-117-112q-68 67-170 67-72 0-133-37t-97-98-36-136 36-136 97-98 133-37q48 0 89 14t67 33 46 46 28 49 13 43h-243v147z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="gplus" unicode="&#xe92c;" d="M802 341q0-117-49-207t-138-142-206-51q-83 0-159 32t-131 87-87 131-32 159 32 159 87 131 131 87 159 32q160 0 274-107l-111-107q-65 63-163 63-69 0-127-34t-92-94-34-130 34-130 92-94 127-34q46 0 85 13t64 32 44 43 27 47 12 41h-232v141h386q7-36 7-68z m484 68v-118h-117v-116h-117v116h-117v118h117v116h117v-116h117z" horiz-adv-x="1285.7" />
+
+<glyph glyph-name="gplus-squared" unicode="&#xe92d;" d="M512 345q0 15-4 36h-202v-74h122q-2-13-10-28t-21-29-37-25-54-10q-55 0-94 40t-39 95 39 95 94 40q52 0 86-33l58 57q-60 55-144 55-89 0-151-62t-63-152 63-151 151-63q92 0 149 58t57 151z m192-26h61v62h-61v61h-61v-61h-61v-62h61v-61h61v61z m153 299v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="html5" unicode="&#xe92e;" d="M631 517l9 98h-494l26-298h342l-12-128-110-29-110 29-7 78h-97l12-155 202-55h2v0l200 55 28 304h-359l-8 101h376z m-631 262h786l-72-803-322-90-321 90z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="instagramm" unicode="&#xe92f;" d="M571 350q0 59-41 101t-101 42-101-42-42-101 42-101 101-42 101 42 41 101z m77 0q0-91-64-156t-155-64-156 64-64 156 64 156 156 64 155-64 64-156z m61 229q0-21-15-36t-37-15-36 15-15 36 15 36 36 15 37-15 15-36z m-280 123q-4 0-43 0t-59 0-54-2-57-5-40-11q-28-11-49-32t-33-49q-6-16-10-40t-6-58-1-53 0-59 0-43 0-43 0-59 1-53 6-58 10-40q12-28 33-49t49-32q16-6 40-11t57-5 54-2 59 0 43 0 42 0 59 0 54 2 58 5 39 11q28 11 50 32t32 49q6 16 10 40t6 58 1 53 0 59 0 43 0 43 0 59-1 53-6 58-10 40q-11 28-32 49t-50 32q-16 6-39 11t-58 5-54 2-59 0-42 0z m428-352q0-128-3-177-5-116-69-180t-179-69q-50-3-177-3t-177 3q-116 6-180 69t-69 180q-3 49-3 177t3 177q5 116 69 180t180 69q49 3 177 3t177-3q116-6 179-69t69-180q3-49 3-177z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="linkedin-squared" unicode="&#xe930;" d="M132 61h129v387h-129v-387z m138 507q-1 29-21 48t-51 19-53-19-21-48q0-29 20-48t52-19h0q33 0 53 19t21 48z m326-507h129v222q0 86-41 130t-107 44q-76 0-117-65h1v56h-129q2-37 0-387h129v217q0 21 4 31 8 19 25 33t41 14q65 0 65-88v-207z m261 557v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="linux" unicode="&#xe931;" d="M370 621q-6-1-9-6t-4-5q-3-1-3 2 0 7 10 9h6z m49-8q-3-1-7 4t-10 2q14 6 18-1 2-3-1-5z m-196-238q-3 0-4-2t-2-7-3-8-6-7q-5-6 0-7 2 0 7 4t7 10q0 2 1 4t1 4 1 2 0 2v2t-1 1-1 2z m477-201q0 10-31 24 2 8 4 15t3 15 2 12 0 12 0 11-2 12-3 12-2 14-4 14q-5 27-26 58t-40 42q13-11 32-47 48-90 30-155-6-22-28-23-17-2-21 10t-5 47-6 60q-5 21-11 38t-11 25-9 14-7 8-4 4q-8 35-17 58t-17 31-13 19-8 22q-3 12 3 30t2 27-24 14q-9 2-25 10t-20 9q-4 1-6 15t4 28 20 15q21 2 29-16t2-33q-6-10-1-15t17 0q7 2 7 20v21q-3 17-8 28t-11 17-13 8-15 4q-60-4-50-74 0-9-1-9-5 5-16 6t-19 0-8 3q0 31-9 50t-25 19q-15 0-23-16t-10-33q0-8 2-20t8-21 8-8q6 2 9 8 2 5-4 4-4 0-8 8t-6 19q0 12 5 21t19 8q10 0 15-12t6-22-1-12q-12-9-17-16-5-7-16-13t-11-7q-7-8-9-16t4-10q8-4 14-10t9-11 11-7 19-4q27-1 57 8 1 1 13 4t19 6 17 7 12 10q5 8 11 5 2-2 3-5t-1-7-10-5q-11-3-31-12t-25-11q-25-11-40-13-14-3-44 1-5 1-5-1t10-10q14-13 37-13 10 1 20 4t20 8 19 10 17 9 13 7 10 1 5-6q0-1-1-2t-2-3-3-3-5-2-5-3-5-3-6-2q-15-8-37-25t-38-24-27 0q-12 6-35 41-12 17-14 12-1-2-1-6 0-14-8-31t-16-31-12-33 6-35q-13-3-35-50t-26-79q-1-10-1-38t-3-33q-4-14-16-2-18 17-20 53-1 15 2 31 2 10-1 10-1-1-2-3-20-36 6-92 3-7 14-16t13-11q11-13 58-51t52-42q9-9 10-22t-8-24-25-13q4-8 16-24t15-31 4-39q26 13 4 51-2 5-6 9t-5 7-1 3q2 3 7 6t11-2q26-29 93-20 74 9 99 49 13 21 19 17 6-4 5-30 0-13-13-51-5-13-3-21t14-8q1 10 8 43t7 50q1 12-3 41t-5 54 13 39q9 10 29 10 0 21 19 30t40 6 34-13z m-351 462q2 9-1 17t-6 8q-5 1-5-4 1-3 2-3 6 0 4-9-1-11 5-11 1 0 1 2z m234-110q-1 4-3 6t-8 3-8 3q-3 2-5 5t-4 4-3 4-2 2-3-1q-7-9 4-24t22-18q5 0 8 5t2 11z m-99 119q0 6-3 11t-6 7-5 1q-3 0-5-1t0-2 3-2q8-2 10-17 0-2 5 1 1 1 1 2z m30 130q0 1-1 3t-5 3-6 4q-8 8-13 8-5 0-7-4t0-7 0-7q-1-3-4-6t-3-5 2-5q2-2 4 0t6 5 9 5q0 1 5 1t8 1 5 4z m315-749q11-6 18-13t6-14-1-12-9-13-13-10-17-11-17-9-18-9-15-7q-21-11-48-31t-42-36q-9-9-38-11t-50 8q-10 5-16 13t-9 15-13 11-26 5q-24 0-72 0-11 0-32 0t-32-2q-25 0-45-8t-30-17-24-16-30-6q-16 0-62 17t-81 24q-11 2-29 5t-28 5-22 6-18 8-10 11q-5 12 4 37t10 30q1 9-2 23t-6 23-2 21 6 15q7 6 31 8t34 6q17 10 23 20t7 28q12-41-18-59-18-11-46-8-19 1-24-6-7-8 3-32 1-3 4-10t5-10 2-9 1-13q0-8-9-27t-8-27q1-9 20-14 12-4 47-11t56-11q13-3 41-12t46-13 31-2q24 3 36 15t13 27-4 33-11 29-11 20q-67 106-94 135-38 42-63 23-6-5-9 8-1 9-1 21 1 16 6 29t13 26 13 24q4 12 14 40t17 43 17 35 21 30q62 79 70 108-7 63-9 173-1 51 13 85t59 58q22 12 58 12 30 1 59-7t50-24q32-23 51-67t17-83q-3-53 16-119 19-63 75-122 30-33 55-91t33-106q5-28 3-48t-7-30-11-13q-5-1-13-10t-15-20-23-19-34-8q-10 1-17 3t-13 8-7 8-7 12-5 11q-12 20-23 16t-15-27 4-54q11-39 0-109-5-36 10-56t41-19 47 20q33 28 50 37t58 24q30 10 43 20t10 20-14 16-28 13q-19 6-28 27t-8 40 8 27q1-18 5-32t8-23 11-15 12-11 12-7 9-6z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="linkedin" unicode="&#xe932;" d="M195 501v-553h-184v553h184z m12 171q0-41-29-68t-75-27h-1q-46 0-74 27t-28 68q0 41 29 68t75 27 74-27 29-68z m650-407v-317h-183v296q0 59-23 92t-71 33q-35 0-58-19t-36-48q-6-17-6-45v-309h-184q1 223 1 361t0 165l-1 27h184v-80h-1q11 18 23 31t31 29 49 24 64 9q95 0 153-63t58-186z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="pagelines" unicode="&#xe933;" d="M782 235q-17-45-42-77t-51-50-55-26-57-8-54 5-48 12-39 15-25 13l-10 6q-63-128-161-201t-215-74q-10 0-18 7t-7 18 7 18 18 7q97 0 180 60t140 164q-20-8-40-13t-46-7-51 1-52 16-51 33-47 56-42 81q64 27 120 32t93-4 70-31 49-43 32-46q29 73 44 162-4 0-10-1t-26-2-39 1-46 5-49 13-47 24-42 36-30 53-16 71q39 16 74 20t63 0 52-17 41-28 31-34 23-35 16-31 9-22l2-9q6 68 6 109-4 3-12 8t-27 25-35 40-30 52-19 63 7 71 39 77q41-14 71-34t47-43 27-47 11-50 0-48-7-42-11-35-9-23l-4-9q0-2 0-28t0-40q2 4 5 10t17 24 29 33 39 31 51 25 63 8 74-14q-1-43-12-79t-28-58-39-40-45-25-48-14-44-5-38 1-26 2l-9 2q-13-82-41-158 3 4 10 10t28 23 43 29 55 24 66 11 72-13 76-43z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="pied-piper-squared" unicode="&#xe934;" d="M584 281q0-36-21-61t-51-25q-24 0-39 8v155q15 9 39 9 29 0 51-25t21-61z m-192 239q0-36-21-61t-51-26q-24 0-39 9v154q16 10 39 10 30 0 51-25t21-61z m314-241q0 75-49 128t-119 53q-11 0-22-2-13-43-43-76-49-53-118-56v-355l118 23v115q28-11 65-11 70 0 119 53t49 128z m-191 238q0 75-50 128t-119 53q-41 0-79-20h-103v-469l117 23v115q31-10 65-10 70 0 119 53t50 127z m342 101v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="pinterest-circled" unicode="&#xe935;" d="M857 350q0-117-57-215t-156-156-215-58q-62 0-122 18 33 52 43 92 6 19 31 118 11-22 40-38t64-16q68 0 121 38t82 105 29 151q0 64-34 120t-96 90-142 36q-59 0-110-17t-86-43-61-61-37-72-12-75q0-58 22-102t66-62q16-7 21 11 1 4 4 17t5 17q3 13-6 24-29 34-29 84 0 84 58 145t153 61q84 0 132-46t47-119q0-95-39-161t-98-67q-34 0-54 25t-13 58q4 19 15 52t17 57 6 43q0 28-15 46t-43 18q-35 0-59-31t-24-80q0-40 14-68l-55-233q-9-39-7-99-115 51-186 157t-71 236q0 117 58 215t155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="pinterest-squared" unicode="&#xe936;" d="M696 779q67 0 114-48t47-113v-536q0-66-47-113t-114-48h-404q47 68 60 118 5 19 30 116 11-21 41-37t63-16q101 0 164 83t64 208q0 47-19 91t-54 77-85 54-110 21q-58 0-109-16t-85-43-60-61-37-71-12-74q0-57 22-101t65-61q7-3 13 0t8 10q6 25 9 35 3 12-7 23-28 35-28 84 0 83 58 143t151 59q83 0 130-45t47-117q0-94-38-160t-97-66q-33 0-54 25t-13 57q5 19 15 52t16 57 6 42q0 27-14 45t-42 18q-34 0-58-31t-24-78q0-40 13-68l-54-231q-14-56-4-142h-102q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="renren" unicode="&#xe937;" d="M632-26q-95-53-205-53-109 0-205 53 77 48 132 118t73 149q19-80 74-149t131-118z m-276 797v-271q0-140-71-256t-184-171q-101 120-101 276 0 104 47 195t128 150 181 77z m501-422q0-156-101-276-114 55-184 171t-71 256v271q100-17 182-77t128-150 46-195z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="skype" unicode="&#xe938;" d="M655 257q0 28-11 51t-27 38-41 27-46 19-49 13l-58 14q-17 4-25 6t-19 6-17 9-9 12-4 16q0 43 80 43 24 0 43-6t30-16 21-19 23-16 27-7q26 0 42 18t16 43q0 31-32 55t-79 38-101 13q-38 0-74-9t-67-26-49-48-19-72q0-34 10-60t32-42 44-27 58-18l81-20q51-12 63-20 18-11 18-34 0-21-23-36t-58-14q-29 0-51 9t-37 22-25 25-26 21-30 9q-28 0-42-17t-14-41q0-52 68-88t162-37q41 0 78 10t69 30 49 52 19 74z m202-121q0-89-63-152t-151-63q-73 0-131 45-43-9-83-9-80 0-153 31t-126 84-83 125-31 153q0 41 9 84-45 58-45 130 0 89 63 152t151 63q73 0 131-45 43 9 84 9 79 0 152-31t126-84 84-125 30-153q0-41-8-84 44-58 44-130z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="slideshare" unicode="&#xe939;" d="M487 437q0-46-35-79t-85-34-85 34-36 79q0 47 36 80t85 33 85-33 35-80z m280 0q0-46-35-79t-85-34q-50 0-85 34t-36 79q0 47 36 80t85 33q50 0 85-33t35-80z m126-100v372q0 48-18 69t-62 20h-620q-47 0-63-19t-17-70v-376q24-13 50-22t45-16 45-10 40-6 39-2 32-1 32 2 25 1q38 0 53-15 3-4 5-5 15-14 34-29 4 51 66 49 3 0 21-1t24-1 25-1 30 1 30 2 34 5 35 7 37 11 38 15 40 20z m91 2q-68-83-208-140 47-159-13-260-36-63-102-82-58-18-101 8-48 28-46 92l-1 182v0q-4 1-13 3t-13 3l-1-188q2-64-46-92-44-26-102-8-66 20-102 83-58 101-12 259-140 57-208 140-14 21-2 36t33-1q3-1 7-4t6-4v387q0 40 26 69t64 28h701q37 0 64-28t26-69v-387l12 8q21 15 33 1t-2-36z" horiz-adv-x="1000" />
+
+<glyph glyph-name="stackexchange" unicode="&#xe93a;" d="M703 151v-37q0-47-32-81t-78-33h-32l-145-150v150h-295q-45 0-77 33t-32 81v37h691z m0 182v-143h-691v143h691z m0 183v-143h-691v143h691z m0 78v-37h-691v37q0 47 32 80t77 33h472q45 0 78-33t32-80z" horiz-adv-x="714.3" />
+
+<glyph glyph-name="stackoverflow" unicode="&#xe93b;" d="M719-61h-624v268h-89v-357h803v357h-90v-268z m-525 293l18 87 437-92-18-87z m57 208l38 82 404-189-37-81z m112 199l57 69 343-287-57-68z m222 211l266-358-71-53-267 357z m-401-821v89h447v-89h-447z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="trello" unicode="&#xe93c;" d="M393 100v571q0 8-5 13t-13 5h-268q-8 0-13-5t-5-13v-571q0-8 5-13t13-5h268q8 0 13 5t5 13z m375 214v357q0 8-5 13t-13 5h-268q-8 0-13-5t-5-13v-357q0-7 5-12t13-6h268q8 0 13 6t5 12z m89 429v-786q0-14-10-25t-26-11h-785q-15 0-25 11t-11 25v786q0 14 11 25t25 11h785q15 0 26-11t10-25z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="tumblr" unicode="&#xe93d;" d="M527 108l44-132q-12-19-61-37t-99-18q-58-1-107 15t-79 41-53 59-31 67-9 66v304h-94v120q40 14 72 39t51 50 32 57 19 55 8 49q1 3 3 5t4 2h136v-237h186v-140h-186v-289q0-17 3-31t13-30 28-23 45-8q44 1 75 16z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="tumblr-squared" unicode="&#xe93e;" d="M634 35l-35 102q-24-12-57-12-20-1-35 5t-21 18-10 23-3 24v222h144v108h-143v182h-105q-5 0-5-5-3-25-10-49t-22-53-43-53-66-38v-92h73v-233q0-32 12-64t36-62 68-48 98-17q39 0 76 14t48 28z m223 583v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="twitter-squared" unicode="&#xe93f;" d="M714 510q-31-14-67-19 38 22 52 65-37-21-75-28-34 36-85 36-49 0-83-34t-35-83q0-16 3-27-72 4-135 37t-107 86q-16-28-16-59 0-64 51-98-27 1-56 15v-1q0-42 28-75t68-40q-16-5-28-5-7 0-22 3 12-36 42-59t67-23q-64-50-145-50-15 0-28 2 82-53 180-53 62 0 117 20t94 53 67 76 42 91 13 94q0 10 0 15 35 25 58 61z m143 108v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="twitter" unicode="&#xe940;" d="M904 622q-37-54-90-93 0-8 0-23 0-73-21-145t-64-139-103-117-144-82-181-30q-151 0-276 81 19-2 43-2 126 0 224 77-59 1-105 36t-64 89q19-3 34-3 24 0 48 6-63 13-104 62t-41 115v2q38-21 82-23-37 25-59 64t-22 86q0 49 25 91 68-83 164-133t208-55q-5 21-5 41 0 75 53 127t127 53q79 0 132-57 61 12 115 44-21-64-80-100 52 6 104 28z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="vimeo-squared" unicode="&#xe941;" d="M721 494q6 121-90 124-129 4-174-146 25 11 46 11 47 0 41-54-2-32-41-93t-59-61q-24 0-46 94-7 30-25 142-16 106-89 99-33-4-91-56l-46-40-45-40 29-37q43 29 49 29 32 0 59-100 9-31 26-92t25-92q38-100 91-100 88 0 214 164 123 158 126 248z m136 124v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="windows" unicode="&#xe942;" d="M381 289v-364l-381 53v311h381z m0 414v-367h-381v315z m548-414v-439l-507 70v369h507z m0 490v-443h-507v373z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="wordpress" unicode="&#xe943;" d="M71 350q0 91 37 175l205-561q-109 53-176 157t-66 229z m719 22q0-11-2-22t-5-27-7-25-9-33-10-32l-43-143-155 461q26 2 49 4 11 2 15 11t-2 17-15 8l-115-6q-42 1-113 6-6 0-11-3t-6-9-1-10 5-9 11-5l44-4 67-183-94-281-156 464q26 2 49 4 11 2 15 11t-2 17-15 8l-115-6q-4 0-13 0t-14 1q58 89 153 141t205 52q82 0 157-29t133-84h-6q-31 0-51-22t-21-53q0-7 1-14t2-12 5-13 5-11 7-13 7-12 8-13 8-13q35-60 35-118z m-283-59l133-361q0-4 2-7-70-24-142-24-62 0-121 18z m369 243q53-97 53-206 0-117-58-215t-156-156l132 379q33 94 33 154 0 23-4 44z m-376 294q102 0 194-40t160-106 106-160 40-194-40-194-106-160-160-106-194-40-194 40-160 106-106 160-40 194 40 194 106 160 160 106 194 40z m0-977q97 0 185 38t152 102 102 152 38 185-38 185-102 152-152 102-185 38-185-38-152-102-102-152-38-185 38-185 102-152 152-102 185-38z" horiz-adv-x="1000" />
+
+<glyph glyph-name="youtube" unicode="&#xe944;" d="M542 156v-118q0-37-22-37-13 0-25 12v168q12 12 25 12 22 0 22-37z m189-1v-25h-51v25q0 38 25 38t26-38z m-540 122h60v52h-174v-52h59v-318h55v318z m161-318h50v276h-50v-211q-17-23-32-23-10 0-11 11-1 2-1 20v203h-50v-218q0-28 5-41 7-21 32-21 27 0 57 34v-30z m240 83v110q0 41-5 55-10 31-40 31-28 0-52-30v121h-50v-370h50v27q25-31 52-31 30 0 40 31 5 15 5 56z m188 6v7h-51q0-29-1-34-4-20-22-20-26 0-26 38v49h100v57q0 44-15 65-22 28-59 28-38 0-60-28-15-21-15-65v-96q0-44 16-65 22-29 60-29 40 0 60 30 10 15 12 30 1 5 1 33z m-339 509v117q0 39-24 39t-24-39v-117q0-39 24-39t24 39z m401-419q0-131-14-195-8-33-33-56t-57-25q-102-12-309-12t-310 12q-32 3-57 25t-32 56q-15 62-15 195 0 131 15 195 7 33 32 56t57 26q103 11 310 11t309-11q33-4 58-26t32-56q14-62 14-195z m-557 712h57l-67-223v-151h-56v151q-8 42-34 119-21 57-37 104h60l39-147z m207-186v-97q0-46-16-66-21-29-59-29-37 0-59 29-15 21-15 66v97q0 45 15 66 22 28 59 28 38 0 59-28 16-21 16-66z m187 91v-279h-51v31q-30-35-58-35-25 0-33 21-4 13-4 42v220h51v-205q0-19 0-20 2-12 12-12 15 0 32 24v213h51z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="youtube-squared" unicode="&#xe945;" d="M513 123v88q0 27-16 27-10 0-19-8v-125q9-9 19-9 16 0 16 27z m103 68h36v19q0 28-18 28t-18-28v-19z m-319 148v-39h-45v-236h-41v236h-44v39h130z m112-70v-205h-37v23q-22-25-43-25-18 0-23 15-3 10-3 30v162h36v-151q0-13 1-14 0-8 8-8 11 0 24 17v156h37z m141-62v-81q0-29-4-41-7-23-30-23-19 0-38 22v-20h-37v275h37v-89q18 22 38 22 23 0 30-24 4-11 4-41z m140-72v-5q0-16-1-24-2-12-9-22-15-22-44-22-29 0-46 21-11 15-11 48v72q0 33 11 48 16 21 45 21t43-21q12-16 12-48v-43h-74v-36q0-28 19-28 13 0 16 14 0 1 1 4t0 9v12h38z m-252 460v-87q0-28-18-28t-18 28v87q0 29 18 29t18-29z m298-398q0 99-11 145-6 25-24 41t-42 20q-76 8-230 8-154 0-230-8-24-3-42-20t-24-41q-11-48-11-145 0-98 11-145 5-24 24-41t42-19q76-9 230-9t230 9q24 2 42 19t23 41q12 47 12 145z m-422 363l50 166h-41l-29-109-29 109h-44q4-13 13-39l13-38q20-58 26-89v-112h41v112z m161-45v73q0 32-11 48-16 22-44 22-28 0-43-22-12-16-12-48v-73q0-32 12-48 15-22 43-22 28 0 44 22 11 15 11 48z m102-67h37v207h-37v-158q-13-17-24-17-8 0-9 8 0 2 0 15v152h-38v-164q0-20 4-30 6-16 24-16 20 0 43 26v-23z m280 170v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="youtube-play" unicode="&#xe946;" d="M397 221l270 139-270 141v-280z m103 481q94 0 181-3t128-5l41-2q0 0 9-1t13-2 13-2 16-5 16-7 17-11 16-15q4-3 9-10t16-33 15-56q4-36 7-76t3-64v-98q1-81-10-162-4-30-14-55t-18-35l-8-9q-7-8-16-15t-17-10-16-7-16-5-13-2-13-2-9-1q-140-11-350-11-115 2-201 4t-111 4l-28 3-20 2q-20 3-30 5t-29 12-31 23q-4 3-9 10t-16 33-15 56q-4 36-7 76t-3 64v98q-1 81 10 162 4 31 14 55t18 35l8 9q8 9 16 15t17 11 16 7 16 5 13 2 13 2 9 1q140 10 350 10z" horiz-adv-x="1000" />
+
+<glyph glyph-name="blank" unicode="&#xe947;" d="M857 618v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="lemon" unicode="&#xe948;" d="M785 389q0 25-4 63t-10 54q-6 17-9 25t-5 20-2 27q0 13 2 39t3 37q0 21-5 31-3 0-8 0-10 0-32-2t-33-3q-34 0-98 14t-98 13q-24 0-53-6t-47-13-50-19q-76-30-113-58-53-41-89-106t-49-131-14-139q0-22 7-67t7-67q0-13-6-38t-6-36 7-20 19-9q13 0 40 7t41 6q32 0 95-9t94-9q101 0 159 21 72 25 131 85t93 137 33 153z m72 1q0-92-39-183t-110-160-157-101q-69-25-182-25-31 0-94 8t-95 9q-13 0-40-9t-41-8q-41 0-69 31t-28 72q0 14 6 38t6 37q0 23-7 68t-7 68q0 61 10 121t31 117 56 108 83 87q44 33 130 67 108 44 176 44 34 0 98-14t97-13q10 0 32 3t32 2q45 0 66-28t21-75q0-13-3-38t-3-38q0-7 1-14t2-9 4-11 5-11q9-23 14-67t5-76z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="note" unicode="&#xe949;" d="M381 820q0-42 46-97t90-100 61-119-39-154q-20-34-26-16-2 6 0 16 10 18 6 56t-13 78-43 73-82 41l0-536q2-48-37-95t-105-71q-74-28-143-8t-89 76 20 115 116 85q86 30 158 4l0 652 80 0z" horiz-adv-x="582" />
+
+<glyph glyph-name="note-beamed" unicode="&#xe94a;" d="M206 714l534 116 0-704q2-42-30-81t-86-59q-64-24-110-8t-62 64q-18 48 7 97t85 73q52 20 106 10l0 376-354-82 0-490q0-42-32-81t-86-59q-64-22-109-7t-61 63q-18 48 6 97t84 73q54 20 108 10l0 592z" horiz-adv-x="740" />
+
+<glyph glyph-name="alert" unicode="&#xe94c;" 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="graduation-cap" unicode="&#xe94f;" 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="water" unicode="&#xe950;" 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="&#xe951;" 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="key" unicode="&#xe952;" d="M802 714c-47 47-106 72-177 74-70-2-130-27-177-74s-70-105-72-176c0-19 2-38 6-56l-382-382v-62l63-63h125l62 63v62h63v63h62v62h125l68 69c19-4 38-6 57-6 71 2 130 26 177 73s71 105 73 177c-2 71-26 129-73 176z m-114-200c-48 0-86 38-86 86s38 86 86 86 85-38 85-86-38-86-85-86z" horiz-adv-x="875" />
+
+<glyph glyph-name="infinity" unicode="&#xe953;" d="M0 350q0 93 66 159t159 66 159-66l72-69 73 70q65 65 157 65 92 0 158-66t67-159-67-159-158-66q-92 0-158 66l-72 69-73-70q-65-65-158-65t-159 66-66 159z m225 95q-39 0-67-28t-28-67q0-40 28-67t67-28 68 28l68 67-68 66q-29 29-68 29z m529-162q27 27 27 67t-27 68-67 27-67-27l-70-68 69-66q27-28 67-28t68 27z" horiz-adv-x="911" />
+
+<glyph glyph-name="at" unicode="&#xe956;" d="M770 548c16-41 25-87 25-138 0-68-17-133-46-182-39-61-94-92-163-92-27 0-52 7-70 21-12 9-23 21-30 36-26-33-68-55-113-55-52 0-95 19-123 58-27 35-41 84-41 141s16 110 49 148c33 41 82 63 141 63 35 0 67-15 90-37l7 26 85 0-17-259c-1-21 1-36 9-43 3-5 10-8 20-8 76 0 102 123 102 183 0 72-24 132-67 176-50 51-122 76-209 76-84 0-158-26-214-76-65-59-101-143-101-245 0-86 31-165 85-221 52-53 122-82 205-82 95 0 167 14 241 47l15 7 0-96-6-3c-69-34-150-50-251-50-108 0-200 33-269 97-81 73-124 183-124 308 0 119 40 220 116 294 38 36 83 65 133 84 52 21 109 31 169 31 113 0 215-37 283-106 30-29 54-64 69-103z m-384-317c30 0 54 14 69 40 14 25 18 61 18 85 0 31-7 56-17 74-13 20-33 28-60 28-28 0-50-12-63-38-13-22-19-53-19-83 0-32 7-106 72-106z" horiz-adv-x="795" />
+
+<glyph glyph-name="money-bag" unicode="&#xe957;" d="M238 378c13 16 35 21 65 24l0-85c-50 5-75 9-75 39 0 7 2 15 10 22z m107-241l0 91c59-5 78-9 78-35 0-30-24-49-78-56z m70 244c30-17 36-24 36-38l8-4 45 90-6 5c-7-5-10-7-14-7s-8 0-13 4c-61 23-90 35-126 35l0 17c0 9 5 15 20 19l0 9-79 0 0-9c14-4 17-11 17-19l0-15c-97-4-153-50-153-122 0-74 40-100 153-110l0-97c-78 8-117 38-117 64l-7 4-41-94 6-4c6 4 9 5 12 5 2 0 7 0 9-2 48-24 94-38 138-40l0-19c0-10-3-16-17-20l0-9 79 0 0 9c-15 4-20 9-20 20l0 19c96 5 159 54 159 126 0 70-53 106-149 115l-10 0 0 88c23-2 46-8 70-20z m41 181c117-50 198-165 198-300 0-181-146-328-326-328-182 0-328 147-328 328 0 135 81 250 198 300l-82 179c0 17 12 25 28 25l366 0c16 0 28-7 28-25z" horiz-adv-x="654" />
+
+<glyph glyph-name="hash" unicode="&#xe958;" d="M2 207q4 25 25 42t46 16h149l36 170h-135q-28 0-46 21-17 22-12 51 5 25 26 42t46 16h149l31 150q6 26 26 42t46 17q30 0 47-21t11-51l-29-137h167l32 150q5 26 26 42t46 17q29 0 46-21 18-21 11-51l-29-137h136q28 0 46-21 17-22 11-51-5-25-25-42t-46-16h-149l-37-170h136q28 0 47-21 17-22 11-51-6-26-26-42t-46-17h-149l-32-150q-5-25-25-42t-46-16q-29 0-47 21-17 22-11 50l29 137h-167l-33-150q-5-25-25-42t-46-16q-28 0-46 21-17 22-12 50l30 137h-136q-29 0-46 22-18 21-11 51z m352 58h168l36 170h-168z" horiz-adv-x="912.1" />
+
+<glyph glyph-name="airport" unicode="&#xe959;" d="M850 275l0-50-350 50 0-200 100-100c0-25-25-50-50-50-100 0-250 0-250 0-25 0-50 25-50 50l100 100 0 200-350-50 0 50 350 200s0 17 0 100c0 50 25 200 75 200s75-150 75-200c0-83 0-100 0-100z" horiz-adv-x="850" />
+
+<glyph glyph-name="fast-food" unicode="&#xe95a;" d="M350 675c-150 0-300-75-300-200l0-100 850 0 0 100c0 125-150 200-300 200z m25-50c14 0 25-11 25-25 0-14-11-25-25-25-14 0-25 11-25 25 0 14 11 25 25 25z m200 0c14 0 25-11 25-25 0-14-11-25-25-25-14 0-25 11-25 25 0 14 11 25 25 25z m-300-100c14 0 25-11 25-25 0-14-11-25-25-25-14 0-25 11-25 25 0 14 11 25 25 25z m200 0c14 0 25-11 25-25 0-14-11-25-25-25-14 0-25 11-25 25 0 14 11 25 25 25z m200 0c14 0 25-11 25-25 0-14-11-25-25-25-14 0-25 11-25 25 0 14 11 25 25 25z m-625-200c-25 0-50-25-50-50 0-25 25-50 50-50l850 0c25 0 50 25 50 50 0 25-25 50-50 50z m0-150l0-50c0-50 50-100 100-100l650 0c50 0 100 50 100 100l0 50z" horiz-adv-x="950" />
+
+<glyph glyph-name="fuel" unicode="&#xe95b;" d="M50 800c-28 0-50-22-50-50l0-800c0-25 25-50 50-50l450 0c25 0 50 25 50 50l0 250 25 0c25 0 25-25 25-25l0-100c0-50 25-75 75-75s75 25 75 75c0 58 0 225 0 275 0 50-100 100-100 150l0 150-50 0-50 50 0 50c0 28-22 50-50 50z m50-100l350 0 0-200-350 0z m450-150l50 0s0-42 0-75c0-50 100-100 100-150l0-250c0-25-25-25-25-25s-25 0-25 25c0 0 0 100 0 125 0 25-25 50-50 50-17 0-50 0-50 0z" horiz-adv-x="750" />
+
+<glyph glyph-name="police" unicode="&#xe95c;" d="M200 800c-25 0-50-25-50-50l0-50 350 0 0 50c0 25-25 50-50 50l-250 0z m-50-150l0-25c0-97 78-175 175-175s175 78 175 175l0 25-350 0z m-50-250c-75 0-100-125-100-200l0-300 134 0 341 500-375 0z m450 0l-341-500 441 0 0 300c0 75-25 200-100 200z" horiz-adv-x="650" />
+
+<glyph glyph-name="religious-christian" unicode="&#xe95d;" d="M325 800c-42 0-75-33-75-75l0-175-175 0c-42 0-75-33-75-75 0-41 33-75 75-75l175 0 0-425c0-42 33-75 75-75 42 0 75 33 75 75l0 425 175 0c42 0 75 34 75 75 0 42-33 75-75 75l-175 0 0 175c0 42-33 75-75 75z" horiz-adv-x="650" />
+
+<glyph glyph-name="religious-islam" unicode="&#xe95e;" d="M425 775c-235 0-425-190-425-425 0-235 190-425 425-425 131 0 249 60 327 153-51-33-112-53-177-53-179 0-325 146-325 325s146 325 325 325c65 0 126-20 177-53-78 93-196 153-327 153z m250-200l-50-150-175 0 150-100-75-175 150 100 150-100-75 175 150 100-175 0-50 150z" horiz-adv-x="900" />
+
+<glyph glyph-name="religious-jewish" unicode="&#xe95f;" d="M400 800l-150-200-250 0 150-250-150-250 250 0 150-200 150 200 250 0-150 250 150 250-250 0z" horiz-adv-x="800" />
+
+<glyph glyph-name="school" unicode="&#xe960;" d="M638 800c-49 0-88-39-88-87s39-88 88-88 87 39 87 88-39 87-87 87z m-400-100c-49 0-88-39-88-87s39-88 88-88 87 39 87 88-39 87-87 87z m462-100c-19 0-49-7-75-25l-162-116c-45-31-4-86 37-59l106 70s70-150 44-220c-1-2-2-4-2-6l-109-291c-12-33 12-53 36-53 16 0 31 10 39 28l136 322s25-150 125-150c60 0 104 0 138 0 37 0 37 38 37 38s0 37-37 37c-25 0-88 0-113 0-53 0-50 80-50 125 0 75-50 200-50 200l150-100c45-30 85 23 41 56l-166 119c-30 22-40 25-75 25 0 0-25 0-50 0z m-525-100c-25 0-37-12-50-25l-106-106c-14-14-19-26-19-44 0-25 38-37 59-16l91 91c50 0 69-125 50-175l-75-200c-21-55 57-72 75-25l75 200s25-50 75-50l150 0c50 0 50 75 0 75l-125 0c-25 0-25 50-25 75 0 100-50 200-100 200z" horiz-adv-x="1050" />
+
+<glyph glyph-name="swimming" unicode="&#xe961;" d="M556 675c-8 0-21-5-28-8l-200-97c-26-12-36-51-19-75l61-82-223-174 103-33 134 44c5 2 11 3 16 3s10-1 16-3l134-44 70 24-192 278 152 76c30 15 28 41 25 57-3 14-21 34-49 34z m94-150c-55 0-100-45-100-100 0-55 45-100 100-100 55 0 100 45 100 100 0 55-45 100-100 100z m-550-350c-5 0-12-2-16-3l-84-28 0-103 100 34 134-47c6-2 11-3 16-3 5 0 11 2 16 3l134 47 134-47c6-2 11-3 16-3 5 0 11 2 16 3l134 47 150-50 0 103-134 44c-5 2-11 3-16 3s-10-1-16-3l-134-44-134 44c-6 2-11 3-16 3s-11-2-16-3l-134-44-134 44c-7 2-11 3-16 3z" horiz-adv-x="850" />
+
+<glyph glyph-name="toilet" unicode="&#xe962;" d="M475 850c-14 0-25-11-25-25l0-950c0-14 11-25 25-25 14 0 25 11 25 25l0 950c0 14-11 25-25 25z m-275-50c-55 0-100-45-100-100s45-100 100-100c55 0 100 45 100 100s-45 100-100 100z m525 0c-55 0-100-45-100-100s45-100 100-100c55 0 100 45 100 100s-45 100-100 100z m-600-250l-124-375c-5-13 11-25 25-25l74 0 0-225c0-14 11-25 25-25 14 0 25 11 25 25l0 225 100 0 0-225c0-14 11-25 25-25 14 0 25 11 25 25l0 225 75 0c14 0 30 12 25 25l-125 375z m525 0c-28 0-50-22-50-50l0-575c0-14 11-25 25-25 14 0 25 11 25 25l0 275 150 0 0-275c0-14 11-25 25-25 14 0 25 11 25 25l0 575c0 28-22 50-50 50z" horiz-adv-x="850" />
+
+<glyph glyph-name="universal-access" unicode="&#xe964;" d="M0 350q0 207 147 354t353 146 354-146 146-354-146-354-354-146-353 146-147 354z m66 0q0-180 127-307t307-127 307 127 127 307-127 307-307 127-307-127-127-307z m163 2q-20 27 2 47l167 146q12 8 22 11t25 3l110 0q15 0 25-3t22-11q9-7 71-62t97-84q21-22 1-47-21-23-46-4-20 18-63 54t-64 57q0-2-3 0t-7 4-6 2q-6 0-6-13l0-58t4-67q2-22 2-26l49-271q4-41-33-49-18-4-33 7t-16 26q-39 221-39 225-6 23-10 23-4-2-6-5t-2-7-1-7l-1-4q0-2-10-59t-19-111l-10-55q-6-18-18-26t-31-7q-39 10-33 49l49 273q6 37 6 147 0 15-6 15t-16-8l-127-109q-27-19-46 4z m199 300q0 30 21 52t52 21 52-21 21-52-21-52-52-21-52 21-21 52z" horiz-adv-x="1000" />
+
+<glyph glyph-name="travel" unicode="&#xe966;" d="M271 350c-58 0-104-47-104-104s46-104 104-104 104 46 104 104-47 104-104 104m0-125c-12 0-21 9-21 21s9 21 21 21 21-10 21-21-10-21-21-21m458 125c-57 0-104-47-104-104s47-104 104-104 104 46 104 104-46 104-104 104m0-125c-11 0-21 9-21 21s10 21 21 21 21-10 21-21-9-21-21-21m208 229l-43 15-2 6h25c23 0 41 18 41 41 0 1 0 1 0 1h0c0 41-37 83-82 83h-27l-30 72c-16 53-65 95-120 95h-397c-56 0-105-42-120-95l-31-72h-27c-45 0-82-42-82-83h0c0 0 0 0 0-1 0-23 18-41 41-41h25l-1-6-44-15c-37-12-60-48-56-87l31-313c2-21 20-37 41-37h46v-42c0-46 37-83 83-83h84c46 0 83 37 83 83v42h250v-42c0-46 37-83 83-83h84c46 0 83 37 83 83v42h46c21 0 39 16 41 37l31 313c4 39-19 75-56 87m-676 194c6 17 22 35 41 35h397c18 0 34-18 40-35l66-173h-610l66 173z m31-673h-84v42h84v-42z m500 0h-84v42h84v-42z m91 125h-8-250-250-250-8l-27 275 35 17h750l36-17-28-275z" horiz-adv-x="1000" />
+
+<glyph glyph-name="symbols" unicode="&#xe967;" d="M0 850l458 0 0-83-458 0z m167-458l125 0 0 208 166 0 0 83-458 0 0-83 167 0z m479-250c57 0 104 46 104 104s-47 103-104 103-104-46-104-103 46-104 104-104m0 124c11 0 21-9 21-20 0-12-10-21-21-21s-21 9-21 21c0 11 9 20 21 20m250-208c-58 0-104-47-104-104s46-104 104-104 104 46 104 104-47 104-104 104m0-125c-12 0-21 9-21 21 0 11 9 20 21 20s21-9 21-20c0-12-10-21-21-21m21 375l-375-375 63-62 374 375z m-209 84c92 0 167 46 167 104v271c0 0 41 6 62-40 22-46 21-127 21-127s42 47 42 131c0 120-125 119-125 119h-83v-264c-25 9-53 14-84 14-92 0-166-47-166-104s74-104 166-104m-279-395l-61 66c-33-26-53-42-60-47-13 12-42 42-86 91 38 34 62 61 72 78s16 37 16 56c0 25-11 49-34 73-23 25-55 37-98 37-42 0-74-13-98-37-23-24-34-49-34-74 0-34 17-73 52-117-35-26-60-50-75-74-14-24-21-50-21-77 0-36 12-65 38-88 26-23 59-34 101-34 49 0 102 16 159 47l43-47h118l-87 99 55 48z m-281 266c9 8 19 12 31 12 13 0 23-4 31-11 8-7 12-16 12-27 0-22-18-47-53-75-22 28-33 52-33 73 0 11 4 20 12 28m8-330c-18 0-33 5-44 15-12 9-18 20-18 32 0 25 22 54 64 87 40-48 72-82 94-102-39-21-71-32-96-32" horiz-adv-x="1000" />
+
+<glyph glyph-name="recent" unicode="&#xe968;" d="M542 683l-84 0 0-291-83 0 0-84 83 0 0-83 84 0 0 83 166 0 0 84-166 0z m-42 167c-276 0-500-224-500-500s224-500 500-500 500 224 500 500-224 500-500 500m0-917c-230 0-417 187-417 417s187 417 417 417 417-187 417-417-187-417-417-417" horiz-adv-x="1000" />
+
+<glyph glyph-name="people" unicode="&#xe969;" d="M500 850c-276 0-500-224-500-500s224-500 500-500 500 224 500 500-224 500-500 500m0-917c-230 0-417 187-417 417s187 417 417 417 417-187 417-417-187-417-417-417m-167 625c-46 0-83-37-83-83s37-83 83-83 84 37 84 83-38 83-84 83m334 0c-46 0-84-37-84-83s38-83 84-83 83 37 83 83-37 83-83 83m-32-333c-29-50-78-83-140-83-61 0-110 33-139 83h269m125 83h-500c0-138 112-250 250-250s250 112 250 250" horiz-adv-x="1000" />
+
+<glyph glyph-name="objects" unicode="&#xe96a;" d="M500 850c-207 0-375-168-375-375 0-130 66-244 167-312l0-188c0 0 85-125 208-125 124 0 208 125 208 125l0 188c101 68 167 182 167 312 0 207-168 375-375 375z m0-83c161 0 292-131 292-292 0-161-131-292-292-292-161 0-292 131-292 292 0 161 131 292 292 292z m-125-645c39-14 81-22 125-22 44 0 86 8 125 22l0-35c-38-18-80-29-125-29-45 0-87 11-125 29l0 35z m10-128c36-12 75-19 115-19 40 0 79 7 115 19-25-26-67-61-115-61-46 0-88 33-115 61z m229 337h0c-35 1-49 36-65 76-18 45-30 65-50 66h0c-20 0-33-21-52-64-18-41-33-76-68-75l-11 2c-24 7-36 29-54 74-5 14-8 27-11 39-2 8-5 22-8 26 0 0-2 0-4 0-23 0-41 19-41 42 0 23 19 41 42 41h0c69 0 84-57 92-89 20 41 54 86 116 87 64-1 95-48 114-89 0 0 0 0 0 0 9 32 25 91 94 91h1c23 0 41-19 41-42 0-23-19-41-42-41h0c-6-3-11-20-13-29-4-13-7-27-13-40-18-41-33-75-68-75" horiz-adv-x="1000" />
+
+<glyph glyph-name="nature" unicode="&#xe96b;" d="M646 517c-35 0-63-28-63-63s28-62 63-62 62 28 62 62-28 63-62 63m-292 0c-34 0-62-28-62-63s28-62 62-62 63 28 63 62-28 63-63 63m435 333h-1c-41 0-89-33-126-62-53 15-109 21-162 21-53 0-109-6-161-22-37 30-86 63-127 63h-1c-71 0-208-111-211-293-2-103 12-176 43-209 11-10 37-28 54-36 8-133 39-219 106-266 37-27 91-40 133-46-1-8-3-17-3-25 0-74 98-125 167-125 69 0 167 51 167 125 0 8-2 16-3 24 107 17 226 79 247 317 16 9 37 23 46 32 31 33 45 106 43 209-3 182-140 293-211 293m-655-381c-10-11-35-48-36-51-7 17-16 56-15 137 3 137 104 207 129 210 11-1 31-12 53-27-46-49-95-122-98-214-6-23-17-36-33-55m366-536c-37 0-81 29-83 42 0 27 20 52 41 67v-25c0-23 19-42 42-42s42 19 42 42v25c22-15 41-40 41-67-2-13-45-42-83-42m125 145v0c-15 17-33 31-53 42 46 22 94 56 94 92 0 77-74 92-166 92-91 0-166-15-166-92 0-36 48-70 94-92-20-11-38-25-53-42v1c-42 3-91 11-124 35-54 38-76 127-77 270 0 0 1 1 1 1 21 35 62 61 75 130 0 85 57 151 99 188 41 15 91 22 149 22 60 0 112-8 155-24 42-37 97-102 97-186 13-69 54-95 75-130 2-2 3-4 4-7-2-249-81-292-204-300m276 342c-1 3-3 6-4 8-10 16-21 30-31 41-16 19-27 32-33 55-3 92-52 165-98 214 22 15 42 26 53 27 26-3 126-74 129-210 1-75-15-134-16-135" horiz-adv-x="1000" />
+
+<glyph glyph-name="foods" unicode="&#xe96c;" d="M708 643c-76 0-119-17-153-39 21 49 74 122 195 122 23 0 42 19 42 42s-19 41-42 41c-122 0-193-57-231-104-3-4-5-7-8-11-22 79-61 155-127 155-26 0-57-12-92-40-82-65-70-122-21-167-121-10-271-98-271-332 0-191 207-459 375-459 82 0 99 20 125 42 26-22 43-42 125-42 168 0 375 267 375 458 0 248-169 334-292 334m-365 101c27 21 40 22 41 22 17-7 40-59 56-128-63 27-114 57-124 77 3 5 10 15 27 29m282-810c-45 0-50 5-65 17l-7 6c-16 13-34 19-53 19s-37-6-53-19l-7-6c-15-12-20-17-65-17-117 0-292 225-292 376 0 242 187 249 209 249 81 0 103-19 141-52 4-4 9-8 13-11 16-13 35-20 54-20s38 7 54 20c4 4 9 7 13 11 38 33 61 52 141 52 22 0 209-7 209-250 0-150-175-375-292-375" horiz-adv-x="1000" />
+
+<glyph glyph-name="activity" unicode="&#xe96d;" d="M500 850c-276 0-500-224-500-500 0-276 224-500 500-500 276 0 500 224 500 500 0 276-224 500-500 500m415-458h-205c10 105 52 199 82 254 68-66 113-155 123-254m-373 0v373c67-7 130-30 184-66-35-62-89-175-99-307h-85z m-84 0h-85c-9 132-64 245-99 307 54 36 117 59 184 66v-373z m0-84v-373c-67 7-130 30-184 66 35 62 90 176 99 307h85z m169 0c10-131 64-245 99-307-54-36-117-59-184-66v373h85z m-419 338c30-55 72-149 82-254h-204c9 99 54 188 122 254m-122-338h204c-10-105-52-198-82-254-68 66-113 155-122 254m706-254c-30 56-72 149-82 254h205c-10-99-55-188-123-254" horiz-adv-x="1000" />
+
+<glyph glyph-name="flags" unicode="&#xe96e;" d="M0 850l254-1000h79l-253 1000h-80z m875-208h-167l-41 166h-500l125-500h125l41-166h84 458l-125 500z m-601 83h328l83-333h-328l-83 333z m368-417l-119-79-20 79h139z m150 0l-63 250h81l83-333h-226l125 83z" horiz-adv-x="1000" />
+
+<glyph glyph-name="people-plus" unicode="&#xe96f;" d="M333 558c-46 0-83-37-83-83s37-83 83-83 84 37 84 83-38 83-84 83m334 0c-46 0-84-37-84-83s38-83 84-83 83 37 83 83-37 83-83 83m-32-333c-29-50-78-83-140-83-61 0-110 33-139 83h269m125 83h-500c0-138 112-250 250-250 138 0 250 112 250 250m250 42c0-276-224-500-500-500s-500 224-500 500c0 30 3 59 8 87h85c-6-28-10-57-10-87 0-230 187-417 417-417 230 0 417 187 417 417 0 230-187 417-417 417-30 0-59-4-87-10v85c28 5 57 8 87 8 276 0 500-224 500-500z m-667 292h-125v-125h-83v125h-125v83h125v125h83v-125h125v-83z" horiz-adv-x="1000" />
+
+<glyph glyph-name="file-pdf" unicode="&#xe970;" d="M819 638q16-16 27-42t11-50v-642q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h500q22 0 49-11t42-27z m-248 136v-210h210q-5 17-12 23l-175 175q-6 7-23 12z m215-853v572h-232q-23 0-38 16t-16 37v233h-429v-858h715z m-287 331q18-14 47-31 33 4 65 4 82 0 99-27 9-13 1-29 0-1-1-1l-1-2v0q-3-21-39-21-27 0-64 11t-73 29q-123-13-219-46-85-146-135-146-8 0-15 4l-14 7q0 0-3 2-6 6-4 20 5 23 32 51t73 54q8 5 13-3 1-1 1-2 29 47 60 110 38 76 58 146-13 46-17 89t4 71q6 22 23 22h12q13 0 20-8 10-12 5-38-1-3-2-4 0-2 0-5v-17q-1-68-8-107 31-91 82-133z m-321-229q29 13 76 88-29-22-49-47t-27-41z m222 513q-9-23-2-73 1 4 4 24 0 2 4 24 1 3 3 5-1 0-1 1-1 1-1 2 0 12-7 20 0-1 0-1v-2z m-70-368q76 30 159 45-1 0-7 5t-9 8q-43 37-71 98-15-48-46-110-17-31-26-46z m361 9q-13 13-78 13 42-16 69-16 8 0 10 1 0 0-1 2z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="file-word" unicode="&#xe971;" d="M819 638q16-16 27-42t11-50v-642q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h500q22 0 49-11t42-27z m-248 136v-210h210q-5 17-12 23l-175 175q-6 7-23 12z m215-853v572h-232q-23 0-38 16t-16 37v233h-429v-858h715z m-656 500v-59h39l92-369h88l72 271q4 11 5 25 2 9 2 14h2l1-14q1-1 2-11t3-14l72-271h89l91 369h39v59h-167v-59h50l-55-245q-3-11-4-25l-1-12h-3q0 2 0 4t-1 4 0 4q-1 2-2 11t-3 14l-81 304h-63l-81-304q-1-5-2-13t-2-12l-2-12h-2l-2 12q-1 14-3 25l-56 245h50v59h-167z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="file-excel" unicode="&#xe972;" d="M819 638q16-16 27-42t11-50v-642q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h500q22 0 49-11t42-27z m-248 136v-210h210q-5 17-12 23l-175 175q-6 7-23 12z m215-853v572h-232q-23 0-38 16t-16 37v233h-429v-858h715z m-547 131v-59h157v59h-42l58 90q3 4 5 9t5 8 2 2h1q0-2 3-6 1-2 2-4t3-4 4-5l60-90h-43v-59h163v59h-38l-107 152 108 158h38v59h-156v-59h41l-57-89q-2-4-6-9t-5-8l-1-1h-1q0 2-3 5-3 6-9 13l-59 89h42v59h-162v-59h38l106-152-109-158h-38z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="file-powerpoint" unicode="&#xe973;" d="M819 638q16-16 27-42t11-50v-642q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h500q22 0 49-11t42-27z m-248 136v-210h210q-5 17-12 23l-175 175q-6 7-23 12z m215-853v572h-232q-23 0-38 16t-16 37v233h-429v-858h715z m-554 131v-59h183v59h-52v93h76q43 0 66 9 37 12 60 48t22 82q0 45-21 78t-56 49q-27 10-72 10h-206v-59h52v-310h-52z m197 156h-66v150h67q29 0 46-10 31-19 31-64 0-50-34-67-18-9-44-9z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="file-image" unicode="&#xe974;" d="M819 638q16-16 27-42t11-50v-642q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h500q22 0 49-11t42-27z m-248 136v-210h210q-5 17-12 23l-175 175q-6 7-23 12z m215-853v572h-232q-23 0-38 16t-16 37v233h-429v-858h715z m-72 250v-178h-571v107l107 107 71-71 215 214z m-464 108q-45 0-76 31t-31 76 31 76 76 31 76-31 31-76-31-76-76-31z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="file-archive" unicode="&#xe975;" d="M357 636v71h-71v-71h71z m72-72v72h-72v-72h72z m-72-71v71h-71v-71h71z m72-72v72h-72v-72h72z m390 217q16-16 27-42t11-50v-642q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h500q22 0 49-11t42-27z m-248 136v-210h210q-5 17-12 23l-175 175q-6 7-23 12z m215-853v572h-232q-23 0-38 16t-16 37v233h-71v-72h-72v72h-286v-858h715z m-350 403l60-195q4-15 4-29 0-46-40-77t-103-30-102 30-41 77q0 14 5 29 12 35 67 221v71h71v-71h44q13 0 22-7t13-19z m-79-260q30 0 51 11t21 25-21 25-51 11-50-11-21-25 21-25 50-11z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="file-audio" unicode="&#xe976;" d="M819 638q16-16 27-42t11-50v-642q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h500q22 0 49-11t42-27z m-248 136v-210h210q-5 17-12 23l-175 175q-6 7-23 12z m215-853v572h-232q-23 0-38 16t-16 37v233h-429v-858h715z m-440 455q11-5 11-17v-304q0-12-11-16-4-1-7-1-6 0-12 5l-93 93h-73q-8 0-13 5t-5 13v107q0 8 5 13t13 5h73l93 93q8 8 19 4z m233-385q17 0 28 14 72 88 72 202t-72 203q-9 11-24 13t-27-8q-11-9-13-24t8-26q56-69 56-158t-56-157q-9-12-8-27t13-23q10-9 23-9z m-118 83q15 0 26 11 49 52 49 122t-49 122q-10 11-25 12t-26-10-11-25 10-26q29-32 29-73t-29-73q-10-11-10-26t11-25q12-9 25-9z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="file-video" unicode="&#xe977;" d="M819 638q16-16 27-42t11-50v-642q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h500q22 0 49-11t42-27z m-248 136v-210h210q-5 17-12 23l-175 175q-6 7-23 12z m215-853v572h-232q-23 0-38 16t-16 37v233h-429v-858h715z m-357 500q29 0 50-21t21-50v-214q0-29-21-50t-50-22h-215q-29 0-50 22t-21 50v214q0 29 21 50t50 21h215z m274-1q11-4 11-16v-322q0-12-11-17-4-1-7-1-7 0-12 5l-148 149v50l148 148q5 5 12 5 3 0 7-1z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="file-code" unicode="&#xe978;" d="M819 638q16-16 27-42t11-50v-642q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h500q22 0 49-11t42-27z m-248 136v-210h210q-5 17-12 23l-175 175q-6 7-23 12z m215-853v572h-232q-23 0-38 16t-16 37v233h-429v-858h715z m-518 500q4 7 12 7t13-3l28-21q7-5 7-12t-3-13l-102-136 102-136q4-6 3-13t-7-12l-28-21q-6-4-13-4t-12 7l-126 168q-8 11 0 22z m447-167q8-11 0-22l-126-168q-4-6-11-7t-14 4l-28 21q-6 5-7 12t3 13l102 136-102 136q-4 6-3 13t7 12l28 21q6 4 14 3t11-7z m-346-258q-7 1-11 8t-3 13l77 464q1 7 7 11t14 3l35-5q7-2 11-8t3-13l-77-464q-1-7-7-11t-13-3z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="issue-closed" unicode="&#xe979;" d="M438 225h125v-125h-125v125z m125 375h-125v-312h125v312z m93-94l-62-62 156-156 250 281-62 62-188-218-94 93z m-156-512c-196 0-356 160-356 356s160 356 356 356c114 0 216-54 281-137l58 57c-80 99-202 162-339 162-241 0-437-197-437-438s196-438 437-438 438 197 438 438l-95-95c-41-150-179-261-343-261z" horiz-adv-x="1000" />
+
+<glyph glyph-name="issue-opened" unicode="&#xe97a;" d="M438 706c196 0 356-160 356-356s-160-356-356-356-357 160-357 356 160 356 357 356m0 82c-242 0-438-197-438-438s196-438 438-438 437 197 437 438-196 438-437 438z m62-188h-125v-312h125v312z m0-375h-125v-125h125v125z" horiz-adv-x="875" />
+
+<glyph glyph-name="issue-reopened" unicode="&#xe97b;" d="M500 288h-125v312h125v-312z m-125-188h125v125h-125v-125z m396 125h-146l94-94c-66-83-167-137-281-137-197 0-357 160-357 356 0 22 2 42 6 63h-82c-3-21-5-41-5-63 0-241 196-438 438-438 136 0 257 64 337 163l100-100v250h-104z m-666 250h145l-94 94c66 83 167 137 282 137 196 0 356-160 356-356 0-21-2-42-6-62h82c3 20 5 41 5 62 0 241-196 438-437 438-137 0-258-64-338-163l-100 100v-250h105z" horiz-adv-x="875" />
+
+<glyph glyph-name="milestone" unicode="&#xe97c;" d="M500 725h-125v125h125v-125z m250-312h-625c-34 0-62 28-62 62v125c0 34 28 63 62 63h625l125-125-125-125z m-250 187h-125v-125h125v125z m-125-750h125v500h-125v-500z" horiz-adv-x="875" />
+
+<glyph glyph-name="mirror" unicode="&#xe97d;" d="M969 556l-438 294-437-294c-19-12-31-28-31-50v-656l468 250 469-250v656c0 22-13 38-31 50z m-31-612l-375 203v78h-63v-78l-375-203v562l375 250v-281h63v281l375-250v-562z m-563 469h313v125l187-188-187-187v125h-313v-125l-187 187 187 188v-125z" horiz-adv-x="1000" />
+
+<glyph glyph-name="plug" unicode="&#xe97e;" d="M979 597q21-21 21-50t-21-51l-223-223 83-84-89-89q-91-91-217-104t-230 56l-202-202h-101v101l202 202q-69 103-56 230t104 217l89 89 84-83 223 223q21 21 51 21t50-21 21-50-21-51l-223-223 131-131 223 223q22 21 51 21t50-21z" horiz-adv-x="1000" />
+
+<glyph glyph-name="repo-forked" unicode="&#xe980;" d="M500 788c-69 0-125-56-125-125 0-46 25-86 63-108v-80l-125-125-125 125v80c37 22 62 62 62 108 0 69-56 125-125 125s-125-56-125-125c0-46 25-86 63-108v-111l187-188v-111c-37-22-62-62-62-107 0-70 55-126 125-126s125 56 125 126c0 45-26 85-63 107v111l188 188v111c37 22 62 62 62 108 0 69-56 125-125 125z m-375-201c-41 0-75 35-75 76s34 75 75 75 75-34 75-75-34-76-75-76z m188-625c-41 0-76 34-76 76s35 75 76 75 75-34 75-75-34-76-75-76z m187 625c-41 0-75 35-75 76s34 75 75 75 75-34 75-75-34-76-75-76z" horiz-adv-x="625" />
+
+<glyph glyph-name="repo-pull" unicode="&#xe981;" d="M813 350v125h-375v125h375v125l187-187-187-188z m-563 375h-62v-62h62v62z m438-312h62v-375c0-35-28-63-62-63h-313v-125l-94 94-93-94v125h-125c-35 0-63 28-63 63v750c0 34 28 62 63 62h625c34 0 62-28 62-62v-125h-62v125h-563v-563h563v188z m0-250h-625v-125h125v62h187v-62h313v125z m-438 312h-62v-62h62v62z m0 125h-62v-62h62v62z m-62-312h62v62h-62v-62z" horiz-adv-x="1000" />
+
+<glyph glyph-name="repo-push" unicode="&#xe982;" d="M250 663h-62v62h62v-62z m-62-125h62v62h-62v-62z m250 0l-188-250h125v-438h125v438h125l-187 250z m250 312h-625c-35 0-63-28-63-62v-750c0-35 28-63 63-63h250v63h-250v125h250v62h-188v563h564l-1-563h-125v-62h125v-125h-125v-63h125c34 0 62 28 62 63v750c0 34-28 62-62 62z" horiz-adv-x="750" />
+
+<glyph glyph-name="shield-key" unicode="&#xe983;" d="M438 850l-438-125v-376c0-292 332-499 438-499s437 207 437 499v376l-437 125z m-125-687l71 174c3 15-4 30-16 37-35 23-55 60-55 101 0 68 55 125 124 125 67 0 126-57 126-125 0-41-21-78-56-101-12-7-19-22-16-37l72-174h-250z" horiz-adv-x="875" />
+
+<glyph glyph-name="repo-clone" unicode="&#xe984;" d="M938 850h-375v-437c0-35 28-63 62-63h63v-62h62v62h188c34 0 62 28 62 63v375c0 34-28 62-62 62z m-250-437h-63v62h63v-62z m250 0h-188v62h188v-62z m0 125h-250v250h250v-250z m-688 0h-62v62h62v-62z m0 125h-62v62h62v-62z m-125 125h375v62h-437c-35 0-63-28-63-62v-750c0-35 28-63 63-63h125v-125l93 94 94-94v125h313c34 0 62 28 62 63v187h-625v563z m563-625v-125h-313v62h-187v-62h-125v125h625z m-500 187h62v-62h-62v62z m62 63h-62v62h62v-62z" horiz-adv-x="1000" />
+
+<glyph glyph-name="repo-force-push" unicode="&#xe985;" d="M625 288h-125v-438h-125v438h-125l141 187h-141l188 250 187-250h-141l141-187z m63 562h-625c-35 0-63-28-63-62v-750c0-35 28-63 63-63h250v63h-250v125h250v62h-188v563h563v-563h-125v-62h125v-125h-125v-63h125c34 0 62 28 62 63v750c0 34-28 62-62 62z" horiz-adv-x="750" />
+
+<glyph glyph-name="unverified" unicode="&#xe986;" d="M980 409l-68 84c-11 13-17 30-19 47l-12 107c-5 44-39 78-83 83l-107 12c-18 2-35 9-48 20l-84 68c-35 27-83 27-118 0l-84-68c-13-11-30-17-47-19l-107-12c-44-5-78-39-83-83l-12-107c-2-18-9-35-20-48l-67-84c-28-35-28-83 0-118l67-84c11-13 18-30 19-47l12-107c5-44 39-78 83-83l107-12c18-2 35-9 48-20l84-68c35-27 83-27 118 0l84 68c13 11 30 17 47 19l107 12c44 5 78 39 83 83l12 107c2 18 9 35 20 48l68 84c27 35 27 83 0 118z m-417-278c0-17-14-31-32-31h-62c-17 0-31 14-31 31v63c0 17 14 31 31 31h62c18 0 32-14 32-31v-63z m97 306c-4-11-11-21-18-29-8-10-9-12-21-24-10-11-19-18-32-28-7-6-13-12-18-17s-8-10-11-16-5-12-7-19-2-8-2-15h-106c0 13 0 19 2 30 2 12 5 22 9 32 4 9 9 18 16 26 7 8 14 16 25 24 17 12 23 18 30 32s13 23 13 37c0 17-4 28-13 36-7 8-19 12-36 12-6 0-11-1-18-3s-11-6-16-10-9-7-13-12-5-9-5-18h-125c0 23 7 35 16 52 10 16 23 31 38 42s34 18 55 23 44 8 68 8c28 0 52-3 74-8 21-6 39-13 54-24 15-11 26-24 34-39 8-16 12-34 12-55 0-14 0-26-5-37z" horiz-adv-x="1000" />
+
+<glyph glyph-name="verified" unicode="&#xe987;" d="M980 409l-68 84c-11 13-17 30-19 47l-12 107c-5 44-39 78-83 83l-107 12c-18 2-35 9-48 20l-84 68c-35 27-83 27-118 0l-84-68c-13-11-30-17-47-19l-107-12c-44-5-78-39-83-83l-12-107c-2-18-9-35-20-48l-67-84c-28-35-28-83 0-118l67-84c11-13 18-30 19-47l12-107c5-44 39-78 83-83l107-12c18-2 35-9 48-20l84-68c35-27 83-27 118 0l84 68c13 11 30 17 47 19l107 12c44 5 78 39 83 83l12 107c2 18 9 35 20 48l68 84c27 35 27 83 0 118z m-574-309l-218 219 93 94 125-125 313 312 94-97-407-403z" horiz-adv-x="1000" />
+
+<glyph glyph-name="zap" unicode="&#xe988;" d="M625 413h-250l188 437-563-562h250l-187-438 562 563z" horiz-adv-x="625" />
+
+<glyph glyph-name="pulse" unicode="&#xe989;" d="M719 350l-169 163-137-194-69 431-195-400h-149v-125h225l56 113 57-338 225 319 100-94h212v125h-156z" horiz-adv-x="875" />
+
+<glyph glyph-name="versions" unicode="&#xe98a;" d="M813 663h-375c-35 0-63-29-63-63v-500c0-34 28-62 63-62h375c34 0 62 28 62 62v500c0 34-28 63-62 63z m-63-500h-250v375h250v-375z m-500 437h63v-62h-63v-375h63v-63h-63c-34 0-62 28-62 63v375c0 34 28 62 62 62z m-187-62h62v-63h-62v-250h62v-62h-62c-35 0-63 28-63 62v250c0 34 28 63 63 63z" horiz-adv-x="875" />
+
+<glyph glyph-name="text-size" unicode="&#xe98b;" d="M1123-25h-141l-59 203h-254l-60-203h-140l-43 146h-205l-44-146h-136l206 600h156l136-397 181 547h157l246-750z m-725 242s-64 226-74 257h-5l-70-257h149z m495 66l-95 339h-4l-94-339h193z" horiz-adv-x="1125" />
+
+<glyph glyph-name="markdown" unicode="&#xe98c;" d="M928 663h-856c-40 0-72-33-72-73v-480c0-40 32-72 72-72h856c40 0 72 32 72 72v480c0 40-32 73-72 73z m-365-500l-125 0v187l-94-120-94 120v-187h-125v375h125l94-125 94 125 125 0v-375z m186-32l-155 219h94v188h125v-188h93l-157-219z" horiz-adv-x="1000" />
+
+<glyph glyph-name="no-newline" unicode="&#xe98d;" d="M1000 538v-188c0-34-28-62-62-62h-188v-125l-187 187 187 188v-125h125v125h125z m-500-188c0-138-112-250-250-250s-250 112-250 250 112 250 250 250 250-112 250-250z m-406-103l260 259c-31 20-66 32-104 32-103 0-187-84-187-188 0-38 11-73 31-103z m344 103c0 38-12 73-32 104l-259-260c30-20 65-31 103-31 104 0 188 84 188 187z" horiz-adv-x="1000" />
+
+<glyph glyph-name="tools" unicode="&#xe98e;" d="M280 396c16-16 80-83 80-83l35 36-55 57 105 112c0 0-47 47-26 28 20 74 1 157-55 215-56 58-135 77-206 57l120-125-31-122-119-33-120 125c-20-74-1-156 55-214 58-60 143-78 217-53z m402-121l-145-144 240-249c20-20 45-31 71-31 26 0 52 11 71 31 40 40 40 106 0 147l-237 246z m318 417l-153 158-451-466 55-57-270-279-62-33-87-142 23-23 137 90 32 64 270 279 55-57 451 466z" horiz-adv-x="1000" />
+
+<glyph glyph-name="tape" unicode="&#xe98f;" 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" />
+</font>
+</defs>
+</svg>
\ No newline at end of file
diff --git a/public/fonts/fontello.ttf b/packages/rocketchat-theme/client/vendor/fontello/font/fontello.ttf
similarity index 100%
rename from public/fonts/fontello.ttf
rename to packages/rocketchat-theme/client/vendor/fontello/font/fontello.ttf
diff --git a/public/fonts/fontello.woff b/packages/rocketchat-theme/client/vendor/fontello/font/fontello.woff
similarity index 100%
rename from public/fonts/fontello.woff
rename to packages/rocketchat-theme/client/vendor/fontello/font/fontello.woff
diff --git a/public/fonts/fontello.woff2 b/packages/rocketchat-theme/client/vendor/fontello/font/fontello.woff2
similarity index 100%
rename from public/fonts/fontello.woff2
rename to packages/rocketchat-theme/client/vendor/fontello/font/fontello.woff2
diff --git a/private/fontello.json b/packages/rocketchat-theme/client/vendor/fontello/fontello.json
similarity index 100%
rename from private/fontello.json
rename to packages/rocketchat-theme/client/vendor/fontello/fontello.json
diff --git a/private/utf8-rtl.html b/packages/rocketchat-theme/client/vendor/fontello/utf8-rtl.html
similarity index 100%
rename from private/utf8-rtl.html
rename to packages/rocketchat-theme/client/vendor/fontello/utf8-rtl.html
diff --git a/packages/rocketchat-theme/client/vendor/jscolor.js b/packages/rocketchat-theme/client/vendor/jscolor.js
new file mode 100644
index 0000000000000000000000000000000000000000..8d65d83740ef0165880e2ab9f696b2619680a0d1
--- /dev/null
+++ b/packages/rocketchat-theme/client/vendor/jscolor.js
@@ -0,0 +1,1844 @@
+/**
+ * jscolor - JavaScript Color Picker
+ *
+ * @link    http://jscolor.com
+ * @license For open source use: GPLv3
+ *          For commercial use: JSColor Commercial License
+ * @author  Jan Odvarko
+ * @version 2.0.4
+ *
+ * See usage examples at http://jscolor.com/examples/
+ */
+
+
+"use strict";
+
+
+if (!window.jscolor) { window.jscolor = (function () {
+
+
+var jsc = {
+
+
+	register : function () {
+		jsc.attachDOMReadyEvent(jsc.init);
+		jsc.attachEvent(document, 'mousedown', jsc.onDocumentMouseDown);
+		jsc.attachEvent(document, 'touchstart', jsc.onDocumentTouchStart);
+		jsc.attachEvent(window, 'resize', jsc.onWindowResize);
+	},
+
+
+	init : function () {
+		if (jsc.jscolor.lookupClass) {
+			jsc.jscolor.installByClassName(jsc.jscolor.lookupClass);
+		}
+	},
+
+
+	tryInstallOnElements : function (elms, className) {
+		var matchClass = new RegExp('(^|\\s)(' + className + ')(\\s*(\\{[^}]*\\})|\\s|$)', 'i');
+
+		for (var i = 0; i < elms.length; i += 1) {
+			if (elms[i].type !== undefined && elms[i].type.toLowerCase() == 'color') {
+				if (jsc.isColorAttrSupported) {
+					// skip inputs of type 'color' if supported by the browser
+					continue;
+				}
+			}
+			var m;
+			if (!elms[i].jscolor && elms[i].className && (m = elms[i].className.match(matchClass))) {
+				var targetElm = elms[i];
+				var optsStr = null;
+
+				var dataOptions = jsc.getDataAttr(targetElm, 'jscolor');
+				if (dataOptions !== null) {
+					optsStr = dataOptions;
+				} else if (m[4]) {
+					optsStr = m[4];
+				}
+
+				var opts = {};
+				if (optsStr) {
+					try {
+						opts = (new Function ('return (' + optsStr + ')'))();
+					} catch(eParseError) {
+						jsc.warn('Error parsing jscolor options: ' + eParseError + ':\n' + optsStr);
+					}
+				}
+				targetElm.jscolor = new jsc.jscolor(targetElm, opts);
+			}
+		}
+	},
+
+
+	isColorAttrSupported : (function () {
+		var elm = document.createElement('input');
+		if (elm.setAttribute) {
+			elm.setAttribute('type', 'color');
+			if (elm.type.toLowerCase() == 'color') {
+				return true;
+			}
+		}
+		return false;
+	})(),
+
+
+	isCanvasSupported : (function () {
+		var elm = document.createElement('canvas');
+		return !!(elm.getContext && elm.getContext('2d'));
+	})(),
+
+
+	fetchElement : function (mixed) {
+		return typeof mixed === 'string' ? document.getElementById(mixed) : mixed;
+	},
+
+
+	isElementType : function (elm, type) {
+		return elm.nodeName.toLowerCase() === type.toLowerCase();
+	},
+
+
+	getDataAttr : function (el, name) {
+		var attrName = 'data-' + name;
+		var attrValue = el.getAttribute(attrName);
+		if (attrValue !== null) {
+			return attrValue;
+		}
+		return null;
+	},
+
+
+	attachEvent : function (el, evnt, func) {
+		if (el.addEventListener) {
+			el.addEventListener(evnt, func, false);
+		} else if (el.attachEvent) {
+			el.attachEvent('on' + evnt, func);
+		}
+	},
+
+
+	detachEvent : function (el, evnt, func) {
+		if (el.removeEventListener) {
+			el.removeEventListener(evnt, func, false);
+		} else if (el.detachEvent) {
+			el.detachEvent('on' + evnt, func);
+		}
+	},
+
+
+	_attachedGroupEvents : {},
+
+
+	attachGroupEvent : function (groupName, el, evnt, func) {
+		if (!jsc._attachedGroupEvents.hasOwnProperty(groupName)) {
+			jsc._attachedGroupEvents[groupName] = [];
+		}
+		jsc._attachedGroupEvents[groupName].push([el, evnt, func]);
+		jsc.attachEvent(el, evnt, func);
+	},
+
+
+	detachGroupEvents : function (groupName) {
+		if (jsc._attachedGroupEvents.hasOwnProperty(groupName)) {
+			for (var i = 0; i < jsc._attachedGroupEvents[groupName].length; i += 1) {
+				var evt = jsc._attachedGroupEvents[groupName][i];
+				jsc.detachEvent(evt[0], evt[1], evt[2]);
+			}
+			delete jsc._attachedGroupEvents[groupName];
+		}
+	},
+
+
+	attachDOMReadyEvent : function (func) {
+		var fired = false;
+		var fireOnce = function () {
+			if (!fired) {
+				fired = true;
+				func();
+			}
+		};
+
+		if (document.readyState === 'complete') {
+			setTimeout(fireOnce, 1); // async
+			return;
+		}
+
+		if (document.addEventListener) {
+			document.addEventListener('DOMContentLoaded', fireOnce, false);
+
+			// Fallback
+			window.addEventListener('load', fireOnce, false);
+
+		} else if (document.attachEvent) {
+			// IE
+			document.attachEvent('onreadystatechange', function () {
+				if (document.readyState === 'complete') {
+					document.detachEvent('onreadystatechange', arguments.callee);
+					fireOnce();
+				}
+			})
+
+			// Fallback
+			window.attachEvent('onload', fireOnce);
+
+			// IE7/8
+			if (document.documentElement.doScroll && window == window.top) {
+				var tryScroll = function () {
+					if (!document.body) { return; }
+					try {
+						document.documentElement.doScroll('left');
+						fireOnce();
+					} catch (e) {
+						setTimeout(tryScroll, 1);
+					}
+				};
+				tryScroll();
+			}
+		}
+	},
+
+
+	warn : function (msg) {
+		if (window.console && window.console.warn) {
+			window.console.warn(msg);
+		}
+	},
+
+
+	preventDefault : function (e) {
+		if (e.preventDefault) { e.preventDefault(); }
+		e.returnValue = false;
+	},
+
+
+	captureTarget : function (target) {
+		// IE
+		if (target.setCapture) {
+			jsc._capturedTarget = target;
+			jsc._capturedTarget.setCapture();
+		}
+	},
+
+
+	releaseTarget : function () {
+		// IE
+		if (jsc._capturedTarget) {
+			jsc._capturedTarget.releaseCapture();
+			jsc._capturedTarget = null;
+		}
+	},
+
+
+	fireEvent : function (el, evnt) {
+		if (!el) {
+			return;
+		}
+		if (document.createEvent) {
+			var ev = document.createEvent('HTMLEvents');
+			ev.initEvent(evnt, true, true);
+			el.dispatchEvent(ev);
+		} else if (document.createEventObject) {
+			var ev = document.createEventObject();
+			el.fireEvent('on' + evnt, ev);
+		} else if (el['on' + evnt]) { // alternatively use the traditional event model
+			el['on' + evnt]();
+		}
+	},
+
+
+	classNameToList : function (className) {
+		return className.replace(/^\s+|\s+$/g, '').split(/\s+/);
+	},
+
+
+	// The className parameter (str) can only contain a single class name
+	hasClass : function (elm, className) {
+		if (!className) {
+			return false;
+		}
+		return -1 != (' ' + elm.className.replace(/\s+/g, ' ') + ' ').indexOf(' ' + className + ' ');
+	},
+
+
+	// The className parameter (str) can contain multiple class names separated by whitespace
+	setClass : function (elm, className) {
+		var classList = jsc.classNameToList(className);
+		for (var i = 0; i < classList.length; i += 1) {
+			if (!jsc.hasClass(elm, classList[i])) {
+				elm.className += (elm.className ? ' ' : '') + classList[i];
+			}
+		}
+	},
+
+
+	// The className parameter (str) can contain multiple class names separated by whitespace
+	unsetClass : function (elm, className) {
+		var classList = jsc.classNameToList(className);
+		for (var i = 0; i < classList.length; i += 1) {
+			var repl = new RegExp(
+				'^\\s*' + classList[i] + '\\s*|' +
+				'\\s*' + classList[i] + '\\s*$|' +
+				'\\s+' + classList[i] + '(\\s+)',
+				'g'
+			);
+			elm.className = elm.className.replace(repl, '$1');
+		}
+	},
+
+
+	getStyle : function (elm) {
+		return window.getComputedStyle ? window.getComputedStyle(elm) : elm.currentStyle;
+	},
+
+
+	setStyle : (function () {
+		var helper = document.createElement('div');
+		var getSupportedProp = function (names) {
+			for (var i = 0; i < names.length; i += 1) {
+				if (names[i] in helper.style) {
+					return names[i];
+				}
+			}
+		};
+		var props = {
+			borderRadius: getSupportedProp(['borderRadius', 'MozBorderRadius', 'webkitBorderRadius']),
+			boxShadow: getSupportedProp(['boxShadow', 'MozBoxShadow', 'webkitBoxShadow'])
+		};
+		return function (elm, prop, value) {
+			switch (prop.toLowerCase()) {
+			case 'opacity':
+				var alphaOpacity = Math.round(parseFloat(value) * 100);
+				elm.style.opacity = value;
+				elm.style.filter = 'alpha(opacity=' + alphaOpacity + ')';
+				break;
+			default:
+				elm.style[props[prop]] = value;
+				break;
+			}
+		};
+	})(),
+
+
+	setBorderRadius : function (elm, value) {
+		jsc.setStyle(elm, 'borderRadius', value || '0');
+	},
+
+
+	setBoxShadow : function (elm, value) {
+		jsc.setStyle(elm, 'boxShadow', value || 'none');
+	},
+
+
+	getElementPos : function (e, relativeToViewport) {
+		var x=0, y=0;
+		var rect = e.getBoundingClientRect();
+		x = rect.left;
+		y = rect.top;
+		if (!relativeToViewport) {
+			var viewPos = jsc.getViewPos();
+			x += viewPos[0];
+			y += viewPos[1];
+		}
+		return [x, y];
+	},
+
+
+	getElementSize : function (e) {
+		return [e.offsetWidth, e.offsetHeight];
+	},
+
+
+	// get pointer's X/Y coordinates relative to viewport
+	getAbsPointerPos : function (e) {
+		if (!e) { e = window.event; }
+		var x = 0, y = 0;
+		if (typeof e.changedTouches !== 'undefined' && e.changedTouches.length) {
+			// touch devices
+			x = e.changedTouches[0].clientX;
+			y = e.changedTouches[0].clientY;
+		} else if (typeof e.clientX === 'number') {
+			x = e.clientX;
+			y = e.clientY;
+		}
+		return { x: x, y: y };
+	},
+
+
+	// get pointer's X/Y coordinates relative to target element
+	getRelPointerPos : function (e) {
+		if (!e) { e = window.event; }
+		var target = e.target || e.srcElement;
+		var targetRect = target.getBoundingClientRect();
+
+		var x = 0, y = 0;
+
+		var clientX = 0, clientY = 0;
+		if (typeof e.changedTouches !== 'undefined' && e.changedTouches.length) {
+			// touch devices
+			clientX = e.changedTouches[0].clientX;
+			clientY = e.changedTouches[0].clientY;
+		} else if (typeof e.clientX === 'number') {
+			clientX = e.clientX;
+			clientY = e.clientY;
+		}
+
+		x = clientX - targetRect.left;
+		y = clientY - targetRect.top;
+		return { x: x, y: y };
+	},
+
+
+	getViewPos : function () {
+		var doc = document.documentElement;
+		return [
+			(window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0),
+			(window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0)
+		];
+	},
+
+
+	getViewSize : function () {
+		var doc = document.documentElement;
+		return [
+			(window.innerWidth || doc.clientWidth),
+			(window.innerHeight || doc.clientHeight),
+		];
+	},
+
+
+	redrawPosition : function () {
+
+		if (jsc.picker && jsc.picker.owner) {
+			var thisObj = jsc.picker.owner;
+
+			var tp, vp;
+
+			if (thisObj.fixed) {
+				// Fixed elements are positioned relative to viewport,
+				// therefore we can ignore the scroll offset
+				tp = jsc.getElementPos(thisObj.targetElement, true); // target pos
+				vp = [0, 0]; // view pos
+			} else {
+				tp = jsc.getElementPos(thisObj.targetElement); // target pos
+				vp = jsc.getViewPos(); // view pos
+			}
+
+			var ts = jsc.getElementSize(thisObj.targetElement); // target size
+			var vs = jsc.getViewSize(); // view size
+			var ps = jsc.getPickerOuterDims(thisObj); // picker size
+			var a, b, c;
+			switch (thisObj.position.toLowerCase()) {
+				case 'left': a=1; b=0; c=-1; break;
+				case 'right':a=1; b=0; c=1; break;
+				case 'top':  a=0; b=1; c=-1; break;
+				default:     a=0; b=1; c=1; break;
+			}
+			var l = (ts[b]+ps[b])/2;
+
+			// compute picker position
+			if (!thisObj.smartPosition) {
+				var pp = [
+					tp[a],
+					tp[b]+ts[b]-l+l*c
+				];
+			} else {
+				var pp = [
+					-vp[a]+tp[a]+ps[a] > vs[a] ?
+						(-vp[a]+tp[a]+ts[a]/2 > vs[a]/2 && tp[a]+ts[a]-ps[a] >= 0 ? tp[a]+ts[a]-ps[a] : tp[a]) :
+						tp[a],
+					-vp[b]+tp[b]+ts[b]+ps[b]-l+l*c > vs[b] ?
+						(-vp[b]+tp[b]+ts[b]/2 > vs[b]/2 && tp[b]+ts[b]-l-l*c >= 0 ? tp[b]+ts[b]-l-l*c : tp[b]+ts[b]-l+l*c) :
+						(tp[b]+ts[b]-l+l*c >= 0 ? tp[b]+ts[b]-l+l*c : tp[b]+ts[b]-l-l*c)
+				];
+			}
+
+			var x = pp[a];
+			var y = pp[b];
+			var positionValue = thisObj.fixed ? 'fixed' : 'absolute';
+			var contractShadow =
+				(pp[0] + ps[0] > tp[0] || pp[0] < tp[0] + ts[0]) &&
+				(pp[1] + ps[1] < tp[1] + ts[1]);
+
+			jsc._drawPosition(thisObj, x, y, positionValue, contractShadow);
+		}
+	},
+
+
+	_drawPosition : function (thisObj, x, y, positionValue, contractShadow) {
+		var vShadow = contractShadow ? 0 : thisObj.shadowBlur; // px
+
+		jsc.picker.wrap.style.position = positionValue;
+		jsc.picker.wrap.style.left = x + 'px';
+		jsc.picker.wrap.style.top = y + 'px';
+
+		jsc.setBoxShadow(
+			jsc.picker.boxS,
+			thisObj.shadow ?
+				new jsc.BoxShadow(0, vShadow, thisObj.shadowBlur, 0, thisObj.shadowColor) :
+				null);
+	},
+
+
+	getPickerDims : function (thisObj) {
+		var displaySlider = !!jsc.getSliderComponent(thisObj);
+		var dims = [
+			2 * thisObj.insetWidth + 2 * thisObj.padding + thisObj.width +
+				(displaySlider ? 2 * thisObj.insetWidth + jsc.getPadToSliderPadding(thisObj) + thisObj.sliderSize : 0),
+			2 * thisObj.insetWidth + 2 * thisObj.padding + thisObj.height +
+				(thisObj.closable ? 2 * thisObj.insetWidth + thisObj.padding + thisObj.buttonHeight : 0)
+		];
+		return dims;
+	},
+
+
+	getPickerOuterDims : function (thisObj) {
+		var dims = jsc.getPickerDims(thisObj);
+		return [
+			dims[0] + 2 * thisObj.borderWidth,
+			dims[1] + 2 * thisObj.borderWidth
+		];
+	},
+
+
+	getPadToSliderPadding : function (thisObj) {
+		return Math.max(thisObj.padding, 1.5 * (2 * thisObj.pointerBorderWidth + thisObj.pointerThickness));
+	},
+
+
+	getPadYComponent : function (thisObj) {
+		switch (thisObj.mode.charAt(1).toLowerCase()) {
+			case 'v': return 'v'; break;
+		}
+		return 's';
+	},
+
+
+	getSliderComponent : function (thisObj) {
+		if (thisObj.mode.length > 2) {
+			switch (thisObj.mode.charAt(2).toLowerCase()) {
+				case 's': return 's'; break;
+				case 'v': return 'v'; break;
+			}
+		}
+		return null;
+	},
+
+
+	onDocumentMouseDown : function (e) {
+		if (!e) { e = window.event; }
+		var target = e.target || e.srcElement;
+
+		if (target._jscLinkedInstance) {
+			if (target._jscLinkedInstance.showOnClick) {
+				target._jscLinkedInstance.show();
+			}
+		} else if (target._jscControlName) {
+			jsc.onControlPointerStart(e, target, target._jscControlName, 'mouse');
+		} else {
+			// Mouse is outside the picker controls -> hide the color picker!
+			if (jsc.picker && jsc.picker.owner) {
+				jsc.picker.owner.hide();
+			}
+		}
+	},
+
+
+	onDocumentTouchStart : function (e) {
+		if (!e) { e = window.event; }
+		var target = e.target || e.srcElement;
+
+		if (target._jscLinkedInstance) {
+			if (target._jscLinkedInstance.showOnClick) {
+				target._jscLinkedInstance.show();
+			}
+		} else if (target._jscControlName) {
+			jsc.onControlPointerStart(e, target, target._jscControlName, 'touch');
+		} else {
+			if (jsc.picker && jsc.picker.owner) {
+				jsc.picker.owner.hide();
+			}
+		}
+	},
+
+
+	onWindowResize : function (e) {
+		jsc.redrawPosition();
+	},
+
+
+	onParentScroll : function (e) {
+		// hide the picker when one of the parent elements is scrolled
+		if (jsc.picker && jsc.picker.owner) {
+			jsc.picker.owner.hide();
+		}
+	},
+
+
+	_pointerMoveEvent : {
+		mouse: 'mousemove',
+		touch: 'touchmove'
+	},
+	_pointerEndEvent : {
+		mouse: 'mouseup',
+		touch: 'touchend'
+	},
+
+
+	_pointerOrigin : null,
+	_capturedTarget : null,
+
+
+	onControlPointerStart : function (e, target, controlName, pointerType) {
+		var thisObj = target._jscInstance;
+
+		jsc.preventDefault(e);
+		jsc.captureTarget(target);
+
+		var registerDragEvents = function (doc, offset) {
+			jsc.attachGroupEvent('drag', doc, jsc._pointerMoveEvent[pointerType],
+				jsc.onDocumentPointerMove(e, target, controlName, pointerType, offset));
+			jsc.attachGroupEvent('drag', doc, jsc._pointerEndEvent[pointerType],
+				jsc.onDocumentPointerEnd(e, target, controlName, pointerType));
+		};
+
+		registerDragEvents(document, [0, 0]);
+
+		if (window.parent && window.frameElement) {
+			var rect = window.frameElement.getBoundingClientRect();
+			var ofs = [-rect.left, -rect.top];
+			registerDragEvents(window.parent.window.document, ofs);
+		}
+
+		var abs = jsc.getAbsPointerPos(e);
+		var rel = jsc.getRelPointerPos(e);
+		jsc._pointerOrigin = {
+			x: abs.x - rel.x,
+			y: abs.y - rel.y
+		};
+
+		switch (controlName) {
+		case 'pad':
+			// if the slider is at the bottom, move it up
+			switch (jsc.getSliderComponent(thisObj)) {
+			case 's': if (thisObj.hsv[1] === 0) { thisObj.fromHSV(null, 100, null); }; break;
+			case 'v': if (thisObj.hsv[2] === 0) { thisObj.fromHSV(null, null, 100); }; break;
+			}
+			jsc.setPad(thisObj, e, 0, 0);
+			break;
+
+		case 'sld':
+			jsc.setSld(thisObj, e, 0);
+			break;
+		}
+
+		jsc.dispatchFineChange(thisObj);
+	},
+
+
+	onDocumentPointerMove : function (e, target, controlName, pointerType, offset) {
+		return function (e) {
+			var thisObj = target._jscInstance;
+			switch (controlName) {
+			case 'pad':
+				if (!e) { e = window.event; }
+				jsc.setPad(thisObj, e, offset[0], offset[1]);
+				jsc.dispatchFineChange(thisObj);
+				break;
+
+			case 'sld':
+				if (!e) { e = window.event; }
+				jsc.setSld(thisObj, e, offset[1]);
+				jsc.dispatchFineChange(thisObj);
+				break;
+			}
+		}
+	},
+
+
+	onDocumentPointerEnd : function (e, target, controlName, pointerType) {
+		return function (e) {
+			var thisObj = target._jscInstance;
+			jsc.detachGroupEvents('drag');
+			jsc.releaseTarget();
+			// Always dispatch changes after detaching outstanding mouse handlers,
+			// in case some user interaction will occur in user's onchange callback
+			// that would intrude with current mouse events
+			jsc.dispatchChange(thisObj);
+		};
+	},
+
+
+	dispatchChange : function (thisObj) {
+		if (thisObj.valueElement) {
+			if (jsc.isElementType(thisObj.valueElement, 'input')) {
+				jsc.fireEvent(thisObj.valueElement, 'change');
+			}
+		}
+	},
+
+
+	dispatchFineChange : function (thisObj) {
+		if (thisObj.onFineChange) {
+			var callback;
+			if (typeof thisObj.onFineChange === 'string') {
+				callback = new Function (thisObj.onFineChange);
+			} else {
+				callback = thisObj.onFineChange;
+			}
+			callback.call(thisObj);
+		}
+	},
+
+
+	setPad : function (thisObj, e, ofsX, ofsY) {
+		var pointerAbs = jsc.getAbsPointerPos(e);
+		var x = ofsX + pointerAbs.x - jsc._pointerOrigin.x - thisObj.padding - thisObj.insetWidth;
+		var y = ofsY + pointerAbs.y - jsc._pointerOrigin.y - thisObj.padding - thisObj.insetWidth;
+
+		var xVal = x * (360 / (thisObj.width - 1));
+		var yVal = 100 - (y * (100 / (thisObj.height - 1)));
+
+		switch (jsc.getPadYComponent(thisObj)) {
+		case 's': thisObj.fromHSV(xVal, yVal, null, jsc.leaveSld); break;
+		case 'v': thisObj.fromHSV(xVal, null, yVal, jsc.leaveSld); break;
+		}
+	},
+
+
+	setSld : function (thisObj, e, ofsY) {
+		var pointerAbs = jsc.getAbsPointerPos(e);
+		var y = ofsY + pointerAbs.y - jsc._pointerOrigin.y - thisObj.padding - thisObj.insetWidth;
+
+		var yVal = 100 - (y * (100 / (thisObj.height - 1)));
+
+		switch (jsc.getSliderComponent(thisObj)) {
+		case 's': thisObj.fromHSV(null, yVal, null, jsc.leavePad); break;
+		case 'v': thisObj.fromHSV(null, null, yVal, jsc.leavePad); break;
+		}
+	},
+
+
+	_vmlNS : 'jsc_vml_',
+	_vmlCSS : 'jsc_vml_css_',
+	_vmlReady : false,
+
+
+	initVML : function () {
+		if (!jsc._vmlReady) {
+			// init VML namespace
+			var doc = document;
+			if (!doc.namespaces[jsc._vmlNS]) {
+				doc.namespaces.add(jsc._vmlNS, 'urn:schemas-microsoft-com:vml');
+			}
+			if (!doc.styleSheets[jsc._vmlCSS]) {
+				var tags = ['shape', 'shapetype', 'group', 'background', 'path', 'formulas', 'handles', 'fill', 'stroke', 'shadow', 'textbox', 'textpath', 'imagedata', 'line', 'polyline', 'curve', 'rect', 'roundrect', 'oval', 'arc', 'image'];
+				var ss = doc.createStyleSheet();
+				ss.owningElement.id = jsc._vmlCSS;
+				for (var i = 0; i < tags.length; i += 1) {
+					ss.addRule(jsc._vmlNS + '\\:' + tags[i], 'behavior:url(#default#VML);');
+				}
+			}
+			jsc._vmlReady = true;
+		}
+	},
+
+
+	createPalette : function () {
+
+		var paletteObj = {
+			elm: null,
+			draw: null
+		};
+
+		if (jsc.isCanvasSupported) {
+			// Canvas implementation for modern browsers
+
+			var canvas = document.createElement('canvas');
+			var ctx = canvas.getContext('2d');
+
+			var drawFunc = function (width, height, type) {
+				canvas.width = width;
+				canvas.height = height;
+
+				ctx.clearRect(0, 0, canvas.width, canvas.height);
+
+				var hGrad = ctx.createLinearGradient(0, 0, canvas.width, 0);
+				hGrad.addColorStop(0 / 6, '#F00');
+				hGrad.addColorStop(1 / 6, '#FF0');
+				hGrad.addColorStop(2 / 6, '#0F0');
+				hGrad.addColorStop(3 / 6, '#0FF');
+				hGrad.addColorStop(4 / 6, '#00F');
+				hGrad.addColorStop(5 / 6, '#F0F');
+				hGrad.addColorStop(6 / 6, '#F00');
+
+				ctx.fillStyle = hGrad;
+				ctx.fillRect(0, 0, canvas.width, canvas.height);
+
+				var vGrad = ctx.createLinearGradient(0, 0, 0, canvas.height);
+				switch (type.toLowerCase()) {
+				case 's':
+					vGrad.addColorStop(0, 'rgba(255,255,255,0)');
+					vGrad.addColorStop(1, 'rgba(255,255,255,1)');
+					break;
+				case 'v':
+					vGrad.addColorStop(0, 'rgba(0,0,0,0)');
+					vGrad.addColorStop(1, 'rgba(0,0,0,1)');
+					break;
+				}
+				ctx.fillStyle = vGrad;
+				ctx.fillRect(0, 0, canvas.width, canvas.height);
+			};
+
+			paletteObj.elm = canvas;
+			paletteObj.draw = drawFunc;
+
+		} else {
+			// VML fallback for IE 7 and 8
+
+			jsc.initVML();
+
+			var vmlContainer = document.createElement('div');
+			vmlContainer.style.position = 'relative';
+			vmlContainer.style.overflow = 'hidden';
+
+			var hGrad = document.createElement(jsc._vmlNS + ':fill');
+			hGrad.type = 'gradient';
+			hGrad.method = 'linear';
+			hGrad.angle = '90';
+			hGrad.colors = '16.67% #F0F, 33.33% #00F, 50% #0FF, 66.67% #0F0, 83.33% #FF0'
+
+			var hRect = document.createElement(jsc._vmlNS + ':rect');
+			hRect.style.position = 'absolute';
+			hRect.style.left = -1 + 'px';
+			hRect.style.top = -1 + 'px';
+			hRect.stroked = false;
+			hRect.appendChild(hGrad);
+			vmlContainer.appendChild(hRect);
+
+			var vGrad = document.createElement(jsc._vmlNS + ':fill');
+			vGrad.type = 'gradient';
+			vGrad.method = 'linear';
+			vGrad.angle = '180';
+			vGrad.opacity = '0';
+
+			var vRect = document.createElement(jsc._vmlNS + ':rect');
+			vRect.style.position = 'absolute';
+			vRect.style.left = -1 + 'px';
+			vRect.style.top = -1 + 'px';
+			vRect.stroked = false;
+			vRect.appendChild(vGrad);
+			vmlContainer.appendChild(vRect);
+
+			var drawFunc = function (width, height, type) {
+				vmlContainer.style.width = width + 'px';
+				vmlContainer.style.height = height + 'px';
+
+				hRect.style.width =
+				vRect.style.width =
+					(width + 1) + 'px';
+				hRect.style.height =
+				vRect.style.height =
+					(height + 1) + 'px';
+
+				// Colors must be specified during every redraw, otherwise IE won't display
+				// a full gradient during a subsequential redraw
+				hGrad.color = '#F00';
+				hGrad.color2 = '#F00';
+
+				switch (type.toLowerCase()) {
+				case 's':
+					vGrad.color = vGrad.color2 = '#FFF';
+					break;
+				case 'v':
+					vGrad.color = vGrad.color2 = '#000';
+					break;
+				}
+			};
+
+			paletteObj.elm = vmlContainer;
+			paletteObj.draw = drawFunc;
+		}
+
+		return paletteObj;
+	},
+
+
+	createSliderGradient : function () {
+
+		var sliderObj = {
+			elm: null,
+			draw: null
+		};
+
+		if (jsc.isCanvasSupported) {
+			// Canvas implementation for modern browsers
+
+			var canvas = document.createElement('canvas');
+			var ctx = canvas.getContext('2d');
+
+			var drawFunc = function (width, height, color1, color2) {
+				canvas.width = width;
+				canvas.height = height;
+
+				ctx.clearRect(0, 0, canvas.width, canvas.height);
+
+				var grad = ctx.createLinearGradient(0, 0, 0, canvas.height);
+				grad.addColorStop(0, color1);
+				grad.addColorStop(1, color2);
+
+				ctx.fillStyle = grad;
+				ctx.fillRect(0, 0, canvas.width, canvas.height);
+			};
+
+			sliderObj.elm = canvas;
+			sliderObj.draw = drawFunc;
+
+		} else {
+			// VML fallback for IE 7 and 8
+
+			jsc.initVML();
+
+			var vmlContainer = document.createElement('div');
+			vmlContainer.style.position = 'relative';
+			vmlContainer.style.overflow = 'hidden';
+
+			var grad = document.createElement(jsc._vmlNS + ':fill');
+			grad.type = 'gradient';
+			grad.method = 'linear';
+			grad.angle = '180';
+
+			var rect = document.createElement(jsc._vmlNS + ':rect');
+			rect.style.position = 'absolute';
+			rect.style.left = -1 + 'px';
+			rect.style.top = -1 + 'px';
+			rect.stroked = false;
+			rect.appendChild(grad);
+			vmlContainer.appendChild(rect);
+
+			var drawFunc = function (width, height, color1, color2) {
+				vmlContainer.style.width = width + 'px';
+				vmlContainer.style.height = height + 'px';
+
+				rect.style.width = (width + 1) + 'px';
+				rect.style.height = (height + 1) + 'px';
+
+				grad.color = color1;
+				grad.color2 = color2;
+			};
+
+			sliderObj.elm = vmlContainer;
+			sliderObj.draw = drawFunc;
+		}
+
+		return sliderObj;
+	},
+
+
+	leaveValue : 1<<0,
+	leaveStyle : 1<<1,
+	leavePad : 1<<2,
+	leaveSld : 1<<3,
+
+
+	BoxShadow : (function () {
+		var BoxShadow = function (hShadow, vShadow, blur, spread, color, inset) {
+			this.hShadow = hShadow;
+			this.vShadow = vShadow;
+			this.blur = blur;
+			this.spread = spread;
+			this.color = color;
+			this.inset = !!inset;
+		};
+
+		BoxShadow.prototype.toString = function () {
+			var vals = [
+				Math.round(this.hShadow) + 'px',
+				Math.round(this.vShadow) + 'px',
+				Math.round(this.blur) + 'px',
+				Math.round(this.spread) + 'px',
+				this.color
+			];
+			if (this.inset) {
+				vals.push('inset');
+			}
+			return vals.join(' ');
+		};
+
+		return BoxShadow;
+	})(),
+
+
+	//
+	// Usage:
+	// var myColor = new jscolor(<targetElement> [, <options>])
+	//
+
+	jscolor : function (targetElement, options) {
+
+		// General options
+		//
+		this.value = null; // initial HEX color. To change it later, use methods fromString(), fromHSV() and fromRGB()
+		this.valueElement = targetElement; // element that will be used to display and input the color code
+		this.styleElement = targetElement; // element that will preview the picked color using CSS backgroundColor
+		this.required = true; // whether the associated text <input> can be left empty
+		this.refine = true; // whether to refine the entered color code (e.g. uppercase it and remove whitespace)
+		this.hash = true; // whether to prefix the HEX color code with # symbol
+		this.uppercase = true; // whether to uppercase the color code
+		this.onFineChange = null; // called instantly every time the color changes (value can be either a function or a string with javascript code)
+		this.activeClass = 'jscolor-active'; // class to be set to the target element when a picker window is open on it
+		this.minS = 0; // min allowed saturation (0 - 100)
+		this.maxS = 100; // max allowed saturation (0 - 100)
+		this.minV = 0; // min allowed value (brightness) (0 - 100)
+		this.maxV = 100; // max allowed value (brightness) (0 - 100)
+
+		// Accessing the picked color
+		//
+		this.hsv = [0, 0, 100]; // read-only  [0-360, 0-100, 0-100]
+		this.rgb = [255, 255, 255]; // read-only  [0-255, 0-255, 0-255]
+
+		// Color Picker options
+		//
+		this.width = 181; // width of color palette (in px)
+		this.height = 101; // height of color palette (in px)
+		this.showOnClick = true; // whether to display the color picker when user clicks on its target element
+		this.mode = 'HSV'; // HSV | HVS | HS | HV - layout of the color picker controls
+		this.position = 'bottom'; // left | right | top | bottom - position relative to the target element
+		this.smartPosition = true; // automatically change picker position when there is not enough space for it
+		this.sliderSize = 16; // px
+		this.crossSize = 8; // px
+		this.closable = false; // whether to display the Close button
+		this.closeText = 'Close';
+		this.buttonColor = '#000000'; // CSS color
+		this.buttonHeight = 18; // px
+		this.padding = 8; // px
+		this.backgroundColor = '#FFFFFF'; // CSS color
+		this.borderWidth = 1; // px
+		this.borderColor = '#BBBBBB'; // CSS color
+		this.borderRadius = 4; // px
+		this.insetWidth = 1; // px
+		this.insetColor = '#BBBBBB'; // CSS color
+		this.shadow = false; // whether to display shadow
+		this.shadowBlur = 15; // px
+		this.shadowColor = 'rgba(0,0,0,0.2)'; // CSS color
+		this.pointerColor = '#4C4C4C'; // px
+		this.pointerBorderColor = '#FFFFFF'; // px
+        this.pointerBorderWidth = 1; // px
+        this.pointerThickness = 2; // px
+		this.zIndex = 1000;
+		this.container = null; // where to append the color picker (BODY element by default)
+
+
+		for (var opt in options) {
+			if (options.hasOwnProperty(opt)) {
+				this[opt] = options[opt];
+			}
+		}
+
+
+		this.hide = function () {
+			if (isPickerOwner()) {
+				detachPicker();
+			}
+		};
+
+
+		this.show = function () {
+			drawPicker();
+		};
+
+
+		this.redraw = function () {
+			if (isPickerOwner()) {
+				drawPicker();
+			}
+		};
+
+
+		this.importColor = function () {
+			if (!this.valueElement) {
+				this.exportColor();
+			} else {
+				if (jsc.isElementType(this.valueElement, 'input')) {
+					if (!this.refine) {
+						if (!this.fromString(this.valueElement.value, jsc.leaveValue)) {
+							if (this.styleElement) {
+								this.styleElement.style.backgroundImage = this.styleElement._jscOrigStyle.backgroundImage;
+								this.styleElement.style.backgroundColor = this.styleElement._jscOrigStyle.backgroundColor;
+								this.styleElement.style.color = this.styleElement._jscOrigStyle.color;
+							}
+							this.exportColor(jsc.leaveValue | jsc.leaveStyle);
+						}
+					} else if (!this.required && /^\s*$/.test(this.valueElement.value)) {
+						this.valueElement.value = '';
+						if (this.styleElement) {
+							this.styleElement.style.backgroundImage = this.styleElement._jscOrigStyle.backgroundImage;
+							this.styleElement.style.backgroundColor = this.styleElement._jscOrigStyle.backgroundColor;
+							this.styleElement.style.color = this.styleElement._jscOrigStyle.color;
+						}
+						this.exportColor(jsc.leaveValue | jsc.leaveStyle);
+
+					} else if (this.fromString(this.valueElement.value)) {
+						// managed to import color successfully from the value -> OK, don't do anything
+					} else {
+						this.exportColor();
+					}
+				} else {
+					// not an input element -> doesn't have any value
+					this.exportColor();
+				}
+			}
+		};
+
+
+		this.exportColor = function (flags) {
+			if (!(flags & jsc.leaveValue) && this.valueElement) {
+				var value = this.toString();
+				if (this.uppercase) { value = value.toUpperCase(); }
+				if (this.hash) { value = '#' + value; }
+
+				if (jsc.isElementType(this.valueElement, 'input')) {
+					this.valueElement.value = value;
+				} else {
+					this.valueElement.innerHTML = value;
+				}
+			}
+			// if (!(flags & jsc.leaveStyle)) {
+			// 	if (this.styleElement) {
+			// 		this.styleElement.style.backgroundImage = 'none';
+			// 		this.styleElement.style.backgroundColor = '#' + this.toString();
+			// 		this.styleElement.style.color = this.isLight() ? '#000' : '#FFF';
+			// 	}
+			// }
+			if (!(flags & jsc.leavePad) && isPickerOwner()) {
+				redrawPad();
+			}
+			if (!(flags & jsc.leaveSld) && isPickerOwner()) {
+				redrawSld();
+			}
+		};
+
+
+		// h: 0-360
+		// s: 0-100
+		// v: 0-100
+		//
+		this.fromHSV = function (h, s, v, flags) { // null = don't change
+			if (h !== null) {
+				if (isNaN(h)) { return false; }
+				h = Math.max(0, Math.min(360, h));
+			}
+			if (s !== null) {
+				if (isNaN(s)) { return false; }
+				s = Math.max(0, Math.min(100, this.maxS, s), this.minS);
+			}
+			if (v !== null) {
+				if (isNaN(v)) { return false; }
+				v = Math.max(0, Math.min(100, this.maxV, v), this.minV);
+			}
+
+			this.rgb = HSV_RGB(
+				h===null ? this.hsv[0] : (this.hsv[0]=h),
+				s===null ? this.hsv[1] : (this.hsv[1]=s),
+				v===null ? this.hsv[2] : (this.hsv[2]=v)
+			);
+
+			this.exportColor(flags);
+		};
+
+
+		// r: 0-255
+		// g: 0-255
+		// b: 0-255
+		//
+		this.fromRGB = function (r, g, b, flags) { // null = don't change
+			if (r !== null) {
+				if (isNaN(r)) { return false; }
+				r = Math.max(0, Math.min(255, r));
+			}
+			if (g !== null) {
+				if (isNaN(g)) { return false; }
+				g = Math.max(0, Math.min(255, g));
+			}
+			if (b !== null) {
+				if (isNaN(b)) { return false; }
+				b = Math.max(0, Math.min(255, b));
+			}
+
+			var hsv = RGB_HSV(
+				r===null ? this.rgb[0] : r,
+				g===null ? this.rgb[1] : g,
+				b===null ? this.rgb[2] : b
+			);
+			if (hsv[0] !== null) {
+				this.hsv[0] = Math.max(0, Math.min(360, hsv[0]));
+			}
+			if (hsv[2] !== 0) {
+				this.hsv[1] = hsv[1]===null ? null : Math.max(0, this.minS, Math.min(100, this.maxS, hsv[1]));
+			}
+			this.hsv[2] = hsv[2]===null ? null : Math.max(0, this.minV, Math.min(100, this.maxV, hsv[2]));
+
+			// update RGB according to final HSV, as some values might be trimmed
+			var rgb = HSV_RGB(this.hsv[0], this.hsv[1], this.hsv[2]);
+			this.rgb[0] = rgb[0];
+			this.rgb[1] = rgb[1];
+			this.rgb[2] = rgb[2];
+
+			this.exportColor(flags);
+		};
+
+
+		this.fromString = function (str, flags) {
+			var m;
+			if (m = str.match(/^\W*([0-9A-F]{3}([0-9A-F]{3})?)\W*$/i)) {
+				// HEX notation
+				//
+
+				if (m[1].length === 6) {
+					// 6-char notation
+					this.fromRGB(
+						parseInt(m[1].substr(0,2),16),
+						parseInt(m[1].substr(2,2),16),
+						parseInt(m[1].substr(4,2),16),
+						flags
+					);
+				} else {
+					// 3-char notation
+					this.fromRGB(
+						parseInt(m[1].charAt(0) + m[1].charAt(0),16),
+						parseInt(m[1].charAt(1) + m[1].charAt(1),16),
+						parseInt(m[1].charAt(2) + m[1].charAt(2),16),
+						flags
+					);
+				}
+				return true;
+
+			} else if (m = str.match(/^\W*rgba?\(([^)]*)\)\W*$/i)) {
+				var params = m[1].split(',');
+				var re = /^\s*(\d*)(\.\d+)?\s*$/;
+				var mR, mG, mB;
+				if (
+					params.length >= 3 &&
+					(mR = params[0].match(re)) &&
+					(mG = params[1].match(re)) &&
+					(mB = params[2].match(re))
+				) {
+					var r = parseFloat((mR[1] || '0') + (mR[2] || ''));
+					var g = parseFloat((mG[1] || '0') + (mG[2] || ''));
+					var b = parseFloat((mB[1] || '0') + (mB[2] || ''));
+					this.fromRGB(r, g, b, flags);
+					return true;
+				}
+			}
+			return false;
+		};
+
+
+		this.toString = function () {
+			return (
+				(0x100 | Math.round(this.rgb[0])).toString(16).substr(1) +
+				(0x100 | Math.round(this.rgb[1])).toString(16).substr(1) +
+				(0x100 | Math.round(this.rgb[2])).toString(16).substr(1)
+			);
+		};
+
+
+		this.toHEXString = function () {
+			return '#' + this.toString().toUpperCase();
+		};
+
+
+		this.toRGBString = function () {
+			return ('rgb(' +
+				Math.round(this.rgb[0]) + ',' +
+				Math.round(this.rgb[1]) + ',' +
+				Math.round(this.rgb[2]) + ')'
+			);
+		};
+
+
+		this.isLight = function () {
+			return (
+				0.213 * this.rgb[0] +
+				0.715 * this.rgb[1] +
+				0.072 * this.rgb[2] >
+				255 / 2
+			);
+		};
+
+
+		this._processParentElementsInDOM = function () {
+			if (this._linkedElementsProcessed) { return; }
+			this._linkedElementsProcessed = true;
+
+			var elm = this.targetElement;
+			do {
+				// If the target element or one of its parent nodes has fixed position,
+				// then use fixed positioning instead
+				//
+				// Note: In Firefox, getComputedStyle returns null in a hidden iframe,
+				// that's why we need to check if the returned style object is non-empty
+				var currStyle = jsc.getStyle(elm);
+				if (currStyle && currStyle.position.toLowerCase() === 'fixed') {
+					this.fixed = true;
+				}
+
+				if (elm !== this.targetElement) {
+					// Ensure to attach onParentScroll only once to each parent element
+					// (multiple targetElements can share the same parent nodes)
+					//
+					// Note: It's not just offsetParents that can be scrollable,
+					// that's why we loop through all parent nodes
+					if (!elm._jscEventsAttached) {
+						jsc.attachEvent(elm, 'scroll', jsc.onParentScroll);
+						elm._jscEventsAttached = true;
+					}
+				}
+			} while ((elm = elm.parentNode) && !jsc.isElementType(elm, 'body'));
+		};
+
+
+		// r: 0-255
+		// g: 0-255
+		// b: 0-255
+		//
+		// returns: [ 0-360, 0-100, 0-100 ]
+		//
+		function RGB_HSV (r, g, b) {
+			r /= 255;
+			g /= 255;
+			b /= 255;
+			var n = Math.min(Math.min(r,g),b);
+			var v = Math.max(Math.max(r,g),b);
+			var m = v - n;
+			if (m === 0) { return [ null, 0, 100 * v ]; }
+			var h = r===n ? 3+(b-g)/m : (g===n ? 5+(r-b)/m : 1+(g-r)/m);
+			return [
+				60 * (h===6?0:h),
+				100 * (m/v),
+				100 * v
+			];
+		}
+
+
+		// h: 0-360
+		// s: 0-100
+		// v: 0-100
+		//
+		// returns: [ 0-255, 0-255, 0-255 ]
+		//
+		function HSV_RGB (h, s, v) {
+			var u = 255 * (v / 100);
+
+			if (h === null) {
+				return [ u, u, u ];
+			}
+
+			h /= 60;
+			s /= 100;
+
+			var i = Math.floor(h);
+			var f = i%2 ? h-i : 1-(h-i);
+			var m = u * (1 - s);
+			var n = u * (1 - s * f);
+			switch (i) {
+				case 6:
+				case 0: return [u,n,m];
+				case 1: return [n,u,m];
+				case 2: return [m,u,n];
+				case 3: return [m,n,u];
+				case 4: return [n,m,u];
+				case 5: return [u,m,n];
+			}
+		}
+
+
+		function detachPicker () {
+			jsc.unsetClass(THIS.targetElement, THIS.activeClass);
+			jsc.picker.wrap.parentNode.removeChild(jsc.picker.wrap);
+			delete jsc.picker.owner;
+		}
+
+
+		function drawPicker () {
+
+			// At this point, when drawing the picker, we know what the parent elements are
+			// and we can do all related DOM operations, such as registering events on them
+			// or checking their positioning
+			THIS._processParentElementsInDOM();
+
+			if (!jsc.picker) {
+				jsc.picker = {
+					owner: null,
+					wrap : document.createElement('div'),
+					box : document.createElement('div'),
+					boxS : document.createElement('div'), // shadow area
+					boxB : document.createElement('div'), // border
+					pad : document.createElement('div'),
+					padB : document.createElement('div'), // border
+					padM : document.createElement('div'), // mouse/touch area
+					padPal : jsc.createPalette(),
+					cross : document.createElement('div'),
+					crossBY : document.createElement('div'), // border Y
+					crossBX : document.createElement('div'), // border X
+					crossLY : document.createElement('div'), // line Y
+					crossLX : document.createElement('div'), // line X
+					sld : document.createElement('div'),
+					sldB : document.createElement('div'), // border
+					sldM : document.createElement('div'), // mouse/touch area
+					sldGrad : jsc.createSliderGradient(),
+					sldPtrS : document.createElement('div'), // slider pointer spacer
+					sldPtrIB : document.createElement('div'), // slider pointer inner border
+					sldPtrMB : document.createElement('div'), // slider pointer middle border
+					sldPtrOB : document.createElement('div'), // slider pointer outer border
+					btn : document.createElement('div'),
+					btnT : document.createElement('span') // text
+				};
+
+				jsc.picker.pad.appendChild(jsc.picker.padPal.elm);
+				jsc.picker.padB.appendChild(jsc.picker.pad);
+				jsc.picker.cross.appendChild(jsc.picker.crossBY);
+				jsc.picker.cross.appendChild(jsc.picker.crossBX);
+				jsc.picker.cross.appendChild(jsc.picker.crossLY);
+				jsc.picker.cross.appendChild(jsc.picker.crossLX);
+				jsc.picker.padB.appendChild(jsc.picker.cross);
+				jsc.picker.box.appendChild(jsc.picker.padB);
+				jsc.picker.box.appendChild(jsc.picker.padM);
+
+				jsc.picker.sld.appendChild(jsc.picker.sldGrad.elm);
+				jsc.picker.sldB.appendChild(jsc.picker.sld);
+				jsc.picker.sldB.appendChild(jsc.picker.sldPtrOB);
+				jsc.picker.sldPtrOB.appendChild(jsc.picker.sldPtrMB);
+				jsc.picker.sldPtrMB.appendChild(jsc.picker.sldPtrIB);
+				jsc.picker.sldPtrIB.appendChild(jsc.picker.sldPtrS);
+				jsc.picker.box.appendChild(jsc.picker.sldB);
+				jsc.picker.box.appendChild(jsc.picker.sldM);
+
+				jsc.picker.btn.appendChild(jsc.picker.btnT);
+				jsc.picker.box.appendChild(jsc.picker.btn);
+
+				jsc.picker.boxB.appendChild(jsc.picker.box);
+				jsc.picker.wrap.appendChild(jsc.picker.boxS);
+				jsc.picker.wrap.appendChild(jsc.picker.boxB);
+			}
+
+			var p = jsc.picker;
+
+			var displaySlider = !!jsc.getSliderComponent(THIS);
+			var dims = jsc.getPickerDims(THIS);
+			var crossOuterSize = (2 * THIS.pointerBorderWidth + THIS.pointerThickness + 2 * THIS.crossSize);
+			var padToSliderPadding = jsc.getPadToSliderPadding(THIS);
+			var borderRadius = Math.min(
+				THIS.borderRadius,
+				Math.round(THIS.padding * Math.PI)); // px
+			var padCursor = 'crosshair';
+
+			// wrap
+			p.wrap.style.clear = 'both';
+			p.wrap.style.width = (dims[0] + 2 * THIS.borderWidth) + 'px';
+			p.wrap.style.height = (dims[1] + 2 * THIS.borderWidth) + 'px';
+			p.wrap.style.zIndex = THIS.zIndex;
+
+			// picker
+			p.box.style.width = dims[0] + 'px';
+			p.box.style.height = dims[1] + 'px';
+
+			p.boxS.style.position = 'absolute';
+			p.boxS.style.left = '0';
+			p.boxS.style.top = '0';
+			p.boxS.style.width = '100%';
+			p.boxS.style.height = '100%';
+			jsc.setBorderRadius(p.boxS, borderRadius + 'px');
+
+			// picker border
+			p.boxB.style.position = 'relative';
+			p.boxB.style.border = THIS.borderWidth + 'px solid';
+			p.boxB.style.borderColor = THIS.borderColor;
+			p.boxB.style.background = THIS.backgroundColor;
+			jsc.setBorderRadius(p.boxB, borderRadius + 'px');
+
+			// IE hack:
+			// If the element is transparent, IE will trigger the event on the elements under it,
+			// e.g. on Canvas or on elements with border
+			p.padM.style.background =
+			p.sldM.style.background =
+				'#FFF';
+			jsc.setStyle(p.padM, 'opacity', '0');
+			jsc.setStyle(p.sldM, 'opacity', '0');
+
+			// pad
+			p.pad.style.position = 'relative';
+			p.pad.style.width = THIS.width + 'px';
+			p.pad.style.height = THIS.height + 'px';
+
+			// pad palettes (HSV and HVS)
+			p.padPal.draw(THIS.width, THIS.height, jsc.getPadYComponent(THIS));
+
+			// pad border
+			p.padB.style.position = 'absolute';
+			p.padB.style.left = THIS.padding + 'px';
+			p.padB.style.top = THIS.padding + 'px';
+			p.padB.style.border = THIS.insetWidth + 'px solid';
+			p.padB.style.borderColor = THIS.insetColor;
+
+			// pad mouse area
+			p.padM._jscInstance = THIS;
+			p.padM._jscControlName = 'pad';
+			p.padM.style.position = 'absolute';
+			p.padM.style.left = '0';
+			p.padM.style.top = '0';
+			p.padM.style.width = (THIS.padding + 2 * THIS.insetWidth + THIS.width + padToSliderPadding / 2) + 'px';
+			p.padM.style.height = dims[1] + 'px';
+			p.padM.style.cursor = padCursor;
+
+			// pad cross
+			p.cross.style.position = 'absolute';
+			p.cross.style.left =
+			p.cross.style.top =
+				'0';
+			p.cross.style.width =
+			p.cross.style.height =
+				crossOuterSize + 'px';
+
+			// pad cross border Y and X
+			p.crossBY.style.position =
+			p.crossBX.style.position =
+				'absolute';
+			p.crossBY.style.background =
+			p.crossBX.style.background =
+				THIS.pointerBorderColor;
+			p.crossBY.style.width =
+			p.crossBX.style.height =
+				(2 * THIS.pointerBorderWidth + THIS.pointerThickness) + 'px';
+			p.crossBY.style.height =
+			p.crossBX.style.width =
+				crossOuterSize + 'px';
+			p.crossBY.style.left =
+			p.crossBX.style.top =
+				(Math.floor(crossOuterSize / 2) - Math.floor(THIS.pointerThickness / 2) - THIS.pointerBorderWidth) + 'px';
+			p.crossBY.style.top =
+			p.crossBX.style.left =
+				'0';
+
+			// pad cross line Y and X
+			p.crossLY.style.position =
+			p.crossLX.style.position =
+				'absolute';
+			p.crossLY.style.background =
+			p.crossLX.style.background =
+				THIS.pointerColor;
+			p.crossLY.style.height =
+			p.crossLX.style.width =
+				(crossOuterSize - 2 * THIS.pointerBorderWidth) + 'px';
+			p.crossLY.style.width =
+			p.crossLX.style.height =
+				THIS.pointerThickness + 'px';
+			p.crossLY.style.left =
+			p.crossLX.style.top =
+				(Math.floor(crossOuterSize / 2) - Math.floor(THIS.pointerThickness / 2)) + 'px';
+			p.crossLY.style.top =
+			p.crossLX.style.left =
+				THIS.pointerBorderWidth + 'px';
+
+			// slider
+			p.sld.style.overflow = 'hidden';
+			p.sld.style.width = THIS.sliderSize + 'px';
+			p.sld.style.height = THIS.height + 'px';
+
+			// slider gradient
+			p.sldGrad.draw(THIS.sliderSize, THIS.height, '#000', '#000');
+
+			// slider border
+			p.sldB.style.display = displaySlider ? 'block' : 'none';
+			p.sldB.style.position = 'absolute';
+			p.sldB.style.right = THIS.padding + 'px';
+			p.sldB.style.top = THIS.padding + 'px';
+			p.sldB.style.border = THIS.insetWidth + 'px solid';
+			p.sldB.style.borderColor = THIS.insetColor;
+
+			// slider mouse area
+			p.sldM._jscInstance = THIS;
+			p.sldM._jscControlName = 'sld';
+			p.sldM.style.display = displaySlider ? 'block' : 'none';
+			p.sldM.style.position = 'absolute';
+			p.sldM.style.right = '0';
+			p.sldM.style.top = '0';
+			p.sldM.style.width = (THIS.sliderSize + padToSliderPadding / 2 + THIS.padding + 2 * THIS.insetWidth) + 'px';
+			p.sldM.style.height = dims[1] + 'px';
+			p.sldM.style.cursor = 'default';
+
+			// slider pointer inner and outer border
+			p.sldPtrIB.style.border =
+			p.sldPtrOB.style.border =
+				THIS.pointerBorderWidth + 'px solid ' + THIS.pointerBorderColor;
+
+			// slider pointer outer border
+			p.sldPtrOB.style.position = 'absolute';
+			p.sldPtrOB.style.left = -(2 * THIS.pointerBorderWidth + THIS.pointerThickness) + 'px';
+			p.sldPtrOB.style.top = '0';
+
+			// slider pointer middle border
+			p.sldPtrMB.style.border = THIS.pointerThickness + 'px solid ' + THIS.pointerColor;
+
+			// slider pointer spacer
+			p.sldPtrS.style.width = THIS.sliderSize + 'px';
+			p.sldPtrS.style.height = sliderPtrSpace + 'px';
+
+			// the Close button
+			function setBtnBorder () {
+				var insetColors = THIS.insetColor.split(/\s+/);
+				var outsetColor = insetColors.length < 2 ? insetColors[0] : insetColors[1] + ' ' + insetColors[0] + ' ' + insetColors[0] + ' ' + insetColors[1];
+				p.btn.style.borderColor = outsetColor;
+			}
+			p.btn.style.display = THIS.closable ? 'block' : 'none';
+			p.btn.style.position = 'absolute';
+			p.btn.style.left = THIS.padding + 'px';
+			p.btn.style.bottom = THIS.padding + 'px';
+			p.btn.style.padding = '0 15px';
+			p.btn.style.height = THIS.buttonHeight + 'px';
+			p.btn.style.border = THIS.insetWidth + 'px solid';
+			setBtnBorder();
+			p.btn.style.color = THIS.buttonColor;
+			p.btn.style.font = '12px sans-serif';
+			p.btn.style.textAlign = 'center';
+			try {
+				p.btn.style.cursor = 'pointer';
+			} catch(eOldIE) {
+				p.btn.style.cursor = 'hand';
+			}
+			p.btn.onmousedown = function () {
+				THIS.hide();
+			};
+			p.btnT.style.lineHeight = THIS.buttonHeight + 'px';
+			p.btnT.innerHTML = '';
+			p.btnT.appendChild(document.createTextNode(THIS.closeText));
+
+			// place pointers
+			redrawPad();
+			redrawSld();
+
+			// If we are changing the owner without first closing the picker,
+			// make sure to first deal with the old owner
+			if (jsc.picker.owner && jsc.picker.owner !== THIS) {
+				jsc.unsetClass(jsc.picker.owner.targetElement, THIS.activeClass);
+			}
+
+			// Set the new picker owner
+			jsc.picker.owner = THIS;
+
+			// The redrawPosition() method needs picker.owner to be set, that's why we call it here,
+			// after setting the owner
+			if (jsc.isElementType(container, 'body')) {
+				jsc.redrawPosition();
+			} else {
+				jsc._drawPosition(THIS, 0, 0, 'relative', false);
+			}
+
+			if (p.wrap.parentNode != container) {
+				container.appendChild(p.wrap);
+			}
+
+			jsc.setClass(THIS.targetElement, THIS.activeClass);
+		}
+
+
+		function redrawPad () {
+			// redraw the pad pointer
+			switch (jsc.getPadYComponent(THIS)) {
+			case 's': var yComponent = 1; break;
+			case 'v': var yComponent = 2; break;
+			}
+			var x = Math.round((THIS.hsv[0] / 360) * (THIS.width - 1));
+			var y = Math.round((1 - THIS.hsv[yComponent] / 100) * (THIS.height - 1));
+			var crossOuterSize = (2 * THIS.pointerBorderWidth + THIS.pointerThickness + 2 * THIS.crossSize);
+			var ofs = -Math.floor(crossOuterSize / 2);
+			jsc.picker.cross.style.left = (x + ofs) + 'px';
+			jsc.picker.cross.style.top = (y + ofs) + 'px';
+
+			// redraw the slider
+			switch (jsc.getSliderComponent(THIS)) {
+			case 's':
+				var rgb1 = HSV_RGB(THIS.hsv[0], 100, THIS.hsv[2]);
+				var rgb2 = HSV_RGB(THIS.hsv[0], 0, THIS.hsv[2]);
+				var color1 = 'rgb(' +
+					Math.round(rgb1[0]) + ',' +
+					Math.round(rgb1[1]) + ',' +
+					Math.round(rgb1[2]) + ')';
+				var color2 = 'rgb(' +
+					Math.round(rgb2[0]) + ',' +
+					Math.round(rgb2[1]) + ',' +
+					Math.round(rgb2[2]) + ')';
+				jsc.picker.sldGrad.draw(THIS.sliderSize, THIS.height, color1, color2);
+				break;
+			case 'v':
+				var rgb = HSV_RGB(THIS.hsv[0], THIS.hsv[1], 100);
+				var color1 = 'rgb(' +
+					Math.round(rgb[0]) + ',' +
+					Math.round(rgb[1]) + ',' +
+					Math.round(rgb[2]) + ')';
+				var color2 = '#000';
+				jsc.picker.sldGrad.draw(THIS.sliderSize, THIS.height, color1, color2);
+				break;
+			}
+		}
+
+
+		function redrawSld () {
+			var sldComponent = jsc.getSliderComponent(THIS);
+			if (sldComponent) {
+				// redraw the slider pointer
+				switch (sldComponent) {
+				case 's': var yComponent = 1; break;
+				case 'v': var yComponent = 2; break;
+				}
+				var y = Math.round((1 - THIS.hsv[yComponent] / 100) * (THIS.height - 1));
+				jsc.picker.sldPtrOB.style.top = (y - (2 * THIS.pointerBorderWidth + THIS.pointerThickness) - Math.floor(sliderPtrSpace / 2)) + 'px';
+			}
+		}
+
+
+		function isPickerOwner () {
+			return jsc.picker && jsc.picker.owner === THIS;
+		}
+
+
+		function blurValue () {
+			THIS.importColor();
+		}
+
+
+		// Find the target element
+		if (typeof targetElement === 'string') {
+			var id = targetElement;
+			var elm = document.getElementById(id);
+			if (elm) {
+				this.targetElement = elm;
+			} else {
+				jsc.warn('Could not find target element with ID \'' + id + '\'');
+			}
+		} else if (targetElement) {
+			this.targetElement = targetElement;
+		} else {
+			jsc.warn('Invalid target element: \'' + targetElement + '\'');
+		}
+
+		if (this.targetElement._jscLinkedInstance) {
+			jsc.warn('Cannot link jscolor twice to the same element. Skipping.');
+			return;
+		}
+		this.targetElement._jscLinkedInstance = this;
+
+		// Find the value element
+		this.valueElement = jsc.fetchElement(this.valueElement);
+		// Find the style element
+		this.styleElement = jsc.fetchElement(this.styleElement);
+
+		var THIS = this;
+		var container =
+			this.container ?
+			jsc.fetchElement(this.container) :
+			document.getElementsByTagName('body')[0];
+		var sliderPtrSpace = 3; // px
+
+		// For BUTTON elements it's important to stop them from sending the form when clicked
+		// (e.g. in Safari)
+		if (jsc.isElementType(this.targetElement, 'button')) {
+			if (this.targetElement.onclick) {
+				var origCallback = this.targetElement.onclick;
+				this.targetElement.onclick = function (evt) {
+					origCallback.call(this, evt);
+					return false;
+				};
+			} else {
+				this.targetElement.onclick = function () { return false; };
+			}
+		}
+
+		/*
+		var elm = this.targetElement;
+		do {
+			// If the target element or one of its offsetParents has fixed position,
+			// then use fixed positioning instead
+			//
+			// Note: In Firefox, getComputedStyle returns null in a hidden iframe,
+			// that's why we need to check if the returned style object is non-empty
+			var currStyle = jsc.getStyle(elm);
+			if (currStyle && currStyle.position.toLowerCase() === 'fixed') {
+				this.fixed = true;
+			}
+
+			if (elm !== this.targetElement) {
+				// attach onParentScroll so that we can recompute the picker position
+				// when one of the offsetParents is scrolled
+				if (!elm._jscEventsAttached) {
+					jsc.attachEvent(elm, 'scroll', jsc.onParentScroll);
+					elm._jscEventsAttached = true;
+				}
+			}
+		} while ((elm = elm.offsetParent) && !jsc.isElementType(elm, 'body'));
+		*/
+
+		// valueElement
+		if (this.valueElement) {
+			if (jsc.isElementType(this.valueElement, 'input')) {
+				var updateField = function () {
+					THIS.fromString(THIS.valueElement.value, jsc.leaveValue);
+					jsc.dispatchFineChange(THIS);
+				};
+				jsc.attachEvent(this.valueElement, 'keyup', updateField);
+				jsc.attachEvent(this.valueElement, 'input', updateField);
+				jsc.attachEvent(this.valueElement, 'blur', blurValue);
+				this.valueElement.setAttribute('autocomplete', 'off');
+			}
+		}
+
+		// styleElement
+		if (this.styleElement) {
+			this.styleElement._jscOrigStyle = {
+				backgroundImage : this.styleElement.style.backgroundImage,
+				backgroundColor : this.styleElement.style.backgroundColor,
+				color : this.styleElement.style.color
+			};
+		}
+
+		if (this.value) {
+			// Try to set the color from the .value option and if unsuccessful,
+			// export the current color
+			this.fromString(this.value) || this.exportColor();
+		} else {
+			this.importColor();
+		}
+	}
+
+};
+
+
+//================================
+// Public properties and methods
+//================================
+
+
+// By default, search for all elements with class="jscolor" and install a color picker on them.
+//
+// You can change what class name will be looked for by setting the property jscolor.lookupClass
+// anywhere in your HTML document. To completely disable the automatic lookup, set it to null.
+//
+jsc.jscolor.lookupClass = 'jscolor';
+
+
+jsc.jscolor.installByClassName = function (className) {
+	var inputElms = document.getElementsByTagName('input');
+	var buttonElms = document.getElementsByTagName('button');
+
+	jsc.tryInstallOnElements(inputElms, className);
+	jsc.tryInstallOnElements(buttonElms, className);
+};
+
+
+jsc.register();
+
+
+return jsc.jscolor;
+
+
+})(); }
diff --git a/packages/rocketchat-theme/package.js b/packages/rocketchat-theme/package.js
index 594e04f00f3b2ce866072c4b5e7531724bc8ac2d..7bd0066eb036b8073196c6c7e5696b6f54b36df5 100644
--- a/packages/rocketchat-theme/package.js
+++ b/packages/rocketchat-theme/package.js
@@ -11,33 +11,33 @@ Package.onUse(function(api) {
 	api.use('rocketchat:assets');
 	api.use('coffeescript');
 	api.use('ecmascript');
+	api.use('less');
 	api.use('underscore');
 	api.use('webapp');
 	api.use('webapp-hashing');
-
 	api.use('templating', 'client');
 
-
+	// Server side files
 	api.addFiles('server/server.coffee', 'server');
 	api.addFiles('server/variables.coffee', 'server');
 
-	api.addFiles('client/minicolors/jquery.minicolors.css', 'client');
-	api.addFiles('client/minicolors/jquery.minicolors.js', 'client');
+	// Colorpicker
+	api.addFiles('client/vendor/jscolor.js', 'client');
+
+	// Fontello
+	api.addFiles('client/vendor/fontello/css/fontello.css', 'client');
+	api.addAssets('client/vendor/fontello/font/fontello.eot', 'client');
+	api.addAssets('client/vendor/fontello/font/fontello.svg', 'client');
+	api.addAssets('client/vendor/fontello/font/fontello.ttf', 'client');
+	api.addAssets('client/vendor/fontello/font/fontello.woff', 'client');
+	api.addAssets('client/vendor/fontello/font/fontello.woff2', 'client');
 
+	// Compiled stylesheets
+	api.addFiles('client/main.less', 'client');
 
-	api.addAssets('assets/stylesheets/global/_variables.less', 'server');
-	api.addAssets('assets/stylesheets/utils/_mixins.import.less', 'server');
-	api.addAssets('assets/stylesheets/utils/_colors.import.less', 'server');
-	api.addAssets('assets/stylesheets/utils/_keyframes.import.less', 'server');
-	api.addAssets('assets/stylesheets/utils/_lesshat.import.less', 'server');
-	api.addAssets('assets/stylesheets/utils/_preloader.import.less', 'server');
-	api.addAssets('assets/stylesheets/utils/_reset.import.less', 'server');
-	api.addAssets('assets/stylesheets/utils/_chatops.less', 'server');
-	api.addAssets('assets/stylesheets/animation.css', 'server');
-	api.addAssets('assets/stylesheets/base.less', 'server');
-	api.addAssets('assets/stylesheets/fontello.css', 'server');
-	api.addAssets('assets/stylesheets/rtl.less', 'server');
-	api.addAssets('assets/stylesheets/swipebox.min.css', 'server');
+	// Run-time stylesheets
+	api.addAssets('server/lesshat.less', 'server');
+	api.addAssets('server/colors.less', 'server');
 });
 
 Npm.depends({
diff --git a/packages/rocketchat-theme/server/colors.less b/packages/rocketchat-theme/server/colors.less
new file mode 100755
index 0000000000000000000000000000000000000000..737a4c432849bb87c0c2fb066d1b6a65aefd6c27
--- /dev/null
+++ b/packages/rocketchat-theme/server/colors.less
@@ -0,0 +1,776 @@
+/** ----------------------------------------------------------------------------
+ * Derivative colours (fixed variants of inherited variables)
+ */
+@default-action-color: darken(@secondary-background-color, 15%);
+@default-action-contrast: contrast(@default-action-color, #444444);
+@primary-background-contrast: contrast(@primary-background-color, #444444);
+@primary-action-contrast: contrast(@primary-action-color, #444444);
+@secondary-background-contrast: contrast(@secondary-background-color, #444444);
+@secondary-action-contrast: contrast(@secondary-action-color, #444444);
+@selection-background: lighten(@selection-color, 30%);
+@success-background: lighten(@success-color, 45%);
+@success-border: lighten(@success-color, 30%);
+@error-background: lighten(@error-color, 45%);
+@error-border: lighten(@error-color, 30%);
+@error-contrast: contrast(@error-color);
+@pending-background: lighten(@pending-color, 45%);
+@pending-border: lighten(@pending-color, 30%);
+
+/** ----------------------------------------------------------------------------
+ * Transparency variables
+ */
+
+@transparent-darkest: rgba(0, 0, 0, 0.5);
+@transparent-darker: rgba(0, 0, 0, 0.15);
+@transparent-dark: rgba(0, 0, 0, 0.05);
+@transparent-light: rgba(255, 255, 255, 0.1);
+@transparent-lighter: rgba(255, 255, 255, 0.3);
+@transparent-lightest: rgba(255, 255, 255, 0.6);
+
+/** ----------------------------------------------------------------------------
+ * Classes for variables
+ */
+
+// Major colors
+
+.content-background-color {
+	background-color: @content-background-color;
+}
+
+.color-content-background-color {
+	color: @content-background-color;
+}
+
+.primary-background-color {
+	background-color: @primary-background-color;
+}
+
+.global-font-family {
+	font-family: @body-font-family;
+}
+
+.color-primary-font-color {
+	color: @primary-font-color;
+}
+
+.color-primary-action-color {
+	color: @primary-action-color;
+}
+
+.background-primary-action-color {
+	background-color: @primary-action-color;
+}
+
+.secondary-background-color {
+	background-color: @secondary-background-color;
+}
+
+.border-secondary-background-color {
+	border-color: @secondary-background-color;
+}
+
+.secondary-font-color {
+	color: @secondary-font-color;
+}
+
+.border-component-color {
+	border-color: @component-color;
+}
+
+.background-component-color {
+	background-color: @component-color;
+}
+
+.success-color {
+	color: @success-color;
+}
+
+.pending-color {
+	color: @pending-color;
+}
+
+.pending-background {
+	background-color: @pending-background;
+}
+
+.pending-border {
+	border-color: @pending-border;
+}
+
+.error-color {
+	color: @error-color;
+}
+
+.background-error-color {
+	background-color: @error-color;
+}
+
+.color-info-font-color {
+	color: @info-font-color;
+}
+
+.background-info-font-color {
+	background-color: @info-font-color;
+}
+
+.background-attention-color {
+	background-color: @attention-color;
+}
+
+// Minor Colors
+
+.tertiary-background-color {
+	background-color: @tertiary-background-color;
+}
+
+.border-tertiary-background-color {
+	border-color: @tertiary-background-color;
+}
+
+// Derivative Colors
+
+.color-tertiary-font-color {
+	color: @tertiary-font-color;
+}
+
+.error-background {
+	background-color: @error-background;
+}
+
+.error-border {
+	border-color: @error-border;
+}
+
+.color-error-contrast {
+	color: @error-contrast;
+}
+
+// transparent
+
+.background-transparent-darkest {
+	background-color: @transparent-darkest;
+}
+
+.background-transparent-darker {
+	background-color: @transparent-darker;
+}
+
+.background-transparent-darker-hover:hover {
+	background-color: @transparent-darker;
+}
+
+.background-transparent-darker-before::before {
+	background-color: @transparent-darker;
+}
+
+.background-transparent-dark {
+	background-color: @transparent-dark;
+}
+
+.background-transparent-dark-hover:hover {
+	background-color: @transparent-dark;
+}
+
+.border-transparent-dark {
+	border-color: @transparent-dark;
+}
+
+.background-transparent-light {
+	background-color: @transparent-light;
+}
+
+.background-transparent-lightest {
+	background-color: @transparent-lightest;
+}
+
+// Derivative Colors
+.color-primary-action-contrast {
+	color: @primary-action-contrast;
+}
+
+/** ----------------------------------------------------------------------------
+ * Special components
+ */
+
+* {
+	-webkit-overflow-scrolling: touch;
+
+	&::-webkit-scrollbar {
+		height: 8px;
+		width: 8px;
+		background: @transparent-dark;
+	}
+
+	&::-webkit-scrollbar-thumb {
+		background-color: @custom-scrollbar-color;
+		-webkit-border-radius: 50px;
+	}
+
+	&::-webkit-scrollbar-corner {
+		background-color: @transparent-dark;
+	}
+}
+
+.filter-item {
+	&:hover {
+		border-color: @info-font-color;
+	}
+
+	&.active {
+		border-color: @primary-background-color;
+	}
+}
+
+/** ----------------------------------------------------------------------------
+ * Document components
+ */
+
+.page-container {
+	tr:hover td {
+		background-color: @content-background-color;
+	}
+}
+
+.burger i {
+	background-color: @primary-font-color;
+}
+
+/** ----------------------------------------------------------------------------
+ * Forms
+ */
+
+.input-shade(@primary-font-color, @content-background-color);
+
+.flex-nav {
+	.input-shade(@primary-background-contrast, @primary-background-color);
+
+	input {
+		&:focus {
+			border-color: fade(@primary-background-contrast, 50%);
+		}
+	}
+
+	.input.checkbox.toggle {
+		input:checked + label::before {
+			background-color: @primary-action-color;
+		}
+	}
+}
+
+.input-line {
+	&.setting-changed > label {
+		color: @selection-color;
+	}
+}
+
+input:-webkit-autofill {
+	color: @primary-font-color !important;
+	background-color: transparent !important;
+}
+
+.input {
+	&.radio {
+		label {
+			&::before {
+				border-color: lighten(@secondary-background-contrast, 30%);
+				background-color: @content-background-color;
+			}
+
+			&::after {
+				background-color: @secondary-background-contrast;
+			}
+		}
+	}
+
+	&.checkbox.toggle {
+		input:checked + label::before {
+			background-color: @secondary-background-contrast;
+		}
+
+		input:disabled + label::before {
+			background-color: lighten(@secondary-background-contrast, 50%) !important;
+		}
+
+		label {
+			&::before {
+				background-color: lighten(@secondary-background-contrast, 30%);
+			}
+
+			&::after {
+				background-color: @content-background-color;
+			}
+
+			&:hover {
+				&::before {
+					background-color: lighten(@secondary-background-contrast, 20%);
+				}
+			}
+		}
+	}
+}
+
+/** ----------------------------------------------------------------------------
+ * Misc typography variants
+ */
+
+a:active,
+a:hover {
+	color: @primary-action-color;
+}
+
+.message,
+.flex-tab {
+	a i,
+	a[class^="icon-"] {
+		color: @primary-font-color;
+
+		&:hover {
+			color: darken(@primary-font-color, 10%);
+		}
+	}
+}
+
+.error {
+	border-color: @error-color;
+}
+
+/** ----------------------------------------------------------------------------
+ * Admin and settings styles
+ */
+
+.page-list,
+.page-settings {
+	a {
+		color: @primary-font-color;
+
+		&:hover {
+			color: @primary-action-color;
+		}
+	}
+}
+
+.admin-table-row {
+	background-color: @transparent-light;
+
+	&:nth-of-type(even) {
+		background-color: @transparent-lightest;
+	}
+}
+
+.new-logs {
+	background: @primary-action-contrast;
+}
+
+.avatar-suggestion-item {
+	.question-mark::before {
+		color: @secondary-font-color;
+	}
+}
+
+/** ----------------------------------------------------------------------------
+ * Asides (external to main application views)
+ */
+
+.full-page,
+.page-loading {
+	.gradient(shade(@primary-background-color), @primary-background-color);
+
+	a {
+		color: @tertiary-font-color;
+	}
+
+	a:hover {
+		color: @primary-background-contrast;
+	}
+}
+
+#login-card {
+	.input-shade(@primary-font-color, @content-background-color);
+
+	.input-text {
+		input:-webkit-autofill {
+			-webkit-box-shadow: 0 0 0 20px @content-background-color inset;
+		}
+	}
+}
+
+/** ----------------------------------------------------------------------------
+ * Room components
+ */
+
+.toggle-favorite {
+	color: @component-color;
+}
+
+.upload-progress-progress {
+	background-color: @success-background;
+}
+
+.messages-container {
+	.edit-room-title {
+		.linkColors(@secondary-font-color, @primary-font-color);
+	}
+
+	.footer {
+		background: @content-background-color;
+	}
+}
+
+.message-form {
+	.message-buttons {
+		.buttonColors(lighten(@primary-font-color, 25%), @secondary-background-color);
+
+		&:hover {
+			background-color: mix(@secondary-background-color, contrast(@primary-font-color), 20%);
+		}
+	}
+
+	.message-form-text {
+		&.editing {
+			background-color: lighten(@pending-color, 40%);
+		}
+	}
+}
+
+.popup-item {
+	&.selected {
+		color: @primary-action-contrast;
+		background-color: @primary-action-color;
+	}
+}
+
+.messages-box {
+	&.selectable .selected {
+		background-color: @selection-background;
+	}
+
+	// .editing .body,
+	// textarea.editing {
+	// 	background-color: lighten(@pending-color, 40%);
+	// }
+}
+
+/** ----------------------------------------------------------------------------
+ * Message content
+ */
+.first-unread {
+	.body {
+		&::before {
+			background: @transparent-darker;
+		}
+
+		&::after {
+			color: @primary-font-color;
+		}
+	}
+}
+
+.first-unread-opaque {
+	.body {
+		&::before {
+			background: @transparent-dark;
+		}
+	}
+}
+
+.message {
+	&.new-day::before {
+		background-color: @content-background-color;
+	}
+
+	&.new-day::after {
+		border-color: @component-color;
+	}
+
+	.message-dropdown,
+	.options-menu {
+		color: lighten(@primary-font-color, 13%);
+
+		ul li:hover {
+			background-color: @tertiary-background-color;
+		}
+	}
+
+	.is-bot,
+	.role-tag {
+		color: contrast(@info-font-color);
+	}
+
+	a {
+		.linkColors(@link-font-color, darken(@link-font-color, 10%));
+	}
+
+	.mention-link {
+		&.mention-link-me {
+			color: @primary-action-contrast;
+		}
+
+		&.mention-link-all {
+			color: @primary-action-contrast;
+		}
+	}
+
+	.highlight-text {
+		background-color: @selection-background;
+	}
+}
+
+/** ----------------------------------------------------------------------------
+ * Side nav
+ */
+.side-nav {
+	a,
+	.info {
+		.linkColors(@tertiary-font-color, @tertiary-font-color);
+	}
+
+	.arrow::before,
+	.arrow::after {
+		background-color: @tertiary-font-color;
+	}
+
+	.rooms-list {
+		background-color: lighten(@primary-background-color, 2.5%);
+	}
+
+	li.active {
+		background-color: @transparent-light !important;
+	}
+
+	i.status-offline {
+		color: @transparent-lighter !important;
+	}
+
+	i {
+		color: @transparent-lighter;
+	}
+
+	.opt i:hover {
+		color: @transparent-lightest;
+	}
+
+	.has-alert .name {
+		color: @primary-background-contrast;
+	}
+
+	.unread {
+		background-color: @success-color;
+		color: contrast(@success-color, #000000, #ffffff, 50%);
+	}
+
+	.button {
+		.buttonColors(@tertiary-font-color, mix(@primary-action-color, @primary-background-color));
+	}
+
+	.options button {
+		.buttonColors(@tertiary-font-color, @primary-background-color);
+	}
+}
+
+/** ----------------------------------------------------------------------------
+ * Flex tabs / admin fly-out panels
+ */
+.flex-tab {
+	input,
+	select,
+	textarea {
+		&:focus {
+			border-color: lighten(@secondary-background-contrast, 30%);
+		}
+	}
+
+	.content,
+	.user-view,
+	.list-view {
+		background-color: @secondary-background-color;
+	}
+
+	.message {
+		&.new-day::before {
+			background-color: @secondary-background-color;
+		}
+	}
+
+	.channel-settings {
+		.buttons {
+			.button {
+				.buttonColors(lighten(@primary-font-color, 25%), @secondary-background-color);
+			}
+		}
+
+		.button.edit {
+			.buttonColors(lighten(@primary-font-color, 25%), @secondary-background-color);
+		}
+
+		.input.checkbox.toggle {
+			input:checked + label::before {
+				background-color: @primary-background-color;
+			}
+		}
+	}
+}
+
+.flex-tab-bar {
+	.tab-button {
+		&:hover {
+			background-color: @secondary-background-color;
+		}
+
+		&.active {
+			background-color: @secondary-background-color;
+			border-right-color: @selection-color;
+		}
+
+		&.attention {
+			.blink(@selection-color);
+		}
+	}
+
+	.counter {
+		background: @secondary-font-color;
+		color: white;
+	}
+}
+
+/** ----------------------------------------------------------------------------
+ * User status / user meta
+ */
+i.status-online {
+	color: @status-online;
+}
+
+.account-box .status-online .thumb::after,
+.account-box .status.online::after,
+.popup-user-status-online,
+.status-online::after,
+.user-image.status-online .avatar::after {
+	background-color: @status-online;
+	border-color: darken(@status-online, 10%);
+}
+
+.account-box .status-offline .thumb::after,
+.account-box .status.offline::after {
+	background-color: @transparent-lighter;
+}
+
+i.status-away {
+	color: @status-away;
+}
+
+.account-box .status-away .thumb::after,
+.account-box .status.away::after,
+.popup-user-status-away,
+.status-pending::after,
+.user-image.status-away .avatar::after {
+	background-color: @status-away;
+	border-color: darken(@status-away, 10%);
+}
+
+i.status-busy {
+	color: @status-busy;
+}
+
+.account-box .status-busy .thumb::after,
+.account-box .status.busy::after,
+.popup-user-status-busy,
+.status-busy::after,
+.user-image.status-busy .avatar::after {
+	background-color: @status-busy;
+	border-color: darken(@status-busy, 10%);
+}
+
+i.status-offline {
+	color: @status-offline;
+}
+
+.popup-user-status-offline,
+.status-offline::after,
+.user-image.status-offline .avatar::after {
+	background-color: @status-offline;
+	border-color: darken(@status-offline, 10%);
+}
+
+// .popup-user-status-system {
+// 	border-color: transparent;
+// }
+
+// .user-view {
+// 	.box::after,
+// 	.stats li,
+// 	.tags li {
+// 		background-color: @component-color;
+// 	}
+// }
+
+/** ----------------------------------------------------------------------------
+ * Buttons!
+ */
+.actionLinks li .action-link {
+	.buttonColors(@primary-action-contrast, @primary-action-color);
+}
+
+// new layout buttons
+
+.button {
+	.buttonColors(@default-action-contrast, @default-action-color);
+
+	&.primary {
+		.buttonColors(@primary-action-contrast, @primary-action-color);
+
+		&[disabled] {
+			background-color: lighten(desaturate(@primary-action-color, 50%), 30%);
+		}
+	}
+
+	&.secondary {
+		.buttonColors(@secondary-action-contrast, @secondary-action-color);
+
+		&[disabled] {
+			background-color: lighten(desaturate(@secondary-action-color, 50%), 30%);
+		}
+	}
+
+	&.tertiary {
+		.buttonColors(@primary-action-contrast, @selection-color);
+
+		&[disabled] {
+			background-color: lighten(desaturate(@selection-color, 50%), 30%);
+		}
+	}
+
+	&.danger {
+		.buttonColors(@error-contrast, @error-color);
+
+		&[disabled] {
+			background-color: lighten(desaturate(@error-color, 50%), 30%);
+		}
+	}
+}
+
+/** ----------------------------------------------------------------------------
+ * Feedback and overlay content
+ */
+
+.alert-warning {
+	color: darken(@pending-color, 25%);
+	background-color: @pending-background;
+}
+
+.alert-link {
+	.linkColors(@link-font-color, darken(@link-font-color, 10%));
+}
+
+label.required::after {
+	color: @error-color;
+}
+
+/** ----------------------------------------------------------------------------
+ * Loading
+ */
+
+.main-content,
+.flex-tab {
+	.loading-animation > div {
+		background-color: @primary-font-color;
+	}
+}
diff --git a/packages/rocketchat-theme/server/lesshat.less b/packages/rocketchat-theme/server/lesshat.less
new file mode 100644
index 0000000000000000000000000000000000000000..cf7cf4758d6f9deee5601a25c46ae3ab82b2e38f
--- /dev/null
+++ b/packages/rocketchat-theme/server/lesshat.less
@@ -0,0 +1,101 @@
+.calc(...) {
+	@process: ~`(function(a){function c(c,t){var r=");\n",s=e.split(","),l=s[0]+":"+c+"("+(s[1].trim()||0)+r;"start"==t?a="0;\n"+l:a+=l}a=a||8121991;var t="@{state}",e=a;if(8121991==a)return a;switch(t){case"1":c("-webkit-calc","start"),c("-moz-calc"),c("calc");break;case"2":c("-webkit-calc","start"),c("-moz-calc");break;case"3":c("-webkit-calc","start"),c("calc");break;case"4":c("-webkit-calc","start");break;case"5":c("-moz-calc","start"),c("calc");break;case"6":c("-moz-calc","start");break;case"7":c("calc","start")}return a=a.replace(/;$/g,"")})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
+	@state: 1; -lh-property: @process;
+}
+
+.transform(...) {
+	@process: ~`(function(e){e=e||"none";var r={translate:"px",rotate:"deg",rotate3d:"deg",skew:"deg"};/^\w*\(?[a-z0-9.]*\)?/.test(e)&&(e=e.replace(/(?:,)(?![^(]*\))/g,""));for(var t in r)e.indexOf(t)>=0&&(e=e.replace(new RegExp(t+"[\\w]?\\([a-z0-9, %]*\\)"),function(e){var n=/(\d+\.?\d*)(?!\w|%)/g;return"rotate3d"==t&&(n=/,\s*\d+$/),e.replace(n,function(e){return e+r[t]})}));return e})((function(){var r="@{arguments}";return r=r.replace(/^\[|\]$/g,"")})())`;
+	-webkit-transform: @process;
+	-moz-transform: @process;
+	-ms-transform: @process;
+	-o-transform: @process;
+	transform: @process;
+}
+
+.gradient(@startColor: #eee, @endColor: white) {
+	background: linear-gradient(to top, @startColor, @endColor);
+}
+
+.input-shade(@color, @bg) {
+	input,
+	select,
+	textarea {
+		color: @color;
+		background-color: transparent;
+		border-color: mix(contrast(@bg), @bg, 10%);
+		border-style: solid;
+
+		&::placeholder {
+			color: mix(@color, @bg, 75%);
+		}
+
+		&[disabled] {
+			background-color: mix(contrast(@bg), @bg, 10%);
+		}
+	}
+
+	.diabled label,
+	[disabled] label {
+		color: mix(@color, @bg, 75%);
+	}
+
+	.-autocomplete-container {
+		background-color: mix(contrast(@bg), @bg, 10%);
+	}
+
+	.-autocomplete-item.selected {
+		background-color: mix(contrast(@bg), @bg, 20%);
+	}
+
+	input[type="button"],
+	input[type="submit"] {
+		color: @color;
+		background: mix(contrast(@bg), @bg, 10%);
+		border-color: mix(contrast(@bg), @bg, 10%);
+	}
+}
+
+.blink(@color) {
+	animation-duration: 1000ms;
+	animation-name: blink;
+	animation-iteration-count: infinite;
+	animation-direction: alternate;
+
+	@keyframes blink {
+		from {
+			color: @color;
+		}
+
+		to {
+			opacity: inherit;
+		}
+	}
+
+	@-webkit-keyframes blink {
+		from {
+			color: @color;
+		}
+
+		to {
+			color: inherit;
+		}
+	}
+}
+
+.linkColors(@color, @hover) {
+	color: @color;
+
+	&:hover {
+		color: @hover;
+	}
+}
+
+.buttonColors(@color, @bg) {
+	color: @color;
+	background-color: @bg;
+
+	&:hover {
+		color: mix(@color, contrast(@bg), 60%);
+		background-color: mix(@bg, contrast(@color), 60%);
+	}
+}
diff --git a/packages/rocketchat-theme/server/server.coffee b/packages/rocketchat-theme/server/server.coffee
index b36ade8333a2e5d0da056ec0ebf920a04e067273..44c76c3c3317aedf6103d49d64b80280672d5744 100644
--- a/packages/rocketchat-theme/server/server.coffee
+++ b/packages/rocketchat-theme/server/server.coffee
@@ -47,19 +47,8 @@ RocketChat.theme = new class
 	variables: {}
 	packageCallbacks: []
 	files: [
-		'assets/stylesheets/global/_variables.less'
-		'assets/stylesheets/utils/_keyframes.import.less'
-		'assets/stylesheets/utils/_lesshat.import.less'
-		'assets/stylesheets/utils/_preloader.import.less'
-		'assets/stylesheets/utils/_reset.import.less'
-		'assets/stylesheets/utils/_chatops.less'
-		'assets/stylesheets/animation.css'
-		'assets/stylesheets/base.less'
-		'assets/stylesheets/fontello.css'
-		'assets/stylesheets/rtl.less'
-		'assets/stylesheets/swipebox.min.css'
-		'assets/stylesheets/utils/_mixins.import.less'
-		'assets/stylesheets/utils/_colors.import.less'
+		'server/lesshat.less'
+		'server/colors.less'
 	]
 
 	constructor: ->
diff --git a/packages/rocketchat-theme/server/variables.coffee b/packages/rocketchat-theme/server/variables.coffee
index 75631d4044bab581ed088fe3909580f2831ead62..2608955bfd1be505f9271349713a69805baa143d 100755
--- a/packages/rocketchat-theme/server/variables.coffee
+++ b/packages/rocketchat-theme/server/variables.coffee
@@ -9,10 +9,12 @@
 # New colors, used for shades on solid backgrounds
 # Defined range of transparencies reduces random colour variances
 alphaColors=
+  'transparent-darkest': 'rgba(0,0,0,0.5)'
   'transparent-darker': 'rgba(0,0,0,0.15)'
-  'transparent-dark': 'rgba(0,0,0,0.03)'
-  'transparent-light': 'rgba(255,255,255,0.60)'
-  'transparent-lighter': 'rgba(255,255,255,0.25)'
+  'transparent-dark': 'rgba(0,0,0,0.05)'
+  'transparent-light': 'rgba(255,255,255,0.10)'
+  'transparent-lighter': 'rgba(255,255,255,0.30)'
+  'transparent-lightest': 'rgba(255,255,255,0.60)'
 
 # Major colors form the core of the scheme
 # Names changed to reflect usage, comments show pre-refactor names
@@ -23,20 +25,21 @@ majorColors=
   'primary-action-color': '#13679A' # was action-buttons-color
   'secondary-background-color': '#F4F4F4'
   'secondary-font-color': '#A0A0A0'
-  'secondary-action-color': '#E5E5E5'
+  'secondary-action-color': '#DDDDDD'
   'component-color': '#EAEAEA'
   'success-color': '#1DCE73'
   'pending-color': '#FCB316'
   'error-color': '#BC2031'
-  'selection-color': '#02ACEC'
+  'selection-color': '#02ACEC',
+  'attention-color': '#9C27B0'
 
 # Minor colours implement major colours by default, but can be overruled
 minorColors=
   'tertiary-background-color': '@component-color'
-  'tertiary-font-color': '@transparent-light'
+  'tertiary-font-color': '@transparent-lightest'
   'link-font-color': '@primary-action-color'
   'info-font-color': '@secondary-font-color'
-  'custom-scrollbar-color': '@transparent-dark'
+  'custom-scrollbar-color': '@transparent-darker'
   'status-online': '@success-color'
   'status-away': '@pending-color'
   'status-busy': '@error-color'
@@ -45,8 +48,6 @@ minorColors=
 # Bulk-add settings for color scheme
 for key, value of majorColors
   RocketChat.theme.addPublicColor key, value, 'Colors'
-for key, value of alphaColors
-  RocketChat.theme.addPublicColor key, value, 'Colors (alphas)'
 for key, value of minorColors
   RocketChat.theme.addPublicColor key, value, 'Colors (minor)', 'expression'
 
diff --git a/packages/rocketchat-tooltip/loadStylesheet.js b/packages/rocketchat-tooltip/loadStylesheet.js
deleted file mode 100644
index 7cda63dac9501e4e7896999d9963942c72cecdeb..0000000000000000000000000000000000000000
--- a/packages/rocketchat-tooltip/loadStylesheet.js
+++ /dev/null
@@ -1,3 +0,0 @@
-RocketChat.theme.addPackageAsset(function() {
-	return Assets.getText('tooltip.less');
-});
diff --git a/packages/rocketchat-tooltip/package.js b/packages/rocketchat-tooltip/package.js
index 747c6da6b7638c204c5dc2a4198c60f562c865c4..857ebbde68a4dc63532c97ef79f807276a6ebabb 100644
--- a/packages/rocketchat-tooltip/package.js
+++ b/packages/rocketchat-tooltip/package.js
@@ -12,9 +12,9 @@ Package.onUse(function(api) {
 	api.use('rocketchat:lib');
 	api.use('rocketchat:theme');
 	api.use('rocketchat:ui-master');
+	api.use('less');
 
-	api.addAssets('tooltip.less', 'server');
-	api.addFiles('loadStylesheet.js', 'server');
+	api.addFiles('tooltip.less', 'client');
 
 	api.addFiles('rocketchat-tooltip.html', 'client');
 	api.addFiles('rocketchat-tooltip.js', 'client');
diff --git a/packages/rocketchat-tooltip/tooltip.less b/packages/rocketchat-tooltip/tooltip.less
index 9be601d13553002b26e108b8098c43ece191e596..e79d9a547abd373c3685b3c16a04deccd769a897 100644
--- a/packages/rocketchat-tooltip/tooltip.less
+++ b/packages/rocketchat-tooltip/tooltip.less
@@ -10,8 +10,7 @@
 	opacity: 0;
 	max-width: 400px;
 	text-align: center;
-
-	.transition(opacity 0.3s ease);
+	transition: opacity 0.3s ease;
 
 	&.show {
 		visibility: visible;
@@ -34,7 +33,7 @@
 		.tooltip-arrow {
 			top: -5px;
 			border-top: none;
-			border-bottom: 5px solid #000;
+			border-bottom: 5px solid #000000;
 		}
 	}
 }
diff --git a/packages/rocketchat-ui-account/account/account.html b/packages/rocketchat-ui-account/account/account.html
index c7b4d54829bdb7964eac9aca8e45ed501223a56e..537dbcdf8dc2f142935416f634e36815927dc2ef 100644
--- a/packages/rocketchat-ui-account/account/account.html
+++ b/packages/rocketchat-ui-account/account/account.html
@@ -1,6 +1,6 @@
 <template name="account">
 	<section class="page-container page-home page-static">
-		<header class="fixed-title">
+		<header class="fixed-title border-component-color">
 			{{> burger}}
 			<h2>
 				<span class="room-title">{{_ "User_Settings"}}</span>
diff --git a/packages/rocketchat-ui-account/account/accountFlex.html b/packages/rocketchat-ui-account/account/accountFlex.html
index 759372dd0a766e3e7ca1e34e218c79bd321c5d4d..6c3e46ddcd6fdf139b7ffe968edbb215ccdf549e 100644
--- a/packages/rocketchat-ui-account/account/accountFlex.html
+++ b/packages/rocketchat-ui-account/account/accountFlex.html
@@ -9,13 +9,16 @@
 			<ul>
 				<li>
 					<a href="{{pathFor 'account' group='preferences'}}" class="account-link">{{_ "Preferences"}}</a>
+				</li>
+				<li>
 					{{#if allowUserProfileChange}}
 						<a href="{{pathFor 'account' group='profile'}}" class="account-link">{{_ "Profile"}}</a>
 					{{/if}}
+				</li>
+				<li>
 					{{#if allowUserAvatarChange}}
 						<a href="{{pathFor 'changeAvatar'}}" class="account-link">{{_ "Avatar"}}</a>
 					{{/if}}
-					{{!-- move this to profile --}}
 				</li>
 			</ul>
 		</div>
diff --git a/packages/rocketchat-ui-account/account/accountPreferences.html b/packages/rocketchat-ui-account/account/accountPreferences.html
index f45a8c40cd4e9d9b4e6af72f194b3ff0aa0a9b58..13d9f8c86b9b5b5e1292b9f51985c109db03a7b8 100644
--- a/packages/rocketchat-ui-account/account/accountPreferences.html
+++ b/packages/rocketchat-ui-account/account/accountPreferences.html
@@ -1,6 +1,6 @@
 <template name="accountPreferences">
 	<section class="page-container page-home page-static">
-		<header class="fixed-title">
+		<header class="fixed-title border-component-color">
 			{{> burger}}
 			<h2>
 				<span class="room-title">{{_ "Preferences"}}</span>
@@ -11,7 +11,7 @@
 				<fieldset>
 					<div class="section">
 						<h1>{{_ "Localization"}}</h1>
-						<div class="section-content">
+						<div class="section-content border-component-color">
 							<div class="input-line">
 								<label for="language">{{_ "Language"}}</label>
 								<div>
@@ -26,18 +26,18 @@
 					</div>
 					<div class="section">
 						<h1>{{_ "Messages"}}</h1>
-						<div class="section-content">
+						<div class="section-content border-component-color">
 							<div class="input-line double-col">
 								<label>{{_ "Desktop_Notifications"}}</label>
 								<div>
 									{{#if desktopNotificationEnabled}}
 										<label>{{_ "Desktop_Notifications_Enabled"}}</label>
-										<label><button class="button test-notifications"><i class="icon-comment-empty"></i> <span>{{_ "Test_Desktop_Notifications"}}</span></button></label>
+										<label><button class="button test-notifications"><i class="icon-comment-empty secondary-font-color"></i> <span>{{_ "Test_Desktop_Notifications"}}</span></button></label>
 									{{else}}
 										{{#if desktopNotificationDisabled}}
 											<label>{{_ "Desktop_Notifications_Disabled"}}</label>
 										{{else}}
-											<label><button class="button enable-notifications"><i class="icon-comment-empty"></i> <span>{{_ "Enable_Desktop_Notifications"}}</span></button></label>
+											<label><button class="button enable-notifications"><i class="icon-comment-empty secondary-font-color"></i> <span>{{_ "Enable_Desktop_Notifications"}}</span></button></label>
 										{{/if}}
 									{{/if}}
 								</div>
@@ -155,7 +155,7 @@
 					</div>
 					<div class="section">
 						<h1>{{_ "Highlights"}}</h1>
-						<div class="section-content">
+						<div class="section-content border-component-color">
 							<div class="input-line double-col">
 								<label>{{_ "Highlights_List"}}</label>
 								<div>
@@ -167,7 +167,7 @@
 					</div>
 					<div class="section">
 						<h1>{{_ "Sound"}}</h1>
-						<div class="section-content">
+						<div class="section-content border-component-color">
 							<div class="input-line double-col">
 								<label>{{_ "New_Room_Notification"}}</label>
 								<div>
diff --git a/packages/rocketchat-ui-account/account/accountProfile.coffee b/packages/rocketchat-ui-account/account/accountProfile.coffee
index 3f191d2b811860165c1a5cf570bd3a03b48b75d2..ec9df5f8fe82b12d2f1371b4b304d35f66256edd 100644
--- a/packages/rocketchat-ui-account/account/accountProfile.coffee
+++ b/packages/rocketchat-ui-account/account/accountProfile.coffee
@@ -30,6 +30,9 @@ Template.accountProfile.helpers
 	passwordChangeDisabled: ->
 		return t('Password_Change_Disabled')
 
+	customFields: ->
+		return Meteor.user().customFields
+
 Template.accountProfile.onCreated ->
 	settingsTemplate = this.parentTemplate(3)
 	settingsTemplate.child ?= []
@@ -79,7 +82,11 @@ Template.accountProfile.onCreated ->
 			else
 				data.email = _.trim $('#email').val()
 
-		Meteor.call 'saveUserProfile', data, (error, results) ->
+		customFields = {}
+		$('[data-customfield=true]').each () ->
+			customFields[this.name] = $(this).val() or ''
+
+		Meteor.call 'saveUserProfile', data, customFields, (error, results) ->
 			if results
 				toastr.remove();
 				toastr.success t('Profile_saved_successfully')
diff --git a/packages/rocketchat-ui-account/account/accountProfile.html b/packages/rocketchat-ui-account/account/accountProfile.html
index 77fc7d16491f00ad4f1135bb27ab7d1bdc96d5aa..2d67e2cfba7bf692c58c3e58d1155005eb8ad954 100644
--- a/packages/rocketchat-ui-account/account/accountProfile.html
+++ b/packages/rocketchat-ui-account/account/accountProfile.html
@@ -1,6 +1,6 @@
 <template name="accountProfile">
 	<section class="page-container page-home page-static">
-		<header class="fixed-title">
+		<header class="fixed-title border-component-color">
 			{{> burger}}
 			<h2>
 				<span class="room-title">{{_ "Profile"}}</span>
@@ -30,7 +30,7 @@
 						<div>
 						{{#if emailVerified}}
 							<div class="right">
-								<i class="icon-ok" title="{{_ "Email_verified" }}"></i>
+								<i class="icon-ok success-color" title="{{_ "Email_verified" }}"></i>
 							</div>
 						{{/if}}
 						{{#if allowEmailChange}}
@@ -56,6 +56,9 @@
 						</div>
 					</div>
 				</fieldset>
+				<fieldset>
+					{{> customFieldsForm hideFromForm=false formData=customFields}}
+				</fieldset>
 				<div class="submit">
 					<button class="button primary send"><i class="icon-send"></i><span>{{_ "Save_changes"}}</span></button>
 				</div>
diff --git a/packages/rocketchat-ui-account/account/avatar/prompt.html b/packages/rocketchat-ui-account/account/avatar/prompt.html
index a3291b8c72d49071493985acd93879b42a31fe48..6a238d35ed3a6b0e4fa2a654b14623de1fc256c2 100644
--- a/packages/rocketchat-ui-account/account/avatar/prompt.html
+++ b/packages/rocketchat-ui-account/account/avatar/prompt.html
@@ -1,7 +1,7 @@
 <template name="avatarSuggestion">
 	{{#if .}}
-		<div class="avatar-suggestion-item">
-			<div class="avatar" style="background-image: url({{blob}});">
+		<div class="avatar-suggestion-item border-component-color">
+			<div class="avatar tertiary-background-color" style="background-image: url({{blob}});">
 			</div>
 			<div class="action">
 				<button type="button" class="button primary {{service}} select-service">{{_ "Use_service_avatar" service}}</button>
@@ -12,8 +12,8 @@
 
 <template name="avatarSuggestionLogin">
 	{{#if .}}
-		<div class="avatar-suggestion-item">
-			<div class="avatar question-mark icon-user"></div>
+		<div class="avatar-suggestion-item border-component-color">
+			<div class="avatar question-mark icon-user tertiary-background-color"></div>
 			<div class="action">
 				<button type="button" class="button primary {{.}} login-with-service">{{_ "Login_with" .}}</button>
 			</div>
@@ -22,8 +22,8 @@
 </template>
 
 <template name="avatarPrompt">
-	<section class="page-container page-home page-static">
-		<header class="fixed-title">
+	<section class="page-container page-home page-static content-background-color">
+		<header class="fixed-title content-background-color border-component-color">
 			{{> burger}}
 			<h2>
 				<span class="room-title">{{_ "Select_an_avatar"}}</span>
@@ -31,12 +31,12 @@
 		</header>
 		<div class="content">
 			<div class="avatarPrompt">
-				<header>
+				<header class="content-background-color border-component-color">
 					<p>{{_ "Select_service_to_login"}}</p>
 				</header>
 				<div>
 					<div class="avatar-suggestions">
-						<div class="avatar-suggestion-item">
+						<div class="avatar-suggestion-item border-component-color">
 							{{> avatar username=initialsUsername }}
 							{{#with service='initials'}}
 								<div class="action">
@@ -44,8 +44,8 @@
 								</div>
 							{{/with}}
 						</div>
-						<div class="avatar-suggestion-item">
-							<div style="background-image: url({{upload.blob}});" class="avatar {{#unless upload}}question-mark icon-upload{{/unless}}">
+						<div class="avatar-suggestion-item border-component-color">
+							<div style="background-image: url({{upload.blob}});" class="avatar tertiary-background-color {{#unless upload}}question-mark icon-upload{{/unless}}">
 							</div>
 							<div class="action">
 								<div class="button primary">{{_ "Select_file"}}
@@ -56,9 +56,9 @@
 								{{/with}}
 							</div>
 						</div>
-						<div class="avatar-suggestion-item">
+						<div class="avatar-suggestion-item border-component-color">
 							{{#with service='url'}}
-								<div class="avatar question-mark icon-upload"></div>
+								<div class="avatar question-mark icon-upload tertiary-background-color"></div>
 								<div class="action">
 									<div class="input-line">
 										<input type="text" name="avatarurl" id="avatarurl" />
diff --git a/packages/rocketchat-ui-account/styles/account.less b/packages/rocketchat-ui-account/styles/account.less
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/packages/rocketchat-ui-admin/admin/admin.coffee b/packages/rocketchat-ui-admin/admin/admin.coffee
index 12a1d056607aecbf4be626da542397137b39ba33..e6ce79cc7f06a2344d82593a13ac7b7da4feb501 100644
--- a/packages/rocketchat-ui-admin/admin/admin.coffee
+++ b/packages/rocketchat-ui-admin/admin/admin.coffee
@@ -2,11 +2,26 @@ import toastr from 'toastr'
 TempSettings = new Meteor.Collection null
 RocketChat.TempSettings = TempSettings
 
-updateColorComponent = ->
-	$('input.minicolors').minicolors
-		theme: 'rocketchat'
-		format: 'hex'
-		opacity: true
+getDefaultSetting = (settingId) ->
+	return RocketChat.settings.cachedCollectionPrivate.collection.findOne({_id: settingId})
+
+setFieldValue = (settingId, value, type, editor) ->
+	input = $('.page-settings').find('[name="' + settingId + '"]')
+
+	switch type
+		when 'boolean'
+			$('.page-settings').find('[name="' + settingId + '"][value="' + Number(value) + '"]').prop('checked', true).change()
+		when 'code'
+			input.next()[0].CodeMirror.setValue(value)
+		when 'color'
+			input.parents('.horizontal').find('select[name="color-editor"]').val(editor).change()
+			input.val(value).change()
+
+			if editor is 'color'
+				new jscolor(input)
+
+		else
+			input.val(value).change()
 
 Template.admin.onCreated ->
 	if not RocketChat.settings.cachedCollectionPrivate?
@@ -60,14 +75,10 @@ Template.admin.helpers
 		return selected
 
 	group: ->
-		group = FlowRouter.getParam('group')
-		group ?= TempSettings.findOne({ type: 'group' })?._id
-		return TempSettings.findOne { _id: group, type: 'group' }
+		return TempSettings.findOne { _id: FlowRouter.getParam('group'), type: 'group' }
 
 	sections: ->
-		group = FlowRouter.getParam('group')
-		group ?= TempSettings.findOne({ type: 'group' })?._id
-		settings = TempSettings.find({ group: group }, {sort: {section: 1, sorter: 1, i18nLabel: 1}}).fetch()
+		settings = TempSettings.find({ group: FlowRouter.getParam('group') }, {sort: {section: 1, sorter: 1, i18nLabel: 1}}).fetch()
 
 		sections = {}
 		for setting in settings
@@ -250,8 +261,12 @@ Template.admin.helpers
 	getColorVariable: (color) ->
 		return color.replace(/theme-color-/, '@')
 
+	isDefaultValue: (settingId) ->
+		setting = TempSettings.findOne({_id: settingId}, {fields: {value: 1, packageValue: 1}})
+		return setting.value is setting.packageValue
+
 Template.admin.events
-	"change .input-monitor": (e, t) ->
+	"change .input-monitor, keyup .input-monitor": (e, t) ->
 		value = _.trim $(e.target).val()
 
 		switch @type
@@ -271,22 +286,50 @@ Template.admin.events
 			$set:
 				editor: value
 
-		Meteor.setTimeout updateColorComponent, 100
-
-	"click .submit .save": (e, t) ->
+	"click .submit .discard": ->
 		group = FlowRouter.getParam('group')
 
 		query =
 			group: group
 			changed: true
 
-		if @section is ''
-			query.$or = [
-				{section: ''}
-				{section: {$exists: false}}
-			]
+		settings = TempSettings.find(query, {fields: {_id: 1, value: 1, packageValue: 1}}).fetch()
+		console.log(settings)
+
+		settings.forEach (setting) ->
+			oldSetting = RocketChat.settings.cachedCollectionPrivate.collection.findOne({_id: setting._id}, {fields: {value: 1, type:1, editor: 1}})
+
+			setFieldValue(setting._id, oldSetting.value, oldSetting.type, oldSetting.editor)
+
+	"click .reset-setting": (e, t) ->
+		e.preventDefault();
+		settingId = $(e.target).data('setting')
+		if typeof settingId is 'undefined' then settingId = $(e.target).parent().data('setting')
+
+		defaultValue = getDefaultSetting(settingId)
+
+		setFieldValue(settingId, defaultValue.packageValue, defaultValue.type, defaultValue.editor)
+
+	"click .reset-group": (e, t) ->
+		e.preventDefault();
+		group = FlowRouter.getParam('group')
+		section = $(e.target).data('section')
+
+		if section is ""
+			settings = TempSettings.find({group: group, section: {$exists: false}}, {fields: {_id: 1}}).fetch()
 		else
-			query.section = @section
+			settings = TempSettings.find({group: group, section: section}, {fields: {_id: 1}}).fetch()
+
+		settings.forEach (setting) ->
+			defaultValue = getDefaultSetting(setting._id)
+			setFieldValue(setting._id, defaultValue.packageValue, defaultValue.type, defaultValue.editor)
+
+	"click .submit .save": (e, t) ->
+		group = FlowRouter.getParam('group')
+
+		query =
+			group: group
+			changed: true
 
 		settings = TempSettings.find(query, {fields: {_id: 1, value: 1, editor: 1}}).fetch()
 
@@ -321,6 +364,14 @@ Template.admin.events
 				if err
 					handleError(err)
 
+	"click .submit .refresh-oauth": (e, t) ->
+		toastr.info TAPi18n.__ 'Refreshing'
+		Meteor.call 'refreshOAuthService', (err) ->
+			if err
+				handleError(err)
+			else
+				toastr.success TAPi18n.__ 'Done'
+
 	"click .submit .remove-custom-oauth": (e, t) ->
 		name = this.section.replace('Custom OAuth: ', '')
 		config =
@@ -390,12 +441,12 @@ Template.admin.events
 
 	"click .button-fullscreen": ->
 		codeMirrorBox = $('.code-mirror-box[data-editor-id="'+this._id+'"]')
-		codeMirrorBox.addClass('code-mirror-box-fullscreen')
+		codeMirrorBox.addClass('code-mirror-box-fullscreen content-background-color')
 		codeMirrorBox.find('.CodeMirror')[0].CodeMirror.refresh()
 
 	"click .button-restore": ->
 		codeMirrorBox = $('.code-mirror-box[data-editor-id="'+this._id+'"]')
-		codeMirrorBox.removeClass('code-mirror-box-fullscreen')
+		codeMirrorBox.removeClass('code-mirror-box-fullscreen content-background-color')
 		codeMirrorBox.find('.CodeMirror')[0].CodeMirror.refresh()
 
 	'autocompleteselect .autocomplete': (event, instance, doc) ->
@@ -427,12 +478,12 @@ Template.admin.onRendered ->
 		SideNav.setFlex "adminFlex"
 		SideNav.openFlex()
 
-	Meteor.setTimeout ->
-		updateColorComponent()
-	, 1000
-
 	Tracker.autorun ->
 		FlowRouter.watchPathChange()
-		Meteor.setTimeout ->
-			updateColorComponent()
-		, 400
+
+		hasColor = TempSettings.findOne { group: FlowRouter.getParam('group'), type: 'color' }
+		if hasColor
+			Meteor.setTimeout ->
+				$('.colorpicker-input').each (index, el) ->
+					new jscolor(el)
+			, 400
diff --git a/packages/rocketchat-ui-admin/admin/admin.html b/packages/rocketchat-ui-admin/admin/admin.html
index fb9af6f0685b38f4ea8c4b847d7ac08a9991d254..d72c5e6b115b7998a35b609d8aeaa6c5da320773 100644
--- a/packages/rocketchat-ui-admin/admin/admin.html
+++ b/packages/rocketchat-ui-admin/admin/admin.html
@@ -1,13 +1,21 @@
 <template name="admin">
 	<section class="page-container page-home page-static page-settings">
-		<header class="fixed-title">
+		<header class="fixed-title border-component-color">
 			{{> burger}}
 			<h2>
 				<span class="room-title">{{#with group}}{{label}}{{/with}}</span>
 			</h2>
+			{{#unless $eq group._id 'Assets'}}
+				<div class="submit">
+					{{#if hasChanges}}
+						<button class="button danger discard"><i class="icon-send"></i><span>{{_ "Cancel"}}</span></button>
+					{{/if}}
+					<button class="button primary save" disabled="{{not hasChanges}}"><i class="icon-send"></i><span>{{_ "Save_changes"}}</span></button>
+				</div>
+			{{/unless}}
 		</header>
 
-		<div class="content">
+		<div class="content background-transparent-dark">
 			{{#unless hasPermission 'view-privileged-setting'}}
 				<p>{{_ "You_are_not_authorized_to_view_this_page"}}</p>
 			{{else}}
@@ -27,11 +35,11 @@
 										{{translateSection section}}
 									</div>
 									<div class="section-title-right">
-										<button class="button secondary expand"><span>{{_ "Expand"}}</span></button>
+										<button class="button primary expand"><span>{{_ "Expand"}}</span></button>
 									</div>
 								</div>
 							{{/if}}
-							<div class="section-content">
+							<div class="section-content border-component-color">
 								{{#if section}}
 									{{#if sectionIsCustomOAuth section}}
 										<div class="section-helper">
@@ -43,8 +51,8 @@
 								{{/if}}
 								{{#each settings}}
 									<div class="input-line double-col {{#if changed}}setting-changed{{/if}}" {{isDisabled}}>
-										<label>{{label}}</label>
-										<div>
+										<label class="setting-label">{{label}}</label>
+										<div class="setting-field">
 											{{#if $eq type 'string'}}
 												{{#if multiline}}
 													<textarea class="input-monitor" name="{{_id}}" rows="4" style="height: auto" {{isDisabled}}>{{value}}</textarea>
@@ -72,7 +80,7 @@
 
 											{{#if $eq type 'select'}}
 												<div class="select-arrow">
-													<i class="icon-down-open"></i>
+													<i class="icon-down-open secondary-font-color"></i>
 												</div>
 												<select class="input-monitor" name="{{_id}}" {{isDisabled}}>
 													{{#each values}}
@@ -83,7 +91,7 @@
 
 											{{#if $eq type 'language'}}
 												<div class="select-arrow">
-													<i class="icon-down-open"></i>
+													<i class="icon-down-open secondary-font-color"></i>
 												</div>
 												<select class="input-monitor" name="{{_id}}" {{isDisabled}}>
 													{{#each languages}}
@@ -96,17 +104,18 @@
 												<div class="horizontal">
 													{{#if $eq editor 'color'}}
 														<div class="flex-grow-1">
-															<input class="input-monitor minicolors" type="text" name="{{_id}}" value="{{value}}" {{isDisabled}}/>
+															<input class="input-monitor colorpicker-input" type="text" name="{{_id}}" value="{{value}}" autocomplete="off" {{isDisabled}}/>
+															<span class="colorpicker-swatch border-component-color" style="background-color: {{value}}"></span>
 														</div>
 													{{/if}}
 													{{#if $eq editor 'expression'}}
 														<div class="flex-grow-1">
-															<input class="input-monitor not-minicolors" type="text" name="{{_id}}" value="{{value}}" {{isDisabled}}/>
+															<input class="input-monitor" type="text" name="{{_id}}" value="{{value}}" {{isDisabled}}/>
 														</div>
 													{{/if}}
 													<div class="color-editor">
 														<div class="select-arrow">
-															<i class="icon-down-open"></i>
+															<i class="icon-down-open secondary-font-color"></i>
 														</div>
 														<select name="color-editor">
 															{{#each allowedTypes}}
@@ -142,7 +151,7 @@
 
 											{{#if $eq type 'action'}}
 												{{#if hasChanges section}}
-													<span style="line-height: 40px" class="secondary-text">{{_ "Save_to_enable_this_action"}}</span>
+													<span style="line-height: 40px" class="secondary-font-color">{{_ "Save_to_enable_this_action"}}</span>
 												{{else}}
 													<button type="button" class="button primary action" data-setting="{{_id}}" data-action="{{value}}" {{isDisabled}}>{{_ actionText}}</button>
 												{{/if}}
@@ -153,12 +162,12 @@
 													<div class="settings-file-preview">
 														<div class="preview" style="background-image:url({{value.url}}?_dc={{random}});"></div>
 														<div class="action">
-															<button type="button" class="button danger delete-asset"><i class="icon-trash"></i>{{_ 'Delete'}}</button>
+															<button type="button" class="button danger delete-asset"><i class="icon-trash secondary-font-color"></i>{{_ 'Delete'}}</button>
 														</div>
 													</div>
 												{{else}}
 													<div class="settings-file-preview">
-														<div class="preview no-file"><i class="icon-upload"></i></div>
+														<div class="preview no-file background-transparent-light secondary-font-color"><i class="icon-upload secondary-font-color"></i></div>
 														<div class="action">
 															<div class="button primary">{{_ 'Select_file'}}
 																<input type="file" accept="{{assetAccept fileConstraints}}" />
@@ -173,7 +182,7 @@
 													{{> inputAutocomplete settings=autocompleteRoom id=_id name=_id class="search autocomplete" autocomplete="off" disabled=isDisabled.disabled}}
 													<ul class="selected-rooms">
 														{{#each selectedRooms}}
-															<li class="remove-room" data-setting={{../_id}}>{{name}} <i class="icon-cancel"></i></li>
+															<li class="remove-room" data-setting={{../_id}}>{{name}} <i class="icon-cancel secondary-font-color"></i></li>
 														{{/each}}
 													</ul>
 												</div>
@@ -183,12 +192,30 @@
 												<div class="settings-description">{{{RocketChatMarkdown description}}}</div>
 											{{/if}}
 											{{#if alert}}
-												<div class="settings-alert"><i class="icon-attention"></i>{{{_ alert}}}</div>
+												<div class="settings-alert pending-color pending-background pending-border"><i class="icon-attention secondary-font-color"></i>{{{_ alert}}}</div>
 											{{/if}}
 										</div>
+										{{#unless $eq group._id 'Assets'}}
+											{{#unless isDefaultValue _id}}
+												<button text="{{_ 'Reset'}}" data-setting="{{_id}}" class="reset-setting button danger">
+													<i class="icon-ccw secondary-font-color color-error-contrast"></i>
+												</button>
+											{{/unless}}
+										{{/unless}}
 									</div>
 								{{/each}}
 
+								{{#unless $eq group._id 'Assets'}}
+									<div class="input-line double-col">
+										<label class="setting-label">{{_ "Reset_section_settings"}}</label>
+										<div class="setting-field">
+											<button data-section="{{section}}" class="reset-group button danger">
+												{{_ "Reset"}}
+											</button>
+										</div>
+									</div>
+								{{/unless}}
+
 								{{#if section}}
 									{{#if sectionIsCustomOAuth section}}
 										<div class="submit">
@@ -196,18 +223,13 @@
 										</div>
 									{{/if}}
 								{{/if}}
-
-								{{#if hasChanges section}}
-									<div class="submit">
-										<button class="button primary save"><i class="icon-send"></i><span>{{_ "Save_changes"}}</span></button>
-									</div>
-								{{/if}}
 							</div>
 						</div>
 					{{/each}}
 
 					<div class="submit">
 						{{#if $eq group._id 'OAuth'}}
+							<button class="button secondary refresh-oauth"><span>{{_ "Refresh_oauth_services"}}</span></button>
 							<button class="button secondary add-custom-oauth"><span>{{_ "Add_custom_oauth"}}</span></button>
 						{{/if}}
 						{{#if $eq group._id 'Assets'}}
diff --git a/packages/rocketchat-ui-admin/admin/adminFlex.coffee b/packages/rocketchat-ui-admin/admin/adminFlex.coffee
index 1dface4a6acf3e503fa981538910b428294b0294..9a1a9b485474c0b8e185b739ecdc74b2d62331a3 100644
--- a/packages/rocketchat-ui-admin/admin/adminFlex.coffee
+++ b/packages/rocketchat-ui-admin/admin/adminFlex.coffee
@@ -1,4 +1,6 @@
 Template.adminFlex.onCreated ->
+	@settingsFilter = new ReactiveVar('')
+
 	if not RocketChat.settings.cachedCollectionPrivate?
 		RocketChat.settings.cachedCollectionPrivate = new RocketChat.CachedCollection({ name: 'private-settings', eventType: 'onAll' })
 		RocketChat.settings.collectionPrivate = RocketChat.settings.cachedCollectionPrivate.collection
@@ -7,9 +9,30 @@ Template.adminFlex.onCreated ->
 
 Template.adminFlex.helpers
 	groups: ->
-		return RocketChat.settings.collectionPrivate.find({type: 'group'}, { sort: { sort: 1, i18nLabel: 1 } }).fetch()
+		filter = Template.instance().settingsFilter.get()
+
+		query =
+			type: 'group'
+
+		if filter
+			filterRegex = new RegExp(_.escapeRegExp(filter), 'i')
+
+			records = RocketChat.settings.collectionPrivate.find().fetch()
+			groups = []
+			records = records.forEach (record) ->
+				if filterRegex.test(TAPi18n.__(record.i18nLabel or record._id))
+					groups.push(record.group or record._id)
+
+			groups = _.unique(groups)
+			if groups.length > 0
+				query._id =
+					$in: groups
+
+		return RocketChat.settings.collectionPrivate.find(query, { sort: { sort: 1, i18nLabel: 1 } }).fetch()
+
 	label: ->
 		return TAPi18n.__(@i18nLabel or @_id)
+
 	adminBoxOptions: ->
 		return RocketChat.AdminBox.getOptions()
 
@@ -29,3 +52,6 @@ Template.adminFlex.events
 
 	'click .admin-link': ->
 		menu.close()
+
+	'keyup [name=settings-search]': (e, t) ->
+		t.settingsFilter.set(e.target.value)
diff --git a/packages/rocketchat-ui-admin/admin/adminFlex.html b/packages/rocketchat-ui-admin/admin/adminFlex.html
index aad3a490ae37595bede65efbce2547f90faa2487..1eb8c60c7f7cb9bf1cd1bb647f55598e0c0a8878 100644
--- a/packages/rocketchat-ui-admin/admin/adminFlex.html
+++ b/packages/rocketchat-ui-admin/admin/adminFlex.html
@@ -42,6 +42,10 @@
 						{{_ "Settings"}}
 					</h3>
 
+					<li>
+						<input type="text" name="settings-search" placeholder="{{_ 'Search'}}">
+					</li>
+
 					{{#each groups}}
 					<li>
 						<a href="{{pathFor 'admin' group=_id}}" class="admin-link">{{label}}</a>
diff --git a/packages/rocketchat-ui-admin/admin/adminInfo.html b/packages/rocketchat-ui-admin/admin/adminInfo.html
index 2e8d9df21ad764e34f618b890197b50c5a48102f..b116f63ff15414c3b10b6c69b17e3b0be495f1f7 100644
--- a/packages/rocketchat-ui-admin/admin/adminInfo.html
+++ b/packages/rocketchat-ui-admin/admin/adminInfo.html
@@ -1,6 +1,6 @@
 <template name="adminInfo">
 	<section class="page-container page-list">
-		<header class="fixed-title">
+		<header class="fixed-title border-component-color">
 			{{> burger}}
 			<h2>
 				<span class="room-title">{{_ "Info"}}</span>
@@ -9,186 +9,186 @@
 		<div class="content">
 			{{#if hasPermission 'view-statistics'}}
 				<h3>{{_ "Rocket.Chat"}}</h3>
-				<table class="statistics-table">
-					<tr>
-						<th>{{_ "Version"}}</th>
-						<td>{{statistics.version}}</td>
+				<table class="statistics-table secondary-background-color">
+					<tr class="admin-table-row">
+						<th class="content-background-color border-component-color">{{_ "Version"}}</th>
+						<td class="border-component-color">{{statistics.version}}</td>
 					</tr>
-					<tr>
-						<th>{{_ "DB_Migration"}}</th>
-						<td>{{statistics.migration.version}}</td>
+					<tr class="admin-table-row">
+						<th class="content-background-color border-component-color">{{_ "DB_Migration"}}</th>
+						<td class="border-component-color">{{statistics.migration.version}}</td>
 					</tr>
-					<tr>
-						<th>{{_ "DB_Migration_Date"}}</th>
-						<td>{{statistics.migration.lockedAt}}</td>
+					<tr class="admin-table-row">
+						<th class="content-background-color border-component-color">{{_ "DB_Migration_Date"}}</th>
+						<td class="border-component-color">{{statistics.migration.lockedAt}}</td>
 					</tr>
-					<tr>
-						<th>{{_ "Installed_at"}}</th>
-						<td>{{statistics.installedAt}}</td>
+					<tr class="admin-table-row">
+						<th class="content-background-color border-component-color">{{_ "Installed_at"}}</th>
+						<td class="border-component-color">{{statistics.installedAt}}</td>
 					</tr>
-					<tr>
-						<th>{{_ "Uptime"}}</th>
-						<td>{{humanReadableTime statistics.process.uptime}}</td>
+					<tr class="admin-table-row">
+						<th class="content-background-color border-component-color">{{_ "Uptime"}}</th>
+						<td class="border-component-color">{{humanReadableTime statistics.process.uptime}}</td>
 					</tr>
-					<tr>
-						<th>{{_ "Deployment_ID"}}</th>
-						<td>{{statistics.uniqueId}}</td>
+					<tr class="admin-table-row">
+						<th class="content-background-color border-component-color">{{_ "Deployment_ID"}}</th>
+						<td class="border-component-color">{{statistics.uniqueId}}</td>
 					</tr>
-					<tr>
-						<th>{{_ "PID"}}</th>
-						<td>{{statistics.process.pid}}</td>
+					<tr class="admin-table-row">
+						<th class="content-background-color border-component-color">{{_ "PID"}}</th>
+						<td class="border-component-color">{{statistics.process.pid}}</td>
 					</tr>
-					<tr>
-						<th>{{_ "Running_Instances"}}</th>
-						<td>{{statistics.instanceCount}}</td>
+					<tr class="admin-table-row">
+						<th class="content-background-color border-component-color">{{_ "Running_Instances"}}</th>
+						<td class="border-component-color">{{statistics.instanceCount}}</td>
 					</tr>
 				</table>
 			{{/if}}
 
 			<h3>{{_ "Commit"}}</h3>
-			<table class="statistics-table">
-				<tr>
-					<th>{{_ "Hash"}}</th>
-					<td>{{info.commit.hash}}</td>
+			<table class="statistics-table secondary-background-color">
+				<tr class="admin-table-row">
+					<th class="content-background-color border-component-color">{{_ "Hash"}}</th>
+					<td class="border-component-color">{{info.commit.hash}}</td>
 				</tr>
-				<tr>
-					<th>{{_ "Date"}}</th>
-					<td>{{info.commit.date}}</td>
+				<tr class="admin-table-row">
+					<th class="content-background-color border-component-color">{{_ "Date"}}</th>
+					<td class="border-component-color">{{info.commit.date}}</td>
 				</tr>
-				<tr>
-					<th>{{_ "Branch"}}</th>
-					<td>{{info.commit.branch}}</td>
+				<tr class="admin-table-row">
+					<th class="content-background-color border-component-color">{{_ "Branch"}}</th>
+					<td class="border-component-color">{{info.commit.branch}}</td>
 				</tr>
-				<tr>
-					<th>{{_ "Tag"}}</th>
-					<td>{{info.commit.tag}}</td>
+				<tr class="admin-table-row">
+					<th class="content-background-color border-component-color">{{_ "Tag"}}</th>
+					<td class="border-component-color">{{info.commit.tag}}</td>
 				</tr>
-				<tr>
-					<th>{{_ "Author"}}</th>
-					<td>{{info.commit.author}}</td>
+				<tr class="admin-table-row">
+					<th class="content-background-color border-component-color">{{_ "Author"}}</th>
+					<td class="border-component-color">{{info.commit.author}}</td>
 				</tr>
-				<tr>
-					<th>{{_ "Subject"}}</th>
-					<td>{{info.commit.subject}}</td>
+				<tr class="admin-table-row">
+					<th class="content-background-color border-component-color">{{_ "Subject"}}</th>
+					<td class="border-component-color">{{info.commit.subject}}</td>
 				</tr>
 			</table>
 
 			{{#if hasPermission 'view-statistics'}}
 				{{#if isReady}}
 					<h3>{{_ "Runtime_Environment"}}</h3>
-					<table class="statistics-table">
-						<tr>
-							<th>{{_ "OS_Type"}}</th>
-							<td>{{statistics.os.type}}</td>
+					<table class="statistics-table secondary-background-color">
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "OS_Type"}}</th>
+							<td class="border-component-color">{{statistics.os.type}}</td>
 						</tr>
-						<tr>
-							<th>{{_ "OS_Platform"}}</th>
-							<td>{{statistics.os.platform}}</td>
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "OS_Platform"}}</th>
+							<td class="border-component-color">{{statistics.os.platform}}</td>
 						</tr>
-						<tr>
-							<th>{{_ "OS_Arch"}}</th>
-							<td>{{statistics.os.arch}}</td>
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "OS_Arch"}}</th>
+							<td class="border-component-color">{{statistics.os.arch}}</td>
 						</tr>
-						<tr>
-							<th>{{_ "OS_Release"}}</th>
-							<td>{{statistics.os.release}}</td>
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "OS_Release"}}</th>
+							<td class="border-component-color">{{statistics.os.release}}</td>
 						</tr>
-						<tr>
-							<th>{{_ "Node_version"}}</th>
-							<td>{{statistics.process.nodeVersion}}</td>
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "Node_version"}}</th>
+							<td class="border-component-color">{{statistics.process.nodeVersion}}</td>
 						</tr>
-						<tr>
-							<th>{{_ "OS_Uptime"}}</th>
-							<td>{{humanReadableTime statistics.os.uptime}}</td>
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "OS_Uptime"}}</th>
+							<td class="border-component-color">{{humanReadableTime statistics.os.uptime}}</td>
 						</tr>
-						<tr>
-							<th>{{_ "OS_Loadavg"}}</th>
-							<td>{{numFormat statistics.os.loadavg.[0]}}, {{numFormat statistics.os.loadavg.[1]}}, {{numFormat statistics.os.loadavg.[2]}}</td>
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "OS_Loadavg"}}</th>
+							<td class="border-component-color">{{numFormat statistics.os.loadavg.[0]}}, {{numFormat statistics.os.loadavg.[1]}}, {{numFormat statistics.os.loadavg.[2]}}</td>
 						</tr>
-						<tr>
-							<th>{{_ "OS_Totalmem"}}</th>
-							<td>{{inGB statistics.os.totalmem}}</td>
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "OS_Totalmem"}}</th>
+							<td class="border-component-color">{{inGB statistics.os.totalmem}}</td>
 						</tr>
-						<tr>
-							<th>{{_ "OS_Freemem"}}</th>
-							<td>{{inGB statistics.os.freemem}}</td>
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "OS_Freemem"}}</th>
+							<td class="border-component-color">{{inGB statistics.os.freemem}}</td>
 						</tr>
-						<tr>
-							<th>{{_ "OS_Cpus"}}</th>
-							<td>{{statistics.os.cpus.length}}</td>
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "OS_Cpus"}}</th>
+							<td class="border-component-color">{{statistics.os.cpus.length}}</td>
 						</tr>
 					</table>
 
 					<h3>{{_ "Build_Environment"}}</h3>
-					<table class="statistics-table">
-						<tr>
-							<th>{{_ "OS_Platform"}}</th>
-							<td>{{build.platform}}</td>
+					<table class="statistics-table secondary-background-color">
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "OS_Platform"}}</th>
+							<td class="border-component-color">{{build.platform}}</td>
 						</tr>
-						<tr>
-							<th>{{_ "OS_Arch"}}</th>
-							<td>{{build.arch}}</td>
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "OS_Arch"}}</th>
+							<td class="border-component-color">{{build.arch}}</td>
 						</tr>
-						<tr>
-							<th>{{_ "OS_Release"}}</th>
-							<td>{{build.osRelease}}</td>
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "OS_Release"}}</th>
+							<td class="border-component-color">{{build.osRelease}}</td>
 						</tr>
-						<tr>
-							<th>{{_ "Node_version"}}</th>
-							<td>{{build.nodeVersion}}</td>
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "Node_version"}}</th>
+							<td class="border-component-color">{{build.nodeVersion}}</td>
 						</tr>
-						<tr>
-							<th>{{_ "Date"}}</th>
-							<td>{{formatDate build.date}}</td>
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "Date"}}</th>
+							<td class="border-component-color">{{formatDate build.date}}</td>
 						</tr>
 					</table>
 
 
 					<h3>{{_ "Usage"}}</h3>
-					<table class="statistics-table">
-						<tr>
-							<th>{{_ "Stats_Total_Users"}}</th>
-							<td>{{statistics.totalUsers}}</td>
-						</tr>
-						<tr>
-							<th>{{_ "Stats_Active_Users"}}</th>
-							<td>{{statistics.activeUsers}}</td>
-						</tr>
-						<tr>
-							<th>{{_ "Stats_Non_Active_Users"}}</th>
-							<td>{{statistics.nonActiveUsers}}</td>
-						</tr>
-						<tr>
-							<th>{{_ "Stats_Online_Users"}}</th>
-							<td>{{statistics.onlineUsers}}</td>
-						</tr>
-						<tr>
-							<th>{{_ "Stats_Away_Users"}}</th>
-							<td>{{statistics.awayUsers}}</td>
-						</tr>
-						<tr>
-							<th>{{_ "Stats_Offline_Users"}}</th>
-							<td>{{statistics.offlineUsers}}</td>
-						</tr>
-						<tr>
-							<th>{{_ "Stats_Total_Rooms"}}</th>
-							<td>{{statistics.totalRooms}}</td>
-						</tr>
-						<tr>
-							<th>{{_ "Stats_Total_Channels"}}</th>
-							<td>{{statistics.totalChannels}}</td>
-						</tr>
-						<tr>
-							<th>{{_ "Stats_Total_Private_Groups"}}</th>
-							<td>{{statistics.totalPrivateGroups}}</td>
-						</tr>
-						<tr>
-							<th>{{_ "Stats_Total_Direct_Messages"}}</th>
-							<td>{{statistics.totalDirect}}</td>
-						</tr>
-						<tr>
-							<th>{{_ "Stats_Total_Messages"}}</th>
-							<td>{{statistics.totalMessages}}</td>
+					<table class="statistics-table secondary-background-color">
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "Stats_Total_Users"}}</th>
+							<td class="border-component-color">{{statistics.totalUsers}}</td>
+						</tr>
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "Stats_Active_Users"}}</th>
+							<td class="border-component-color">{{statistics.activeUsers}}</td>
+						</tr>
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "Stats_Non_Active_Users"}}</th>
+							<td class="border-component-color">{{statistics.nonActiveUsers}}</td>
+						</tr>
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "Stats_Online_Users"}}</th>
+							<td class="border-component-color">{{statistics.onlineUsers}}</td>
+						</tr>
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "Stats_Away_Users"}}</th>
+							<td class="border-component-color">{{statistics.awayUsers}}</td>
+						</tr>
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "Stats_Offline_Users"}}</th>
+							<td class="border-component-color">{{statistics.offlineUsers}}</td>
+						</tr>
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "Stats_Total_Rooms"}}</th>
+							<td class="border-component-color">{{statistics.totalRooms}}</td>
+						</tr>
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "Stats_Total_Channels"}}</th>
+							<td class="border-component-color">{{statistics.totalChannels}}</td>
+						</tr>
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "Stats_Total_Private_Groups"}}</th>
+							<td class="border-component-color">{{statistics.totalPrivateGroups}}</td>
+						</tr>
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "Stats_Total_Direct_Messages"}}</th>
+							<td class="border-component-color">{{statistics.totalDirect}}</td>
+						</tr>
+						<tr class="admin-table-row">
+							<th class="content-background-color border-component-color">{{_ "Stats_Total_Messages"}}</th>
+							<td class="border-component-color">{{statistics.totalMessages}}</td>
 						</tr>
 					</table>
 
diff --git a/packages/rocketchat-ui-admin/admin/rooms/adminRoomInfo.html b/packages/rocketchat-ui-admin/admin/rooms/adminRoomInfo.html
index 7544c1facd46d3582c0d9e991de6310c761350f6..48655d977163c4e7e0c9cefabbbed138200ab766 100644
--- a/packages/rocketchat-ui-admin/admin/rooms/adminRoomInfo.html
+++ b/packages/rocketchat-ui-admin/admin/rooms/adminRoomInfo.html
@@ -12,7 +12,7 @@
 								<label>{{_ "Name"}}</label>
 								<div>
 									{{#if editing 'roomName'}}
-										<input type="text" name="roomName" value="{{roomName}}" class="editing" />
+										<input type="text" name="roomName" value="{{roomName}}" class="content-background-color editing" />
 										<button type="button" class="button cancel">{{_ "Cancel"}}</button>
 										<button type="button" class="button primary save">{{_ "Save"}}</button>
 									{{else}}
@@ -25,7 +25,7 @@
 							<label>{{_ "Topic"}}</label>
 							<div>
 								{{#if editing 'roomTopic'}}
-									<input type="text" name="roomTopic" value="{{roomTopic}}" class="editing" />
+									<input type="text" name="roomTopic" value="{{roomTopic}}" class="content-background-color editing" />
 									<button type="button" class="button cancel">{{_ "Cancel"}}</button>
 									<button type="button" class="button primary save">{{_ "Save"}}</button>
 								{{else}}
diff --git a/packages/rocketchat-ui-admin/admin/rooms/adminRooms.coffee b/packages/rocketchat-ui-admin/admin/rooms/adminRooms.coffee
index 277b9b24eab48829433aa52ac3d435efde6846ff..ac484d8ff2314a0e4fe9bbad55b90b7c32c07e25 100644
--- a/packages/rocketchat-ui-admin/admin/rooms/adminRooms.coffee
+++ b/packages/rocketchat-ui-admin/admin/rooms/adminRooms.coffee
@@ -14,10 +14,10 @@ Template.adminRooms.helpers
 	roomCount: ->
 		return Template.instance().rooms?().count()
 	name: ->
-		if @t is 'c' or @t is 'p'
-			return @name
-		else if @t is 'd'
-			return @usernames.join ' x '
+		# if @t is 'c' or @t is 'p'
+		return @name
+		# else if @t is 'd'
+		# 	return @usernames.join ' x '
 	type: ->
 		if @t is 'c'
 			return TAPi18n.__ 'Channel'
diff --git a/packages/rocketchat-ui-admin/admin/rooms/adminRooms.html b/packages/rocketchat-ui-admin/admin/rooms/adminRooms.html
index 8315a3d91285b9069e0f4d21c64c369bee4c1cf1..74522f97b799dca296485b89a57fb7e838f39927 100644
--- a/packages/rocketchat-ui-admin/admin/rooms/adminRooms.html
+++ b/packages/rocketchat-ui-admin/admin/rooms/adminRooms.html
@@ -1,6 +1,6 @@
 <template name="adminRooms">
 	<section class="page-container page-list">
-		<header class="fixed-title">
+		<header class="fixed-title border-component-color">
 			{{> burger}}
 			<h2>
 				<span class="room-title">{{_ "Rooms"}}</span>
@@ -13,7 +13,7 @@
 				<form class="search-form" role="form">
 					<div class="input-line search">
 						<input type="text" id="rooms-filter" placeholder="{{_ "Search"}}" dir="auto">
-						<i class="icon-search"></i>
+						<i class="icon-search secondary-font-color"></i>
 						{{#unless isReady}}<i class="icon-spin"></i>{{/unless}}
 					</div>
 					<label><input type="checkbox" name="room-type" value="c"> {{_ "Channels"}}</label>
@@ -24,24 +24,24 @@
 					{{{_ "Showing_results" roomCount}}}
 				</div>
 				<div class="list">
-					<table>
+					<table class="secondary-background-color">
 						<thead>
-							<tr>
-								<th width="30%">{{_ "Name"}}</th>
-								<th width="20%">{{_ "Type"}}</th>
-								<th width="20%">{{_ "Users"}}</th>
-								<th width="10%">{{_ "Msgs"}}</th>
-								<th width="20%">{{_ "Default"}}</th>
+							<tr class="admin-table-row">
+								<th class="content-background-color border-component-color" width="30%">{{_ "Name"}}</th>
+								<th class="content-background-color border-component-color" width="20%">{{_ "Type"}}</th>
+								<th class="content-background-color border-component-color" width="20%">{{_ "Users"}}</th>
+								<th class="content-background-color border-component-color" width="10%">{{_ "Msgs"}}</th>
+								<th class="content-background-color border-component-color" width="20%">{{_ "Default"}}</th>
 							</tr>
 						</thead>
 						<tbody>
 							{{#each rooms}}
 							<tr class="room-info row-link">
-								<td>{{name}}</td>
-								<td>{{type}}</td>
-								<td>{{usernames.length}}</td>
-								<td>{{msgs}}</td>
-								<td>{{default}}</td>
+								<td class="border-component-color">{{name}}</td>
+								<td class="border-component-color">{{type}}</td>
+								<td class="border-component-color">{{usernames.length}}</td>
+								<td class="border-component-color">{{msgs}}</td>
+								<td class="border-component-color">{{default}}</td>
 							</tr>
 							{{/each}}
 						</tbody>
@@ -53,7 +53,7 @@
 			{{/unless}}
 		</div>
 	</section>
-	<section class="flex-tab">
+	<section class="flex-tab secondary-background-color">
 		{{> Template.dynamic template=flexTemplate data=flexData}}
 	</section>
 </template>
diff --git a/packages/rocketchat-ui-admin/admin/users/adminInviteUser.html b/packages/rocketchat-ui-admin/admin/users/adminInviteUser.html
index 78991c1a9972c436be2ac20c0e1888aad8ee7ab0..439484d64ecddf3ef455d33f0c741ff64e0daf32 100644
--- a/packages/rocketchat-ui-admin/admin/users/adminInviteUser.html
+++ b/packages/rocketchat-ui-admin/admin/users/adminInviteUser.html
@@ -5,7 +5,7 @@
 				<h3>{{_ "Send_invitation_email"}}</h3>
 				<div class="input-line">
 					<label for="inviteEmails">{{_ "Send_invitation_email_info"}}</label>
-					<textarea id="inviteEmails" rows="3" style="height: auto"></textarea>
+					<textarea id="inviteEmails" rows="3" style="height: auto" class="content-background-color"></textarea>
 				</div>
 			</form>
 		</div>
diff --git a/packages/rocketchat-ui-admin/admin/users/adminUsers.html b/packages/rocketchat-ui-admin/admin/users/adminUsers.html
index cab9a39673cb8927a3e8566c22a5bb8b0dd4f955..bbdbe94c55e97b76541e490983b7cd30f0ea8d02 100644
--- a/packages/rocketchat-ui-admin/admin/users/adminUsers.html
+++ b/packages/rocketchat-ui-admin/admin/users/adminUsers.html
@@ -1,6 +1,6 @@
 <template name="adminUsers">
 	<section class="page-container page-list">
-		<header class="fixed-title">
+		<header class="fixed-title border-component-color">
 			{{> burger}}
 			<h2>
 				<span class="room-title">{{_ "Users"}}</span>
@@ -13,34 +13,34 @@
 				<form class="search-form" role="form">
 					<div class="input-line search">
 						<input type="text" id="users-filter" placeholder="{{_ "Search"}}" dir="auto">
-						<i class="icon-search"></i>
-						{{#unless isReady}}<i class="icon-spin"></i>{{/unless}}
+						<i class="icon-search secondary-font-color"></i>
+						{{#unless isReady}}<i class="icon-spin secondary-font-color"></i>{{/unless}}
 					</div>
 				</form>
 				<div class="results">
 					{{{_ "Showing_results" users.length}}}
 				</div>
 				<div class="list">
-					<table>
+					<table class="secondary-background-color">
 						<thead>
-							<tr>
-								<th>&nbsp;</th>
-								<th width="34%">{{_ "Name"}}</th>
-								<th width="33%">{{_ "Username"}}</th>
-								<th width="33%">{{_ "Email"}}</th>
+							<tr class="admin-table-row">
+								<th class="content-background-color border-component-color">&nbsp;</th>
+								<th class="content-background-color border-component-color" width="34%">{{_ "Name"}}</th>
+								<th class="content-background-color border-component-color" width="33%">{{_ "Username"}}</th>
+								<th class="content-background-color border-component-color" width="33%">{{_ "Email"}}</th>
 							</tr>
 						</thead>
 						<tbody>
 							{{#each users}}
 							<tr class="user-info row-link">
-								<td>
+								<td class="border-component-color">
 									<div class="user-image status-{{status}}">
 										{{> avatar username=username}}
 									</div>
 								</td>
-								<td>{{name}}</td>
-								<td>{{username}}</td>
-								<td>{{emailAddress}}</td>
+								<td class="border-component-color">{{name}}</td>
+								<td class="border-component-color">{{username}}</td>
+								<td class="border-component-color">{{emailAddress}}</td>
 							</tr>
 							{{/each}}
 						</tbody>
@@ -52,7 +52,7 @@
 			{{/unless}}
 		</div>
 	</section>
-	<section class="flex-tab">
+	<section class="flex-tab secondary-background-color">
 		{{> Template.dynamic template=flexTemplate data=flexData}}
 	</section>
 </template>
diff --git a/packages/rocketchat-ui-admin/publications/adminRooms.js b/packages/rocketchat-ui-admin/publications/adminRooms.js
index 950b70213f57dd586eeabcb7ec758ae3c7e70e21..9d82b4bd2c733b82c581beb8aef101addc4c3d57 100644
--- a/packages/rocketchat-ui-admin/publications/adminRooms.js
+++ b/packages/rocketchat-ui-admin/publications/adminRooms.js
@@ -31,10 +31,13 @@ Meteor.publish('adminRooms', function(filter, types, limit) {
 	};
 	filter = _.trim(filter);
 	if (filter && types.length) {
+		// CACHE: can we stop using publications here?
 		return RocketChat.models.Rooms.findByNameContainingAndTypes(filter, types, options);
 	} else if (types.length) {
+		// CACHE: can we stop using publications here?
 		return RocketChat.models.Rooms.findByTypes(types, options);
 	} else {
+		// CACHE: can we stop using publications here?
 		return RocketChat.models.Rooms.findByNameContaining(filter, options);
 	}
 });
diff --git a/packages/rocketchat-ui-flextab/flex-tab/flexTabBar.coffee b/packages/rocketchat-ui-flextab/flex-tab/flexTabBar.coffee
index 2838c88f81a741a239e7e0e71da064aebbddd652..c47a31ba59e4d8e4b77b2ae10f62e1e73674fa9f 100644
--- a/packages/rocketchat-ui-flextab/flex-tab/flexTabBar.coffee
+++ b/packages/rocketchat-ui-flextab/flex-tab/flexTabBar.coffee
@@ -17,6 +17,7 @@ Template.flexTabBar.events
 			RocketChat.TabBar.closeFlex()
 			$('.flex-tab').css('max-width', '')
 			$('.main-content').css('right', '')
+			RocketChat.TabBar._setTemplate ''
 		else
 			if not @openClick? or @openClick(e,t)
 				if @width?
diff --git a/packages/rocketchat-ui-flextab/flex-tab/tabs/membersList.coffee b/packages/rocketchat-ui-flextab/flex-tab/tabs/membersList.coffee
index 50f11b24641704374bd47e24a004fc97cfb72214..322a17cceb9dfb154e1545194308ad73929fd965 100644
--- a/packages/rocketchat-ui-flextab/flex-tab/tabs/membersList.coffee
+++ b/packages/rocketchat-ui-flextab/flex-tab/tabs/membersList.coffee
@@ -16,23 +16,20 @@ Template.membersList.helpers
 
 	roomUsers: ->
 		onlineUsers = RoomManager.onlineUsers.get()
+		roomUsernames = Template.instance().users.get()
 		room = ChatRoom.findOne(this.rid)
-		roomUsernames = room?.usernames or []
-		roomOnlineUsernames = roomUsernames.filter((username) -> onlineUsers[username])
 		roomMuted = room?.muted or []
 
-		if Template.instance().showAllUsers.get()
-			usernames = roomUsernames
-		else
-			usernames = roomOnlineUsernames
-
-		users = usernames.map (username) ->
-			utcOffset = onlineUsers[username]?.utcOffset
+		totalOnline = 0
+		users = roomUsernames.map (username) ->
+			if onlineUsers[username]?
+				totalOnline++
+				utcOffset = onlineUsers[username].utcOffset
 
-			if utcOffset?
-				if utcOffset > 0
-					utcOffset = "+#{utcOffset}"
-				utcOffset = "(UTC #{utcOffset})"
+				if utcOffset?
+					if utcOffset > 0
+						utcOffset = "+#{utcOffset}"
+					utcOffset = "(UTC #{utcOffset})"
 
 			return {
 				username: username
@@ -50,14 +47,13 @@ Template.membersList.helpers
 		hasMore = users.length > usersLimit
 		users = _.first(users, usersLimit)
 
-		totalUsers = roomUsernames.length
 		totalShowing = users.length
-		totalOnline = roomOnlineUsernames.length
 
 		ret =
 			_id: this.rid
-			total: totalUsers
+			total: Template.instance().total.get()
 			totalShowing: totalShowing
+			loading: Template.instance().loading.get()
 			totalOnline: totalOnline
 			users: users
 			hasMore: hasMore
@@ -133,6 +129,17 @@ Template.membersList.onCreated ->
 	@userDetail = new ReactiveVar
 	@showDetail = new ReactiveVar false
 
+	@users = new ReactiveVar []
+	@total = new ReactiveVar
+	@loading = new ReactiveVar true
+
+	Tracker.autorun =>
+		@loading.set true
+		Meteor.call 'getUsersOfRoom', this.data.rid, this.showAllUsers.get(), (error, users) =>
+			@users.set users.records
+			@total.set users.total
+			@loading.set false
+
 	@clearUserDetail = =>
 		@showDetail.set(false)
 		setTimeout =>
diff --git a/packages/rocketchat-ui-flextab/flex-tab/tabs/membersList.html b/packages/rocketchat-ui-flextab/flex-tab/tabs/membersList.html
index 2e403adb74e056f9325a660b46e18777f8ec366c..4f1675dead84a80006c7719b6f838de1a1be47a2 100644
--- a/packages/rocketchat-ui-flextab/flex-tab/tabs/membersList.html
+++ b/packages/rocketchat-ui-flextab/flex-tab/tabs/membersList.html
@@ -6,34 +6,40 @@
 				{{#with roomUsers}}
 					<div class="title">
 						<h2>{{_ "Members_List"}}</h2>
-						<p>
-							{{{_ "Showing_online_users" total_showing=totalShowing online=totalOnline total=total}}}
-							<button class="see-all">{{seeAll}}</button>
-						</p>
 						{{> videoButtons}}
 						{{#if canAddUser}}
 							<div class="control">
 								<div class="search-form">
 									<div class="input-line search">
-										{{> inputAutocomplete settings=autocompleteSettingsAddUser id="user-add-search" class="search" placeholder=tAddUsers}}
-										<i class="icon-plus"></i>
+										{{> inputAutocomplete settings=autocompleteSettingsAddUser id="user-add-search" class="search content-background-color" placeholder=tAddUsers}}
+										<i class="icon-plus secondary-font-color"></i>
 									</div>
 								</div>
 							</div>
 						{{/if}}
+						<p>
+							{{#unless loading}}
+								{{{_ "Showing_online_users" total_showing=totalShowing online=totalOnline total=total}}}
+								<button class="see-all">{{seeAll}}</button>
+							{{/unless}}
+						</p>
 					</div>
 					<ul class='list clearfix lines'>
-						{{#each users}}
-							<li class='user-image user-card-room status-{{status}}'>
-								<button data-username="{{username}}" tabindex="0" title="{{username}}">
-									{{> avatar username=username}}
-									<p>{{username}} {{utcOffset}}</p>
-									{{#if muted}}
-										<i class="icon-mute" title="{{_ "User_muted"}}"></i>
-									{{/if}}
-								</button>
-							</li>
-						{{/each}}
+						{{#if loading}}
+							{{> loading}}
+						{{else}}
+							{{#each users}}
+								<li class='user-image user-card-room status-{{status}}'>
+									<button data-username="{{username}}" tabindex="0" title="{{username}}">
+										{{> avatar username=username}}
+										<p>{{username}} {{utcOffset}}</p>
+										{{#if muted}}
+											<i class="icon-mute" title="{{_ "User_muted"}}"></i>
+										{{/if}}
+									</button>
+								</li>
+							{{/each}}
+						{{/if}}
 					</ul>
 					{{#if hasMore}}
 						<button class="button show-more-users">{{_ "Show_more"}}</button>
diff --git a/packages/rocketchat-ui-flextab/flex-tab/tabs/messageSearch.html b/packages/rocketchat-ui-flextab/flex-tab/tabs/messageSearch.html
index 8a2862ab7f903c5ba80b961c6e1953e581606611..540b8b3ba6e3409e118708c7fcec8a88432d5aa3 100644
--- a/packages/rocketchat-ui-flextab/flex-tab/tabs/messageSearch.html
+++ b/packages/rocketchat-ui-flextab/flex-tab/tabs/messageSearch.html
@@ -3,13 +3,13 @@
 		<div class="list-view search-messages-list">
 			<div class="title">
 				<h2>{{_ "Search_Messages"}}</h2>
-				<p>{{_ "You_can_search_using_RegExp_eg"}} <code class="inline">/^text$/i</code></p>
+				<p>{{_ "You_can_search_using_RegExp_eg"}} <code class="code-colors inline">/^text$/i</code></p>
 			</div>
 			<div class="control">
 				<form class="search-form" role="form">
 					<div class="input-line search">
-						<input type="text" id="message-search" class="search" placeholder="{{tSearchMessages}}" autocomplete="off" />
-						<i class="icon-right-open-small"></i>
+						<input type="text" id="message-search" class="search content-background-color" placeholder="{{tSearchMessages}}" autocomplete="off" />
+						<i class="icon-search secondary-font-color"></i>
 					</div>
 				</form>
 			</div>
@@ -19,23 +19,19 @@
 				{{/unless}}
 			{{/if}}
 		</div>
-		<ul class="list clearfix">
-			{{#if currentSearchTerm}}
-				{{#if searchResultMessages}}
+		{{#if currentSearchTerm}}
+			{{#if searchResultMessages}}
+				<ul class="list clearfix">
 					{{#each searchResultMessages}}
 						{{#nrr nrrargs 'message' message}}{{/nrr}}
 					{{/each}}
-					{{#if hasMore}}
-						<li class="load-more">
-							{{#if ready}}
-								<button>{{_ "Has_more"}}...</button>
-							{{else}}
-								<div class="load-more-loading">{{_ "Loading..."}}</div>
-							{{/if}}
-						</li>
-					{{/if}}
+				</ul>
+				{{#if hasMore}}
+					<div class="load-more">
+						{{> loading}}
+					</div>
 				{{/if}}
 			{{/if}}
-		</ul>
+		{{/if}}
 	</div>
 </template>
diff --git a/packages/rocketchat-ui-flextab/flex-tab/tabs/uploadedFilesList.coffee b/packages/rocketchat-ui-flextab/flex-tab/tabs/uploadedFilesList.coffee
index e0196df020a9e7eb2e597c00e2e7def246a8f562..7bc48eb25b71cb896f6c971037bd190e0d9126db 100644
--- a/packages/rocketchat-ui-flextab/flex-tab/tabs/uploadedFilesList.coffee
+++ b/packages/rocketchat-ui-flextab/flex-tab/tabs/uploadedFilesList.coffee
@@ -29,6 +29,22 @@ Template.uploadedFilesList.helpers
 	url: ->
 		return '/file-upload/' + @_id + '/' + @name
 
+	fixCordova: (url) ->
+		if Meteor.isCordova and url?[0] is '/'
+			url = Meteor.absoluteUrl().replace(/\/$/, '') + url
+			query = "rc_uid=#{Meteor.userId()}&rc_token=#{Meteor._localStorage.getItem('Meteor.loginToken')}"
+			if url.indexOf('?') is -1
+				url = url + '?' + query
+			else
+				url = url + '&' + query
+
+		if Meteor.settings.public.sandstorm or url.match /^(https?:)?\/\//i
+			return url
+		else if navigator.userAgent.indexOf('Electron') > -1
+			return __meteor_runtime_config__.ROOT_URL_PATH_PREFIX + url
+		else
+			return Meteor.absoluteUrl().replace(/\/$/, '') + __meteor_runtime_config__.ROOT_URL_PATH_PREFIX + url
+
 Template.uploadedFilesList.events
 	'click .room-file-item': (e, t) ->
 		if $(e.currentTarget).siblings('.icon-picture').length
diff --git a/packages/rocketchat-ui-flextab/flex-tab/tabs/uploadedFilesList.html b/packages/rocketchat-ui-flextab/flex-tab/tabs/uploadedFilesList.html
index 4d8a25c79b01c5907331318289149d221fb15b9a..22d4bb206f04d39c9e8ae85102c0b5bf87f70e14 100644
--- a/packages/rocketchat-ui-flextab/flex-tab/tabs/uploadedFilesList.html
+++ b/packages/rocketchat-ui-flextab/flex-tab/tabs/uploadedFilesList.html
@@ -10,25 +10,21 @@
 						{{#if canDelete}}
 						<i class="icon-trash file-delete"></i>
 						{{/if}}
-						<a title="{{escapedName}}" href="{{url}}" target="_blank" class="file-download" download="">
+						<a title="{{escapedName}}" href="{{fixCordova url}}" target="_blank" class="file-download" download="">
 							<i class="icon-download file-download"></i>
 						</a>
-						<a title="{{escapedName}}" href="{{url}}" target="_blank" class="room-file-item file-name {{customClassForFileType}}">
+						<a title="{{escapedName}}" href="{{fixCordova url}}" target="_blank" class="room-file-item file-name {{customClassForFileType}}">
 							<i class="{{getFileIcon type}}"></i>
 							<p>{{name}}</p>
 						</a>
 					</li>
 				{{/each}}
-				{{#if hasMore}}
-					<li class="load-more">
-						{{#if Template.subscriptionsReady}}
-							<button>{{_ "Has_more"}}...</button>
-						{{else}}
-							<div class="load-more-loading">{{_ "Loading..."}}</div>
-						{{/if}}
-					</li>
-				{{/if}}
 			</ul>
+			{{#if hasMore}}
+				<div class="load-more">
+					{{> loading}}
+				</div>
+			{{/if}}
 			{{#if Template.subscriptionsReady}}
 				{{#unless hasFiles}}
 					<h2>{{_ "Room_uploaded_file_list_empty"}}</h2>
diff --git a/packages/rocketchat-ui-flextab/flex-tab/tabs/userEdit.html b/packages/rocketchat-ui-flextab/flex-tab/tabs/userEdit.html
index 7fd153244033bd319b581ca7962e52a0d49e9979..f05851461c57e4fc39d8ce9cb6c1240768f0978d 100644
--- a/packages/rocketchat-ui-flextab/flex-tab/tabs/userEdit.html
+++ b/packages/rocketchat-ui-flextab/flex-tab/tabs/userEdit.html
@@ -1,6 +1,6 @@
 <template name="userEdit">
 	{{#unless canEditOrAdd}}
-		<p>{{_ "You_are_not_authorized_to_view_this_page"}}</p>
+		<p class="secondary-font-color">{{_ "You_are_not_authorized_to_view_this_page"}}</p>
 	{{else}}
 		<div class="about clearfix">
 			<form class="edit-form" autocomplete="off">
diff --git a/packages/rocketchat-ui-flextab/flex-tab/tabs/userInfo.coffee b/packages/rocketchat-ui-flextab/flex-tab/tabs/userInfo.coffee
index a86ed4aee1cee21c911b85da222350779c41df4b..c78c5f5c600c40179a1fa8228abf08596e15b514 100644
--- a/packages/rocketchat-ui-flextab/flex-tab/tabs/userInfo.coffee
+++ b/packages/rocketchat-ui-flextab/flex-tab/tabs/userInfo.coffee
@@ -111,6 +111,15 @@ Template.userInfo.helpers
 		roles = _.union(UserRoles.findOne(uid)?.roles, RoomRoles.findOne({'u._id': uid, rid: Session.get('openedRoom') })?.roles)
 		return RocketChat.models.Roles.find({ _id: { $in: roles }, description: { $exists: 1 } }, { fields: { description: 1 } })
 
+	isDirect: ->
+		room = ChatRoom.findOne(Session.get('openedRoom'))
+
+		return room?.t is 'd'
+
+	isBlocker: ->
+		subscription = ChatSubscription.findOne({rid:Session.get('openedRoom'), 'u._id': Meteor.userId()}, { fields: { blocker: 1 } });
+		return subscription.blocker
+
 Template.userInfo.events
 	'click .thumb': (e) ->
 		$(e.currentTarget).toggleClass('bigger')
@@ -123,7 +132,7 @@ Template.userInfo.events
 			if result?.rid?
 				FlowRouter.go('direct', { username: @username }, FlowRouter.current().queryParams, ->
 				if window.matchMedia("(max-width: 500px)").matches
-					RocketChat.TabBar.closeFlex())                   
+					RocketChat.TabBar.closeFlex())
 
 	"click .flex-tab  .video-remote" : (e) ->
 		if RocketChat.TabBar.isFlexOpen()
@@ -343,6 +352,26 @@ Template.userInfo.events
 
 		instance.editingUser.set instance.user.get()._id
 
+	'click .block-user': (e, instance) ->
+		e.stopPropagation()
+		e.preventDefault()
+
+		Meteor.call 'blockUser', { rid: Session.get('openedRoom'), blocked: instance.user.get()._id }, (error, result) ->
+			if result
+				toastr.success t('User_is_blocked')
+			if error
+				handleError(error)
+
+	'click .unblock-user': (e, instance) ->
+		e.stopPropagation()
+		e.preventDefault()
+
+		Meteor.call 'unblockUser', { rid: Session.get('openedRoom'), blocked: instance.user.get()._id }, (error, result) ->
+			if result
+				toastr.success t('User_is_unblocked')
+			if error
+				handleError(error)
+
 Template.userInfo.onCreated ->
 	@now = new ReactiveVar moment()
 
diff --git a/packages/rocketchat-ui-flextab/flex-tab/tabs/userInfo.html b/packages/rocketchat-ui-flextab/flex-tab/tabs/userInfo.html
index 7d4a872bfff51ad5dc1f2e2ab1dcb9b171d752dc..4d31d1bb69e9458747f22e29e37e1418fa53d323 100644
--- a/packages/rocketchat-ui-flextab/flex-tab/tabs/userInfo.html
+++ b/packages/rocketchat-ui-flextab/flex-tab/tabs/userInfo.html
@@ -12,30 +12,30 @@
 				</div>
 				<div class="info">
 					<h3 title="{{username}}"><i class="status-{{status}}"></i> {{username}}</h3>
-					<p>{{name}}</p>
-					<p>
+					<p class="secondary-font-color">{{name}}</p>
+					<p class="secondary-font-color">
 						{{#each roleTags}}
 							<span class="role-tag" data-role="{{description}}">{{description}}</span>
 						{{/each}}
 					</p>
-					{{#if utc}}<p><i class="icon-clock"></i>{{userTime}} (UTC {{utc}})</p>{{/if}}
+					{{#if utc}}<p class="secondary-font-color"><i class="icon-clock"></i>{{userTime}} (UTC {{utc}})</p>{{/if}}
 					{{#if hasPermission 'view-full-other-user-info'}}
 						{{#if hasEmails}}
-							{{#each emails}} <p><i class="icon-mail"></i> {{address}}{{#if verified}}&nbsp;<i class="icon-ok"></i>{{/if}}</p> {{/each}}
+							{{#each emails}} <p class="secondary-font-color"><i class="icon-mail"></i> {{address}}{{#if verified}}&nbsp;<i class="icon-ok success-color"></i>{{/if}}</p> {{/each}}
 						{{/if}}
 						{{#if hasPhone}}
-							{{#each phone}} <p><i class="icon-phone"></i> {{phoneNumber}}</p> {{/each}}
+							{{#each phone}} <p class="secondary-font-color"><i class="icon-phone"></i> {{phoneNumber}}</p> {{/each}}
 						{{/if}}
-						{{#if lastLogin}} <p><i class="icon-calendar"></i> {{_ "Created_at"}}: {{createdAt}}</p> {{/if}}
-						{{#if lastLogin}} <p><i class="icon-calendar"></i> {{_ "Last_login"}}: {{lastLogin}}</p> {{/if}}
-						{{#if services.facebook.id}} <p><i class="icon-facebook"></i><a href="{{services.facebook.link}}" target="_blank">{{services.facebook.name}}</a></p> {{/if}}
-						{{#if services.github.id}} <p><i class="icon-github-circled"></i><a href="https://www.github.com/{{services.github.username}}" target="_blank">{{services.github.username}}</a></p> {{/if}}
-						{{#if services.gitlab.id}} <p><i class="icon-gitlab"></i>{{services.gitlab.username}}</p> {{/if}}
-						{{#if services.google.id}} <p><i class="icon-gplus"></i><a href="https://plus.google.com/{{services.google.id}}" target="_blank">{{services.google.name}}</a></p> {{/if}}
-						{{#if services.linkedin.id}} <p><i class="icon-linkedin"></i><a href="{{services.linkedin.publicProfileUrl}}" target="_blank">{{linkedinUsername}}</a></p> {{/if}}
-						{{#if servicesMeteor.id}} <p><i class="icon-meteor"></i>{{servicesMeteor.username}}</p> {{/if}}
-						{{#if services.twitter.id}} <p><i class="icon-twitter"></i><a href="https://twitter.com/{{services.twitter.screenName}}" target="_blank">{{services.twitter.screenName}}</a></p> {{/if}}
-						{{#if services.wordpress.id}} <p><i class="icon-wordpress"></i>{{services.wordpress.user_login}}</p> {{/if}}
+						{{#if lastLogin}} <p class="secondary-font-color"><i class="icon-calendar"></i> {{_ "Created_at"}}: {{createdAt}}</p> {{/if}}
+						{{#if lastLogin}} <p class="secondary-font-color"><i class="icon-calendar"></i> {{_ "Last_login"}}: {{lastLogin}}</p> {{/if}}
+						{{#if services.facebook.id}} <p class="secondary-font-color"><i class="icon-facebook"></i><a href="{{services.facebook.link}}" target="_blank">{{services.facebook.name}}</a></p> {{/if}}
+						{{#if services.github.id}} <p class="secondary-font-color"><i class="icon-github-circled"></i><a href="https://www.github.com/{{services.github.username}}" target="_blank">{{services.github.username}}</a></p> {{/if}}
+						{{#if services.gitlab.id}} <p class="secondary-font-color"><i class="icon-gitlab"></i>{{services.gitlab.username}}</p> {{/if}}
+						{{#if services.google.id}} <p class="secondary-font-color"><i class="icon-gplus"></i><a href="https://plus.google.com/{{services.google.id}}" target="_blank">{{services.google.name}}</a></p> {{/if}}
+						{{#if services.linkedin.id}} <p class="secondary-font-color"><i class="icon-linkedin"></i><a href="{{services.linkedin.publicProfileUrl}}" target="_blank">{{linkedinUsername}}</a></p> {{/if}}
+						{{#if servicesMeteor.id}} <p class="secondary-font-color"><i class="icon-meteor"></i>{{servicesMeteor.username}}</p> {{/if}}
+						{{#if services.twitter.id}} <p class="secondary-font-color"><i class="icon-twitter"></i><a href="https://twitter.com/{{services.twitter.screenName}}" target="_blank">{{services.twitter.screenName}}</a></p> {{/if}}
+						{{#if services.wordpress.id}} <p class="secondary-font-color"><i class="icon-wordpress"></i>{{services.wordpress.user_login}}</p> {{/if}}
 					{{/if}}
 				</div>
 			</div>
@@ -44,23 +44,29 @@
 				{{#if user.active}}
 					{{> videoButtons}}
 				{{/if}}
+				{{#if isDirect}}
+					{{#if isBlocker}}
+						<button class='button button-block tertiary unblock-user'><span><i class='icon-block'></i> {{_ "Unblock_User"}}</span></button>
+					{{else}}
+						<button class='button button-block danger block-user'><span><i class='icon-block'></i> {{_ "Block_User"}}</span></button>
+					{{/if}}
+				{{/if}}
 
 				{{#if showAll}}
 					{{#if canDirectMessage user.username}}
-						<button class='button button-block primary pvt-msg'><span><i class='icon-chat'></i> {{_ "Conversation"}}</span></button>
-					{{/if}}
+						<button class='button button-block primary pvt-msg'><span><i class='icon-chat'></i> {{_ "Conversation"}}</span></button> {{/if}}
 					{{#if canSetOwner}}
 						{{#if isOwner}}
 							<button class="button button-block danger unset-owner"><span>{{_ "Remove_as_owner"}}</span></button>
 						{{else}}
-							<button class="button button-block secondary set-owner"><span>{{_ "Set_as_owner"}}</span></button>
+							<button class="button button-block tertiary set-owner"><span>{{_ "Set_as_owner"}}</span></button>
 						{{/if}}
 					{{/if}}
 					{{#if canSetModerator}}
 						{{#if isModerator}}
 							<button class="button button-block danger unset-moderator"><span>{{_ "Remove_as_moderator"}}</span></button>
 						{{else}}
-							<button class="button button-block secondary set-moderator"><span>{{_ "Set_as_moderator"}}</span></button>
+							<button class="button button-block tertiary set-moderator"><span>{{_ "Set_as_moderator"}}</span></button>
 						{{/if}}
 					{{/if}}
 					{{#if canMuteUser}}
diff --git a/packages/rocketchat-ui-login/login/form.coffee b/packages/rocketchat-ui-login/login/form.coffee
index 6f35258fec2c44504d8e42a062fc4296b6161b34..53abe369367725fa6c631c364962d6b54c583806 100644
--- a/packages/rocketchat-ui-login/login/form.coffee
+++ b/packages/rocketchat-ui-login/login/form.coffee
@@ -47,22 +47,6 @@ Template.loginForm.helpers
 	hasOnePassword: ->
 		return OnePassword?.findLoginForUrl? && device?.platform?.toLocaleLowerCase() is 'ios'
 
-	customFields: ->
-		if not Template.instance().customFields.get()
-			return []
-
-		customFieldsArray = []
-		for key, value of Template.instance().customFields.get()
-			if value.hideFromForm is true
-				continue
-
-			customFieldsArray.push
-				fieldName: key,
-				field: value
-
-		return customFieldsArray
-
-
 Template.loginForm.events
 	'submit #login-card': (event, instance) ->
 		event.preventDefault()
@@ -155,13 +139,6 @@ Template.loginForm.events
 
 		OnePassword.findLoginForUrl(succesCallback, errorCallback, Meteor.absoluteUrl())
 
-	'focus .input-text input': (event) ->
-		$(event.currentTarget).parents('.input-text').addClass('focus')
-
-	'blur .input-text input': (event) ->
-		if event.currentTarget.value is ''
-			$(event.currentTarget).parents('.input-text').removeClass('focus')
-
 
 Template.loginForm.onCreated ->
 	instance = @
diff --git a/packages/rocketchat-ui-login/login/form.html b/packages/rocketchat-ui-login/login/form.html
index fd86236712577da1c54d8372f008888d118674e9..c761e8f19c5bec18409cf770d16d2955cd739f4e 100644
--- a/packages/rocketchat-ui-login/login/form.html
+++ b/packages/rocketchat-ui-login/login/form.html
@@ -1,10 +1,10 @@
 <template name="loginForm">
 	{{#if state 'sandstorm'}}
-		<div class="alert alert-danger">
+		<div class="alert error-color error-background error-border">
 			You must login to Sandstorm (on the top right) in order to access this chat.
 		</div>
 	{{else}}
-		<form id="login-card" method='/' novalidate>
+		<form id="login-card" class="content-background-color color-primary-font-color" method='/' novalidate>
 			{{#if state 'wait-activation'}}
 				<header>
 					<h2>{{{_ "Registration_Succeeded"}}}</h2>
@@ -12,85 +12,75 @@
 					<p>{{{_ "Please_wait_activation"}}}</p>
 				</header>
 			{{else}}
-				{{ > loginServices }}
+				{{> loginServices }}
 				{{#if needsValidateEmail}}
-					<div class="alert alert-danger">
+					<div class="alert error-color error-background error-border">
 						{{_ "You_need_confirm_email"}}
 					</div>
 				{{/if}}
 				{{#if showFormLogin}}
 					<div class="fields">
 						{{#if state 'login'}}
-							<div class='input-text active'>
+							<div class="input-line">
 								<label for="emailOrUsername">{{emailOrUsernamePlaceholder}}</label>
-								<input type="text" name='emailOrUsername' id="emailOrUsername" autocapitalize="off" autocorrect="off" />
-								{{#if hasOnePassword}}
-									<div class="one-passsword"></div>
-								{{/if}}
-								<div class="input-error"></div>
+								<div>
+									<input type="text" name='emailOrUsername' id="emailOrUsername" autocapitalize="off" autocorrect="off" />
+									{{#if hasOnePassword}}
+										<div class="one-passsword"></div>
+									{{/if}}
+									<div class="input-error"></div>
+								</div>
 							</div>
-							<div class='input-text active'>
+							<div class="input-line">
 								<label for="pass">{{passwordPlaceholder}}</label>
-								<input type="password" name='pass' id="pass" />
-								<div class="input-error"></div>
+								<div>
+									<input type="password" name='pass' id="pass" />
+									<div class="input-error"></div>
+								</div>
 							</div>
 						{{/if}}
 						{{#if state 'register'}}
-							<div class='input-text active'>
+							<div class="input-line">
 								<label for="name">{{namePlaceholder}}</label>
-								<input type="text" name='name' id="name" dir="auto" />
-								<div class="input-error"></div>
+								<div>
+									<input type="text" name='name' id="name" dir="auto" />
+									<div class="input-error"></div>
+								</div>
 							</div>
-							<div class='input-text active'>
+							<div class="input-line">
 								<label for="email">{{_ "Email"}}</label>
-								<input type="email" name='email' id="email" />
-								<div class="input-error"></div>
+								<div>
+									<input type="email" name='email' id="email" />
+									<div class="input-error"></div>
+								</div>
 							</div>
-							{{#each customFields}}
-								{{#if $eq field.type 'select'}}
-									<div class='input-text active focus'>
-										<label for="{{fieldName}}">{{_ fieldName}}</label>
-										<div class="select-arrow">
-											<i class="icon-down-open"></i>
-										</div>
-										<select name="{{fieldName}}" data-customfield="true">
-											{{#each field.options}}
-												{{#if $eq . ../field.defaultValue}}
-													<option value="{{.}}" selected>{{_ .}}</option>
-												{{else}}
-													<option value="{{.}}">{{_ .}}</option>
-												{{/if}}
-											{{/each}}
-										</select>
-										<div class="input-error"></div>
-									</div>
-								{{/if}}
-								{{#if $eq field.type 'text'}}
-									<div class='input-text active'>
-										<label for="{{fieldName}}">{{_ fieldName}}</label>
-										<input type="text" name="{{fieldName}}" id="{{fieldName}}" data-customfield="true" value="{{field.defaultValue}}" maxlength="{{field.maxLength}}" />
-										<div class="input-error"></div>
-									</div>
-								{{/if}}
-							{{/each}}
-							<div class='input-text active'>
+
+							{{> customFieldsForm hideFromForm=true}}
+
+							<div class="input-line">
 								<label for="pass">{{passwordPlaceholder}}</label>
-								<input type="password" name='pass' id="pass" />
-								<div class="input-error"></div>
+								<div>
+									<input type="password" name='pass' id="pass" />
+									<div class="input-error"></div>
+								</div>
 							</div>
 							{{#if requirePasswordConfirmation}}
-								<div class='input-text active'>
+								<div class="input-line">
 									<label for="confirm-pass">{{_ "Confirm_password"}}</label>
-									<input type="password" name='confirm-pass' id="confirm-pass" />
-									<div class="input-error"></div>
+									<div>
+										<input type="password" name='confirm-pass' id="confirm-pass" />
+										<div class="input-error"></div>
+									</div>
 								</div>
 							{{/if}}
 						{{/if}}
 						{{#if state 'forgot-password' 'email-verification'}}
-							<div class='input-text active'>
+							<div class="input-line">
 								<label for="email">{{_ "Email"}}</label>
-								<input type="email" name='email' id="email" />
-								<div class="input-error"></div>
+								<div>
+									<input type="email" name='email' id="email" />
+									<div class="input-error"></div>
+								</div>
 							</div>
 						{{/if}}
 					</div>
@@ -126,7 +116,7 @@
 		<div class='login-terms'>
 			{{{loginTerms}}}
 			<div class="powered-by">
-				Powered by <a href="https://rocket.chat">Open Source Chat Platform Rocket.Chat</a>.
+				Powered by <a class="color-tertiary-font-color" href="https://rocket.chat">Open Source Chat Platform Rocket.Chat</a>.
 			</div>
 		</div>
 	{{/if}}
diff --git a/packages/rocketchat-ui-login/login/layout.html b/packages/rocketchat-ui-login/login/layout.html
index a097d5834bb2a9f91fd6892e1a06221dd2e17524..056958c7a019802d863a419880ad392c79fb8a66 100644
--- a/packages/rocketchat-ui-login/login/layout.html
+++ b/packages/rocketchat-ui-login/login/layout.html
@@ -1,9 +1,9 @@
 <template name="loginLayout">
-	<section class="full-page">
+	<section class="full-page color-tertiary-font-color">
 		<div class="wrapper">
-			{{ > loginHeader }}
+			{{> loginHeader }}
 			{{> Template.dynamic template=center}}
-			{{ > loginFooter }}
+			{{> loginFooter }}
 		</div>
 	</section>
 </template>
diff --git a/packages/rocketchat-ui-login/reset-password/resetPassword.html b/packages/rocketchat-ui-login/reset-password/resetPassword.html
index 8592692eb7532b06ada3286046af2fbce03be70e..cb35991720aab3ee82fade1d6bd8bdbd5dc8888d 100644
--- a/packages/rocketchat-ui-login/reset-password/resetPassword.html
+++ b/packages/rocketchat-ui-login/reset-password/resetPassword.html
@@ -1,5 +1,5 @@
 <template name="resetPassword">
-	<form id="login-card" action="/">
+	<form id="login-card" class="content-background-color color-primary-font-color" action="/">
 		<div class="fields">
 			<header>
 			{{#if requirePasswordChange}}
diff --git a/packages/rocketchat-ui-login/username/layout.html b/packages/rocketchat-ui-login/username/layout.html
index 7302211d5d537631daccbea46c4949cd1be63adb..d2e6407055288ba35a1ecefa7ad2315713dee882 100644
--- a/packages/rocketchat-ui-login/username/layout.html
+++ b/packages/rocketchat-ui-login/username/layout.html
@@ -1,5 +1,5 @@
 <template name="usernameLayout">
-	<section class="full-page">
+	<section class="full-page color-tertiary-font-color">
 		<div class="wrapper">
 			{{> Template.dynamic template=render}}
 		</div>
diff --git a/packages/rocketchat-ui-login/username/username.coffee b/packages/rocketchat-ui-login/username/username.coffee
index 48686fa7459cf5c74687b46809f684a778782fc3..225d190b79cb582754b71028550a5aa00fa5fe15 100644
--- a/packages/rocketchat-ui-login/username/username.coffee
+++ b/packages/rocketchat-ui-login/username/username.coffee
@@ -52,6 +52,3 @@ Template.username.events
 			RocketChat.Button.reset(button)
 			instance.username.set(username)
 			RocketChat.callbacks.run('usernameSet')
-
-			if not err?
-				Meteor.call 'joinDefaultChannels'
diff --git a/packages/rocketchat-ui-login/username/username.html b/packages/rocketchat-ui-login/username/username.html
index 4f12d49f0d30636fc0807c594f1c0937c02e63de..1f64b55e25c66b325e41d9a78b233bea906a1a43 100644
--- a/packages/rocketchat-ui-login/username/username.html
+++ b/packages/rocketchat-ui-login/username/username.html
@@ -1,23 +1,23 @@
 <template name="username">
-	<section class="full-page">
+	<section class="full-page color-tertiary-font-color">
 		<div class="wrapper">
-			<form id="login-card" method='/'>
+			<form id="login-card" class="content-background-color color-primary-font-color" method='/'>
 				<header>
 					<h2>{{_ "Username_title"}}</h2>
 					<p>{{_ "Username_description"}}</p>
 				</header>
 				{{#if username.error}}
-					<div class="alert alert-danger">
+					<div class="alert error-color error-background error-border">
 						{{{_ "error-field-unavailable" field=username.username}}}
 					</div>
 				{{/if}}
 				{{#if username.invalid}}
-					<div class="alert alert-danger">
+					<div class="alert error-color error-background error-border">
 						{{{_ "Username_invalid" username.username}}}
 					</div>
 				{{/if}}
 				{{#if username.empty}}
-					<div class="alert alert-danger">
+					<div class="alert error-color error-background error-border">
 						{{{_ "Username_cant_be_empty"}}}
 					</div>
 				{{/if}}
diff --git a/packages/rocketchat-ui-master/master/error.html b/packages/rocketchat-ui-master/master/error.html
index 4290413f22fad872fffab3571336116722b2058e..07060aac8b95f5740579a8b6e77fe979d8ff7cb5 100644
--- a/packages/rocketchat-ui-master/master/error.html
+++ b/packages/rocketchat-ui-master/master/error.html
@@ -1,5 +1,5 @@
 <template name="error">
-	<section class="full-page">
+	<section class="full-page color-tertiary-font-color">
 		<div class="wrapper">
 			<header>
 				<a class="logo" href="/">
diff --git a/packages/rocketchat-ui-master/master/loading.html b/packages/rocketchat-ui-master/master/loading.html
index d6c4bae4c36ae6ae24b0218a1cd1c8ad7d9c2cd2..8cfdfef28ffca04f0279ef9fbae6b2f2feeb6d89 100644
--- a/packages/rocketchat-ui-master/master/loading.html
+++ b/packages/rocketchat-ui-master/master/loading.html
@@ -1,5 +1,5 @@
 <template name="loading">
-	<div class="loading">
+	<div class="loading-animation">
 		<div class="bounce1"></div>
 		<div class="bounce2"></div>
 		<div class="bounce3"></div>
diff --git a/packages/rocketchat-ui-master/master/logoLayout.html b/packages/rocketchat-ui-master/master/logoLayout.html
index c7decca4f52c297799e74cdbae85ab589289497a..f59261572c31a83e9f702f9e01375196bfe10b44 100644
--- a/packages/rocketchat-ui-master/master/logoLayout.html
+++ b/packages/rocketchat-ui-master/master/logoLayout.html
@@ -1,5 +1,5 @@
 <template name="logoLayout">
-	<section class="full-page">
+	<section class="full-page color-tertiary-font-color">
 		<div class="wrapper">
 			<header>
 				<a class="logo" href="/">
diff --git a/packages/rocketchat-ui-master/master/main.coffee b/packages/rocketchat-ui-master/master/main.coffee
index 96e72c2c0d5b0eb28ea9f394ad8d6be5a3d0b3da..2e80fe1425be45a1f958c0109925f1a578ee672a 100644
--- a/packages/rocketchat-ui-master/master/main.coffee
+++ b/packages/rocketchat-ui-master/master/main.coffee
@@ -79,68 +79,6 @@ Template.body.onRendered ->
 				j.src = '//www.googletagmanager.com/gtm.js?id=' + i + dl
 				f.parentNode.insertBefore j, f
 
-	Tracker.autorun (c) ->
-		if RocketChat.settings.get 'Meta_language'
-			c.stop()
-
-			Meta.set
-				name: 'http-equiv'
-				property: 'content-language'
-				content: RocketChat.settings.get 'Meta_language'
-			Meta.set
-				name: 'name'
-				property: 'language'
-				content: RocketChat.settings.get 'Meta_language'
-
-	Tracker.autorun (c) ->
-		if RocketChat.settings.get 'Meta_fb_app_id'
-			c.stop()
-
-			Meta.set
-				name: 'property'
-				property: 'fb:app_id'
-				content: RocketChat.settings.get 'Meta_fb_app_id'
-
-	Tracker.autorun (c) ->
-		if RocketChat.settings.get 'Meta_robots'
-			c.stop()
-
-			Meta.set
-				name: 'name'
-				property: 'robots'
-				content: RocketChat.settings.get 'Meta_robots'
-
-	Tracker.autorun (c) ->
-		if RocketChat.settings.get 'Meta_google-site-verification'
-			c.stop()
-
-			Meta.set
-				name: 'name'
-				property: 'google-site-verification'
-				content: RocketChat.settings.get 'Meta_google-site-verification'
-
-	Tracker.autorun (c) ->
-		if RocketChat.settings.get 'Meta_msvalidate01'
-			c.stop()
-
-			Meta.set
-				name: 'name'
-				property: 'msvalidate.01'
-				content: RocketChat.settings.get 'Meta_msvalidate01'
-
-	Tracker.autorun (c) ->
-		c.stop()
-
-		Meta.set
-			name: 'name'
-			property: 'application-name'
-			content: RocketChat.settings.get 'Site_Name'
-
-		Meta.set
-			name: 'name'
-			property: 'apple-mobile-web-app-title'
-			content: RocketChat.settings.get 'Site_Name'
-
 	if Meteor.isCordova
 		$(document.body).addClass 'is-cordova'
 
@@ -199,12 +137,10 @@ Template.main.helpers
 	embeddedVersion: ->
 		return 'embedded-view' if RocketChat.Layout.isEmbedded()
 
-
 Template.main.events
 
 	"click .burger": ->
 		console.log 'room click .burger' if window.rocketDebug
-		chatContainer = $("#rocket-chat")
 		menu.toggle()
 
 	'touchstart': (e, t) ->
@@ -215,17 +151,18 @@ Template.main.events
 		t.touchstartY = undefined
 		t.movestarted = false
 		t.blockmove = false
+		t.isRtl = isRtl localStorage.getItem "userLanguage"
 		if $(e.currentTarget).closest('.main-content').length > 0
 			t.touchstartX = e.originalEvent.touches[0].clientX
 			t.touchstartY = e.originalEvent.touches[0].clientY
-			t.mainContent = $('.main-content')
+			t.mainContent = $('.main-content, .flex-tab-bar')
 			t.wrapper = $('.messages-box > .wrapper')
 
 	'touchmove': (e, t) ->
 		if t.touchstartX?
 			touch = e.originalEvent.touches[0]
-			diffX = t.touchstartX - touch.clientX
-			diffY = t.touchstartY - touch.clientY
+			diffX = touch.clientX - t.touchstartX
+			diffY = touch.clientY - t.touchstartY
 			absX = Math.abs(diffX)
 			absY = Math.abs(diffY)
 
@@ -235,37 +172,58 @@ Template.main.events
 			if t.blockmove isnt true and (t.movestarted is true or absX > 5)
 				t.movestarted = true
 
-				if menu.isOpen()
-					t.left = 260 - diffX
+				if t.isRtl
+					if menu.isOpen()
+						t.diff = -260 + diffX
+					else
+						t.diff = diffX
+
+					if t.diff < -260
+						t.diff = -260
+					if t.diff > 0
+						t.diff = 0
 				else
-					t.left = -diffX
+					if menu.isOpen()
+						t.diff = 260 + diffX
+					else
+						t.diff = diffX
 
-				if t.left > 260
-					t.left = 260
-				if t.left < 0
-					t.left = 0
+					if t.diff > 260
+						t.diff = 260
+					if t.diff < 0
+						t.diff = 0
 
 				t.mainContent.addClass('notransition')
-				t.mainContent.css('transform', 'translate('+t.left+'px)')
+				t.mainContent.css('transform', 'translate(' + t.diff + 'px)')
 				t.wrapper.css('overflow', 'hidden')
 
 	'touchend': (e, t) ->
 		if t.movestarted is true
 			t.mainContent.removeClass('notransition')
-			t.mainContent.css('transform', '');
 			t.wrapper.css('overflow', '')
 
-			if menu.isOpen()
-				if t.left >= 200
-					menu.open()
+			if t.isRtl
+				if menu.isOpen()
+					if t.diff >= -200
+						menu.close()
+					else
+						menu.open()
 				else
-					menu.close()
+					if t.diff <= -60
+						menu.open()
+					else
+						menu.close()
 			else
-				if t.left >= 60
-					menu.open()
+				if menu.isOpen()
+					if t.diff >= 200
+						menu.open()
+					else
+						menu.close()
 				else
-					menu.close()
-
+					if t.diff >= 60
+						menu.open()
+					else
+						menu.close()
 
 Template.main.onRendered ->
 
diff --git a/packages/rocketchat-ui-master/master/main.html b/packages/rocketchat-ui-master/master/main.html
index ff577bb694aa257915303aeab505d38ee6d34fc6..754aadcb59603bbc658712280c43d80ee106b62f 100644
--- a/packages/rocketchat-ui-master/master/main.html
+++ b/packages/rocketchat-ui-master/master/main.html
@@ -2,41 +2,25 @@
 	<meta charset="utf-8" />
 	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
 	<meta http-equiv="expires" content="-1" />
-	<meta http-equiv="X-UA-Compatible" content="IE=edge">
+	<meta http-equiv="X-UA-Compatible" content="IE=edge" />
 	<meta name="fragment" content="!" />
 	<meta name="distribution" content="global" />
 	<meta name="rating" content="general" />
 	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
-	<meta name="msapplication-TileColor" content="#04436a">
-	<meta name="msapplication-TileImage" content="images/logo/mstile-144x144.png?v=3">
-	<meta name="msapplication-config" content="images/logo/browserconfig.xml?v=3">
-	<meta name="theme-color" content="#04436a">
-	<link rel="manifest" href="images/logo/manifest.json?v=3">
-	<link rel="chrome-webstore-item" href="https://chrome.google.com/webstore/detail/nocfbnnmjnndkbipkabodnheejiegccf">
-	<link rel="icon" sizes="any" type="image/svg+xml" href="assets/favicon.svg?v=3">
-	<link rel="icon" sizes="256x256" type="image/png" href="assets/favicon_256.png?v=3">
-	<link rel="icon" sizes="192x192" type="image/png" href="assets/favicon_192.png?v=3">
-	<link rel="icon" sizes="128x128" type="image/png" href="assets/favicon_128.png?v=3">
-	<link rel="icon" sizes="96x96" type="image/png" href="assets/favicon_96.png?v=3">
-	<link rel="icon" sizes="64x64" type="image/png" href="assets/favicon_64.png?v=3">
-	<!--
-	<link rel="icon" sizes="48x48" type="image/png" href="/images/logo/favicon-48x48.png?v=3">
-	<link rel="icon" sizes="32x32" type="image/png" href="/images/logo/favicon-32x32.png?v=3">
-	<link rel="icon" sizes="16x16" type="image/png" href="/images/logo/favicon-16x16.png?v=3">
-	-->
-	<link rel="shortcut icon" sizes="16x16 32x32 48x48" type="image/x-icon" href="assets/favicon_ico.ico?v=3" />
-	<link rel="apple-touch-icon" sizes="57x57" href="images/logo/apple-touch-icon-57x57.png?v=3">
-	<link rel="apple-touch-icon" sizes="60x60" href="images/logo/apple-touch-icon-60x60.png?v=3">
-	<link rel="apple-touch-icon" sizes="72x72" href="images/logo/apple-touch-icon-72x72.png?v=3">
-	<link rel="apple-touch-icon" sizes="76x76" href="images/logo/apple-touch-icon-76x76.png?v=3">
-	<link rel="apple-touch-icon" sizes="114x114" href="images/logo/apple-touch-icon-114x114.png?v=3">
-	<link rel="apple-touch-icon" sizes="120x120" href="images/logo/apple-touch-icon-120x120.png?v=3">
-	<link rel="apple-touch-icon" sizes="144x144" href="images/logo/apple-touch-icon-144x144.png?v=3">
-	<link rel="apple-touch-icon" sizes="152x152" href="images/logo/apple-touch-icon-152x152.png?v=3">
-	<link rel="apple-touch-icon" sizes="180x180" href="images/logo/apple-touch-icon-180x180.png?v=3">
+	<meta name="mobile-web-app-capable" content="yes" />
+	<meta name="apple-mobile-web-app-capable" content="yes" />
+	<meta name="msapplication-TileImage" content="images/logo/mstile-144x144.png?v=3" />
+	<meta name="msapplication-config" content="images/logo/browserconfig.xml?v=3" />
+	<link rel="manifest" href="images/logo/manifest.json?v=3" />
+	<link rel="chrome-webstore-item" href="https://chrome.google.com/webstore/detail/nocfbnnmjnndkbipkabodnheejiegccf" />
+	<link rel="icon" sizes="any" type="image/svg+xml" href="assets/favicon.svg?v=3" />
+	<link rel="icon" sizes="32x32" type="image/png" href="/images/logo/favicon-32x32.png?v=3" />
+	<link rel="icon" sizes="16x16" type="image/png" href="/images/logo/favicon-16x16.png?v=3" />
+	<link rel="mask-icon" href="/images/logo/safari-pinned-tab.svg" color="#04436a">
+	<link rel="apple-touch-icon" sizes="180x180" href="images/logo/apple-touch-icon-180x180.png?v=3" />
 </head>
 
-<body>
+<body class="global-font-family color-primary-font-color">
 </body>
 
 <template name="main">
@@ -63,16 +47,16 @@
 					{{> spotlight}}
 					{{> videoCall overlay=true}}
 					<div id="user-card-popover"></div>
-					<div id="rocket-chat" class="{{embeddedVersion}} menu-nav menu-closed">
+					<div id="rocket-chat" class="{{embeddedVersion}} menu-nav">
 						<div class="connection-status">
 							{{> status}}
 						</div>
 						{{#unless modal}}
-							<div class="flex-tab-bar" role="toolbar">
+							<div class="flex-tab-bar content-background-color" role="toolbar">
 								{{> flexTabBar}}
 							</div>
 						{{/unless}}
-						<div class="main-content {{flexOpened}} {{flexOpenedRTC1}} {{flexOpenedRTC2}} {{#if modal}}main-modal{{/if}}">
+						<div class="main-content content-background-color {{flexOpened}} {{flexOpenedRTC1}} {{flexOpenedRTC2}} {{#if modal}}main-modal{{/if}}">
 							{{> Template.dynamic template=center}}
 						</div>
 						{{#unless modal}}
diff --git a/packages/rocketchat-ui-master/server/inject.js b/packages/rocketchat-ui-master/server/inject.js
index 6f4dca356aa38399c0eca9d82ffa163c3d4bde80..98b8b585dea84694da7af1781cda3618d392fc47 100644
--- a/packages/rocketchat-ui-master/server/inject.js
+++ b/packages/rocketchat-ui-master/server/inject.js
@@ -1,8 +1,8 @@
 /* globals Inject */
 
-Inject.rawBody('page-loading', `
+Inject.rawHead('page-loading', `
 <style>
-.loading {
+.loading-animation {
 	top: 0;
 	right: 0;
 	bottom: 0;
@@ -13,60 +13,70 @@ Inject.rawBody('page-loading', `
 	justify-content: center;
 	text-align: center;
 }
-.loading > div {
+.loading-animation > div {
 	width: 10px;
 	height: 10px;
 	margin: 2px;
 	border-radius: 100%;
 	display: inline-block;
+	background-color: rgba(255,255,255,0.6);
 	-webkit-animation: loading-bouncedelay 1.4s infinite ease-in-out both;
 	animation: loading-bouncedelay 1.4s infinite ease-in-out both;
 }
-.loading .bounce1 {
+.loading-animation .bounce1 {
 	-webkit-animation-delay: -0.32s;
 	animation-delay: -0.32s;
 }
-.loading .bounce2 {
+.loading-animation .bounce2 {
 	-webkit-animation-delay: -0.16s;
 	animation-delay: -0.16s;
 }
 @-webkit-keyframes loading-bouncedelay {
-	0%, 80%, 100% { -webkit-transform: scale(0) }
+	0%,
+	80%,
+	100% { -webkit-transform: scale(0) }
 	40% { -webkit-transform: scale(1.0) }
 }
 @keyframes loading-bouncedelay {
-	0%, 80%, 100% { transform: scale(0); }
+	0%,
+	80%,
+	100% { transform: scale(0); }
 	40% { transform: scale(1.0); }
 }
-</style>
+</style>`);
+
+Inject.rawBody('page-loading-div', `
 <div id="initial-page-loading" class="page-loading">
-	<div class="loading">
+	<div class="loading-animation">
 		<div class="bounce1"></div>
 		<div class="bounce2"></div>
 		<div class="bounce3"></div>
 	</div>
 </div>`);
 
+if (process.env.DISABLE_ANIMATION || process.env.TEST_MODE === 'true') {
+	Inject.rawHead('disable-animation', `
+	<style>
+		body, body * {
+			animation: none !important;
+			transition: none !important;
+		}
+	</style>
+	<script>
+		window.DISABLE_ANIMATION = true;
+	</script>
+	`);
+}
 
-RocketChat.settings.get('theme-color-primary-background-color', function(key, value) {
-	if (value) {
-		Inject.rawHead('theme-color-primary-background-color', `<style>body { background-color: ${value};}</style>`);
-	} else {
-		Inject.rawHead('theme-color-primary-background-color', '<style>body { background-color: #04436a;}</style>');
-	}
+RocketChat.settings.get('theme-color-primary-background-color', (key, value = '#04436a') => {
+	Inject.rawHead(key, `<style>body { background-color: ${value};}</style>` +
+						`<meta name="msapplication-TileColor" content="${value}" />` +
+						`<meta name="theme-color" content="${value}" />`);
 });
 
-RocketChat.settings.get('theme-color-tertiary-background-color', function(key, value) {
+RocketChat.settings.get('Accounts_ForgetUserSessionOnWindowClose', (key, value) => {
 	if (value) {
-		Inject.rawHead('theme-color-tertiary-background-color', `<style>.loading > div { background-color: ${value};}</style>`);
-	} else {
-		Inject.rawHead('theme-color-tertiary-background-color', '<style>.loading > div { background-color: #cccccc;}</style>');
-	}
-});
-
-RocketChat.settings.get('Accounts_ForgetUserSessionOnWindowClose', function(key, value) {
-	if (value) {
-		Inject.rawModHtml('Accounts_ForgetUserSessionOnWindowClose', function(html) {
+		Inject.rawModHtml(key, (html) => {
 			const script = `
 				<script>
 					if (Meteor._localStorage._data === undefined && window.sessionStorage) {
@@ -74,42 +84,58 @@ RocketChat.settings.get('Accounts_ForgetUserSessionOnWindowClose', function(key,
 					}
 				</script>
 			`;
-			return html.replace(/<\/body>/, script+'\n</body>');
+			return html.replace(/<\/body>/, script + '\n</body>');
 		});
 	} else {
-		Inject.rawModHtml('Accounts_ForgetUserSessionOnWindowClose', function(html) {
+		Inject.rawModHtml(key, (html) => {
 			return html;
 		});
 	}
 });
 
-RocketChat.settings.get('Site_Url', function() {
-	Meteor.defer(function() {
-		let baseUrl;
-		if (__meteor_runtime_config__.ROOT_URL_PATH_PREFIX && __meteor_runtime_config__.ROOT_URL_PATH_PREFIX.trim() !== '') {
-			baseUrl = __meteor_runtime_config__.ROOT_URL_PATH_PREFIX;
-		} else {
-			baseUrl = '/';
-		}
-		if (/\/$/.test(baseUrl) === false) {
-			baseUrl += '/';
-		}
-		Inject.rawHead('base', `<base href="${baseUrl}">`);
-	});
+RocketChat.settings.get('Site_Name', (key, value = 'Rocket.Chat') => {
+	Inject.rawHead(key,
+		`<title>${value}</title>` +
+		`<meta name="application-name" content="${value}">` +
+		`<meta name="apple-mobile-web-app-title" content="${value}">`);
 });
 
-RocketChat.settings.get('Site_Name', function(key, value) {
-	if (value) {
-		Inject.rawHead('title', `<title>${value}</title>`);
-	} else {
-		Inject.rawHead('title', '<title>Rocket.Chat</title>');
-	}
+RocketChat.settings.get('Meta_language', (key, value = '') => {
+	Inject.rawHead(key,
+		`<meta http-equiv="content-language" content="${value}">` +
+		`<meta name="language" content="${value}">`);
 });
 
-RocketChat.settings.get('GoogleSiteVerification_id', function(key, value) {
-	if (value) {
-		Inject.rawHead('google-site-verification', `<meta name="google-site-verification" content="${value}" />`);
+RocketChat.settings.get('Meta_robots', (key, value = '') => {
+	Inject.rawHead(key, `<meta name="robots" content="${value}">`);
+});
+
+RocketChat.settings.get('Meta_msvalidate01', (key, value = '') => {
+	Inject.rawHead(key, `<meta name="msvalidate.01" content="${value}">`);
+});
+
+RocketChat.settings.get('Meta_google-site-verification', (key, value = '') => {
+	Inject.rawHead(key, `<meta name="google-site-verification" content="${value}" />`);
+});
+
+RocketChat.settings.get('Meta_fb_app_id', (key, value = '') => {
+	Inject.rawHead(key, `<meta property="fb:app_id" content="${value}">`);
+});
+
+RocketChat.settings.get('Meta_custom', (key, value = '') => {
+	Inject.rawHead(key, value);
+});
+
+Meteor.defer(() => {
+	let baseUrl;
+	if (__meteor_runtime_config__.ROOT_URL_PATH_PREFIX && __meteor_runtime_config__.ROOT_URL_PATH_PREFIX.trim() !== '') {
+		baseUrl = __meteor_runtime_config__.ROOT_URL_PATH_PREFIX;
 	} else {
-		Inject.rawHead('google-site-verification', '');
+		baseUrl = '/';
+	}
+	if (/\/$/.test(baseUrl) === false) {
+		baseUrl += '/';
 	}
+	Inject.rawHead('base', `<base href="${baseUrl}">`);
 });
+
diff --git a/packages/rocketchat-ui-message/message/message.coffee b/packages/rocketchat-ui-message/message/message.coffee
index df3f6cb50fffb74e086b4256f3860388b0726624..76590ba3e3400eb510f0f66446c7ade179fe1b7a 100644
--- a/packages/rocketchat-ui-message/message/message.coffee
+++ b/packages/rocketchat-ui-message/message/message.coffee
@@ -32,8 +32,11 @@ Template.message.helpers
 			return 'temp'
 	body: ->
 		return Template.instance().body
-	system: ->
+	system: (returnClass) ->
 		if RocketChat.MessageTypes.isSystemMessage(this)
+			if returnClass
+				return 'color-info-font-color'
+
 			return 'system'
 	edited: ->
 		return Template.instance().wasEdited
@@ -128,7 +131,6 @@ Template.message.helpers
 	hideReactions: ->
 		return 'hidden' if _.isEmpty(@reactions)
 
-
 	actionLinks: ->
 		# remove 'method_id' and 'params' properties
 		return _.map(@actionLinks, (actionLink, key) -> _.extend({ id: key }, _.omit(actionLink, 'method_id', 'params')))
@@ -230,4 +232,4 @@ Template.message.onViewRendered = (context) ->
 			else
 				if templateInstance?.firstNode && templateInstance?.atBottom is false
 					newMessage = templateInstance?.find(".new-message")
-					newMessage?.className = "new-message"
+					newMessage?.className = "new-message background-primary-action-color"
diff --git a/packages/rocketchat-ui-message/message/message.html b/packages/rocketchat-ui-message/message/message.html
index a5be3b79903fe2859f4eab06ead942f87b468ae3..cb42e24f478d17ce76992f10259c39f94c5b3789 100644
--- a/packages/rocketchat-ui-message/message/message.html
+++ b/packages/rocketchat-ui-message/message/message.html
@@ -1,5 +1,5 @@
 <template name="message">
-	<li id="{{_id}}" class="message {{isSequential}} {{system}} {{t}} {{own}} {{isTemp}} {{chatops}} {{customClass}}" data-username="{{u.username}}" data-groupable="{{isGroupable}}" data-date="{{date}}" data-timestamp="{{timestamp}}">
+	<li id="{{_id}}" class="message background-transparent-dark-hover {{isSequential}} {{system}} {{t}} {{own}} {{isTemp}} {{chatops}} {{customClass}}" data-username="{{u.username}}" data-groupable="{{isGroupable}}" data-date="{{date}}" data-timestamp="{{timestamp}}">
 		<div class="day-divider">
 			<span>{{date}}</span>
 		</div>
@@ -25,16 +25,16 @@
 			{{/if}}
 		{{/if}}
 		{{#if alias}}
-			<button type="button" class="user user-card-message" data-username="{{u.username}}" tabindex="1">{{alias}} <span class="message-alias">@{{u.username}}</span></button>
+			<button type="button" class="user user-card-message color-primary-font-color" data-username="{{u.username}}" tabindex="1">{{alias}} <span class="message-alias border-component-color color-info-font-color">@{{u.username}}</span></button>
 		{{else}}
-			<button type="button" class="user user-card-message" data-username="{{u.username}}" tabindex="1">{{u.username}}</button>
+			<button type="button" class="user user-card-message color-primary-font-color" data-username="{{u.username}}" tabindex="1">{{u.username}}</button>
 		{{/if}}
-		<span class="info">
+		<span class="info border-component-color color-info-font-color">
 		{{#each roleTags}}
-			<span class="role-tag" data-role="{{description}}">{{description}}</span>
+			<span class="role-tag background-info-font-color" data-role="{{description}}">{{description}}</span>
 		{{/each}}
 		{{#if isBot}}
-			<span class="is-bot">BOT</span>
+			<span class="is-bot background-info-font-color">BOT</span>
 		{{/if}}
 		<span class="time" title='{{date}} {{time}}'>{{time}}</span>
 		{{#if edited}}
@@ -50,7 +50,7 @@
 				<i class="icon-cog message-cog" aria-label="{{_ "Actions"}}"></i>
 			</div>
 		</span>
-		<div class="body" dir="auto">
+		<div class="body color-primary-font-color {{system true}}" dir="auto">
 			{{{body}}}
 			{{#if hasOembed}}
 				{{#each urls}}
@@ -63,7 +63,7 @@
 		</div>
 		<ul class="actionLinks {{hideActionLinks}}">
 			{{#each actionLink in actionLinks}}
-				<li>
+				<li class="color-primary-action-color">
 					<span class="action-link" data-actionlink="{{actionLink.id}}">
 						{{#if actionLink.icon}}
 							<i class="{{actionLink.icon}}"></i>
diff --git a/packages/rocketchat-ui-message/message/messageBox.coffee b/packages/rocketchat-ui-message/message/messageBox.coffee
index 869cbf1fc53ba5a8df1e33025cb33c9c2bf422b8..e3f31cb39cb3875d59d89855e74c036fe953e0fd 100644
--- a/packages/rocketchat-ui-message/message/messageBox.coffee
+++ b/packages/rocketchat-ui-message/message/messageBox.coffee
@@ -40,10 +40,17 @@ Template.messageBox.helpers
 
 		roomData = Session.get('roomData' + this._id)
 		if roomData?.t is 'd'
-			if ChatSubscription.findOne({ rid: this._id }, { fields: { archived: 1 } })?.archived
+			subscription = ChatSubscription.findOne({ rid: this._id }, { fields: { archived: 1, blocked: 1, blocker: 1 } })
+			if subscription and (subscription.archived or subscription.blocked or subscription.blocker)
 				return false
 
 		return true
+	isBlockedOrBlocker: ->
+		roomData = Session.get('roomData' + this._id)
+		if roomData?.t is 'd'
+			subscription = ChatSubscription.findOne({ rid: this._id }, { fields: { blocked: 1, blocker: 1 } })
+			if subscription and (subscription.blocked or subscription.blocker)
+				return true
 
 	getPopupConfig: ->
 		template = Template.instance()
@@ -105,7 +112,7 @@ Template.messageBox.helpers
 		return RocketChat.roomTypes.getNotSubscribedTpl @_id
 
 	showSandstorm: ->
-		return Meteor.settings.public.sandstorm
+		return Meteor.settings.public.sandstorm && !Meteor.isCordova
 
 
 Template.messageBox.events
@@ -191,7 +198,7 @@ Template.messageBox.events
 
 		fileUpload filesToUpload
 
-	'click .message-form .geo-location': (event, instance) ->
+	'click .message-form .message-buttons.location': (event, instance) ->
 		roomId = @_id
 
 		position = RocketChat.Geolocation.get()
diff --git a/packages/rocketchat-ui-message/message/messageBox.html b/packages/rocketchat-ui-message/message/messageBox.html
index 80a3ac1d8378bc82706788b57b0786d8096ba1e7..65a36bf0e109781b7eac0577f0ae14b807191f8a 100644
--- a/packages/rocketchat-ui-message/message/messageBox.html
+++ b/packages/rocketchat-ui-message/message/messageBox.html
@@ -1,11 +1,11 @@
 <template name="messageBox">
 	{{#if subscribed}}
-		<form class="message-form" method="post" action="/">
+		<form class="message-form secondary-font-color" method="post" action="/">
 			{{> messagePopupConfig getPopupConfig}}
 			{{#if allowedToSend}}
-			<div class="message-input">
-				<div class="input-message-container">
-					<textarea dir="auto" name="msg" maxlength="{{maxMessageLength}}" class="input-message autogrow-short" placeholder="{{_ 'Message'}}"></textarea>
+			<div class="message-input border-component-color">
+				<div class="input-message-container content-background-color">
+					<textarea dir="auto" name="msg" maxlength="{{maxMessageLength}}" class="message-form-text input-message autogrow-short" placeholder="{{_ 'Message'}}"></textarea>
 
 					<div class="inner-left-toolbar">
 						<i class="emoji-picker-icon icon-people"></i>
@@ -59,7 +59,11 @@
 			</div>
 			{{else}}
 			<div class="stream-info">
-				{{_ "room_is_read_only"}}
+				{{#if isBlockedOrBlocker}}
+					{{_ "room_is_blocked"}}
+				{{else}}
+					{{_ "room_is_read_only"}}
+				{{/if}}
 			</div>
 			{{/if}}
 			<div class="stream-info">
@@ -89,8 +93,8 @@
 					<span>~<strike>{{_ "strike"}}</strike>~</span>
 					{{/if}}
 					{{#if showMarkdownCode}}
-					<code class="inline">`{{_ "inline_code"}}`</code>
-					<code class="inline"><span class="hidden-br"><br></span>```<span class="hidden-br"><br></span><i class="icon-level-down"></i>{{_ "multi"}}<span class="hidden-br"><br></span><i class="icon-level-down"></i>{{_ "line"}}<span class="hidden-br"><br></span><i class="icon-level-down"></i>```</code>
+					<code class="code-colors inline">`{{_ "inline_code"}}`</code>
+					<code class="code-colors inline"><span class="hidden-br"><br></span>```<span class="hidden-br"><br></span><i class="icon-level-down"></i>{{_ "multi"}}<span class="hidden-br"><br></span><i class="icon-level-down"></i>{{_ "line"}}<span class="hidden-br"><br></span><i class="icon-level-down"></i>```</code>
 					{{/if}}
 					{{#if katexSyntax}}
 					<span><a href="https://github.com/Khan/KaTeX/wiki/Function-Support-in-KaTeX" target="_blank">{{katexSyntax}}</a></span>
diff --git a/packages/rocketchat-ui-message/message/messageDropdown.html b/packages/rocketchat-ui-message/message/messageDropdown.html
index 93468e4bd65a7e6a8da086006cfd678b1e236725..aeef21c9abe01d9ba9f863897f77e827cd3cb21d 100644
--- a/packages/rocketchat-ui-message/message/messageDropdown.html
+++ b/packages/rocketchat-ui-message/message/messageDropdown.html
@@ -1,7 +1,7 @@
 <template name="messageDropdown">
 	<div class="message-dropdown">
 		<ul>
-			<li class="message-dropdown-close"><i class=" icon-angle-left" aria-label="{{_ "Close"}}"></i></li>
+			<li class="message-dropdown-close secondary-background-color border-component-color"><i class=" icon-angle-left" aria-label="{{_ "Close"}}"></i></li>
 			{{#if actions.length}}
 				{{#each actions}}
 					<li class="{{id}} {{classes}} message-action" title="{{_ i18nLabel}}" data-id="{{id}}"><i class="{{icon}}" aria-label="{{_ i18nLabel}}"></i></li>
diff --git a/packages/rocketchat-ui-message/message/popup/messagePopup.html b/packages/rocketchat-ui-message/message/popup/messagePopup.html
index 685ae84704424ba3fda7e1636cac18c4f75382a5..c81aff00d73f075504dc1c2945d45a11f5e3e99c 100644
--- a/packages/rocketchat-ui-message/message/popup/messagePopup.html
+++ b/packages/rocketchat-ui-message/message/popup/messagePopup.html
@@ -1,14 +1,13 @@
 <template name="messagePopup">
 	{{#if isOpen}}
 		<div class="message-popup-position">
-			<div class="message-popup {{cls}}">
+			<div class="message-popup content-background-color {{cls}}">
 				{{#if title}}
-					<div class="message-popup-title">
+					<div class="message-popup-title secondary-background-color">
 						{{title}}
 					</div>
 				{{/if}}
 				<div class="message-popup-items">
-					{{> loading}}
 					{{#each data}}
 						<div class="popup-item" data-id="{{_id}}">
 							{{> Template.dynamic template=../template}}
diff --git a/packages/rocketchat-ui-message/message/popup/messagePopupConfig.coffee b/packages/rocketchat-ui-message/message/popup/messagePopupConfig.coffee
index cc5252b0ab23de21c1a05c3b8bcb152249759fb7..3cf38b4ffc6700a6ae9656eb1f679695cb19dc99 100644
--- a/packages/rocketchat-ui-message/message/popup/messagePopupConfig.coffee
+++ b/packages/rocketchat-ui-message/message/popup/messagePopupConfig.coffee
@@ -82,21 +82,21 @@ Template.messagePopupConfig.helpers
 							status: item.status
 							sort: 1
 
-				# Get users of room
-				if items.length < 5 and filter?.trim() isnt ''
-					messageUsers = _.pluck(items, 'username')
-					Tracker.nonreactive ->
-						roomUsernames = RocketChat.models.Rooms.findOne(Session.get('openedRoom')).usernames
-						for roomUsername in roomUsernames
-							if messageUsers.indexOf(roomUsername) is -1 and exp.test(roomUsername)
-								items.push
-									_id: roomUsername
-									username: roomUsername
-									status: Session.get('user_' + roomUsername + '_status') or 'offline'
-									sort: 2
-
-								if items.length >= 5
-									break
+				# # Get users of room
+				# if items.length < 5 and filter?.trim() isnt ''
+				# 	messageUsers = _.pluck(items, 'username')
+				# 	Tracker.nonreactive ->
+				# 		roomUsernames = RocketChat.models.Rooms.findOne(Session.get('openedRoom')).usernames
+				# 		for roomUsername in roomUsernames
+				# 			if messageUsers.indexOf(roomUsername) is -1 and exp.test(roomUsername)
+				# 				items.push
+				# 					_id: roomUsername
+				# 					username: roomUsername
+				# 					status: Session.get('user_' + roomUsername + '_status') or 'offline'
+				# 					sort: 2
+
+				# 				if items.length >= 5
+				# 					break
 
 				# Get users from db
 				if items.length < 5 and filter?.trim() isnt ''
diff --git a/packages/rocketchat-ui-message/message/popup/messagePopupUser.html b/packages/rocketchat-ui-message/message/popup/messagePopupUser.html
index 48d84d6129d68255d765a6b2b9be3a224c22e08a..c90a04375d3de1a2647ed158467b871fa7f0274a 100644
--- a/packages/rocketchat-ui-message/message/popup/messagePopupUser.html
+++ b/packages/rocketchat-ui-message/message/popup/messagePopupUser.html
@@ -1,7 +1,7 @@
 <template name="messagePopupUser">
 	{{#unless system}}
-		<div class="popup-user-status popup-user-status-{{status}}"></div>
+		<div class="popup-user-status border-transparent-dark popup-user-status-{{status}}"></div>
 		<div class="popup-user-avatar" style="background-image:url({{avatarUrlFromUsername username}});"></div>
 	{{/unless}}
 	<strong>{{username}}</strong> {{name}}
-</template>
\ No newline at end of file
+</template>
diff --git a/packages/rocketchat-ui-sidenav/side-nav/accountBox.coffee b/packages/rocketchat-ui-sidenav/side-nav/accountBox.coffee
index 7d5e89e70cb561dbdec203b43f48bd7bef9fb571..b0f2bf2741b2ef312c5a2c1ed738e7d8cda7c6d7 100644
--- a/packages/rocketchat-ui-sidenav/side-nav/accountBox.coffee
+++ b/packages/rocketchat-ui-sidenav/side-nav/accountBox.coffee
@@ -59,6 +59,9 @@ Template.accountBox.events
 		AccountBox.openFlex()
 
 	'click .account-box-item': ->
+		if @href
+			FlowRouter.go @href
+
 		if @sideNav?
 			SideNav.setFlex @sideNav
 			SideNav.openFlex()
diff --git a/packages/rocketchat-ui-sidenav/side-nav/accountBox.html b/packages/rocketchat-ui-sidenav/side-nav/accountBox.html
index 5f79fea9a0b45eca8a018f36751a68739ab7d4e6..61282239834df5aaf8e83d8607dceb66e5ba96b4 100644
--- a/packages/rocketchat-ui-sidenav/side-nav/accountBox.html
+++ b/packages/rocketchat-ui-sidenav/side-nav/accountBox.html
@@ -1,7 +1,7 @@
 <template name="accountBox">
 	<div class="account-box" aria-label="{{_ "Account"}}" role="region">
 		{{#with myUserInfo}}
-			<div class="info status-{{status}}">
+			<div class="info status-{{status}} primary-background-color">
 				{{#if username}}
 					<div class="thumb" data-status='{{visualStatus}}'>
 						{{> avatar username=username}}
@@ -11,7 +11,7 @@
 					</div>
 				{{/if}}
 			</div>
-			<nav class="options animated-hidden">
+			<nav class="options primary-background-color animated-hidden">
 				<div class="wrapper">
 					<button data-status="online" class="status online"><span>{{_ "Online"}}</span></button>
 					<button data-status="away" class="status away"><span>{{_ "Away" context="male"}}</span></button>
@@ -19,7 +19,7 @@
 					<button data-status="offline" class="status offline"><span>{{_ "Invisible"}}</span></button>
 					<button id="account" class='account-link'><i class="icon-sliders"></i><span>{{_ "My_Account"}}</span></button>
 					{{#each registeredMenus}}
-						<a href="{{pathFor href}}" class="account-box-item"><i class="{{icon}}"></i><span>{{name}}</span></a>
+						<button class="account-box-item"><i class="{{icon}}"></i><span>{{name}}</span></button>
 					{{/each}}
 					{{#if showAdminOption }}
 						<button id="admin" class='account-link'><i class="icon-wrench"></i><span>{{_ "Administration"}}</span></button>
diff --git a/packages/rocketchat-ui-sidenav/side-nav/channels.html b/packages/rocketchat-ui-sidenav/side-nav/channels.html
index 746fc7bb51d0ace134dbbf617ef8408aae5515d4..9658c595dfce84b51bde22c561915df0feb4acd2 100644
--- a/packages/rocketchat-ui-sidenav/side-nav/channels.html
+++ b/packages/rocketchat-ui-sidenav/side-nav/channels.html
@@ -1,5 +1,5 @@
 <template name="channels">
-	<h3 class="add-room {{isActive}}">
+	<h3 class="add-room background-transparent-darker-hover {{isActive}}">
 		{{_ "Channels"}} <span class="room-count-small">({{rooms.count}})</span>
 		{{#if canCreate}}
 			<i class="icon-plus" aria-label="{{_ "Create channel"}}" role="button"></i>
@@ -12,5 +12,5 @@
 			<p class="empty">{{_ "No_channels_yet" }}</p>
 		{{/each}}
 	</ul>
-	<button class="more more-channels">{{_ "More_channels"}}...</button>
+	<button class="more more-channels background-transparent-darker-hover">{{_ "More_channels"}}...</button>
 </template>
diff --git a/packages/rocketchat-ui-sidenav/side-nav/chatRoomItem.coffee b/packages/rocketchat-ui-sidenav/side-nav/chatRoomItem.coffee
index fd7697f138cb255e629d2e96a2671f9493330600..99b126be34929f0f5fdba0d388ee1216cee79d33 100644
--- a/packages/rocketchat-ui-sidenav/side-nav/chatRoomItem.coffee
+++ b/packages/rocketchat-ui-sidenav/side-nav/chatRoomItem.coffee
@@ -9,7 +9,8 @@ Template.chatRoomItem.helpers
 			return this.unread
 
 	userStatus: ->
-		return 'status-' + (Session.get('user_' + this.name + '_status') or 'offline') if this.t is 'd'
+		userStatus = RocketChat.roomTypes.getUserStatus(this.t, this.rid);
+		return 'status-' + (userStatus or 'offline')
 
 	name: ->
 		return this.name
diff --git a/packages/rocketchat-ui-sidenav/side-nav/chatRoomItem.html b/packages/rocketchat-ui-sidenav/side-nav/chatRoomItem.html
index c3bf57b7711440368f31cba18776f4eb25d8ed94..92c8f8c63abddec275d84a04eee0a13ed6354a77 100644
--- a/packages/rocketchat-ui-sidenav/side-nav/chatRoomItem.html
+++ b/packages/rocketchat-ui-sidenav/side-nav/chatRoomItem.html
@@ -1,5 +1,5 @@
 <template name="chatRoomItem">
-	<li class="link-room-{{rid}} {{active}} {{#if unread}}has-unread{{/if}} {{#if alert}}has-alert{{/if}}">
+	<li class="link-room-{{rid}} background-transparent-darker-hover {{active}} {{#if unread}}has-unread{{/if}} {{#if alert}}has-alert{{/if}}">
 		<a class="open-room" href="{{route}}" title="{{name}}">
 			{{#if unread}}
 				<span class="unread">{{unread}}</span>
diff --git a/packages/rocketchat-ui-sidenav/side-nav/combined.html b/packages/rocketchat-ui-sidenav/side-nav/combined.html
index 25a19a812d5eb000950c418f5c0b1e63b4ec08e8..912120f588a2424d341371fe2e736c1ab1f9fb4c 100644
--- a/packages/rocketchat-ui-sidenav/side-nav/combined.html
+++ b/packages/rocketchat-ui-sidenav/side-nav/combined.html
@@ -1,5 +1,5 @@
 <template name="combined">
-	<h3 class="add-room {{isActive}}">
+	<h3 class="add-room background-transparent-darker-hover {{isActive}}">
 		{{_ "Channels"}} <span class="room-count-small">({{rooms.count}})</span>
 		{{#if canCreate}}
 			<i class="icon-plus" aria-label="{{_ "Create channel"}}" role="button"></i>
@@ -12,5 +12,5 @@
 			<p class="empty">{{_ "No_channels_yet" }}</p>
 		{{/each}}
 	</ul>
-	<button class="more more-channels">{{_ "More_channels"}}...</button>
+	<button class="more more-channels background-transparent-darker-hover">{{_ "More_channels"}}...</button>
 </template>
diff --git a/packages/rocketchat-ui-sidenav/side-nav/createChannelFlex.html b/packages/rocketchat-ui-sidenav/side-nav/createChannelFlex.html
index d188757768f49eb507351c1b16bf836e2dd477eb..346125416a1f9fa5e05a125199c79ca462b8e225 100644
--- a/packages/rocketchat-ui-sidenav/side-nav/createChannelFlex.html
+++ b/packages/rocketchat-ui-sidenav/side-nav/createChannelFlex.html
@@ -1,31 +1,31 @@
 <template name="createChannelFlex">
-	<header>
+	<header class="primary-background-color">
 		<div>
 			<h4>{{_ "Channels"}}</h4>
 		</div>
 	</header>
-	<div class="content">
+	<div class="content primary-background-color">
 		<div class="wrapper">
 			<h4>{{_ "Create_new" }}</h4>
 			<div class="input-line">
-				<label for="channel-name">{{_ "Name"}}</label>
+				<label class="color-tertiary-font-color" for="channel-name">{{_ "Name"}}</label>
 				<input type="text" id="channel-name" class="required" dir="auto" placeholder="{{_ 'Enter_name_here'}}">
 			</div>
 			<div class="input-line">
-				<label for="channel-ro">{{_ "Read_only_channel"}}</label>
+				<label class="color-tertiary-font-color" for="channel-ro">{{_ "Read_only_channel"}}</label>
 				<input type="checkbox" id="channel-ro">
 			</div>
 			<div class="input-line">
-				<label for="channel-members">{{_ "Select_users"}}</label>
+				<label class="color-tertiary-font-color" for="channel-members">{{_ "Select_users"}}</label>
 				{{> inputAutocomplete settings=autocompleteSettings id="channel-members" class="search" placeholder=(_ "Search_by_username") autocomplete="off"}}
 				<ul class="selected-users">
 					{{#each selectedUsers}}
-						<li>{{.}} <i class="icon-cancel remove-room-member"></i></li>
+						<li class="background-transparent-darker">{{.}} <i class="icon-cancel remove-room-member secondary-font-color"></i></li>
 					{{/each}}
 				</ul>
 			</div>
 			{{#if error.fields}}
-				<div class="input-error">
+				<div class="input-error error-color">
 					<strong>{{_ "Oops!"}}</strong>
 					{{#each error.fields}}
 						<p>{{_ "The_field_is_required" .}}</p>
@@ -33,19 +33,19 @@
 				</div>
 			{{/if}}
 			{{#if error.invalid}}
-				<div class="input-error">
+				<div class="input-error error-color">
 					<strong>{{_ "Oops!"}}</strong>
 					{{{_ "Invalid_room_name" roomName}}}
 				</div>
 			{{/if}}
 			{{#if error.duplicate}}
-				<div class="input-error">
+				<div class="input-error error-color">
 					<strong>{{_ "Oops!"}}</strong>
 					{{{_ "Duplicate_channel_name" roomName}}}
 				</div>
 			{{/if}}
 			{{#if error.archivedduplicate}}
-				<div class="input-error">
+				<div class="input-error error-color">
 					<strong>{{_ "Oops!"}}</strong>
 					{{{_ "Duplicate_archived_channel_name" roomName}}}
 				</div>
@@ -56,7 +56,7 @@
 			</div>
 		</div>
 	</div>
-	<footer>
+	<footer class="primary-background-color">
 		<div>
 			<button class="button all">{{_ "All_channels"}}</button>
 		</div>
diff --git a/packages/rocketchat-ui-sidenav/side-nav/createCombinedFlex.html b/packages/rocketchat-ui-sidenav/side-nav/createCombinedFlex.html
index acb8bdb1349c7ae18830c43fb3c0d668fe905706..1b68e172105e7f0c7bcf37a2066c84eaeded733c 100644
--- a/packages/rocketchat-ui-sidenav/side-nav/createCombinedFlex.html
+++ b/packages/rocketchat-ui-sidenav/side-nav/createCombinedFlex.html
@@ -1,35 +1,41 @@
 <template name="createCombinedFlex">
-	<header>
+	<header class="primary-background-color">
 		<div>
 			<h4>{{_ "Channels"}}</h4>
 		</div>
 	</header>
-	<div class="content">
+	<div class="content primary-background-color">
 		<div class="wrapper">
 			<h4>{{_ "Create_new" }}</h4>
-			<div class="input-line">
-				<label for="channel-name">{{_ "Name"}}</label>
+			<div class="input-line no-icon">
+				<span>{{_ "Name"}}</span>
 				<input type="text" id="channel-name" class="required" dir="auto" placeholder="{{_ 'Enter_name_here'}}">
 			</div>
-			<div class="input-line">
-				<label for="channel-type">{{_ "Private_Group"}}</label>
-				<input type="checkbox" id="channel-type" {{privateSwitchDisabled}} {{privateSwitchChecked}}>
+			<div class="input-line toggle">
+				<span>{{_ "Private"}}</span>
+				<div class="input checkbox toggle">
+					<input type="checkbox" id="channel-type" {{privateSwitchDisabled}} {{privateSwitchChecked}}>
+					<label class="color-tertiary-font-color" for="channel-type"></label>
+				</div>
 			</div>
-			<div class="input-line">
-				<label for="channel-ro">{{_ "Read_only_channel"}}</label>
-				<input type="checkbox" id="channel-ro">
+			<div class="input-line toggle">
+				<span>{{_ "Read_only_channel"}}</span>
+				<div class="input checkbox toggle">
+					<input type="checkbox" id="channel-ro">
+					<label class="color-tertiary-font-color" for="channel-ro"></label>
+				</div>
 			</div>
-			<div class="input-line">
-				<label for="channel-members">{{_ "Select_users"}}</label>
+			<div class="input-line no-icon">
+				<label class="color-tertiary-font-color" for="channel-members">{{_ "Select_users"}}</label>
 				{{> inputAutocomplete settings=autocompleteSettings id="channel-members" class="search" placeholder=(_ "Search_by_username") autocomplete="off"}}
 				<ul class="selected-users">
 					{{#each selectedUsers}}
-						<li>{{.}} <i class="icon-cancel remove-room-member"></i></li>
+						<li class="background-transparent-darker">{{.}} <i class="icon-cancel remove-room-member"></i></li>
 					{{/each}}
 				</ul>
 			</div>
 			{{#if error.fields}}
-				<div class="input-error">
+				<div class="input-error error-color">
 					<strong>{{_ "Oops!"}}</strong>
 					{{#each error.fields}}
 						<p>{{_ "The_field_is_required" .}}</p>
@@ -37,19 +43,19 @@
 				</div>
 			{{/if}}
 			{{#if error.invalid}}
-				<div class="input-error">
+				<div class="input-error error-color">
 					<strong>{{_ "Oops!"}}</strong>
 					{{{_ "Invalid_room_name" roomName}}}
 				</div>
 			{{/if}}
 			{{#if error.duplicate}}
-				<div class="input-error">
+				<div class="input-error error-color">
 					<strong>{{_ "Oops!"}}</strong>
 					{{{_ "Duplicate_channel_name" roomName}}}
 				</div>
 			{{/if}}
 			{{#if error.archivedduplicate}}
-				<div class="input-error">
+				<div class="input-error error-color">
 					<strong>{{_ "Oops!"}}</strong>
 					{{{_ "Duplicate_archived_channel_name" roomName}}}
 				</div>
@@ -60,7 +66,7 @@
 			</div>
 		</div>
 	</div>
-	<footer>
+	<footer class="primary-background-color">
 		<div>
 			<button class="button all">{{_ "All_channels"}}</button>
 		</div>
diff --git a/packages/rocketchat-ui-sidenav/side-nav/directMessages.html b/packages/rocketchat-ui-sidenav/side-nav/directMessages.html
index 9bcf597e859458999b927bc8f6fb44d691489d76..2e8fddcc8972bd85e89dc43ac59726c48e9e24ad 100644
--- a/packages/rocketchat-ui-sidenav/side-nav/directMessages.html
+++ b/packages/rocketchat-ui-sidenav/side-nav/directMessages.html
@@ -1,5 +1,5 @@
 <template name="directMessages">
-	<h3 class="add-room {{isActive}}">
+	<h3 class="add-room background-transparent-darker-hover {{isActive}}">
 		{{_ "Direct_Messages"}} <span class="room-count-small">({{rooms.count}})</span>
 		{{#if canCreate}}
 			<i class="icon-plus"></i>
@@ -11,6 +11,6 @@
 		{{else}}
 			<p class="empty">{{_ "No_direct_messages_yet" }}</p>
 		{{/each}}
-		<button class="more more-direct-messages">{{_ "More_direct_messages"}}...</button>
+		<button class="more more-direct-messages background-transparent-darker-hover">{{_ "More_direct_messages"}}...</button>
 	</ul>
 </template>
diff --git a/packages/rocketchat-ui-sidenav/side-nav/directMessagesFlex.html b/packages/rocketchat-ui-sidenav/side-nav/directMessagesFlex.html
index 78dd378cac3a851d4e5b625097de9bfd425da75b..43b66dbbd715d499589fbee76283fa6665e202b2 100644
--- a/packages/rocketchat-ui-sidenav/side-nav/directMessagesFlex.html
+++ b/packages/rocketchat-ui-sidenav/side-nav/directMessagesFlex.html
@@ -1,18 +1,18 @@
 <template name="directMessagesFlex">
-	<header>
+	<header class="primary-background-color">
 		<div>
 			<h4>{{_ "Direct_Messages"}}</h4>
 		</div>
 	</header>
-	<div class="content">
+	<div class="content primary-background-color">
 		<div class="wrapper">
 			<h4>{{_ "Create_new"}}</h4>
-			<div class="input-line">
-				<label for="who">{{_ "Select_user" }}</label>
+			<div class="input-line no-icon">
+				<label class="color-tertiary-font-color" for="who">{{_ "Select_user" }}</label>
 				{{> inputAutocomplete settings=autocompleteSettings id="who" class="required search" autocomplete="off" placeholder=(_ "Search_by_username")}}
 			</div>
 			{{#if error}}
-				<div class="input-error">
+				<div class="input-error error-color">
 					<strong>{{_ "Oops!"}}</strong>
 					{{#each error}}
 						<p>{{_ "The_field_is_required" error}}</p>
diff --git a/packages/rocketchat-ui-sidenav/side-nav/listChannelsFlex.html b/packages/rocketchat-ui-sidenav/side-nav/listChannelsFlex.html
index f4eef9e163454c673acb49173be0051ba5a337e1..8df15568b591b858fa4789cbc6069c6cc190f3a1 100644
--- a/packages/rocketchat-ui-sidenav/side-nav/listChannelsFlex.html
+++ b/packages/rocketchat-ui-sidenav/side-nav/listChannelsFlex.html
@@ -1,10 +1,10 @@
 <template name="listChannelsFlex">
-	<header>
+	<header class="primary-background-color">
 		<div>
 			<h4>{{_ "Channels"}}</h4>
 		</div>
 	</header>
-	<div class="content">
+	<div class="content primary-background-color">
 		<div class="wrapper">
 			<div class="flex-control">
 				<div class="search">
@@ -14,7 +14,7 @@
 								<option value="joined" selected="{{showSelected 'joined'}}">{{_ "Joined"}}</option>
 								<option value="all" selected="{{showSelected 'all'}}">{{_ "All"}}</option>
 							</select>
-							<i class="icon-comment"></i>
+							<i class="icon-comment secondary-font-color"></i>
 						</div>
 						<div class="input-line search">
 							<select class="c-select" id="sort-channels">
@@ -25,46 +25,42 @@
 								<option value="name" selected="{{sortSubscriptionsSelected 'name'}}">{{_ "Name"}}</option>
 								<option value="ls" selected="{{sortSubscriptionsSelected 'ls'}}">{{_ "Last_seen"}}</option>
 							</select>
-							<i class="icon-sort-alt-up"></i>
+							<i class="icon-sort-alt-up secondary-font-color"></i>
 						</div>
 						<div class="input-line search">
 							<input type="text" id="channel-search" class="search" placeholder="{{_ "Search_Channels"}}" autocomplete="off" />
-							<i class="icon-right-open-small"></i>
+							<i class="icon-right-open-small secondary-font-color"></i>
 						</div>
 					</form>
 				</div>
 			</div>
 			<h4>{{_ "Channels_list"}}</h4>
 			<ul>
-			{{#each channel}}
-				<li>
-					<a href="{{pathFor 'channel' name=name}}" class="channel-link">
-						<i class="icon-hash"></i>
-						{{name}}
-						<span class='opt fixed'>
-							{{#if member}}
-							<i class="icon-eye" title="{{_ "Open"}}" aria-label="{{_ "Open"}}"></i>
-							{{/if}}
-							{{#if hidden}}
-							<i class="icon-eye-off" title="{{_ "Hidden"}}" aria-label="{{_ "Hidden"}}"></i>
-							{{/if}}
-						</span>
-					</a>
-				</li>
-			{{/each}}
+				{{#each channel}}
+					<li>
+						<a href="{{pathFor 'channel' name=name}}" class="channel-link">
+							<i class="icon-hash"></i>
+							{{name}}
+							<span class='opt fixed'>
+								{{#if member}}
+								<i class="icon-eye" title="{{_ "Open"}}" aria-label="{{_ "Open"}}"></i>
+								{{/if}}
+								{{#if hidden}}
+								<i class="icon-eye-off" title="{{_ "Hidden"}}" aria-label="{{_ "Hidden"}}"></i>
+								{{/if}}
+							</span>
+						</a>
+					</li>
+				{{/each}}
+			</ul>
 			{{#if hasMore}}
-				<li class="load-more">
-					{{#if Template.subscriptionsReady}}
-						<button>{{_ "Has_more"}}...</button>
-					{{else}}
-						<div class="load-more-loading">{{_ "Loading..."}}</div>
-					{{/if}}
-				</li>
+				<div class="load-more">
+					{{> loading}}
+				</div>
 			{{/if}}
-			</ul>
 		</div>
 	</div>
-	<footer>
+	<footer class="primary-background-color">
 		<div>
 		{{#if hasPermission 'create-c'}}
 			<button class="button primary create">{{_ "Create_new"}}</button>
diff --git a/packages/rocketchat-ui-sidenav/side-nav/listCombinedFlex.html b/packages/rocketchat-ui-sidenav/side-nav/listCombinedFlex.html
index 34225805643d453f5ed5a3001351e75ebb4ef4c9..371cd9ff32bcc54abb2776dcdcd15ff4022ab4af 100644
--- a/packages/rocketchat-ui-sidenav/side-nav/listCombinedFlex.html
+++ b/packages/rocketchat-ui-sidenav/side-nav/listCombinedFlex.html
@@ -1,10 +1,10 @@
 <template name="listCombinedFlex">
-	<header>
+	<header class="primary-background-color">
 		<div>
 			<h4>{{_ "Channels"}}</h4>
 		</div>
 	</header>
-	<div class="content">
+	<div class="content primary-background-color">
 		<div class="wrapper">
 			<div class="flex-control">
 				<div class="search">
@@ -14,7 +14,7 @@
 								<option value="joined" selected="{{showSelected 'joined'}}">{{_ "Joined"}}</option>
 								<option value="all" selected="{{showSelected 'all'}}">{{_ "All"}}</option>
 							</select>
-							<i class="icon-comment"></i>
+							<i class="icon-comment secondary-font-color"></i>
 						</div>
 						<div class="input-line search">
 							<select class="c-select" id="sort-channels">
@@ -25,7 +25,7 @@
 								<option value="name" selected="{{sortSubscriptionsSelected 'name'}}">{{_ "Name"}}</option>
 								<option value="ls" selected="{{sortSubscriptionsSelected 'ls'}}">{{_ "Last_seen"}}</option>
 							</select>
-							<i class="icon-sort-alt-up"></i>
+							<i class="icon-sort-alt-up secondary-font-color"></i>
 						</div>
 						<div class="input-line search">
 							<select class="c-select" id="channel-type">
@@ -33,46 +33,42 @@
 								<option value="public" selected="{{channelTypeSelected 'public'}}">{{_ "Public"}}</option>
 								<option value="private" selected="{{channelTypeSelected 'private'}}">{{_ "Private"}}</option>
 							</select>
-							<i class="icon-lock"></i>
+							<i class="icon-lock secondary-font-color"></i>
 						</div>
 						<div class="input-line search">
-							<input type="text" id="channel-search" class="search" placeholder="{{_ "Search_Channels"}}" autocomplete="off" />
-							<i class="icon-right-open-small"></i>
+							<input type="text" id="channel-search" class="search" placeholder="{{_ "Search"}}" autocomplete="off" />
+							<i class="icon-search secondary-font-color"></i>
 						</div>
 					</form>
 				</div>
 			</div>
 			<h4>{{_ "List_of_Channels"}}</h4>
 			<ul>
-			{{#each channel}}
-				<li>
-					<a href="{{pathFor url name=name}}" class="channel-link">
-						<i class="{{roomIcon}}"></i>
-						{{name}}
-						<span class='opt fixed'>
-							{{#if member}}
-							<i class="icon-eye" title="{{_ "Open"}}" aria-label="{{_ "Open"}}"></i>
-							{{/if}}
-							{{#if hidden}}
-							<i class="icon-eye-off" title="{{_ "Hidden"}}" aria-label="{{_ "Hidden"}}"></i>
-							{{/if}}
-						</span>
-					</a>
-				</li>
-			{{/each}}
+				{{#each channel}}
+					<li>
+						<a href="{{pathFor url name=name}}" class="channel-link">
+							<i class="{{roomIcon}}"></i>
+							{{name}}
+							<span class='opt fixed'>
+								{{#if member}}
+								<i class="icon-eye" title="{{_ "Open"}}" aria-label="{{_ "Open"}}"></i>
+								{{/if}}
+								{{#if hidden}}
+								<i class="icon-eye-off" title="{{_ "Hidden"}}" aria-label="{{_ "Hidden"}}"></i>
+								{{/if}}
+							</span>
+						</a>
+					</li>
+				{{/each}}
+			</ul>
 			{{#if hasMore}}
-				<li class="load-more">
-					{{#if Template.subscriptionsReady}}
-						<button>{{_ "Has_more"}}...</button>
-					{{else}}
-						<div class="load-more-loading">{{_ "Loading..."}}</div>
-					{{/if}}
-				</li>
+				<div class="load-more">
+					{{> loading}}
+				</div>
 			{{/if}}
-			</ul>
 		</div>
 	</div>
-	<footer>
+	<footer class="primary-background-color">
 		<div>
 		{{#if canCreate}}
 			<button class="button primary create">{{_ "Create_new"}}</button>
diff --git a/packages/rocketchat-ui-sidenav/side-nav/listDirectMessagesFlex.html b/packages/rocketchat-ui-sidenav/side-nav/listDirectMessagesFlex.html
index 50fdf94ed23024169ad802a0a398af27882e8f22..c252bea71e441627e1303e26da8f8e26d28f9046 100644
--- a/packages/rocketchat-ui-sidenav/side-nav/listDirectMessagesFlex.html
+++ b/packages/rocketchat-ui-sidenav/side-nav/listDirectMessagesFlex.html
@@ -1,53 +1,49 @@
 <template name="listDirectMessagesFlex">
-	<header>
+	<header class="primary-background-color">
 		<div>
 			<h4>{{_ "Direct_Messages"}}</h4>
 		</div>
 	</header>
-	<div class="content">
+	<div class="content primary-background-color">
 		<div class="wrapper">
 			<div class="flex-control">
 				<div class="search">
 					<form class="search-form" role="form">
 						<div class="input-line search">
-							<input type="text" id="channel-search" class="search" placeholder="{{_ "Search_Direct_Messages"}}" autocomplete="off" />
-							<i class="icon-right-open-small"></i>
+							<input type="text" id="channel-search" class="search" placeholder="{{_ "Search"}}" autocomplete="off" />
+							<i class="icon-search secondary-font-color"></i>
 						</div>
 						<div class="input-line search">
 							<select class="c-select" id="sort">
 								<option value="name" selected="{{sortSelected 'name'}}">{{_ "Name"}}</option>
 								<option value="ls" selected="{{sortSelected 'ls'}}">{{_ "Last_seen"}}</option>
 							</select>
-							<i class="icon-sort-alt-up"></i>
+							<i class="icon-sort-alt-up secondary-font-color"></i>
 						</div>
 					</form>
 				</div>
 			</div>
 			<h4>{{_ "List_of_Direct_Messages"}}</h4>
 			<ul>
-			{{#each rooms}}
-				<li>
-					<a href="{{pathFor 'direct' username=name}}" class="channel-link">
-						<i class="icon-at {{userStatus}}"></i>
-						{{name}}
-						<span class='opt fixed'>
-							{{#if hidden}}
-							<i class="icon-eye-off" title="{{_ "Hidden"}}" aria-label="{{_ "Hidden"}}"></i>
-							{{/if}}
-						</span>
-					</a>
-				</li>
-			{{/each}}
+				{{#each rooms}}
+					<li>
+						<a href="{{pathFor 'direct' username=name}}" class="channel-link">
+							<i class="icon-at {{userStatus}}"></i>
+							{{name}}
+							<span class='opt fixed'>
+								{{#if hidden}}
+								<i class="icon-eye-off" title="{{_ "Hidden"}}" aria-label="{{_ "Hidden"}}"></i>
+								{{/if}}
+							</span>
+						</a>
+					</li>
+				{{/each}}
+			</ul>
 			{{#if hasMore}}
-				<li class="load-more">
-					{{#if Template.subscriptionsReady}}
-						<button>{{_ "Has_more"}}...</button>
-					{{else}}
-						<div class="load-more-loading">{{_ "Loading..."}}</div>
-					{{/if}}
-				</li>
+				<div class="load-more">
+					{{> loading}}
+				</div>
 			{{/if}}
-			</ul>
 		</div>
 	</div>
 </template>
diff --git a/packages/rocketchat-ui-sidenav/side-nav/listPrivateGroupsFlex.html b/packages/rocketchat-ui-sidenav/side-nav/listPrivateGroupsFlex.html
index 6a43dcf50df9432245c4563f190798bddc27e533..f664e26c66693869886b603749333a3e468e2e66 100644
--- a/packages/rocketchat-ui-sidenav/side-nav/listPrivateGroupsFlex.html
+++ b/packages/rocketchat-ui-sidenav/side-nav/listPrivateGroupsFlex.html
@@ -1,10 +1,10 @@
 <template name="listPrivateGroupsFlex">
-	<header>
+	<header class="primary-background-color">
 		<div>
 			<h4>{{_ "Private_Groups"}}</h4>
 		</div>
 	</header>
-	<div class="content">
+	<div class="content primary-background-color">
 		<div class="wrapper">
 			<div class="flex-control">
 				<div class="search">
@@ -14,43 +14,39 @@
 								<option value="name" selected="{{sortSelected 'name'}}">{{_ "Name"}}</option>
 								<option value="ls" selected="{{sortSelected 'ls'}}">{{_ "Last_seen"}}</option>
 							</select>
-							<i class="icon-sort-alt-up"></i>
+							<i class="icon-sort-alt-up secondary-font-color"></i>
 						</div>
 						<div class="input-line search">
 							<input type="text" id="channel-search" class="search" placeholder="{{_ "Search_Private_Groups"}}" autocomplete="off" />
-							<i class="icon-right-open-small"></i>
+							<i class="icon-right-open-small secondary-font-color"></i>
 						</div>
 					</form>
 				</div>
 			</div>
 			<h4>{{_ "Private_Groups_list"}}</h4>
 			<ul>
-			{{#each groups}}
-				<li>
-					<a href="{{pathFor 'group' name=name}}" class="channel-link">
-						<i class="icon-lock"></i>
-						{{name}}
-						<span class='opt fixed'>
-							{{#if hidden}}
-							<i class="icon-eye-off" title="{{_ "Hidden"}}" aria-label="{{_ "Hidden"}}"></i>
-							{{/if}}
-						</span>
-					</a>
-				</li>
-			{{/each}}
+				{{#each groups}}
+					<li>
+						<a href="{{pathFor 'group' name=name}}" class="channel-link">
+							<i class="icon-lock"></i>
+							{{name}}
+							<span class='opt fixed'>
+								{{#if hidden}}
+								<i class="icon-eye-off" title="{{_ "Hidden"}}" aria-label="{{_ "Hidden"}}"></i>
+								{{/if}}
+							</span>
+						</a>
+					</li>
+				{{/each}}
+			</ul>
 			{{#if hasMore}}
-				<li class="load-more">
-					{{#if Template.subscriptionsReady}}
-						<button>{{_ "Has_more"}}...</button>
-					{{else}}
-						<div class="load-more-loading">{{_ "Loading..."}}</div>
-					{{/if}}
-				</li>
+				<div class="load-more">
+					{{> loading}}
+				</div>
 			{{/if}}
-			</ul>
 		</div>
 	</div>
-	<footer>
+	<footer class="primary-background-color">
 		<div>
 			<button class="button primary create">{{_ "Create_new"}}</button>
 		</div>
diff --git a/packages/rocketchat-ui-sidenav/side-nav/privateGroups.html b/packages/rocketchat-ui-sidenav/side-nav/privateGroups.html
index 9238e93da07229daa7b19a79730210d8d89af920..f23c44a824f9612ea07df696382c03544873fc6d 100644
--- a/packages/rocketchat-ui-sidenav/side-nav/privateGroups.html
+++ b/packages/rocketchat-ui-sidenav/side-nav/privateGroups.html
@@ -1,5 +1,5 @@
 <template name="privateGroups">
-	<h3 class="add-room {{isActive}}">
+	<h3 class="add-room background-transparent-darker-hover {{isActive}}">
 		{{_ "Private_Groups"}} <span class="room-count-small">({{rooms.count}})</span>
 		{{#if canCreate}}
 			<i class="icon-plus"></i>
@@ -13,6 +13,6 @@
 		{{/each}}
 	</ul>
 	{{#if $gt total totalOpen}}
-		<button class="more more-groups">{{_ "More_groups"}}...</button>
+		<button class="more more-groups background-transparent-darker-hover">{{_ "More_groups"}}...</button>
 	{{/if}}
 </template>
diff --git a/packages/rocketchat-ui-sidenav/side-nav/privateGroupsFlex.html b/packages/rocketchat-ui-sidenav/side-nav/privateGroupsFlex.html
index a434b28ce8b977218ae55fd6d1ea8f5665bddefb..b44af2de8eb56b7629e86588078b232f72e4fd23 100644
--- a/packages/rocketchat-ui-sidenav/side-nav/privateGroupsFlex.html
+++ b/packages/rocketchat-ui-sidenav/side-nav/privateGroupsFlex.html
@@ -1,31 +1,31 @@
 <template name="privateGroupsFlex">
-	<header>
+	<header class="primary-background-color">
 		<div>
 			<h4>{{_ "Private_Groups"}}</h4>
 		</div>
 	</header>
-	<div class="content">
+	<div class="content primary-background-color">
 		<div class="wrapper">
 			<h4>{{_ "Create_new"}}</h4>
 			<div class="input-line">
-				<label for="pvt-group-name">{{_ "Name"}}</label>
+				<label class="color-tertiary-font-color" for="pvt-group-name">{{_ "Name"}}</label>
 				<input type="text" id="pvt-group-name" class="required" dir="auto" placeholder="{{_ 'Enter_name_here'}}">
 			</div>
 			<div class="input-line">
-				<label for="channel-ro">{{_ "Read_only_group"}}</label>
+				<label class="color-tertiary-font-color" for="channel-ro">{{_ "Read_only_group"}}</label>
 				<input type="checkbox" id="channel-ro">
 			</div>
 			<div class="input-line">
-				<label for="pvt-group-members">{{_ "Select_users" }}</label>
+				<label class="color-tertiary-font-color" for="pvt-group-members">{{_ "Select_users" }}</label>
 				{{> inputAutocomplete settings=autocompleteSettings id="pvt-group-members" class="search" placeholder=(_ "Search_by_username") autocomplete="off"}}
 				<ul class="selected-users">
 					{{#each selectedUsers}}
-						<li>{{.}} <i class="icon-cancel remove-room-member"></i></li>
+						<li class="background-transparent-darker">{{.}} <i class="icon-cancel remove-room-member"></i></li>
 					{{/each}}
 				</ul>
 			</div>
 			{{#if error.fields}}
-				<div class="input-error">
+				<div class="input-error error-color">
 					<strong>{{_ "Oops!"}}</strong>
 					{{#each error.fields}}
 						<p>{{_ "The_field_is_required" .}}</p>
@@ -33,19 +33,19 @@
 				</div>
 			{{/if}}
 			{{#if error.invalid}}
-				<div class="input-error">
+				<div class="input-error error-color">
 					<strong>{{_ "Oops!"}}</strong>
 					{{{_ "Invalid_room_name" groupName}}}
 				</div>
 			{{/if}}
 			{{#if error.duplicate}}
-				<div class="input-error">
+				<div class="input-error error-color">
 					<strong>{{_ "Oops!"}}</strong>
 					{{{_ "Duplicate_private_group_name" groupName}}}
 				</div>
 			{{/if}}
 			{{#if error.archivedduplicate}}
-				<div class="input-error">
+				<div class="input-error error-color">
 					<strong>{{_ "Oops!"}}</strong>
 					{{{_ "Duplicate_archived_private_group_name" groupName}}}
 				</div>
diff --git a/packages/rocketchat-ui-sidenav/side-nav/sideNav.html b/packages/rocketchat-ui-sidenav/side-nav/sideNav.html
index b728c3433827de557d4020068fc02a8718baec01..4d15c91a242b900bdb16382aea6ab6e69b1a77f8 100644
--- a/packages/rocketchat-ui-sidenav/side-nav/sideNav.html
+++ b/packages/rocketchat-ui-sidenav/side-nav/sideNav.html
@@ -1,15 +1,15 @@
 <template name="sideNav">
-	<aside class="side-nav" role="navigation">
+	<aside class="side-nav primary-background-color color-tertiary-font-color" role="navigation">
 		<header class="header">
 			{{> accountBox }}
 		</header>
 		{{#if currentUser}}
-			<div class="unread-rooms top-unread-rooms hidden">
+			<div class="unread-rooms background-primary-action-color color-primary-action-contrast top-unread-rooms hidden">
 				{{_ "More_unreads"}} <i class="icon-up-big"></i>
 			</div>
 			<div class="rooms-list" aria-label="{{_ "Channels"}}" role="region">
 				<div class="wrapper">
-					{{ > unreadRooms }}
+					{{> unreadRooms }}
 
 					{{#each roomType}}
 						{{#if canShowRoomType}}
@@ -24,10 +24,10 @@
 					{{/if}}
 				</div>
 			</div>
-			<div class="unread-rooms bottom-unread-rooms hidden">
+			<div class="unread-rooms background-primary-action-color color-primary-action-contrast bottom-unread-rooms hidden">
 				{{_ "More_unreads"}} <i class="icon-down-big"></i>
 			</div>
-			<div class="flex-nav animated-hidden">
+			<div class="flex-nav primary-background-color animated-hidden">
 				<section>
 					{{> Template.dynamic template=flexTemplate data=flexData}}
 				</section>
diff --git a/packages/rocketchat-ui-sidenav/side-nav/userStatus.html b/packages/rocketchat-ui-sidenav/side-nav/userStatus.html
index 66dc5a7e632c925f63496c57f81e04c778579bd0..b92728ef1379afe08788f2149420f974e356a4af 100644
--- a/packages/rocketchat-ui-sidenav/side-nav/userStatus.html
+++ b/packages/rocketchat-ui-sidenav/side-nav/userStatus.html
@@ -1,7 +1,7 @@
 <template name="userStatus">
 	<div class="account-box">
 		{{#with myUserInfo}}
-			<div class="info status-{{status}}">
+			<div class="info status-{{status}} primary-background-color">
 				{{#if username}}
 					<div class="thumb" data-status='{{visualStatus}}'>
 						{{> avatar username=username}}
@@ -11,7 +11,7 @@
 					</div>
 				{{/if}}
 			</div>
-			<nav class="options animated-hidden">
+			<nav class="options primary-background-color animated-hidden">
 				<div class="wrapper">
 					<button data-status="online" class="status online"><span>{{_ "Online"}}</span></button>
 					<button data-status="away" class="status away"><span>{{_ "Away" context="male"}}</span></button>
diff --git a/packages/rocketchat-ui-vrecord/client/vrecord.html b/packages/rocketchat-ui-vrecord/client/vrecord.html
index 3b4046a4e4c19476e6a38b7c5565f749c71f4eba..881a941a01d4a35e11d90f416429acaa5cd8f539 100644
--- a/packages/rocketchat-ui-vrecord/client/vrecord.html
+++ b/packages/rocketchat-ui-vrecord/client/vrecord.html
@@ -1,16 +1,16 @@
 <template name="vrecDialog">
-	<div class="vrec-dialog">
+	<div class="vrec-dialog secondary-background-color">
 		<div class="video-container">
 			<video width="320" height="240" src=""></video>
 		</div>
 		<div class="buttons">
 			<ul>
-				<li class="left-aligned">
+				<li class="left-aligned border-secondary-background-color">
 					<button class="button primary record {{recordDisabled}}" {{recordDisabled}}>
 						<i class="{{recordIcon}}"></i>
 					</button>
 				</li>
-				<li class="right-aligned">
+				<li class="right-aligned border-secondary-background-color">
 					<button class="button cancel">{{_ "Cancel"}}</button>
 					<button class="button primary ok {{okDisabled}}" {{okDisabled}}>{{_ "Ok"}}</button>
 				</li>
diff --git a/packages/rocketchat-ui-vrecord/client/vrecord.less b/packages/rocketchat-ui-vrecord/client/vrecord.less
index 71a8892c6395b8517a5b3c1f7b8b7912a9695a4a..5bfd1d2f73d8857f686df2aadfb64a1662d58b25 100644
--- a/packages/rocketchat-ui-vrecord/client/vrecord.less
+++ b/packages/rocketchat-ui-vrecord/client/vrecord.less
@@ -2,9 +2,10 @@
 	opacity: 0;
 	visibility: hidden;
 	position: absolute;
-	background-color: @secondary-background-color;
 	border-radius: 5px;
-	box-shadow: 0px 1px 1px 0 rgba(0,0,0,0.2), 0 2px 10px 0 rgba(0,0,0,.16);
+	box-shadow:
+		0 1px 1px 0 rgba(0, 0, 0, 0.2),
+		0 2px 10px 0 rgba(0, 0, 0, 0.16);
 
 	&.show {
 		opacity: 1;
@@ -25,20 +26,21 @@
 				display: table-cell;
 				margin: 0 2px;
 				padding: 6px 0;
-
-				border-bottom: 2px solid @secondary-background-color;
+				border-bottom-width: 2px;
 
 				&.right-aligned {
 					text-align: right;
 				}
+
 				&.left-aligned {
 					text-align: left;
 				}
 			}
 		}
 	}
+
 	.video-container {
-		padding: 5px 5px 5px 5px;
+		padding: 5px;
 	}
 }
 
diff --git a/packages/rocketchat-ui-vrecord/loadStylesheet.coffee b/packages/rocketchat-ui-vrecord/loadStylesheet.coffee
deleted file mode 100644
index 62be80a50dd00c377a17c606e42654566eb0a6ea..0000000000000000000000000000000000000000
--- a/packages/rocketchat-ui-vrecord/loadStylesheet.coffee
+++ /dev/null
@@ -1,2 +0,0 @@
-RocketChat.theme.addPackageAsset ->
-	return Assets.getText 'client/vrecord.less'
diff --git a/packages/rocketchat-ui-vrecord/package.js b/packages/rocketchat-ui-vrecord/package.js
index eb8101001eef70059a28801ec63eaa4831fd43d7..309ac94c2904cb99ced38d2fb10866e1b2ed9cd6 100644
--- a/packages/rocketchat-ui-vrecord/package.js
+++ b/packages/rocketchat-ui-vrecord/package.js
@@ -18,12 +18,11 @@ Package.onUse(function(api) {
 	]);
 
 
-	api.addAssets('client/vrecord.less', 'server');
+	api.addFiles('client/vrecord.less', 'client');
 
 	api.addFiles('client/vrecord.html', 'client');
 	api.addFiles('client/vrecord.coffee', 'client');
 	api.addFiles('client/VRecDialog.coffee', 'client');
 
 	api.addFiles('server/settings.coffee', 'server');
-	api.addFiles('loadStylesheet.coffee', 'server');
 });
diff --git a/packages/rocketchat-ui/lib/RoomManager.coffee b/packages/rocketchat-ui/lib/RoomManager.coffee
index e5d0eb489d7328d5791ea970cdf61babe81a3f69..99296113cb0e0bda88cb1433f3587d870669f1f4 100644
--- a/packages/rocketchat-ui/lib/RoomManager.coffee
+++ b/packages/rocketchat-ui/lib/RoomManager.coffee
@@ -57,10 +57,6 @@ Tracker.autorun ->
 
 	close = (typeName) ->
 		if openedRooms[typeName]
-			if openedRooms[typeName].sub?
-				for sub in openedRooms[typeName].sub
-					sub.stop()
-
 			if openedRooms[typeName].rid?
 				msgStream.removeAllListeners openedRooms[typeName].rid
 				RocketChat.Notifications.unRoom openedRooms[typeName].rid, 'deleteMessage', onDeleteMessageStream
@@ -87,14 +83,10 @@ Tracker.autorun ->
 				unless user?.username
 					return
 
-				record.sub = [
-					Meteor.subscribe 'room', typeName
-				]
-
 				if record.ready is true
 					return
 
-				ready = record.sub[0].ready() and CachedChatSubscription.ready.get() is true
+				ready = CachedChatRoom.ready.get() and CachedChatSubscription.ready.get() is true
 
 				if ready is true
 					type = typeName.substr(0, 1)
@@ -232,9 +224,9 @@ Tracker.autorun ->
 			topOffset = $(item).offset().top + scrollTop
 			percent = 100 / totalHeight * topOffset
 			if $(item).hasClass('mention-link-all')
-				ticksBar.append('<div class="tick tick-all" style="top: '+percent+'%;"></div>')
+				ticksBar.append('<div class="tick background-attention-color" style="top: '+percent+'%;"></div>')
 			else
-				ticksBar.append('<div class="tick" style="top: '+percent+'%;"></div>')
+				ticksBar.append('<div class="tick background-primary-action-color" style="top: '+percent+'%;"></div>')
 
 	open: open
 	close: close
@@ -252,3 +244,4 @@ Tracker.autorun ->
 
 RocketChat.callbacks.add 'afterLogoutCleanUp', ->
 	RoomManager.closeAllRooms()
+, RocketChat.callbacks.priority.MEDIUM, 'roommanager-after-logout-cleanup'
diff --git a/packages/rocketchat-ui/lib/codeMirror/codeMirror.js b/packages/rocketchat-ui/lib/codeMirror/codeMirror.js
new file mode 100644
index 0000000000000000000000000000000000000000..61991d3d72c14aa378b0cac5cea253226f63a085
--- /dev/null
+++ b/packages/rocketchat-ui/lib/codeMirror/codeMirror.js
@@ -0,0 +1,160 @@
+import './codeMirrorComponent.html';
+import './codeMirrorComponent.js';
+
+import 'codemirror/addon/fold/brace-fold.js';
+import 'codemirror/addon/fold/comment-fold.js';
+import 'codemirror/addon/fold/foldcode.js';
+import 'codemirror/addon/fold/foldgutter.css';
+import 'codemirror/addon/fold/foldgutter.js';
+import 'codemirror/addon/fold/indent-fold.js';
+import 'codemirror/addon/fold/markdown-fold.js';
+import 'codemirror/addon/fold/xml-fold.js';
+
+// lints
+// import 'codemirror/addon/lint/jsonlint.js';
+// import 'codemirror/addon/lint/jshint.js';
+// import 'codemirror/addon/lint/csslint.js';
+// import 'codemirror/addon/lint/css-lint.js';
+// import 'codemirror/addon/lint/html-lint.js';
+// import 'codemirror/addon/lint/javascript-lint.js';
+// import 'codemirror/addon/lint/json-lint.js';
+// import 'codemirror/addon/lint/yaml-lint.js';
+// import 'codemirror/addon/lint/lint.css';
+// import 'codemirror/addon/lint/lint.js';
+
+// active line mode
+import 'codemirror/addon/selection/active-line.js';
+
+// search/replace
+import 'codemirror/addon/search/search.js';
+import 'codemirror/addon/search/searchcursor.js';
+import 'codemirror/addon/dialog/dialog.js';
+import 'codemirror/addon/dialog/dialog.css';
+
+// overlay: required by `gfm.js`
+import 'codemirror/addon/mode/overlay.js';
+
+// markdown list continuation; nice complement for gfm
+import 'codemirror/addon/edit/continuelist.js';
+
+// modes
+import 'codemirror/mode/apl/apl.js';
+import 'codemirror/mode/asterisk/asterisk.js';
+import 'codemirror/mode/clike/clike.js';
+import 'codemirror/mode/clojure/clojure.js';
+import 'codemirror/mode/cobol/cobol.js';
+import 'codemirror/mode/commonlisp/commonlisp.js';
+import 'codemirror/mode/coffeescript/coffeescript.js';
+import 'codemirror/mode/css/css.js';
+import 'codemirror/mode/cypher/cypher.js';
+import 'codemirror/mode/d/d.js';
+import 'codemirror/mode/diff/diff.js';
+import 'codemirror/mode/django/django.js';
+import 'codemirror/mode/dockerfile/dockerfile.js';
+import 'codemirror/mode/dtd/dtd.js';
+import 'codemirror/mode/dylan/dylan.js';
+import 'codemirror/mode/ecl/ecl.js';
+import 'codemirror/mode/eiffel/eiffel.js';
+import 'codemirror/mode/erlang/erlang.js';
+import 'codemirror/mode/fortran/fortran.js';
+import 'codemirror/mode/gas/gas.js';
+import 'codemirror/mode/gfm/gfm.js';
+import 'codemirror/mode/gherkin/gherkin.js';
+import 'codemirror/mode/go/go.js';
+import 'codemirror/mode/groovy/groovy.js';
+import 'codemirror/mode/haml/haml.js';
+import 'codemirror/mode/haskell/haskell.js';
+import 'codemirror/mode/haxe/haxe.js';
+import 'codemirror/mode/htmlembedded/htmlembedded.js';
+import 'codemirror/mode/htmlmixed/htmlmixed.js';
+import 'codemirror/mode/http/http.js';
+import 'codemirror/mode/idl/idl.js';
+import 'codemirror/mode/javascript/javascript.js';
+import 'codemirror/mode/jinja2/jinja2.js';
+import 'codemirror/mode/julia/julia.js';
+import 'codemirror/mode/livescript/livescript.js';
+import 'codemirror/mode/lua/lua.js';
+import 'codemirror/mode/markdown/markdown.js';
+import 'codemirror/mode/mirc/mirc.js';
+import 'codemirror/mode/mllike/mllike.js';
+import 'codemirror/mode/modelica/modelica.js';
+import 'codemirror/mode/nginx/nginx.js';
+import 'codemirror/mode/ntriples/ntriples.js';
+import 'codemirror/mode/octave/octave.js';
+import 'codemirror/mode/pascal/pascal.js';
+import 'codemirror/mode/pegjs/pegjs.js';
+import 'codemirror/mode/perl/perl.js';
+import 'codemirror/mode/php/php.js';
+import 'codemirror/mode/pig/pig.js';
+import 'codemirror/mode/properties/properties.js';
+import 'codemirror/mode/puppet/puppet.js';
+import 'codemirror/mode/python/python.js';
+import 'codemirror/mode/q/q.js';
+import 'codemirror/mode/r/r.js';
+import 'codemirror/mode/rpm/rpm.js';
+import 'codemirror/mode/rst/rst.js';
+import 'codemirror/mode/ruby/ruby.js';
+import 'codemirror/mode/rust/rust.js';
+import 'codemirror/mode/sass/sass.js';
+import 'codemirror/mode/scheme/scheme.js';
+import 'codemirror/mode/shell/shell.js';
+import 'codemirror/mode/sieve/sieve.js';
+import 'codemirror/mode/slim/slim.js';
+import 'codemirror/mode/smalltalk/smalltalk.js';
+import 'codemirror/mode/smarty/smarty.js';
+import 'codemirror/mode/solr/solr.js';
+import 'codemirror/mode/sparql/sparql.js';
+import 'codemirror/mode/sql/sql.js';
+import 'codemirror/mode/stex/stex.js';
+import 'codemirror/mode/tcl/tcl.js';
+import 'codemirror/mode/textile/textile.js';
+import 'codemirror/mode/tiddlywiki/tiddlywiki.js';
+import 'codemirror/mode/tiki/tiki.js';
+import 'codemirror/mode/toml/toml.js';
+import 'codemirror/mode/tornado/tornado.js';
+import 'codemirror/mode/turtle/turtle.js';
+import 'codemirror/mode/vb/vb.js';
+import 'codemirror/mode/vbscript/vbscript.js';
+import 'codemirror/mode/velocity/velocity.js';
+import 'codemirror/mode/verilog/verilog.js';
+import 'codemirror/mode/xml/xml.js';
+import 'codemirror/mode/xquery/xquery.js';
+import 'codemirror/mode/yaml/yaml.js';
+import 'codemirror/mode/z80/z80.js';
+
+// themes
+// import 'codemirror/theme/3024-day.css';
+// import 'codemirror/theme/3024-night.css';
+// import 'codemirror/theme/ambiance-mobile.css';
+// import 'codemirror/theme/ambiance.css';
+// import 'codemirror/theme/base16-dark.css';
+// import 'codemirror/theme/base16-light.css';
+// import 'codemirror/theme/blackboard.css';
+// import 'codemirror/theme/cobalt.css';
+// import 'codemirror/theme/eclipse.css';
+// import 'codemirror/theme/elegant.css';
+// import 'codemirror/theme/erlang-dark.css';
+// import 'codemirror/theme/lesser-dark.css';
+// import 'codemirror/theme/mbo.css';
+// import 'codemirror/theme/mdn-like.css';
+// import 'codemirror/theme/midnight.css';
+// import 'codemirror/theme/monokai.css';
+// import 'codemirror/theme/neat.css';
+// import 'codemirror/theme/neo.css';
+// import 'codemirror/theme/night.css';
+// import 'codemirror/theme/paraiso-dark.css';
+// import 'codemirror/theme/paraiso-light.css';
+// import 'codemirror/theme/pastel-on-dark.css';
+// import 'codemirror/theme/rubyblue.css';
+// import 'codemirror/theme/solarized.css';
+// import 'codemirror/theme/the-matrix.css';
+// import 'codemirror/theme/tomorrow-night-eighties.css';
+// import 'codemirror/theme/twilight.css';
+// import 'codemirror/theme/vibrant-ink.css';
+// import 'codemirror/theme/xq-dark.css';
+// import 'codemirror/theme/xq-light.css';
+
+// key bindings
+// import 'codemirror/keymap/emacs.js';
+import 'codemirror/keymap/sublime.js';
+// import 'codemirror/keymap/vim.js';
diff --git a/packages/rocketchat-ui/lib/codeMirror/codeMirrorComponent.html b/packages/rocketchat-ui/lib/codeMirror/codeMirrorComponent.html
new file mode 100644
index 0000000000000000000000000000000000000000..143889e8e198e059c67a55fd3cb6748dcbd41c23
--- /dev/null
+++ b/packages/rocketchat-ui/lib/codeMirror/codeMirrorComponent.html
@@ -0,0 +1,3 @@
+<template name="CodeMirror">
+	<textarea id="{{editorId}}" name="{{editorName}}" style="display: none">{{code}}</textarea>
+</template>
diff --git a/packages/rocketchat-ui/lib/codeMirror/codeMirrorComponent.js b/packages/rocketchat-ui/lib/codeMirror/codeMirrorComponent.js
new file mode 100644
index 0000000000000000000000000000000000000000..3508c89cc565a7499d5abe2ea82c879745494c4a
--- /dev/null
+++ b/packages/rocketchat-ui/lib/codeMirror/codeMirrorComponent.js
@@ -0,0 +1,50 @@
+/* global CodeMirrors */
+CodeMirrors = {};
+
+import 'codemirror/lib/codemirror.css';
+import CodeMirror from 'codemirror/lib/codemirror.js';
+
+Template.CodeMirror.rendered = function() {
+	var options = this.data.options || { lineNumbers: true };
+	var textarea = this.find('textarea');
+	var editor = CodeMirror.fromTextArea(textarea, options);
+
+	CodeMirrors[this.data.id || 'code-mirror-textarea'] = editor;
+
+	var self = this;
+	editor.on('change', function(doc) {
+		var val = doc.getValue();
+		textarea.value = val;
+		if (self.data.reactiveVar) {
+			Session.set(self.data.reactiveVar, val);
+		}
+	});
+
+	if (this.data.reactiveVar) {
+		this.autorun(function() {
+			var val = Session.get(self.data.reactiveVar) || '';
+			if (val !== editor.getValue()) {
+				editor.setValue(val);
+			}
+		});
+	}
+
+	Meteor.defer(function() {
+		editor.refresh();
+	});
+};
+
+Template.CodeMirror.destroyed = function() {
+	delete CodeMirrors[this.data.id || 'code-mirror-textarea'];
+	this.$('#' + (this.data.id || 'code-mirror-textarea')).next('.CodeMirror').remove();
+};
+
+Template.CodeMirror.helpers({
+	editorId() {
+		return this.id || 'code-mirror-textarea';
+	},
+
+	editorName() {
+		return this.name || 'code-mirror-textarea';
+	}
+});
diff --git a/packages/rocketchat-ui/lib/collections.coffee b/packages/rocketchat-ui/lib/collections.coffee
index 7ee8ca9ab69ff3fadeb768fcb3a3aa4f31c08a9e..3f32ee66eea03ea67d799a7c4cf691a5977bf738 100644
--- a/packages/rocketchat-ui/lib/collections.coffee
+++ b/packages/rocketchat-ui/lib/collections.coffee
@@ -1,5 +1,6 @@
 @ChatMessage = new Meteor.Collection null
-@ChatRoom = new Meteor.Collection 'rocketchat_room'
+@CachedChatRoom = new RocketChat.CachedCollection({ name: 'rooms', initOnLogin: true })
+@ChatRoom = CachedChatRoom.collection
 
 @CachedChatSubscription = new RocketChat.CachedCollection({ name: 'subscriptions', initOnLogin: true })
 @ChatSubscription = CachedChatSubscription.collection
diff --git a/packages/rocketchat-ui/lib/cordova/keyboard-fix.coffee b/packages/rocketchat-ui/lib/cordova/keyboard-fix.coffee
index 9b45da2a5e6b4776264c70effb57fd0d17da4aec..119946b249905fe86bc1efae6ff72eef949dc3c9 100644
--- a/packages/rocketchat-ui/lib/cordova/keyboard-fix.coffee
+++ b/packages/rocketchat-ui/lib/cordova/keyboard-fix.coffee
@@ -8,7 +8,6 @@ if Meteor.isCordova
 		if device?.platform.toLowerCase() isnt 'android'
 			if Meteor.userId()?
 				$('.main-content').css 'height', window.innerHeight
-				$('.mobile-message-menu').css 'height', window.innerHeight
 				$('.sweet-alert').css 'transform', "translateY(-#{(document.height - window.innerHeight)/2}px)"
 				$('.sweet-alert').css '-webkit-transform', "translateY(-#{(document.height - window.innerHeight)/2}px)"
 			else
@@ -19,9 +18,8 @@ if Meteor.isCordova
 		if device?.platform.toLowerCase() isnt 'android'
 			if Meteor.userId()?
 				$('.main-content').css 'height', window.innerHeight
-				$('.mobile-message-menu').css 'height', window.innerHeight
 				$('.sweet-alert').css 'transform', ''
 				$('.sweet-alert').css '-webkit-transform', ''
 			else
 				$(document.body).css 'height', window.innerHeight
-				$(document.body).css 'overflow', 'visible'
\ No newline at end of file
+				$(document.body).css 'overflow', 'visible'
diff --git a/packages/rocketchat-ui/lib/fileUpload.coffee b/packages/rocketchat-ui/lib/fileUpload.coffee
index e23f8762497033810bfca2722e39a5d316276ce9..014b88d2d5f0d1a304cc97a37892acb33be39252 100644
--- a/packages/rocketchat-ui/lib/fileUpload.coffee
+++ b/packages/rocketchat-ui/lib/fileUpload.coffee
@@ -49,7 +49,10 @@ readAsArrayBuffer = (file, callback) ->
 							Your browser does not support the audio element.
 						</audio>
 					</div>
-					<div class='upload-preview-title'>#{Handlebars._escape(file.name)}</div>
+					<div class='upload-preview-title'>
+						<input id='file-name' style='display: inherit;' value='#{Handlebars._escape(file.name)}' placeholder='#{t("Upload_file_name")}'>
+						<input id='file-description' style='display: inherit;' value='' placeholder='#{t("Upload_file_description")}'>
+					</div>
 				"""
 			else if file.type is 'video'
 				text = """
@@ -59,14 +62,20 @@ readAsArrayBuffer = (file, callback) ->
 							Your browser does not support the video element.
 						</video>
 					</div>
-					<div class='upload-preview-title'>#{Handlebars._escape(file.name)}</div>
+					<div class='upload-preview-title'>
+						<input id='file-name' style='display: inherit;' value='#{Handlebars._escape(file.name)}' placeholder='#{t("Upload_file_name")}'>
+						<input id='file-description' style='display: inherit;' value='' placeholder='#{t("Upload_file_description")}'>
+					</div>
 				"""
 			else
 				text = """
 					<div class='upload-preview'>
 						<div class='upload-preview-file' style='background-image: url(#{fileContent})'></div>
 					</div>
-					<div class='upload-preview-title'>#{Handlebars._escape(file.name)}</div>
+					<div class='upload-preview-title'>
+						<input id='file-name' style='display: inherit;' value='#{Handlebars._escape(file.name)}' placeholder='#{t("Upload_file_name")}'>
+						<input id='file-description' style='display: inherit;' value='' placeholder='#{t("Upload_file_description")}'>
+					</div>
 				"""
 
 			swal
@@ -78,15 +87,15 @@ readAsArrayBuffer = (file, callback) ->
 				html: true
 			, (isConfirm) ->
 				consume()
-
 				if isConfirm isnt true
 					return
 
 				record =
-					name: file.name or file.file.name
+					name: document.getElementById('file-name').value or file.name or file.file.name
 					size: file.file.size
 					type: file.file.type
 					rid: roomId
+					description: document.getElementById('file-description').value
 
 				upload = fileUploadHandler record, file.file
 
diff --git a/packages/rocketchat-ui/lib/getAvatarUrlFromUsername.coffee b/packages/rocketchat-ui/lib/getAvatarUrlFromUsername.coffee
index 392e2ebfe4aa040af9ed6c79ec699016ade1727c..90761f6b720d0bc8f03577bbc913eb2827be1e93 100644
--- a/packages/rocketchat-ui/lib/getAvatarUrlFromUsername.coffee
+++ b/packages/rocketchat-ui/lib/getAvatarUrlFromUsername.coffee
@@ -1,10 +1,19 @@
 @getAvatarUrlFromUsername = (username) ->
 	key = "avatar_random_#{username}"
 	random = Session?.keys[key] or 0
+
 	if not username?
 		return
-	if Meteor.isCordova
-		path = Meteor.absoluteUrl().replace /\/$/, ''
+
+	cdnPrefix = (RocketChat.settings.get('CDN_PREFIX') or '').trim().replace(/\/$/, '')
+	pathPrefix = (__meteor_runtime_config__.ROOT_URL_PATH_PREFIX or '').trim().replace(/\/$/, '')
+
+	if cdnPrefix
+		path = cdnPrefix + pathPrefix
+	else if Meteor.isCordova
+		# Meteor.absoluteUrl alread has path prefix
+		path = Meteor.absoluteUrl().replace(/\/$/, '')
 	else
-		path = __meteor_runtime_config__.ROOT_URL_PATH_PREFIX || '';
-	"#{path}/avatar/#{encodeURIComponent(username)}.jpg?_dc=#{random}"
+		path = pathPrefix
+
+	return "#{path}/avatar/#{encodeURIComponent(username)}?_dc=#{random}"
diff --git a/packages/rocketchat-ui/lib/iframeCommands.js b/packages/rocketchat-ui/lib/iframeCommands.js
index 4e74ca1ff5a064a86a164280f7e9ae616bdb7a4c..5ff57ff1807318c76f87ab6b3102b919715672da 100644
--- a/packages/rocketchat-ui/lib/iframeCommands.js
+++ b/packages/rocketchat-ui/lib/iframeCommands.js
@@ -19,12 +19,17 @@ const commands = {
 			}, event.origin);
 		};
 
-		if (typeof data.service === 'string') {
+		const siteUrl = Meteor.settings.Site_Url + '/';
+		if (typeof data.redirectUrl !== 'string' || !data.redirectUrl.startsWith(siteUrl)) {
+			data.redirectUrl = null;
+		}
+
+		if (typeof data.service === 'string' && window.ServiceConfiguration) {
 			const customOauth = ServiceConfiguration.configurations.findOne({service: data.service});
 
 			if (customOauth) {
 				const customLoginWith = Meteor['loginWith' + _.capitalize(customOauth.service, true)];
-				const customRedirectUri = window.OAuth._redirectUri(customOauth.service, customOauth);
+				const customRedirectUri = data.redirectUrl || siteUrl;
 				customLoginWith.call(Meteor, {'redirectUrl': customRedirectUri}, customOAuthCallback);
 			}
 		}
diff --git a/packages/rocketchat-theme/assets/stylesheets/swipebox.min.css b/packages/rocketchat-ui/lib/jquery.swipebox.min.css
similarity index 100%
rename from packages/rocketchat-theme/assets/stylesheets/swipebox.min.css
rename to packages/rocketchat-ui/lib/jquery.swipebox.min.css
diff --git a/packages/rocketchat-ui/lib/menu.coffee b/packages/rocketchat-ui/lib/menu.coffee
index f2ad61eb7bdda1ee9a388c70153cfb8e9671263d..c94d8de8c39d6cfecc69c465f4c6cf816171f313 100644
--- a/packages/rocketchat-ui/lib/menu.coffee
+++ b/packages/rocketchat-ui/lib/menu.coffee
@@ -1,18 +1,23 @@
 @menu = new class
 	init: ->
-		@container = $("#rocket-chat")
+		@mainContent = $('.main-content, .flex-tab-bar')
 		@list = $('.rooms-list')
 
+		Session.set("isMenuOpen", false)
+
 	isOpen: ->
-		return @container?.hasClass("menu-opened") is true
+		return Session.get("isMenuOpen")
 
 	open: ->
-		if not @isOpen()
-			@container?.removeClass("menu-closed").addClass("menu-opened")
+		Session.set("isMenuOpen", true)
+		if isRtl localStorage.getItem "userLanguage"
+			@mainContent?.css('transform', 'translateX(-260px)')
+		else
+			@mainContent?.css('transform', 'translateX(260px)')
 
 	close: ->
-		if @isOpen()
-			@container?.removeClass("menu-opened").addClass("menu-closed")
+		Session.set("isMenuOpen", false)
+		@mainContent?.css('transform', 'translateX(0)')
 
 	toggle: ->
 		if @isOpen()
diff --git a/packages/rocketchat-ui/lib/recorderjs/audioRecorder.coffee b/packages/rocketchat-ui/lib/recorderjs/audioRecorder.coffee
index 013af2a24e52a488fc445c298c93d3d63b4840ec..e51dbeff7a2b6ba9655cea1147753ade205fee34 100644
--- a/packages/rocketchat-ui/lib/recorderjs/audioRecorder.coffee
+++ b/packages/rocketchat-ui/lib/recorderjs/audioRecorder.coffee
@@ -4,7 +4,7 @@
 		navigator.getUserMedia = navigator.getUserMedia or navigator.webkitGetUserMedia
 		window.URL = window.URL or window.webkitURL
 
-		@audio_context = new AudioContext
+		window.audioContext = new AudioContext
 
 		ok = (stream) =>
 			@startUserMedia(stream)
@@ -18,7 +18,7 @@
 
 	startUserMedia: (stream) ->
 		@stream = stream
-		input = @audio_context.createMediaStreamSource(stream)
+		input = window.audioContext.createMediaStreamSource(stream)
 		@recorder = new Recorder(input, {workerPath: '/recorderWorker.js'})
 		@recorder.record()
 
@@ -32,9 +32,10 @@
 
 		@recorder.clear()
 
-		delete @audio_context
+		window.audioContext.close()
+		delete window.audioContext
 		delete @recorder
 		delete @stream
 
 	getBlob: (cb) ->
-		@recorder.exportWAV cb
\ No newline at end of file
+		@recorder.exportWAV cb
diff --git a/packages/rocketchat-ui/package.js b/packages/rocketchat-ui/package.js
index 72f8da9b1a6b0ac3330fdc1c4a5b9493bd66c1f0..3b868ee1e7709c3f76cc592065ddc5b583d37810 100644
--- a/packages/rocketchat-ui/package.js
+++ b/packages/rocketchat-ui/package.js
@@ -40,6 +40,7 @@ Package.onUse(function(api) {
 	api.addFiles('lib/fileUpload.coffee', 'client');
 	api.addFiles('lib/fireEvent.js', 'client');
 	api.addFiles('lib/iframeCommands.js', 'client');
+	api.addFiles('lib/jquery.swipebox.min.css', 'client');
 	api.addFiles('lib/jquery.swipebox.min.js', 'client');
 	api.addFiles('lib/jquery.swipebox.init.js', 'client');
 	api.addFiles('lib/menu.coffee', 'client');
@@ -56,6 +57,8 @@ Package.onUse(function(api) {
 	api.addFiles('lib/tapi18n.coffee', 'client');
 	api.addFiles('lib/textarea-autogrow.js', 'client');
 
+	api.addFiles('lib/codeMirror/codeMirror.js', 'client');
+
 	// LIB CORDOVA
 	api.addFiles('lib/cordova/facebook-login.coffee', 'client');
 	api.addFiles('lib/cordova/keyboard-fix.coffee', 'client');
diff --git a/packages/rocketchat-ui/views/404/roomNotFound.html b/packages/rocketchat-ui/views/404/roomNotFound.html
index b3c028106873fbe190d092de915e15ecb622ea16..9d653a0cce26d77d3863fc532a63112117bc91ad 100644
--- a/packages/rocketchat-ui/views/404/roomNotFound.html
+++ b/packages/rocketchat-ui/views/404/roomNotFound.html
@@ -1,12 +1,12 @@
 <template name="roomNotFound">
-	<section class="page-container page-list">
-		<header class="fixed-title">
+	<section class="page-container page-list content-background-color">
+		<header class="fixed-title content-background-color border-component-color">
 			{{> burger}}
 			<h2>
 				<span class="room-title">{{_ "Room_not_found"}}</span>
 			</h2>
 		</header>
-		<div class="content room-not-found">
+		<div class="content room-not-found error-color">
 			<i class="icon-attention"></i>
 			<div>
 				{{#with data}}
diff --git a/packages/rocketchat-ui/views/app/burger.coffee b/packages/rocketchat-ui/views/app/burger.coffee
index 6af03ca0dbde668839a27d2ee309af32d5e40701..58ca516db8820a852c787a3ebbc707e2a9b2963f 100644
--- a/packages/rocketchat-ui/views/app/burger.coffee
+++ b/packages/rocketchat-ui/views/app/burger.coffee
@@ -1,3 +1,5 @@
 Template.burger.helpers
 	unread: ->
-		return Session.get 'unread'
\ No newline at end of file
+		return Session.get 'unread'
+	isMenuOpen: ->
+		if Session.equals('isMenuOpen', true) then 'menu-opened'
diff --git a/packages/rocketchat-ui/views/app/burger.html b/packages/rocketchat-ui/views/app/burger.html
index 8cfe49e46a8beb34d31eb32a89015b3a9bf9c3f0..2ae6d163307dff5b35196ee6f5b7fdbf254eeb08 100644
--- a/packages/rocketchat-ui/views/app/burger.html
+++ b/packages/rocketchat-ui/views/app/burger.html
@@ -1,12 +1,12 @@
 <template name="burger">
-	<div class="burger">
+	<div class="burger {{isMenuOpen}}">
 		<i></i>
 		<i></i>
 		<i></i>
 		{{#if unread}}
-			<div class="unread-burger-alert">
+			<div class="unread-burger-alert color-error-contrast background-error-color">
 				{{unread}}
 			</div>
 		{{/if}}
 	</div>
-</template>
\ No newline at end of file
+</template>
diff --git a/packages/rocketchat-ui/views/app/home.html b/packages/rocketchat-ui/views/app/home.html
index 2983174eb66df61b4f413c27b5068012d16aef9c..f9463714cae06f078863972e3ea46048b6383f28 100644
--- a/packages/rocketchat-ui/views/app/home.html
+++ b/packages/rocketchat-ui/views/app/home.html
@@ -1,6 +1,6 @@
 <template name="home">
-	<section class="page-container page-home page-static">
-		<header class="fixed-title">
+	<section class="page-container page-home page-static content-background-color">
+		<header class="fixed-title content-background-color border-component-color">
 			{{> burger}}
 			<h2>
 				<span class="room-title">{{title}}</span>
diff --git a/packages/rocketchat-ui/views/app/pageContainer.html b/packages/rocketchat-ui/views/app/pageContainer.html
index 0508293eb397ae845c9479f5f35b8d9ce6b0b0f3..666501273d9621f23237436651491a17a411b938 100644
--- a/packages/rocketchat-ui/views/app/pageContainer.html
+++ b/packages/rocketchat-ui/views/app/pageContainer.html
@@ -1,6 +1,6 @@
 <template name="pageContainer">
-	<section class="page-container page-home page-static page-list">
-		<header class="fixed-title">
+	<section class="page-container page-home page-static page-list content-background-color">
+		<header class="fixed-title content-background-color border-component-color">
 			{{> burger}}
 			<h2>
 				<span class="page-title">
diff --git a/packages/rocketchat-ui/views/app/pageSettingsContainer.html b/packages/rocketchat-ui/views/app/pageSettingsContainer.html
index e37b35c19920719564f04525394c526d33ed3c00..46bfee36ebb01a66a9d565910170f53762afd634 100644
--- a/packages/rocketchat-ui/views/app/pageSettingsContainer.html
+++ b/packages/rocketchat-ui/views/app/pageSettingsContainer.html
@@ -1,6 +1,6 @@
 <template name="pageSettingsContainer">
-	<section class="page-container page-home page-static page-settings">
-		<header class="fixed-title">
+	<section class="page-container page-home page-static page-settings content-background-color">
+		<header class="fixed-title content-background-color border-component-color">
 			{{> burger}}
 			<h2>
 				<span class="page-title">{{pageTitle}}</span>
diff --git a/packages/rocketchat-ui/views/app/privateHistory.html b/packages/rocketchat-ui/views/app/privateHistory.html
index 15eaf15df7aba6d4945f12d58d83f2f0796cd2f7..5544350792f9a83286208e1901c8ffa85c6252dd 100644
--- a/packages/rocketchat-ui/views/app/privateHistory.html
+++ b/packages/rocketchat-ui/views/app/privateHistory.html
@@ -1,6 +1,6 @@
 <template name="privateHistory">
-	<section class="page-container page-list">
-		<header class="fixed-title">
+	<section class="page-container page-list content-background-color">
+		<header class="fixed-title content-background-color border-component-color">
 			{{> burger}}
 			<h2>
 				<span class="room-title">{{_ "History"}}</span>
@@ -10,7 +10,7 @@
 			<form class="search-form" role="form">
 				<div class="input-line search">
 					<input type="text" id="history-filter" placeholder="{{_ "Search"}}" dir="auto">
-					<i class="icon-search"></i>
+					<i class="icon-search secondary-font-color"></i>
 				</div>
 			</form>
 			<div class="results">
diff --git a/packages/rocketchat-ui/views/app/room.coffee b/packages/rocketchat-ui/views/app/room.coffee
index 14863c92045dd2ec05f1710d08a3a5342bdc6780..69bb49fc23454c5c6fb34da7ba1044610f7d79eb 100644
--- a/packages/rocketchat-ui/views/app/room.coffee
+++ b/packages/rocketchat-ui/views/app/room.coffee
@@ -18,7 +18,7 @@ Template.room.helpers
 
 	favorite: ->
 		sub = ChatSubscription.findOne { rid: this._id }, { fields: { f: 1 } }
-		return 'icon-star favorite-room' if sub?.f? and sub.f and favoritesEnabled()
+		return 'icon-star favorite-room pending-color' if sub?.f? and sub.f and favoritesEnabled()
 		return 'icon-star-empty'
 
 	favoriteLabel: ->
@@ -93,14 +93,7 @@ Template.room.helpers
 
 	userStatus: ->
 		roomData = Session.get('roomData' + this._id)
-
-		return {} unless roomData
-
-		if roomData.t in ['d', 'l']
-			subscription = RocketChat.models.Subscriptions.findOne({rid: this._id});
-			return Session.get('user_' + subscription.name + '_status') || 'offline'
-		else
-			return 'offline'
+		return RocketChat.roomTypes.getUserStatus(roomData.t, this._id) or 'offline'
 
 	flexOpened: ->
 		return 'opened' if RocketChat.TabBar.isFlexOpen()
@@ -127,7 +120,10 @@ Template.room.helpers
 		return moment(this.since).calendar(null, {sameDay: 'LT'})
 
 	flexTemplate: ->
-		return RocketChat.TabBar.getTemplate()
+		if Session.get('openedRoom') is this._id
+			return RocketChat.TabBar.getTemplate()
+
+		return ''
 
 	flexData: ->
 		return _.extend {
@@ -579,13 +575,13 @@ Template.room.onRendered ->
 	template.isAtBottom = (scrollThreshold) ->
 		if not scrollThreshold? then scrollThreshold = 0
 		if wrapper.scrollTop + scrollThreshold >= wrapper.scrollHeight - wrapper.clientHeight
-			newMessage.className = "new-message not"
+			newMessage.className = "new-message background-primary-action-color not"
 			return true
 		return false
 
 	template.sendToBottom = ->
 		wrapper.scrollTop = wrapper.scrollHeight - wrapper.clientHeight
-		newMessage.className = "new-message not"
+		newMessage.className = "new-message background-primary-action-color not"
 
 	template.checkIfScrollIsAtBottom = ->
 		template.atBottom = template.isAtBottom(100)
diff --git a/packages/rocketchat-ui/views/app/room.html b/packages/rocketchat-ui/views/app/room.html
index ba3500d5e008ff9996e612757cc932bb5dec508a..a79f89aa5183c2d4e35ab4864868bbad75b294e5 100644
--- a/packages/rocketchat-ui/views/app/room.html
+++ b/packages/rocketchat-ui/views/app/room.html
@@ -1,13 +1,13 @@
 <template name="room">
 	<div class="dropzone">
-		<div class="dropzone-overlay">
-			<div>
+		<div class="dropzone-overlay background-transparent-darkest color-content-background-color">
+			<div class="background-transparent-darkest">
 				{{_ "Drop_to_upload_file"}}
 			</div>
 		</div>
-		<section class="messages-container {{adminClass}}" id="{{windowId}}" aria-label="{{_ "Channel"}}">
+		<section class="messages-container border-component-color {{adminClass}}" id="{{windowId}}" aria-label="{{_ "Channel"}}">
 			{{#unless embeddedVersion}}
-			<header class="fixed-title">
+			<header class="fixed-title content-background-color border-component-color">
 				{{> burger}}
 				<h2>
 					{{#if showToggleFavorite}}
@@ -23,7 +23,7 @@
 				{{#with unreadData}}
 					{{#if since}}
 						{{#if count}}
-							<div class="unread-bar">
+							<div class="unread-bar color-primary-action-color background-component-color">
 								<button class="jump-to">
 									<span class="jump-to-large">{{_ "Jump_to_first_unread"}}</span>
 									<span class="jump-to-small">{{_ "Jump"}}</span>
@@ -42,7 +42,7 @@
 					{{/if}}
 				{{/with}}
 				{{#each uploading}}
-					<div class="upload-progress {{#if error}}upload-error{{/if}}">
+					<div class="upload-progress color-primary-action-color background-component-color {{#if error}}error-background error-border{{/if}}">
 						{{#if error}}
 							<div class="upload-progress-text">
 								{{error}}
@@ -64,15 +64,15 @@
 			</div>
 			<div class="messages-box {{#if selectable}}selectable{{/if}} {{viewMode}}">
 				<div class="ticks-bar"></div>
-				<button class="new-message not">
+				<button class="new-message background-primary-action-color color-primary-action-contrast not">
 					<i class="icon-down-big"></i>
 					{{_ "New_messages"}}
 				</button>
-				<div class="jump-recent {{#unless hasMoreNext}}not{{/unless}}">
+				<div class="jump-recent background-component-color {{#unless hasMoreNext}}not{{/unless}}">
 					<button>{{_ "Jump_to_recent_messages"}} <i class="icon-level-down"></i></button>
 				</div>
 				{{#unless canPreview}}
-					<div class="content room-not-found">
+					<div class="content room-not-found error-color">
 						<div>
 							{{_ "You_must_join_to_view_messages_in_this_channel"}}
 						</div>
@@ -83,14 +83,10 @@
 						{{#if canPreview}}
 							{{#if hasMore}}
 								<li class="load-more">
-									{{#if isLoading}}
-										<div class="load-more-loading">{{_ "Loading_more_from_history"}}...</div>
-									{{else}}
-										<button>{{_ "Has_more"}}...</button>
-									{{/if}}
+									{{> loading}}
 								</li>
 							{{else}}
-								<li class="start">
+								<li class="start color-info-font-color">
 									{{_ "Start_of_conversation"}}
 								</li>
 							{{/if}}
@@ -100,21 +96,17 @@
 						{{/each}}
 						{{#if hasMoreNext}}
 							<li class="load-more">
-								{{#if isLoading}}
-									<div class="load-more-loading">{{_ "Loading_more_from_history"}}...</div>
-								{{else}}
-									<button>{{_ "Has_more"}}...</button>
-								{{/if}}
+								{{> loading}}
 							</li>
 						{{/if}}
 					</ul>
 				</div>
 			</div>
-			<footer class="footer">
+			<footer class="footer border-component-color">
 				{{> messageBox}}
 			</footer>
 		</section>
-		<section class="flex-tab">
+		<section class="flex-tab secondary-background-color">
 			{{> Template.dynamic template=flexTemplate data=flexData}}
 		</section>
 	</div>
diff --git a/packages/rocketchat-ui/views/app/spotlight/spotlight.coffee b/packages/rocketchat-ui/views/app/spotlight/spotlight.coffee
index e1a51bab1f308e7160b2e83ee3d2d25ad46c8985..5e43e46d9b80968ff9173a55585fc00203fc82bf 100644
--- a/packages/rocketchat-ui/views/app/spotlight/spotlight.coffee
+++ b/packages/rocketchat-ui/views/app/spotlight/spotlight.coffee
@@ -26,7 +26,7 @@ getFromServer = (filter, records, cb) =>
 			for room in results.rooms
 				server.push({
 					_id: room._id
-					t: 'c',
+					t: room.t,
 					name: room.name
 				})
 
@@ -57,7 +57,7 @@ Template.spotlight.helpers
 			getValue: (_id, collection, records, firstPartValue) ->
 				doc = _.findWhere(records, {_id: _id})
 
-				FlowRouter.go(RocketChat.roomTypes.getRouteLink(doc.t, doc), null, FlowRouter.current().queryParams)
+				RocketChat.roomTypes.openRouteLink(doc.t, doc, FlowRouter.current().queryParams)
 
 				spotlight.hide()
 
diff --git a/packages/rocketchat-ui/views/app/spotlight/spotlight.html b/packages/rocketchat-ui/views/app/spotlight/spotlight.html
index 5eacde1e2feb56ffe8c2a5dfaf76fa245f6283fd..f291a1bbf9eb2b8dceb585499cfad05cee2ae663 100644
--- a/packages/rocketchat-ui/views/app/spotlight/spotlight.html
+++ b/packages/rocketchat-ui/views/app/spotlight/spotlight.html
@@ -1,7 +1,7 @@
 <template name="spotlight">
-	<div class="spotlight hidden">
-		<div class="spotlight-input">
-			<i class="icon-search"></i>
+	<div class="spotlight hidden background-transparent-darker">
+		<div class="spotlight-input secondary-background-color secondary-font-color">
+			<i class="icon-search secondary-font-color"></i>
 			<input type="text" name="spotlight">
 			{{> messagePopup popupConfig}}
 		</div>
diff --git a/packages/rocketchat-ui/views/app/spotlight/spotlightTemplate.js b/packages/rocketchat-ui/views/app/spotlight/spotlightTemplate.js
index a0c0276e88a424cff880fe40a26800ff4b4a0b53..631931f6eb687ad6b912eac2f5ed7cc893300062 100644
--- a/packages/rocketchat-ui/views/app/spotlight/spotlightTemplate.js
+++ b/packages/rocketchat-ui/views/app/spotlight/spotlightTemplate.js
@@ -4,9 +4,10 @@ Template.spotlightTemplate.helpers({
 	},
 
 	userStatus() {
-		if (this.t === 'd' || this.t === 'l') {
+		if (this.t === 'd') {
 			return 'status-' + (Session.get(`user_${this.name}_status`) || 'offline');
+		} else {
+			return 'status-' + (RocketChat.roomTypes.getUserStatus(this.t, this.rid || this._id) || 'offline');
 		}
-		return 'status-offline';
 	}
 });
diff --git a/packages/rocketchat-ui/views/app/videoCall/videoCall.html b/packages/rocketchat-ui/views/app/videoCall/videoCall.html
index ce641e2ab9b35055923b866659659404c5e443b4..1fe1594f2be1ce205fafc5b8005cd6f00b7f193e 100644
--- a/packages/rocketchat-ui/views/app/videoCall/videoCall.html
+++ b/packages/rocketchat-ui/views/app/videoCall/videoCall.html
@@ -1,17 +1,17 @@
 <template name="videoCall">
 	{{#if videoAvaliable}}
 		{{#if videoActive}}
-			<div class="webrtc-video {{#if overlay}}webrtc-video-overlay{{/if}}">
-				<div class="main-video">
-					<video src="{{mainVideoUrl}}" autoplay muted="true" class="{{#if $eq mainVideoUrl selfVideoUrl}}video-flip{{/if}}"></video>
-					<div>{{mainVideoUsername}}</div>
+			<div class="webrtc-video {{#if overlay}}webrtc-video-overlay background-transparent-darker{{/if}}">
+				<div class="main-video background-transparent-darker">
+					<video src="{{mainVideoUrl}}" autoplay muted="true" class="webrtc-video-element {{#if $eq mainVideoUrl selfVideoUrl}}video-flip{{/if}}"></video>
+					<div class="background-transparent-darker">{{mainVideoUsername}}</div>
 				</div>
 				<div class="videos">
 					{{#if selfVideoUrl}}
-						<div class="video-item" data-username="$self">
-							<video src="{{selfVideoUrl}}" autoplay muted="true" class="{{#unless screenShareEnabled}}video-flip{{/unless}}"></video>
+						<div class="video-item background-transparent-darker" data-username="$self">
+							<video src="{{selfVideoUrl}}" autoplay muted="true" class="webrtc-video-element {{#unless screenShareEnabled}}video-flip{{/unless}}"></video>
 							{{#unless audioAndVideoEnabled}}
-								<div class="video-muted-overlay">
+								<div class="video-muted-overlay background-transparent-darker">
 									{{#unless audioEnabled}}
 										<button><i class="icon-mute"></i></button>
 									{{/unless}}
@@ -20,13 +20,13 @@
 									{{/unless}}
 								</div>
 							{{/unless}}
-							<div>{{_ "you"}}</div>
+							<div class="background-transparent-darker">{{_ "you"}}</div>
 						</div>
 					{{/if}}
 					{{#each remoteVideoItems}}
-						<div class="video-item {{#unless connected}}state-overlay{{/unless}}" data-state-text="{{stateText}}" data-username="{{id}}">
-							<video src="{{url}}" autoplay></video>
-							<div>{{usernameByUserId id}}</div>
+						<div class="video-item background-transparent-darker {{#unless connected}}state-overlay background-transparent-darker-before{{/unless}}" data-state-text="{{stateText}}" data-username="{{id}}">
+							<video src="{{url}}" autoplay class="webrtc-video-element"></video>
+							<div class="background-transparent-darker">{{usernameByUserId id}}</div>
 						</div>
 					{{/each}}
 				</div>
diff --git a/packages/rocketchat-ui/views/cmsPage.html b/packages/rocketchat-ui/views/cmsPage.html
index 9cd5c7fbddb278b8cb545316f5f0a08e65eca019..30e92787934f0d35b96c99fdc08821aa3b8526b1 100644
--- a/packages/rocketchat-ui/views/cmsPage.html
+++ b/packages/rocketchat-ui/views/cmsPage.html
@@ -1,5 +1,5 @@
 <template name="cmsPage">
-	<div class="cms-page">
+	<div class="cms-page content-background-color">
 		<div class="cms-page-close">
 			<a href="/login" class="button primary"><i class="icon-cancel"></i></a>
 		</div>
diff --git a/packages/rocketchat-ui/views/fxos.html b/packages/rocketchat-ui/views/fxos.html
index 23c767884d16662c87cc927b643acc3a882a82a0..c12762c3ef9c1ce289b650e7097b4a60c49c0b8f 100644
--- a/packages/rocketchat-ui/views/fxos.html
+++ b/packages/rocketchat-ui/views/fxos.html
@@ -1,12 +1,12 @@
 <template name="fxOsInstallPrompt">
-	<section class="full-page">
+	<section class="full-page color-tertiary-font-color">
 		<div class="wrapper">
 			<header>
 				<a class="logo" href="/">
 					<img src="images/logo/logo.svg?v=3" />
 				</a>
 			</header>
-			<div class="cms-page">
+			<div class="cms-page content-background-color">
 				<h1>{{_ "Install_FxOs"}}</h1>
 				<p>{{_ "Install_FxOs_follow_instructions"}}</p>
 			</div>
@@ -15,14 +15,14 @@
 </template>
 
 <template name="fxOsInstallDone">
-	<section class="full-page">
+	<section class="full-page color-tertiary-font-color">
 		<div class="wrapper">
 			<header>
 				<a class="logo" href="/">
 					<img src="images/logo/logo.svg?v=3" />
 				</a>
 			</header>
-			<div class="cms-page">
+			<div class="cms-page content-background-color">
 				<h1>{{_ "Install_FxOs"}}</h1>
 				<p>{{_ "Install_FxOs_done"}}</p>
 			</div>
@@ -31,14 +31,14 @@
 </template>
 
 <template name="fxOsInstallError">
-	<section class="full-page">
+	<section class="full-page color-tertiary-font-color">
 		<div class="wrapper">
 			<header>
 				<a class="logo" href="/">
 					<img src="images/logo/logo.svg?v=3" />
 				</a>
 			</header>
-			<div class="cms-page">
+			<div class="cms-page content-background-color">
 				<h1>{{_ "Install_FxOs"}}</h1>
 				<p>{{_ "Install_FxOs_error"}}</p>
 				<p>{{installError}}</p>
diff --git a/packages/rocketchat-videobridge/client/stylesheets/video.less b/packages/rocketchat-videobridge/client/stylesheets/video.less
index 5b9638601eef2dd8151c268f674d04027f6d85ed..f9f00d45035edffedf19924b14e763b3e005e61c 100644
--- a/packages/rocketchat-videobridge/client/stylesheets/video.less
+++ b/packages/rocketchat-videobridge/client/stylesheets/video.less
@@ -1,18 +1,18 @@
 .flex-tab {
-  .video-chat {
-    ul {
-      li {
-        margin-bottom: 20px;
-      }
-    }
-  }
+	.video-chat {
+		ul {
+			li {
+				margin-bottom: 20px;
+			}
+		}
+	}
 }
 
 .video-chat {
-  .main-video {
-    iframe {
-      width: 100%;
-      min-height: 299px;
-    }
-  }
+	.main-video {
+		iframe {
+			width: 100%;
+			min-height: 299px;
+		}
+	}
 }
diff --git a/packages/rocketchat-videobridge/client/views/videoFlexTab.html b/packages/rocketchat-videobridge/client/views/videoFlexTab.html
index a3595d17085b1bebe76a53bc36f2a5873ddd5dcf..71230ec318c411df2fd9fb39b35e371491559383 100644
--- a/packages/rocketchat-videobridge/client/views/videoFlexTab.html
+++ b/packages/rocketchat-videobridge/client/views/videoFlexTab.html
@@ -1,10 +1,18 @@
 <template name="videoFlexTab">
-
-    <div class="content">
-        <div class="video-chat">
-            <div class="main-video">
-				<div id="videoContainer"></div>
-            </div>
-        </div>
-    </div>
+	<div class="content">
+		{{#if openInNewWindow}}
+			<div class="list-view">
+				<div class="title">
+					<h2>{{_ "Video_Conference"}}</h2>
+				</div>
+				<p>{{_ "Opened_in_a_new_window"}}</p>
+			</div>
+		{{else}}
+			<div class="video-chat">
+				<div class="main-video">
+					<div id="videoContainer"></div>
+				</div>
+			</div>
+		{{/if}}
+	</div>
 </template>
diff --git a/packages/rocketchat-videobridge/client/views/videoFlexTab.js b/packages/rocketchat-videobridge/client/views/videoFlexTab.js
index 6e379d0ebcb8ed601fb3c2237dc274f1528cc0f7..42f1027846d0fe3211018a19d1059d2795fe52c9 100644
--- a/packages/rocketchat-videobridge/client/views/videoFlexTab.js
+++ b/packages/rocketchat-videobridge/client/views/videoFlexTab.js
@@ -2,7 +2,9 @@
 /* eslint new-cap: [2, {"capIsNewExceptions": ["MD5"]}] */
 
 Template.videoFlexTab.helpers({
-
+	openInNewWindow() {
+		return RocketChat.settings.get('Jitsi_Open_New_Window');
+	}
 });
 
 Template.videoFlexTab.onCreated(function() {
@@ -20,83 +22,91 @@ Template.videoFlexTab.onCreated(function() {
 
 	let jitsiRoomActive = null;
 
+	const closePanel = () => {
+		// Reset things.  Should probably be handled better in closeFlex()
+		$('.flex-tab').css('max-width', '');
+		$('.main-content').css('right', '');
+
+		RocketChat.TabBar.closeFlex();
+
+		RocketChat.TabBar.updateButton('video', { class: '' });
+	};
+
 	this.timeout = null;
 	this.autorun(() => {
 		if (RocketChat.settings.get('Jitsi_Enabled')) {
-			if (RocketChat.TabBar.getTemplate() === 'videoFlexTab') {
-				if (RocketChat.TabBar.isFlexOpen()) {
-					let roomId = Session.get('openedRoom');
-
-					let domain = RocketChat.settings.get('Jitsi_Domain');
-					let jitsiRoom = 'RocketChat' + CryptoJS.MD5(RocketChat.settings.get('uniqueID') + roomId).toString();
-					let noSsl = RocketChat.settings.get('Jitsi_SSL') ? false : true;
-					console.debug('Jitsi Room ID:', jitsiRoom, 'If from direct message or private group don\'t share.  Or you will be letting the invitee join any future conversation.');
+			if (RocketChat.TabBar.isFlexOpen() && RocketChat.TabBar.getTemplate() === 'videoFlexTab') {
+				let roomId = Session.get('openedRoom');
 
-					if (jitsiRoomActive !== null && jitsiRoomActive !== jitsiRoom) {
-						jitsiRoomActive = null;
+				let domain = RocketChat.settings.get('Jitsi_Domain');
+				let jitsiRoom = RocketChat.settings.get('Jitsi_URL_Room_Prefix') + CryptoJS.MD5(RocketChat.settings.get('uniqueID') + roomId).toString();
+				let noSsl = RocketChat.settings.get('Jitsi_SSL') ? false : true;
 
-						console.log('Room Changed... Close panel!');
-						// Reset things.  Should probably be handled better in closeFlex()
-						$('.flex-tab').css('max-width', '');
-						$('.main-content').css('right', '');
+				if (jitsiRoomActive !== null && jitsiRoomActive !== jitsiRoom) {
+					jitsiRoomActive = null;
 
-						RocketChat.TabBar.closeFlex();
+					closePanel();
 
-						RocketChat.TabBar.updateButton('video', { class: '' });
+					// Clean up and stop updating timeout.
+					Meteor.defer(() => this.api && this.api.dispose());
+					if (timeOut) {
+						clearInterval(timeOut);
+					}
+				} else {
+					jitsiRoomActive = jitsiRoom;
 
-						// Clean up and stop updating timeout.
-						if (timeOut) {
-							Meteor.defer(() => {
-								this.api.dispose();
-							});
-							clearInterval(timeOut);
-						}
-					} else {
-						jitsiRoomActive = jitsiRoom;
+					RocketChat.TabBar.updateButton('video', { class: 'red' });
 
-						RocketChat.TabBar.updateButton('video', { class: 'red' });
+					if (RocketChat.settings.get('Jitsi_Open_New_Window')) {
+						Meteor.call('jitsi:updateTimeout', roomId);
 
-						// Lets make sure its loaded before we try to show it.
-						if (typeof JitsiMeetExternalAPI !== 'undefined') {
+						timeOut = Meteor.setInterval(() => Meteor.call('jitsi:updateTimeout', roomId), 10*1000);
 
-							// Keep it from showing duplicates when re-evaluated on variable change.
-							if (!$('[id^=jitsiConference]').length) {
-								this.api = new JitsiMeetExternalAPI(domain, jitsiRoom, width, height, document.getElementById('videoContainer'), configOverwrite, interfaceConfigOverwrite, noSsl);
+						const newWindow = window.open((noSsl ? 'http://' : 'https://') + domain + '/' + jitsiRoom, jitsiRoom);
+						newWindow.focus();
 
-								/*
-								* Hack to send after frame is loaded.
-								* postMessage converts to events in the jitsi meet iframe.
-								* For some reason those aren't working right.
-								*/
-								Meteor.setTimeout(() => {
-									this.api.executeCommand('displayName', [Meteor.user().name]);
-								}, 5000);
+						let closeInterval = setInterval(() => {
+							if (newWindow.closed !== false) {
+								closePanel();
+								clearInterval(closeInterval);
+								clearInterval(timeOut);
+							}
+						}, 300);
 
-								Meteor.call('jitsi:updateTimeout', roomId);
+					// Lets make sure its loaded before we try to show it.
+					} else if (typeof JitsiMeetExternalAPI !== 'undefined') {
 
-								timeOut = Meteor.setInterval(() => Meteor.call('jitsi:updateTimeout', roomId), 10*1000);
-							}
+						// Keep it from showing duplicates when re-evaluated on variable change.
+						if (!$('[id^=jitsiConference]').length) {
+							this.api = new JitsiMeetExternalAPI(domain, jitsiRoom, width, height, document.getElementById('videoContainer'), configOverwrite, interfaceConfigOverwrite, noSsl);
 
-							// Execute any commands that might be reactive.  Like name changing.
-							if (this.api) {
+							/*
+							* Hack to send after frame is loaded.
+							* postMessage converts to events in the jitsi meet iframe.
+							* For some reason those aren't working right.
+							*/
+							Meteor.setTimeout(() => {
 								this.api.executeCommand('displayName', [Meteor.user().name]);
-							}
-						}
-					}
+							}, 5000);
 
-				} else {
-					RocketChat.TabBar.updateButton('video', { class: '' });
+							Meteor.call('jitsi:updateTimeout', roomId);
 
-					// Clean up and stop updating timeout.
-					if (timeOut) {
-						Meteor.defer(() => {
-							this.api.dispose();
-						});
-						clearInterval(timeOut);
+							timeOut = Meteor.setInterval(() => Meteor.call('jitsi:updateTimeout', roomId), 10*1000);
+						}
+
+						// Execute any commands that might be reactive.  Like name changing.
+						this.api && this.api.executeCommand('displayName', [Meteor.user().name]);
 					}
 				}
+			} else {
+				RocketChat.TabBar.updateButton('video', { class: '' });
+
+				// Clean up and stop updating timeout.
+				if (timeOut) {
+					Meteor.defer(() => this.api && this.api.dispose());
+					clearInterval(timeOut);
+				}
 			}
 		}
 	});
-
 });
diff --git a/packages/rocketchat-videobridge/server/settings.js b/packages/rocketchat-videobridge/server/settings.js
index c325c5dc219e6e8edaeffbb2538021b3a8d2e50f..a08f09b62d13e7005fb218baf3b3b3727ec52c97 100644
--- a/packages/rocketchat-videobridge/server/settings.js
+++ b/packages/rocketchat-videobridge/server/settings.js
@@ -17,6 +17,16 @@ Meteor.startup(function() {
 			public: true
 		});
 
+		this.add('Jitsi_URL_Room_Prefix', 'RocketChat', {
+			type: 'string',
+			enableQuery: {
+				_id: 'Jitsi_Enabled',
+				value: true
+			},
+			i18nLabel: 'URL_room_prefix',
+			public: true
+		});
+
 		this.add('Jitsi_SSL', true, {
 			type: 'boolean',
 			enableQuery: {
@@ -27,6 +37,16 @@ Meteor.startup(function() {
 			public: true
 		});
 
+		this.add('Jitsi_Open_New_Window', false, {
+			type: 'boolean',
+			enableQuery: {
+				_id: 'Jitsi_Enabled',
+				value: true
+			},
+			i18nLabel: 'Always_open_in_new_window',
+			public: true
+		});
+
 		this.add('Jitsi_Enable_Channels', false, {
 			type: 'boolean',
 			enableQuery: {
diff --git a/packages/rocketchat-webrtc/WebRTCClass.coffee b/packages/rocketchat-webrtc/WebRTCClass.coffee
index e7c1f3fbb6ca158173dacae5d767c754402fa170..4ac810fac618b818e5446b1288cfc68cd7c09a70 100644
--- a/packages/rocketchat-webrtc/WebRTCClass.coffee
+++ b/packages/rocketchat-webrtc/WebRTCClass.coffee
@@ -160,7 +160,7 @@ class WebRTCClass
 		@screenShareAvailable = @navigator in ['chrome', 'firefox']
 
 		@media =
-			video: true
+			video: false
 			audio: true
 
 		@transport = new @transportClass @
@@ -228,10 +228,10 @@ class WebRTCClass
 		if @active isnt true or @monitor is true or @remoteMonitoring is true then return
 
 		remoteConnections = []
-		for id, peerConnections of @peerConnections
+		for id, peerConnection of @peerConnections
 			remoteConnections.push
 				id: id
-				media: peerConnections.remoteMedia
+				media: peerConnection.remoteMedia
 
 		@transport.sendStatus
 			media: @media
@@ -340,6 +340,8 @@ class WebRTCClass
 				stream.addTrack(peer.stream.getAudioTracks()[0])
 				stream.volume = volume
 
+				this.audioContext = audioContext
+
 			onSuccess(stream)
 
 		navigator.getUserMedia media, onSuccessLocal, onError
@@ -461,7 +463,8 @@ class WebRTCClass
 
 	stopAllPeerConnections: ->
 		for id, peerConnection of @peerConnections
-				@stopPeerConnection id
+			@stopPeerConnection id
+		window.audioContext?.close()
 
 	setAudioEnabled: (enabled=true) ->
 		if @localStream?
@@ -592,7 +595,7 @@ class WebRTCClass
 				title = "Group audio call from #{subscription.name}"
 
 		swal
-			title: "<i class='icon-#{icon} alert-icon'></i>#{title}"
+			title: "<i class='icon-#{icon} alert-icon success-color'></i>#{title}"
 			text: "Do you want to accept?"
 			html: true
 			showCancelButton: true
diff --git a/public/images/logo/android-chrome-144x144.png b/public/images/logo/android-chrome-144x144.png
deleted file mode 100644
index fe9b2a8a988b3d38509f700fe0e34c6a2e2aea0a..0000000000000000000000000000000000000000
Binary files a/public/images/logo/android-chrome-144x144.png and /dev/null differ
diff --git a/public/images/logo/android-chrome-36x36.png b/public/images/logo/android-chrome-36x36.png
deleted file mode 100644
index c5cade5e3024b429ebeb5dd0eda19bb522712e86..0000000000000000000000000000000000000000
Binary files a/public/images/logo/android-chrome-36x36.png and /dev/null differ
diff --git a/public/images/logo/android-chrome-48x48.png b/public/images/logo/android-chrome-48x48.png
deleted file mode 100644
index ae7d50d9f5f2281d8086298cbb8ca1d5a508087e..0000000000000000000000000000000000000000
Binary files a/public/images/logo/android-chrome-48x48.png and /dev/null differ
diff --git a/public/images/logo/android-chrome-72x72.png b/public/images/logo/android-chrome-72x72.png
deleted file mode 100644
index 17ab1f42d7552fa02363da29b2fa2a16ffbebd1f..0000000000000000000000000000000000000000
Binary files a/public/images/logo/android-chrome-72x72.png and /dev/null differ
diff --git a/public/images/logo/android-chrome-96x96.png b/public/images/logo/android-chrome-96x96.png
deleted file mode 100644
index f98245a8abef2561c41b9068854dcabc1057dbc8..0000000000000000000000000000000000000000
Binary files a/public/images/logo/android-chrome-96x96.png and /dev/null differ
diff --git a/public/images/logo/android-hdpi.png b/public/images/logo/android-hdpi.png
deleted file mode 100644
index cf331a1ad66f57e3bf50d0a163a807f17b74480d..0000000000000000000000000000000000000000
Binary files a/public/images/logo/android-hdpi.png and /dev/null differ
diff --git a/public/images/logo/android-mdpi.png b/public/images/logo/android-mdpi.png
deleted file mode 100644
index 5f9e164a90b657ed7f1b095b2528cf071f29cb44..0000000000000000000000000000000000000000
Binary files a/public/images/logo/android-mdpi.png and /dev/null differ
diff --git a/public/images/logo/android-xhdpi.png b/public/images/logo/android-xhdpi.png
deleted file mode 100644
index 36fb209536b883171c3770402a33c3b218341afc..0000000000000000000000000000000000000000
Binary files a/public/images/logo/android-xhdpi.png and /dev/null differ
diff --git a/public/images/logo/android-xxhdpi.png b/public/images/logo/android-xxhdpi.png
deleted file mode 100644
index 5dbee688043451ee114a5d0775a6eab7344b9d2c..0000000000000000000000000000000000000000
Binary files a/public/images/logo/android-xxhdpi.png and /dev/null differ
diff --git a/public/images/logo/android-xxxhdpi.png b/public/images/logo/android-xxxhdpi.png
deleted file mode 100644
index 5de255141fe405860ca98fb45b02d52980ded29b..0000000000000000000000000000000000000000
Binary files a/public/images/logo/android-xxxhdpi.png and /dev/null differ
diff --git a/public/images/logo/apple-touch-icon-1024x1024.png b/public/images/logo/apple-touch-icon-1024x1024.png
deleted file mode 100644
index 107dcda3db9653ef1608843b69cca1091627edee..0000000000000000000000000000000000000000
Binary files a/public/images/logo/apple-touch-icon-1024x1024.png and /dev/null differ
diff --git a/public/images/logo/apple-touch-icon-114x114.png b/public/images/logo/apple-touch-icon-114x114.png
deleted file mode 100644
index a5513bec2d0dd2693a7fb4e061eac110aaef2eab..0000000000000000000000000000000000000000
Binary files a/public/images/logo/apple-touch-icon-114x114.png and /dev/null differ
diff --git a/public/images/logo/apple-touch-icon-120x120.png b/public/images/logo/apple-touch-icon-120x120.png
deleted file mode 100644
index 98a86b1d6c2cef75bca6c365efcfdd9fde8ad711..0000000000000000000000000000000000000000
Binary files a/public/images/logo/apple-touch-icon-120x120.png and /dev/null differ
diff --git a/public/images/logo/apple-touch-icon-144x144.png b/public/images/logo/apple-touch-icon-144x144.png
deleted file mode 100644
index adf2a0a18d02d82dd989fb0661d367fcdcfd95ee..0000000000000000000000000000000000000000
Binary files a/public/images/logo/apple-touch-icon-144x144.png and /dev/null differ
diff --git a/public/images/logo/apple-touch-icon-152x152.png b/public/images/logo/apple-touch-icon-152x152.png
deleted file mode 100644
index 026c0a7b2c3765532ef356dbe86dc7a49561fa75..0000000000000000000000000000000000000000
Binary files a/public/images/logo/apple-touch-icon-152x152.png and /dev/null differ
diff --git a/public/images/logo/apple-touch-icon-172x172.png b/public/images/logo/apple-touch-icon-172x172.png
deleted file mode 100644
index 26e1f2e62d92c5cf596aadbd88af4f4292479226..0000000000000000000000000000000000000000
Binary files a/public/images/logo/apple-touch-icon-172x172.png and /dev/null differ
diff --git a/public/images/logo/apple-touch-icon-180x180.png b/public/images/logo/apple-touch-icon-180x180.png
deleted file mode 100644
index bb4688bc622d6d6909e063c44aecd4690e628730..0000000000000000000000000000000000000000
Binary files a/public/images/logo/apple-touch-icon-180x180.png and /dev/null differ
diff --git a/public/images/logo/apple-touch-icon-196x196.png b/public/images/logo/apple-touch-icon-196x196.png
deleted file mode 100644
index 3522df38db74cb72cf2c5a5b1cc6e44e87fffe0b..0000000000000000000000000000000000000000
Binary files a/public/images/logo/apple-touch-icon-196x196.png and /dev/null differ
diff --git a/public/images/logo/apple-touch-icon-29x29.png b/public/images/logo/apple-touch-icon-29x29.png
deleted file mode 100644
index b8f76bff8a032178395a863d0ac9db795bf98f8e..0000000000000000000000000000000000000000
Binary files a/public/images/logo/apple-touch-icon-29x29.png and /dev/null differ
diff --git a/public/images/logo/apple-touch-icon-40x40.png b/public/images/logo/apple-touch-icon-40x40.png
deleted file mode 100644
index eedb40059b192f7e1c1db20b5410a33781149dc3..0000000000000000000000000000000000000000
Binary files a/public/images/logo/apple-touch-icon-40x40.png and /dev/null differ
diff --git a/public/images/logo/apple-touch-icon-48x48.png b/public/images/logo/apple-touch-icon-48x48.png
deleted file mode 100644
index 3bf6d17cbb544f5a433835292571611eac27c310..0000000000000000000000000000000000000000
Binary files a/public/images/logo/apple-touch-icon-48x48.png and /dev/null differ
diff --git a/public/images/logo/apple-touch-icon-55x55.png b/public/images/logo/apple-touch-icon-55x55.png
deleted file mode 100644
index 5f3c8428e366c55deb4e3e64cdcd7611712b99b4..0000000000000000000000000000000000000000
Binary files a/public/images/logo/apple-touch-icon-55x55.png and /dev/null differ
diff --git a/public/images/logo/apple-touch-icon-57x57.png b/public/images/logo/apple-touch-icon-57x57.png
deleted file mode 100644
index 706de25b5b7e940bfb1460938cad14aa96122fe2..0000000000000000000000000000000000000000
Binary files a/public/images/logo/apple-touch-icon-57x57.png and /dev/null differ
diff --git a/public/images/logo/apple-touch-icon-58x58.png b/public/images/logo/apple-touch-icon-58x58.png
deleted file mode 100644
index 2d10e689d7efbbe91df2cfaae5cfa1ddc43403c7..0000000000000000000000000000000000000000
Binary files a/public/images/logo/apple-touch-icon-58x58.png and /dev/null differ
diff --git a/public/images/logo/apple-touch-icon-60x60.png b/public/images/logo/apple-touch-icon-60x60.png
deleted file mode 100644
index 9efb96495ff371ed5a42ba2fb44f66eb21303bc3..0000000000000000000000000000000000000000
Binary files a/public/images/logo/apple-touch-icon-60x60.png and /dev/null differ
diff --git a/public/images/logo/apple-touch-icon-72x72.png b/public/images/logo/apple-touch-icon-72x72.png
deleted file mode 100644
index af17998cc3acb6db525049ee050e7372a0b17033..0000000000000000000000000000000000000000
Binary files a/public/images/logo/apple-touch-icon-72x72.png and /dev/null differ
diff --git a/public/images/logo/apple-touch-icon-76x76.png b/public/images/logo/apple-touch-icon-76x76.png
deleted file mode 100644
index 9c84cc658f6d7c8f7ae6d8b61e5d92cc5ccd74d7..0000000000000000000000000000000000000000
Binary files a/public/images/logo/apple-touch-icon-76x76.png and /dev/null differ
diff --git a/public/images/logo/apple-touch-icon-80x80.png b/public/images/logo/apple-touch-icon-80x80.png
deleted file mode 100644
index 8d815759b6ee959d9a11b9fc0384ac867007889e..0000000000000000000000000000000000000000
Binary files a/public/images/logo/apple-touch-icon-80x80.png and /dev/null differ
diff --git a/public/images/logo/apple-touch-icon-87x87.png b/public/images/logo/apple-touch-icon-87x87.png
deleted file mode 100644
index ff9274db491dd9cd68a2dfe4a7fb55f1de0d3f76..0000000000000000000000000000000000000000
Binary files a/public/images/logo/apple-touch-icon-87x87.png and /dev/null differ
diff --git a/public/images/logo/apple-touch-icon-88x88.png b/public/images/logo/apple-touch-icon-88x88.png
deleted file mode 100644
index 7620721e2bb977873b81b4a62df73fe540c3ec9a..0000000000000000000000000000000000000000
Binary files a/public/images/logo/apple-touch-icon-88x88.png and /dev/null differ
diff --git a/public/images/logo/browserconfig.xml b/public/images/logo/browserconfig.xml
index 8f51ba5fdcd557518e0680c02a6f902386e7f1e0..fe60a23024c474687d774e9dde9216fd4e60b70e 100644
--- a/public/images/logo/browserconfig.xml
+++ b/public/images/logo/browserconfig.xml
@@ -1,12 +1,11 @@
 <?xml version="1.0" encoding="utf-8"?>
 <browserconfig>
-  <msapplication>
-    <tile>
-      <square70x70logo src="/images/logo/mstile-70x70.png?v=3"/>
-      <square150x150logo src="/images/logo/mstile-150x150.png?v=3"/>
-      <square310x310logo src="/images/logo/mstile-310x310.png?v=3"/>
-      <wide310x150logo src="/images/logo/mstile-310x150.png?v=3"/>
-      <TileColor>#04436a</TileColor>
-    </tile>
-  </msapplication>
+	<msapplication>
+		<tile>
+			<square150x150logo src="/images/logo/mstile-150x150.png?v=3"/>
+			<square310x310logo src="/images/logo/mstile-310x310.png?v=3"/>
+			<wide310x150logo src="/images/logo/mstile-310x150.png?v=3"/>
+			<TileColor>#04436a</TileColor>
+		</tile>
+	</msapplication>
 </browserconfig>
diff --git a/public/images/logo/favicon-128x128.png b/public/images/logo/favicon-128x128.png
deleted file mode 100644
index 713aa256fd775d56790dbca9bda2eafb8ccd9204..0000000000000000000000000000000000000000
Binary files a/public/images/logo/favicon-128x128.png and /dev/null differ
diff --git a/public/images/logo/favicon-256x256.png b/public/images/logo/favicon-256x256.png
deleted file mode 100644
index 912112d2c9794607a75a6b0a76187da730810f8e..0000000000000000000000000000000000000000
Binary files a/public/images/logo/favicon-256x256.png and /dev/null differ
diff --git a/public/images/logo/favicon-48x48.png b/public/images/logo/favicon-48x48.png
deleted file mode 100644
index e03c317cb2263ae66185d08ff876c79236150a10..0000000000000000000000000000000000000000
Binary files a/public/images/logo/favicon-48x48.png and /dev/null differ
diff --git a/public/images/logo/favicon-64x64.png b/public/images/logo/favicon-64x64.png
deleted file mode 100644
index e218cb72aeb3d82c7800e2149baeb632be9f0139..0000000000000000000000000000000000000000
Binary files a/public/images/logo/favicon-64x64.png and /dev/null differ
diff --git a/public/images/logo/favicon-96x96.png b/public/images/logo/favicon-96x96.png
deleted file mode 100644
index d09d598190debcccb9741a61d9d36c14f226177d..0000000000000000000000000000000000000000
Binary files a/public/images/logo/favicon-96x96.png and /dev/null differ
diff --git a/public/images/logo/icon-loader.svg b/public/images/logo/icon-loader.svg
deleted file mode 100644
index 3564228a97114ef583db20f6b3ab4e229057e963..0000000000000000000000000000000000000000
--- a/public/images/logo/icon-loader.svg
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg class="rocket-loader" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-	 width="200px" height="200px" viewBox="0 0 200 200" enable-background="new 0 0 200 200" xml:space="preserve">
-<path class="outer" fill="#C1282D" d="M185.094,100.547c0-8.516-2.547-16.683-7.574-24.274c-4.513-6.815-10.835-12.848-18.792-17.93
-	c-15.359-9.812-35.55-15.216-56.846-15.216c-7.114,0-14.125,0.601-20.926,1.792c-4.22-3.949-9.159-7.502-14.385-10.312
-	c-27.923-13.532-51.079-0.318-51.079-0.318S37.021,51.974,33.52,67.478c-9.632,9.554-14.852,21.075-14.852,33.07
-	c0,0.038,0.002,0.076,0.002,0.115c0,0.038-0.002,0.076-0.002,0.114c0,11.995,5.22,23.516,14.852,33.071
-	c3.501,15.503-18.028,33.188-18.028,33.188s23.156,13.214,51.079-0.317c5.227-2.811,10.166-6.364,14.385-10.313
-	c6.801,1.19,13.812,1.792,20.925,1.792c21.297,0,41.486-5.404,56.847-15.216c7.956-5.083,14.278-11.115,18.792-17.931
-	c5.027-7.592,7.574-15.758,7.574-24.274c0-0.038-0.002-0.076-0.002-0.114C185.092,100.624,185.094,100.586,185.094,100.547z"/>
-<path class="inner" fill="#FFFFFF" d="M101.882,55.167c39.433,0,71.401,20.419,71.401,45.609c0,25.188-31.968,45.609-71.401,45.609
-	c-8.781,0-17.189-1.016-24.958-2.866c-7.896,9.498-25.265,22.704-42.138,18.435c5.489-5.896,13.62-15.856,11.879-32.262
-	c-10.113-7.87-16.185-17.94-16.185-28.916C30.479,75.587,62.448,55.167,101.882,55.167"/>
-<g>
-	<circle fill="#C1282D" cx="101.882" cy="102.245" r="9.484"/>
-	<circle fill="#C1282D" cx="134.86" cy="102.245" r="9.484"/>
-	<circle fill="#C1282D" cx="68.902" cy="102.245" r="9.484"/>
-</g>
-<g>
-	<path fill="#CDCCCC" d="M101.882,140.385c-8.781,0-17.189-0.88-24.958-2.484c-6.972,7.269-21.331,17.04-36.212,16.681
-		c-1.959,2.972-4.09,5.401-5.926,7.374c16.873,4.269,34.243-8.937,42.138-18.436c7.769,1.852,16.178,2.867,24.958,2.867
-		c39.117,0,70.882-20.096,71.39-45.006C172.764,122.97,140.999,140.385,101.882,140.385z"/>
-</g>
-</svg>
diff --git a/public/images/logo/loading.gif b/public/images/logo/loading.gif
deleted file mode 100644
index bacd16c39e3bc5d1dfbc119508973afbe1c1578b..0000000000000000000000000000000000000000
Binary files a/public/images/logo/loading.gif and /dev/null differ
diff --git a/public/images/logo/manifest.json b/public/images/logo/manifest.json
index 30898278e784dc11e8b219136a21b1c58334e4ff..31c4bb75839071bdc3464a806ca1d6bc710b36cf 100644
--- a/public/images/logo/manifest.json
+++ b/public/images/logo/manifest.json
@@ -1,41 +1,15 @@
 {
 	"name": "Rocket.Chat",
 	"icons": [
-		{
-			"src": "\/images\/logo\/android-chrome-36x36.png?v=3",
-			"sizes": "36x36",
-			"type": "image\/png",
-			"density": "0.75"
-		},
-		{
-			"src": "\/images\/logo\/android-chrome-48x48.png?v=3",
-			"sizes": "48x48",
-			"type": "image\/png",
-			"density": "1.0"
-		},
-		{
-			"src": "\/images\/logo\/android-chrome-72x72.png?v=3",
-			"sizes": "72x72",
-			"type": "image\/png",
-			"density": "1.5"
-		},
-		{
-			"src": "\/images\/logo\/android-chrome-96x96.png?v=3",
-			"sizes": "96x96",
-			"type": "image\/png",
-			"density": "2.0"
-		},
-		{
-			"src": "\/images\/logo\/android-chrome-144x144.png?v=3",
-			"sizes": "144x144",
-			"type": "image\/png",
-			"density": "3.0"
-		},
 		{
 			"src": "\/images\/logo\/android-chrome-192x192.png?v=3",
 			"sizes": "192x192",
-			"type": "image\/png",
-			"density": "4.0"
+			"type": "image\/png"
+		},
+		{
+			"src": "\/images\/logo\/512x512.png?v=3",
+			"sizes": "512x512",
+			"type": "image\/png"
 		}
 	],
 	"start_url": "https:\/\/rocket.chat\/home",
diff --git a/public/images/logo/mstile-70x70.png b/public/images/logo/mstile-70x70.png
deleted file mode 100644
index c42cacee61b484e1f553ba81973d5c72ecc189b7..0000000000000000000000000000000000000000
Binary files a/public/images/logo/mstile-70x70.png and /dev/null differ
diff --git a/public/images/logo/safari-pinned-tab.svg b/public/images/logo/safari-pinned-tab.svg
new file mode 100644
index 0000000000000000000000000000000000000000..05a9c740658b8a7f537fb9cc5913288317c60740
--- /dev/null
+++ b/public/images/logo/safari-pinned-tab.svg
@@ -0,0 +1,28 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+ "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
+ width="512.000000pt" height="512.000000pt" viewBox="0 0 512.000000 512.000000"
+ preserveAspectRatio="xMidYMid meet">
+<metadata>
+Created by potrace 1.11, written by Peter Selinger 2001-2013
+</metadata>
+<g transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)"
+fill="#000000" stroke="none">
+<path d="M758 4695 c-2 -1 -43 -5 -93 -8 -91 -6 -217 -26 -297 -47 -23 -7 -50
+-14 -58 -15 -44 -10 -223 -79 -257 -100 -1 -1 55 -60 126 -131 284 -288 418
+-537 413 -768 -2 -77 1 -72 -96 -182 -166 -192 -292 -437 -331 -649 -20 -109
+-25 -288 -12 -405 28 -241 151 -503 334 -714 111 -128 104 -115 105 -213 0
+-49 -5 -99 -10 -113 -5 -14 -10 -29 -11 -35 -1 -5 -8 -32 -17 -60 -54 -165
+-199 -371 -400 -569 l-105 -103 61 -27 c118 -53 233 -87 405 -120 134 -26 387
+-26 545 -1 200 32 441 115 575 199 122 76 286 197 337 248 13 13 28 18 46 14
+66 -12 133 -21 242 -32 41 -3 89 -8 105 -10 37 -5 433 -4 495 0 41 3 69 6 210
+22 25 3 81 11 125 19 44 8 94 16 110 19 17 3 62 12 100 21 39 9 80 18 91 21
+35 7 345 110 389 129 187 81 401 199 525 291 122 90 302 258 348 326 9 13 19
+25 23 28 22 17 130 190 170 275 89 189 122 337 122 545 0 212 -36 376 -124
+556 -209 431 -652 781 -1241 980 -103 35 -302 88 -368 99 -19 3 -42 8 -50 10
+-16 4 -30 7 -145 25 -303 48 -822 48 -1068 -1 -73 -14 -89 -11 -128 24 -71 62
+-92 79 -172 136 -206 145 -406 232 -651 281 -87 18 -101 19 -221 25 -60 4
+-118 8 -127 9 -9 2 -18 3 -20 1z"/>
+</g>
+</svg>
diff --git a/public/manifest.webapp b/public/manifest.webapp
index 30949605959370c8ab0a367d4f90876bd083b6b3..6a76a1684dab68a5fe38ccf1f18a5453c1be3603 100644
--- a/public/manifest.webapp
+++ b/public/manifest.webapp
@@ -3,7 +3,7 @@
     "description": "The Ultimate Open Source WebChat Platform",
     "launch_path": "/",
     "icons": {
-        "128": "/images/logo/favicon-128x128.png",
+        "192": "/images/logo/android-chrome-192x192.png",
         "512": "/images/logo/512x512.png"
     },
     "developer": {
diff --git a/server/lib/accounts.coffee b/server/lib/accounts.coffee
index 36bb63af6db973532c01ebb323572e89f53d52ee..acfe73bf263bfe770bcebc1c3245afef0b8b9698 100644
--- a/server/lib/accounts.coffee
+++ b/server/lib/accounts.coffee
@@ -81,6 +81,11 @@ Accounts.insertUserDoc = _.wrap Accounts.insertUserDoc, (insertUserDoc, options,
 
 	_id = insertUserDoc.call(Accounts, options, user)
 
+	# Add user to default channels
+	if user.username? and options.joinDefaultChannels isnt false and user.joinDefaultChannels isnt false
+		Meteor.runAsUser _id, ->
+			Meteor.call('joinDefaultChannels', options.joinDefaultChannelsSilenced)
+
 	if roles.length is 0
 		# when inserting first user give them admin privileges otherwise make a regular user
 		hasAdmin = RocketChat.models.Users.findOne({ roles: 'admin' }, {fields: {_id: 1}})
diff --git a/server/methods/addRoomModerator.coffee b/server/methods/addRoomModerator.coffee
index 963a75e1b2365af31539080512a5387b469ee588..ed54a154a04e5f03a07eec6e6fe8edb8a17c6cf2 100644
--- a/server/methods/addRoomModerator.coffee
+++ b/server/methods/addRoomModerator.coffee
@@ -10,13 +10,20 @@ Meteor.methods
 		unless RocketChat.authz.hasPermission Meteor.userId(), 'set-moderator', rid
 			throw new Meteor.Error 'error-not-allowed', 'Not allowed', { method: 'addRoomModerator' }
 
-		subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId rid, userId
+		user = RocketChat.models.Users.findOneById userId
+
+		unless user?.username
+			throw new Meteor.Error 'error-invalid-user', 'Invalid user', { method: 'addRoomModerator' }
+
+		subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId rid, user._id
 		unless subscription?
-			throw new Meteor.Error 'error-invalid-room', 'Invalid room', { method: 'addRoomModerator' }
+			throw new Meteor.Error 'error-user-not-in-room', 'User is not in this room', { method: 'addRoomModerator' }
+
+		if 'moderator' in (subscription.roles or [])
+			throw new Meteor.Error 'error-user-already-moderator', 'User is already a moderator', { method: 'addRoomModerator' }
 
 		RocketChat.models.Subscriptions.addRoleById(subscription._id, 'moderator')
 
-		user = RocketChat.models.Users.findOneById userId
 		fromUser = RocketChat.models.Users.findOneById Meteor.userId()
 		RocketChat.models.Messages.createSubscriptionRoleAddedWithRoomIdAndUser rid, user,
 			u:
diff --git a/server/methods/addRoomOwner.coffee b/server/methods/addRoomOwner.coffee
index 7d051bcbaffd7279ab82c07dfbe5691fb4821087..6e6c8b937d1aec671d5f1a43212add790c7013fb 100644
--- a/server/methods/addRoomOwner.coffee
+++ b/server/methods/addRoomOwner.coffee
@@ -10,13 +10,20 @@ Meteor.methods
 		unless RocketChat.authz.hasPermission Meteor.userId(), 'set-owner', rid
 			throw new Meteor.Error 'error-not-allowed', 'Not allowed', { method: 'addRoomOwner' }
 
-		subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId rid, userId
+		user = RocketChat.models.Users.findOneById userId
+
+		unless user?.username
+			throw new Meteor.Error 'error-invalid-user', 'Invalid user', { method: 'addRoomOwner' }
+
+		subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId rid, user._id
 		unless subscription?
-			throw new Meteor.Error 'error-invalid-room', 'Invalid room', { method: 'addRoomOwner' }
+			throw new Meteor.Error 'error-user-not-in-room', 'User is not in this room', { method: 'addRoomOwner' }
+
+		if 'owner' in (subscription.roles or [])
+			throw new Meteor.Error 'error-user-already-owner', 'User is already an owner', { method: 'addRoomOwner' }
 
 		RocketChat.models.Subscriptions.addRoleById(subscription._id, 'owner')
 
-		user = RocketChat.models.Users.findOneById userId
 		fromUser = RocketChat.models.Users.findOneById Meteor.userId()
 		RocketChat.models.Messages.createSubscriptionRoleAddedWithRoomIdAndUser rid, user,
 			u:
diff --git a/server/methods/groupsList.js b/server/methods/groupsList.js
index 37a5fe771f62caf02a1d372ebe0b2654750d6c3f..0094a81adc608daa1b2b0adedb76f7b0ce8a0a26 100644
--- a/server/methods/groupsList.js
+++ b/server/methods/groupsList.js
@@ -1,7 +1,7 @@
 Meteor.methods({
 	groupsList: function(nameFilter, limit, sort) {
 
-		check(nameFilter, String);
+		check(nameFilter, Match.Optional(String));
 		check(limit, Match.Optional(Number));
 		check(sort, Match.Optional(String));
 
diff --git a/server/methods/messageSearch.js b/server/methods/messageSearch.js
index b1009be1a0720f97c118cd54d8cbcc1649353bfe..4cea4d84126aef48fa522dc5dc2f179a64ae7089 100644
--- a/server/methods/messageSearch.js
+++ b/server/methods/messageSearch.js
@@ -148,7 +148,7 @@ Meteor.methods({
 		text = text.replace(/after:(\d{1,2})[\/\.-](\d{1,2})[\/\.-](\d{4})/g, filterAfterDate);
 		text = text.replace(/on:(\d{1,2})[\/\.-](\d{1,2})[\/\.-](\d{4})/g, filterOnDate);
 		// Sort order
-		text = text.replace(/(?:order|sort):(asc|ascend|ascending|desc|descend|descening)/g, sortByTimestamp);
+		text = text.replace(/(?:order|sort):(asc|ascend|ascending|desc|descend|descending)/g, sortByTimestamp);
 
 		// Query in message text
 		text = text.trim().replace(/\s\s/g, ' ');
diff --git a/server/methods/removeRoomModerator.coffee b/server/methods/removeRoomModerator.coffee
index c46b57aca4628b3c4d6387cd9760e384bad23f30..b375c8f731ceb596e7dc8b8de706a4de5d860ac0 100644
--- a/server/methods/removeRoomModerator.coffee
+++ b/server/methods/removeRoomModerator.coffee
@@ -10,13 +10,20 @@ Meteor.methods
 		unless RocketChat.authz.hasPermission Meteor.userId(), 'set-moderator', rid
 			throw new Meteor.Error 'error-not-allowed', 'Not allowed', { method: 'removeRoomModerator' }
 
-		subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId rid, userId
+		user = RocketChat.models.Users.findOneById userId
+
+		unless user?.username
+			throw new Meteor.Error 'error-invalid-user', 'Invalid user', { method: 'removeRoomModerator' }
+
+		subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId rid, user._id
 		unless subscription?
 			throw new Meteor.Error 'error-invalid-room', 'Invalid room', { method: 'removeRoomModerator' }
 
+		if 'moderator' not in (subscription.roles or [])
+			throw new Meteor.Error 'error-user-not-moderator', 'User is not a moderator', { method: 'removeRoomModerator' }
+
 		RocketChat.models.Subscriptions.removeRoleById(subscription._id, 'moderator')
 
-		user = RocketChat.models.Users.findOneById userId
 		fromUser = RocketChat.models.Users.findOneById Meteor.userId()
 		RocketChat.models.Messages.createSubscriptionRoleRemovedWithRoomIdAndUser rid, user,
 			u:
diff --git a/server/methods/removeRoomOwner.coffee b/server/methods/removeRoomOwner.coffee
index 1a0c09011107b223a1de16c050d9467b8c6295ef..dcc9a21470ef346eb9950e9c784d43d8d89d0bc2 100644
--- a/server/methods/removeRoomOwner.coffee
+++ b/server/methods/removeRoomOwner.coffee
@@ -10,17 +10,24 @@ Meteor.methods
 		unless RocketChat.authz.hasPermission Meteor.userId(), 'set-owner', rid
 			throw new Meteor.Error 'error-not-allowed', 'Not allowed', { method: 'removeRoomOwner' }
 
-		subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId rid, userId
+		user = RocketChat.models.Users.findOneById userId
+
+		unless user?.username
+			throw new Meteor.Error 'error-invalid-user', 'Invalid user', { method: 'removeRoomOwner' }
+
+		subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId rid, user._id
 		unless subscription?
 			throw new Meteor.Error 'error-invalid-room', 'Invalid room', { method: 'removeRoomOwner' }
 
+		if 'owner' not in (subscription.roles or [])
+			throw new Meteor.Error 'error-user-not-owner', 'User is not an owner', { method: 'removeRoomOwner' }
+
 		numOwners = RocketChat.authz.getUsersInRole('owner', rid).count()
 		if numOwners is 1
 			throw new Meteor.Error 'error-remove-last-owner', 'This is the last owner. Please set a new owner before removing this one.', { method: 'removeRoomOwner' }
 
 		RocketChat.models.Subscriptions.removeRoleById(subscription._id, 'owner')
 
-		user = RocketChat.models.Users.findOneById userId
 		fromUser = RocketChat.models.Users.findOneById Meteor.userId()
 		RocketChat.models.Messages.createSubscriptionRoleRemovedWithRoomIdAndUser rid, user,
 			u:
diff --git a/server/methods/removeUserFromRoom.coffee b/server/methods/removeUserFromRoom.coffee
index fbccfbed8109e7f67ec4634d85bceab1e34713f5..5029f792bda18f0de41940bed4213b795e0f6988 100644
--- a/server/methods/removeUserFromRoom.coffee
+++ b/server/methods/removeUserFromRoom.coffee
@@ -13,6 +13,9 @@ Meteor.methods
 
 		room = RocketChat.models.Rooms.findOneById data.rid
 
+		if room.t is 'd'
+			throw new Meteor.Error 'error-not-allowed', 'Not allowed', { method: 'removeUserFromRoom' }
+
 		if data.username not in (room?.usernames or [])
 			throw new Meteor.Error 'error-user-not-in-room', 'User is not in this room', { method: 'removeUserFromRoom' }
 
diff --git a/server/methods/saveUserProfile.coffee b/server/methods/saveUserProfile.coffee
index 428c8c1a0c9d2fbaa1f1614951c1ddd0fd4dc4ef..d591ecfdc1e6cbcef2b781e390525d004dba27e3 100644
--- a/server/methods/saveUserProfile.coffee
+++ b/server/methods/saveUserProfile.coffee
@@ -1,5 +1,5 @@
 Meteor.methods
-	saveUserProfile: (settings) ->
+	saveUserProfile: (settings, customFields) ->
 
 		check settings, Object
 
@@ -43,4 +43,6 @@ Meteor.methods
 
 		RocketChat.models.Users.setProfile Meteor.userId(), profile
 
+		RocketChat.saveCustomFields Meteor.userId(), customFields
+
 		return true
diff --git a/server/publications/channelAndPrivateAutocomplete.coffee b/server/publications/channelAndPrivateAutocomplete.coffee
index af229b8302af0ad279552be2c2cb24315cb2e2de..190fd834bcd41cd474be79a6e45339ca12f84826 100644
--- a/server/publications/channelAndPrivateAutocomplete.coffee
+++ b/server/publications/channelAndPrivateAutocomplete.coffee
@@ -15,6 +15,7 @@ Meteor.publish 'channelAndPrivateAutocomplete', (selector) ->
 		sort:
 			name: 1
 
+	# CACHE: can we stop using publications here?
 	cursorHandle = RocketChat.models.Rooms.findByNameStartingAndTypes(selector.name, ['c', 'p'], options).observeChanges
 		added: (_id, record) ->
 			pub.added('autocompleteRecords', _id, record)
diff --git a/server/publications/fullUserData.coffee b/server/publications/fullUserData.coffee
index 65147c24a80746ae15e28cf1f1416e68681b0083..abe05de05a576f3df07bb65a00b06e74b3e1c806 100644
--- a/server/publications/fullUserData.coffee
+++ b/server/publications/fullUserData.coffee
@@ -2,43 +2,9 @@ Meteor.publish 'fullUserData', (filter, limit) ->
 	unless @userId
 		return @ready()
 
-	fields =
-		name: 1
-		username: 1
-		status: 1
-		utcOffset: 1
-		type: 1
-		active: 1
+	result = RocketChat.getFullUserData { userId: @userId, filter, limit }
 
-	if RocketChat.authz.hasPermission( @userId, 'view-full-other-user-info') is true
-		fields = _.extend fields,
-			emails: 1
-			phone: 1
-			statusConnection: 1
-			createdAt: 1
-			lastLogin: 1
-			services: 1
-			requirePasswordChange: 1
-			requirePasswordChangeReason: 1
-			roles: 1
-	else
-		limit = 1
-
-	filter = s.trim filter
-
-	if not filter and limit is 1
+	if not result
 		return @ready()
 
-	options =
-		fields: fields
-		limit: limit
-		sort: { username: 1 }
-
-	if filter
-		if limit is 1
-			return RocketChat.models.Users.findByUsername filter, options
-		else
-			filterReg = new RegExp s.escapeRegExp(filter), "i"
-			return RocketChat.models.Users.findByUsernameNameOrEmailAddress filterReg, options
-
-	return RocketChat.models.Users.find {}, options
+	return result
diff --git a/server/publications/privateHistory.coffee b/server/publications/privateHistory.coffee
index 115796f52c8fdeea347acec3447d2df5f083481f..5f8d8e90f048aeabad67e5c9475fa7822b08a482 100644
--- a/server/publications/privateHistory.coffee
+++ b/server/publications/privateHistory.coffee
@@ -2,7 +2,7 @@ Meteor.publish 'privateHistory', ->
 	unless this.userId
 		return this.ready()
 
-	RocketChat.models.Rooms.findByContainigUsername RocketChat.models.Users.findOneById(this.userId).username,
+	RocketChat.models.Rooms.findByContainingUsername RocketChat.models.Users.findOneById(this.userId).username,
 		fields:
 			t: 1
 			name: 1
@@ -10,4 +10,3 @@ Meteor.publish 'privateHistory', ->
 			ts: 1
 			lm: 1
 			cl: 1
-
diff --git a/server/publications/room.coffee b/server/publications/room.coffee
deleted file mode 100644
index c251ff777f3ca1baf07ace6933d16b335f045ad3..0000000000000000000000000000000000000000
--- a/server/publications/room.coffee
+++ /dev/null
@@ -1,11 +0,0 @@
-Meteor.publish 'room', (typeName) ->
-	unless this.userId
-		return this.ready()
-
-	if typeof typeName isnt 'string'
-		return this.ready()
-
-	type = typeName.substr(0, 1)
-	name = typeName.substr(1)
-
-	return RocketChat.roomTypes.runPublish(this, type, name)
diff --git a/server/publications/room.js b/server/publications/room.js
new file mode 100644
index 0000000000000000000000000000000000000000..c665df94131f0e05287e7abac2e68cbff7b90de7
--- /dev/null
+++ b/server/publications/room.js
@@ -0,0 +1,97 @@
+const options = {
+	fields: {
+		_id: 1,
+		name: 1,
+		t: 1,
+		cl: 1,
+		u: 1,
+		// usernames: 1,
+		topic: 1,
+		muted: 1,
+		archived: 1,
+		jitsiTimeout: 1,
+		description: 1,
+		default: 1,
+
+		// @TODO create an API to register this fields based on room type
+		livechatData: 1,
+		tags: 1,
+		sms: 1,
+		code: 1,
+		open: 1,
+		v: 1,
+		label: 1,
+		ro: 1
+	}
+};
+
+
+const roomMap = (record) => {
+	if (record._room) {
+		return _.pick(record._room, ...Object.keys(options.fields));
+	}
+	console.log('Empty Room for Subscription', record);
+	return {};
+};
+
+
+Meteor.methods({
+	'rooms/get'(updatedAt) {
+		if (!Meteor.userId()) {
+			return [];
+		}
+
+		this.unblock();
+
+		if (updatedAt instanceof Date) {
+			return {
+				update: RocketChat.models.Rooms.findBySubscriptionUserIdUpdatedAfter(Meteor.userId(), updatedAt, options).fetch(),
+				remove: RocketChat.models.Rooms.trashFindDeletedAfter(updatedAt, {}, {fields: {_id: 1, _deletedAt: 1}}).fetch()
+			};
+		}
+
+		return RocketChat.models.Rooms.findBySubscriptionUserId(Meteor.userId(), options).fetch();
+	},
+
+	getRoomByTypeAndName(type, name) {
+		if (!Meteor.userId()) {
+			throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getRoomByTypeAndName' });
+		}
+
+		const roomFind = RocketChat.roomTypes.getRoomFind(type);
+
+		let room;
+
+		if (roomFind) {
+			room = roomFind.call(this, name);
+		} else {
+			room = RocketChat.models.Rooms.findByTypeAndName(type, name).fetch();
+		}
+
+		if (!room) {
+			throw new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'getRoomByTypeAndName' });
+		}
+
+		if (!Meteor.call('canAccessRoom', room._id, Meteor.userId())) {
+			throw new Meteor.Error('error-no-permission', 'No permission', { method: 'getRoomByTypeAndName' });
+		}
+
+		return roomMap({_room: room});
+	}
+});
+
+RocketChat.models.Rooms.cache.on('sync', (type, room/*, diff*/) => {
+	const records = RocketChat.models.Subscriptions.findByRoomId(room._id).fetch();
+	for (const record of records) {
+		RocketChat.Notifications.notifyUserInThisInstance(record.u._id, 'rooms-changed', type, roomMap({_room: room}));
+	}
+});
+
+RocketChat.models.Subscriptions.on('changed', (type, subscription/*, diff*/) => {
+	if (type === 'inserted') {
+		const room = RocketChat.models.Rooms.findOneById(subscription.rid);
+		if (room) {
+			RocketChat.Notifications.notifyUserInThisInstance(subscription.u._id, 'rooms-changed', type, roomMap({_room: room}));
+		}
+	}
+});
diff --git a/server/publications/subscription.coffee b/server/publications/subscription.coffee
index ab44cdb5efad903d526b51d386dbaa70000bd745..b51560c25d42dc9a25d116d5873145ec18e6e37c 100644
--- a/server/publications/subscription.coffee
+++ b/server/publications/subscription.coffee
@@ -18,6 +18,8 @@ fields =
 	emailNotifications: 1
 	unreadAlert: 1
 	_updatedAt: 1
+	blocked: 1
+	blocker: 1
 
 
 Meteor.methods
@@ -30,14 +32,17 @@ Meteor.methods
 		options =
 			fields: fields
 
-		if updatedAt instanceof Date
-			return RocketChat.models.Subscriptions.dinamicFindChangesAfter('findByUserId', updatedAt, Meteor.userId(), options);
+		records = RocketChat.models.Subscriptions.findByUserId(Meteor.userId(), options).fetch()
 
-		return RocketChat.models.Subscriptions.findByUserId(Meteor.userId(), options).fetch()
+		if updatedAt instanceof Date
+			return {
+				update: records.filter (record) ->
+					return record._updatedAt > updatedAt
+				remove: RocketChat.models.Subscriptions.trashFindDeletedAfter(updatedAt, {'u._id': Meteor.userId()}, {fields: {_id: 1, _deletedAt: 1}}).fetch()
+			}
 
+		return records
 
-RocketChat.models.Subscriptions.on 'change', (type, args...) ->
-	records = RocketChat.models.Subscriptions.getChangedRecords type, args[0], fields
 
-	for record in records
-		RocketChat.Notifications.notifyUser record.u._id, 'subscriptions-changed', type, record
+RocketChat.models.Subscriptions.on 'changed', (type, subscription) ->
+	RocketChat.Notifications.notifyUserInThisInstance subscription.u._id, 'subscriptions-changed', type, RocketChat.models.Subscriptions.processQueryOptionsOnResult(subscription, {fields: fields})
diff --git a/server/publications/userData.coffee b/server/publications/userData.coffee
index 1301239dbf6dec6862854278624563f469171835..39429349f5320c83741c2533251d2fda9906961e 100644
--- a/server/publications/userData.coffee
+++ b/server/publications/userData.coffee
@@ -16,6 +16,7 @@ Meteor.publish 'userData', ->
 			roles: 1
 			active: 1
 			defaultRoom: 1
+			customFields: 1
 			'services.github': 1
 			'services.gitlab': 1
 			requirePasswordChange: 1
diff --git a/server/restapi/README.md b/server/restapi/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..9905e0753b673ac42ad04da09efd3d71e04c77c4
--- /dev/null
+++ b/server/restapi/README.md
@@ -0,0 +1,3 @@
+# Important Information
+
+The REST API has moved to `/api/v1/${endpoint}`, please see the [Rocket.Chat Documentation](https://rocket.chat/docs/developer-guides/rest-api) for details on the current REST API. If a feature is currently missing, feel free to open a new pull request to add it. :heart:
diff --git a/server/restapi/restapi.coffee b/server/restapi/restapi.coffee
deleted file mode 100644
index 8f3f3bba98e00398406ca22cb9f2f8607ffd941b..0000000000000000000000000000000000000000
--- a/server/restapi/restapi.coffee
+++ /dev/null
@@ -1,281 +0,0 @@
-Api = new Restivus
-	useDefaultAuth: true
-	prettyJson: true
-	enableCors: false
-
-
-Api.addRoute 'info', authRequired: false,
-	get: -> RocketChat.Info
-
-
-Api.addRoute 'version', authRequired: false,
-	get: ->
-		version = {api: '0.1', rocketchat: '0.5'}
-		status: 'success', versions: version
-
-Api.addRoute 'publicRooms', authRequired: true,
-	get: ->
-		rooms = RocketChat.models.Rooms.findByType('c', { sort: { msgs:-1 } }).fetch()
-		status: 'success', rooms: rooms
-
-###
-@api {get} /joinedRooms Get joined rooms.
-###
-Api.addRoute 'joinedRooms', authRequired: true,
-	get: ->
-		rooms = RocketChat.models.Rooms.findByContainigUsername(@user.username).fetch()
-		status: 'success', rooms: rooms
-
-# join a room
-Api.addRoute 'rooms/:id/join', authRequired: true,
-	post: ->
-		Meteor.runAsUser this.userId, () =>
-			Meteor.call('joinRoom', @urlParams.id)
-		status: 'success'   # need to handle error
-
-# leave a room
-Api.addRoute 'rooms/:id/leave', authRequired: true,
-	post: ->
-		Meteor.runAsUser this.userId, () =>
-			Meteor.call('leaveRoom', @urlParams.id)
-		status: 'success'   # need to handle error
-
-
-###
-@api {get} /rooms/:id/messages?skip=:skip&limit=:limit Get messages in a room.
-@apiParam {Number} id         Room ID
-@apiParam {Number} [skip=0]   Number of results to skip at the beginning
-@apiParam {Number} [limit=50] Maximum number of results to return
-###
-Api.addRoute 'rooms/:id/messages', authRequired: true,
-	get: ->
-		try
-			rid = @urlParams.id
-			# `variable | 0` means converting to int
-			skip = @queryParams.skip | 0 or 0
-			limit = @queryParams.limit | 0 or 50
-			limit = 50 if limit > 50
-			if Meteor.call('canAccessRoom', rid, this.userId)
-				msgs = RocketChat.models.Messages.findVisibleByRoomId(rid,
-					sort:
-						ts: -1
-					skip: skip
-					limit: limit
-				).fetch()
-				status: 'success', messages: msgs
-			else
-				statusCode: 403   # forbidden
-				body: status: 'fail', message: 'Cannot access room.'
-		catch e
-			statusCode: 400    # bad request or other errors
-			body: status: 'fail', message: e.name + ' :: ' + e.message
-
-
-
-# send a message in a room -  POST body should be { "msg" : "this is my message"}
-Api.addRoute 'rooms/:id/send', authRequired: true,
-	post: ->
-		Meteor.runAsUser this.userId, () =>
-			console.log @bodyParams.msg
-			Meteor.call('sendMessage', {msg: this.bodyParams.msg, rid: @urlParams.id} )
-		status: 'success'	#need to handle error
-
-# get list of online users in a room
-Api.addRoute 'rooms/:id/online', authRequired: true,
-	get: ->
-		room = RocketChat.models.Rooms.findOneById @urlParams.id
-		online = RocketChat.models.Users.findUsersNotOffline(fields:
-			username: 1
-			status: 1).fetch()
-		onlineInRoom = []
-		for user, i in online
-			if room.usernames.indexOf(user.username) != -1
-				onlineInRoom.push user.username
-
-		status: 'success', online: onlineInRoom
-
-# validate an array of users
-Api.testapiValidateUsers =  (users) ->
-	for user, i in users
-		if user.name?
-			if user.email?
-				if user.pass?
-					try
-						nameValidation = new RegExp '^' + RocketChat.settings.get('UTF8_Names_Validation') + '$', 'i'
-					catch
-						nameValidation = new RegExp '^[0-9a-zA-Z-_.]+$', 'i'
-
-					if nameValidation.test user.name
-						if  /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]+\b/i.test user.email
-							continue
-		throw new Meteor.Error 'invalid-user-record', "[restapi] bulk/register -> record #" + i + " is invalid"
-	return
-
-
-###
-@api {post} /bulk/register  Register multiple users based on an input array.
-@apiName register
-@apiGroup TestAndAdminAutomation
-@apiVersion 0.0.1
-@apiDescription  Caller must have 'testagent' or 'adminautomation' role.
-NOTE:   remove room is NOT recommended; use Meteor.reset() to clear db and re-seed instead
-@apiParam {json} rooms An array of users in the body of the POST.
-@apiParamExample {json} POST Request Body example:
-  {
-    'users':[ {'email': 'user1@user1.com',
-               'name': 'user1',
-               'pass': 'abc123' },
-              {'email': 'user2@user2.com',
-               'name': 'user2',
-               'pass': 'abc123'},
-              ...
-            ]
-  }
-@apiSuccess {json} ids An array of IDs of the registered users.
-@apiSuccessExample {json} Success-Response:
-  HTTP/1.1 200 OK
-  {
-    'ids':[ {'uid': 'uid_1'},
-            {'uid': 'uid_2'},
-            ...
-    ]
-  }
-###
-Api.addRoute 'bulk/register', authRequired: true,
-	post:
-		# restivus 0.8.4 does not support alanning:roles using groups
-		#roleRequired: ['testagent', 'adminautomation']
-		action: ->
-			if RocketChat.authz.hasPermission(@userId, 'bulk-register-user')
-				try
-
-					Api.testapiValidateUsers  @bodyParams.users
-					this.response.setTimeout (500 * @bodyParams.users.length)
-					ids = []
-					endCount = @bodyParams.users.length - 1
-					for incoming, i in @bodyParams.users
-						ids[i] = {uid: Meteor.call 'registerUser', incoming}
-						Meteor.runAsUser ids[i].uid, () =>
-							Meteor.call 'setUsername', incoming.name
-							Meteor.call 'joinDefaultChannels'
-
-					status: 'success', ids: ids
-				catch e
-					statusCode: 400    # bad request or other errors
-					body: status: 'fail', message: e.name + ' :: ' + e.message
-			else
-				console.log '[restapi] bulk/register -> '.red, "User does not have 'bulk-register-user' permission"
-				statusCode: 403
-				body: status: 'error', message: 'You do not have permission to do this'
-
-
-
-
-# validate an array of rooms
-Api.testapiValidateRooms =  (rooms) ->
-	for room, i in rooms
-		if room.name?
-			if room.members?
-				if room.members.length > 0
-					try
-						nameValidation = new RegExp '^' + RocketChat.settings.get('UTF8_Names_Validation') + '$', 'i'
-					catch
-						nameValidation = new RegExp '^[0-9a-zA-Z-_.]+$', 'i'
-
-					if nameValidation.test room.name
-						continue
-		throw new Meteor.Error 'invalid-room-record', "[restapi] bulk/createRoom -> record #" + i + " is invalid"
-	return
-
-
-###
-@api {post} /bulk/createRoom Create multiple rooms based on an input array.
-@apiName createRoom
-@apiGroup TestAndAdminAutomation
-@apiVersion 0.0.1
-@apiParam {json} rooms An array of rooms in the body of the POST. 'name' is room name, 'members' is array of usernames
-@apiParamExample {json} POST Request Body example:
-  {
-    'rooms':[ {'name': 'room1',
-               'members': ['user1', 'user2']
-              },
-              {'name': 'room2',
-               'members': ['user1', 'user2', 'user3']
-              }
-              ...
-            ]
-  }
-@apiDescription  Caller must have 'testagent' or 'adminautomation' role.
-NOTE:   remove room is NOT recommended; use Meteor.reset() to clear db and re-seed instead
-
-@apiSuccess {json} ids An array of ids of the rooms created.
-@apiSuccessExample {json} Success-Response:
-  HTTP/1.1 200 OK
-  {
-    'ids':[ {'rid': 'rid_1'},
-            {'rid': 'rid_2'},
-            ...
-    ]
-  }
-###
-Api.addRoute 'bulk/createRoom', authRequired: true,
-	post:
-		# restivus 0.8.4 does not support alanning:roles using groups
-		#roleRequired: ['testagent', 'adminautomation']
-		action: ->
-			# user must also have create-c permission because
-			# createChannel method requires it
-			if RocketChat.authz.hasPermission(@userId, 'bulk-create-c')
-				try
-					this.response.setTimeout (1000 * @bodyParams.rooms.length)
-					Api.testapiValidateRooms @bodyParams.rooms
-					ids = []
-					Meteor.runAsUser this.userId, () =>
-						(if incoming.private
-							ids[i] = Meteor.call 'createPrivateGroup', incoming.name, incoming.members
-						else 
-							ids[i] = Meteor.call 'createChannel', incoming.name, incoming.members) for incoming,i in @bodyParams.rooms
-					status: 'success', ids: ids   # need to handle error
-				catch e
-					statusCode: 400    # bad request or other errors
-					body: status: 'fail', message: e.name + ' :: ' + e.message
-			else
-				console.log '[restapi] bulk/createRoom -> '.red, "User does not have 'bulk-create-c' permission"
-				statusCode: 403
-				body: status: 'error', message: 'You do not have permission to do this'
-
-# archive a room by it's ID
-Api.addRoute 'room/:id/archive', authRequired: true,
-	post:
-		action: ->
-			# user must also have archive-room permission
-			if RocketChat.authz.hasPermission(@userId, 'archive-room')
-				try
-					Meteor.runAsUser this.userId, () =>
-						Meteor.call('archiveRoom', @urlParams.id)
-					status: 'success'   # need to handle error
-				catch e
-					statusCode: 400    # bad request or other errors
-					body: status: 'fail', message: e.name + ' :: ' + e.message
-			else
-				console.log '[restapi] archiveRoom -> '.red, "User does not have 'archive-room' permission"
-				statusCode: 403
-				body: status: 'error', message: 'You do not have permission to do this'
-				
-# unarchive a room by it's ID
-Api.addRoute 'room/:id/unarchive', authRequired: true,
-	post:
-		action: ->
-			# user must also have unarchive-room permission 
-			if RocketChat.authz.hasPermission(@userId, 'unarchive-room')
-				try
-					Meteor.runAsUser this.userId, () =>
-						Meteor.call('unarchiveRoom', @urlParams.id)
-					status: 'success'   # need to handle error
-				catch e
-					statusCode: 400    # bad request or other errors
-					body: status: 'fail', message: e.name + ' :: ' + e.message
-			else
-				console.log '[restapi] unarchiveRoom -> '.red, "User does not have 'unarchive-room' permission"
-				statusCode: 403
-				body: status: 'error', message: 'You do not have permission to do this'
diff --git a/server/startup/avatar.coffee b/server/startup/avatar.coffee
index 28ae6bc4f2b17d013b1d5a714f59a07221d4d947..bfb2e4f92acb57072a8a141ac71b309fffcca50f 100644
--- a/server/startup/avatar.coffee
+++ b/server/startup/avatar.coffee
@@ -1,3 +1,5 @@
+import getFileType from 'file-type'
+
 Meteor.startup ->
 	storeType = 'GridFS'
 
@@ -18,7 +20,11 @@ Meteor.startup ->
 		height = RocketChat.settings.get 'Accounts_AvatarSize'
 		width = height
 
-		RocketChatFile.gm(readStream, file.fileName).background('#ffffff').resize(width, height+'^>').gravity('Center').extent(width, height).stream('jpeg').pipe(writeStream)
+		# - Resize the image using the width or height as minium value
+		# - Keep the image aspect ratio
+		# - Crop image to keep max size of width and height
+		# - Use extent to set background color for transparent images
+		RocketChatFile.gm(readStream, file.fileName).background('#ffffff').resize(width, height+'^').gravity('Center').crop(width, height).extent(width, height).stream('jpeg').pipe(writeStream)
 
 	path = "~/uploads"
 
@@ -34,6 +40,8 @@ Meteor.startup ->
 		params =
 			username: decodeURIComponent(req.url.replace(/^\//, '').replace(/\?.*$/, ''))
 
+		username = params.username.replace(/\.jpg$/, '').replace(/^@/, '')
+
 		if _.isEmpty params.username
 			res.writeHead 403
 			res.write 'Forbidden'
@@ -42,15 +50,13 @@ Meteor.startup ->
 
 		if params.username[0] isnt '@'
 			if Meteor.settings?.public?.sandstorm
-				user = RocketChat.models.Users.findOneByUsername(params.username.replace('.jpg', ''))
+				user = RocketChat.models.Users.findOneByUsername(username)
 				if user?.services?.sandstorm?.picture
 					res.setHeader 'Location', user.services.sandstorm.picture
 					res.writeHead 302
 					res.end()
 					return
-			file = RocketChatFileAvatarInstance.getFileWithReadStream encodeURIComponent(params.username)
-		else
-			params.username = params.username.replace '@', ''
+			file = RocketChatFileAvatarInstance.getFileWithReadStream encodeURIComponent("#{username}.jpg")
 
 		#console.log "[avatar] checking username #{@params.username} (derrived from path #{req.url})"
 		res.setHeader 'Content-Disposition', 'inline'
@@ -70,7 +76,6 @@ Meteor.startup ->
 
 			colors = ['#F44336','#E91E63','#9C27B0','#673AB7','#3F51B5','#2196F3','#03A9F4','#00BCD4','#009688','#4CAF50','#8BC34A','#CDDC39','#FFC107','#FF9800','#FF5722','#795548','#9E9E9E','#607D8B']
 
-			username = params.username.replace('.jpg', '')
 			if RocketChat.settings.get 'UI_Use_Name_Avatar'
 				user = RocketChat.models.Users.findOneByUsername(username, { fields: { name: 1 } })
 				if user?.name
@@ -116,8 +121,17 @@ Meteor.startup ->
 		res.setHeader 'Cache-Control', 'public, max-age=0'
 		res.setHeader 'Expires', '-1'
 		res.setHeader 'Last-Modified', file.uploadDate?.toUTCString() or new Date().toUTCString()
-		res.setHeader 'Content-Type', 'image/jpeg'
 		res.setHeader 'Content-Length', file.length
 
+		if file.contentType?
+			res.setHeader 'Content-Type', file.contentType
+		else
+			file.readStream.once 'data', (chunk) ->
+				fileType = getFileType(chunk)
+				if fileType?
+					res.setHeader 'Content-Type', fileType.mime
+				else
+					res.setHeader 'Content-Type', 'image/jpeg'
+
 		file.readStream.pipe res
 		return
diff --git a/server/startup/initialData.coffee b/server/startup/initialData.coffee
index 84e492d9122625380c31e8f2a4f9eae0bbcda80f..5644753e73f4ae7e62426ca936083f48a4ddfa0d 100644
--- a/server/startup/initialData.coffee
+++ b/server/startup/initialData.coffee
@@ -5,7 +5,7 @@ Meteor.startup ->
 			RocketChat.models.Rooms.createWithIdTypeAndName 'GENERAL', 'c', 'general',
 				default: true
 
-		if not RocketChat.models.Users.findOneById('rocket.cat')?
+		if not RocketChat.models.Users.db.findOneById('rocket.cat')?
 			RocketChat.models.Users.create
 				_id: 'rocket.cat'
 				name: "Rocket.Cat"
@@ -89,3 +89,41 @@ Meteor.startup ->
 			if oldestUser
 				RocketChat.authz.addUserRoles( oldestUser._id, 'admin')
 				console.log "No admins are found. Set #{oldestUser.username} as admin for being the oldest user"
+
+
+		RocketChat.models.Users.removeById 'rocketchat.internal.admin.test'
+
+		if process.env.TEST_MODE is 'true'
+			console.log 'Inserting admin test user:'.green
+
+			adminUser =
+				_id: 'rocketchat.internal.admin.test'
+				name: 'RocketChat Internal Admin Test'
+				username: 'rocketchat.internal.admin.test'
+				emails: [
+					address: 'rocketchat.internal.admin.test@rocket.chat'
+					verified: true
+				]
+				status: 'offline'
+				statusDefault: 'online'
+				utcOffset: 0
+				active: true
+				type: 'user'
+
+			console.log "Name: #{adminUser.name}".green
+			console.log "Email: #{adminUser.emails[0].address}".green
+			console.log "Username: #{adminUser.username}".green
+			console.log "Password: #{adminUser._id}".green
+
+			if RocketChat.models.Users.db.findOneByEmailAddress(adminUser.emails[0].address)
+				throw new Meteor.Error "Email #{adminUser.emails[0].address} already exists", 'Rocket.Chat can\'t run in test mode'
+
+			if not RocketChat.checkUsernameAvailability(adminUser.username)
+				throw new Meteor.Error "Username #{adminUser.username} already exists", 'Rocket.Chat can\'t run in test mode'
+
+			RocketChat.models.Users.create adminUser
+
+			Accounts.setPassword adminUser._id, adminUser._id
+			RocketChat.authz.addUserRoles(adminUser._id, 'admin')
+
+			RocketChat.addUserToDefaultChannels(adminUser, true)
diff --git a/server/startup/migrations/v067.js b/server/startup/migrations/v067.js
new file mode 100644
index 0000000000000000000000000000000000000000..86a10fd7417e186b4863b140e93de83dd7d95177
--- /dev/null
+++ b/server/startup/migrations/v067.js
@@ -0,0 +1,12 @@
+RocketChat.Migrations.add({
+	version: 67,
+	up: function() {
+		if (RocketChat && RocketChat.models && RocketChat.models.LivechatDepartment) {
+			RocketChat.models.LivechatDepartment.model.update({}, {
+				$set: {
+					showOnRegistration: true
+				}
+			}, { multi: true });
+		}
+	}
+});
diff --git a/server/startup/migrations/v068.js b/server/startup/migrations/v068.js
new file mode 100644
index 0000000000000000000000000000000000000000..8039aa97b58e8b64ee5398ead8508769c8944d28
--- /dev/null
+++ b/server/startup/migrations/v068.js
@@ -0,0 +1,17 @@
+RocketChat.Migrations.add({
+	version: 68,
+	up: function() {
+		var GoogleSiteVerification_id = RocketChat.models.Settings.findOne({ _id: 'GoogleSiteVerification_id' });
+
+		if (GoogleSiteVerification_id && GoogleSiteVerification_id.value) {
+			RocketChat.models.Settings.update({ _id: 'Meta_google-site-verification' }, {
+				$set: {
+					value: GoogleSiteVerification_id.value
+				}
+			});
+		}
+
+		RocketChat.models.Settings.remove({ _id: 'GoogleSiteVerification_id' });
+	}
+});
+
diff --git a/server/startup/migrations/v069.js b/server/startup/migrations/v069.js
new file mode 100644
index 0000000000000000000000000000000000000000..8e56b7a932d39114a7e217ef7778946342733dba
--- /dev/null
+++ b/server/startup/migrations/v069.js
@@ -0,0 +1,87 @@
+RocketChat.Migrations.add({
+	version: 69,
+	up: function() {
+		RocketChat.models.Settings.update({
+			'_id': 'theme-color-custom-scrollbar-color',
+			'value': 'rgba(255, 255, 255, 0.05)'
+		}, {
+			$set: {
+				'editor': 'expression',
+				'value': '@transparent-darker'
+			}
+		});
+		RocketChat.models.Settings.update({
+			'_id': 'theme-color-info-font-color',
+			'value': '#aaaaaa'
+		}, {
+			$set: {
+				'editor': 'expression',
+				'value': '@secondary-font-color'
+			}
+		});
+		RocketChat.models.Settings.update({
+			'_id': 'theme-color-link-font-color',
+			'value': '#008ce3'
+		}, {
+			$set: {
+				'editor': 'expression',
+				'value': '@primary-action-color'
+			}
+		});
+		RocketChat.models.Settings.update({
+			'_id': 'theme-color-status-away',
+			'value': '#fcb316'
+		}, {
+			$set: {
+				'editor': 'expression',
+				'value': '@pending-color'
+			}
+		});
+		RocketChat.models.Settings.update({
+			'_id': 'theme-color-status-busy',
+			'value': '#d30230'
+		}, {
+			$set: {
+				'editor': 'expression',
+				'value': '@error-color'
+			}
+		});
+		RocketChat.models.Settings.update({
+			'_id': 'theme-color-status-offline',
+			'value': 'rgba(150, 150, 150, 0.50)'
+		}, {
+			$set: {
+				'editor': 'expression',
+				'value': '@transparent-darker'
+			}
+		});
+		RocketChat.models.Settings.update({
+			'_id': 'theme-color-status-online',
+			'value': '#35ac19'
+		}, {
+			$set: {
+				'editor': 'expression',
+				'value': '@success-color'
+			}
+		});
+		RocketChat.models.Settings.update({
+			'_id': 'theme-color-tertiary-background-color',
+			'value': '#eaeaea'
+		}, {
+			$set: {
+				'editor': 'expression',
+				'value': '@component-color'
+			}
+		});
+		return RocketChat.models.Settings.update({
+			'_id': 'theme-color-tertiary-font-color',
+			'value': 'rgba(255, 255, 255, 0.6)'
+		}, {
+			$set: {
+				'editor': 'expression',
+				'value': '@transparent-lightest'
+			}
+		});
+	}
+});
+
diff --git a/server/startup/migrations/v070.js b/server/startup/migrations/v070.js
new file mode 100644
index 0000000000000000000000000000000000000000..cd4df94d909a9a39416ba542eff0d5f2c49f8c46
--- /dev/null
+++ b/server/startup/migrations/v070.js
@@ -0,0 +1,14 @@
+RocketChat.Migrations.add({
+	version: 70,
+	up: function() {
+		const settings = RocketChat.models.Settings.find({ _id: /^Accounts_OAuth_Custom_.+/ }).fetch();
+		for (const setting of settings) {
+			const _id = setting._id;
+			setting._id = setting._id.replace(/Accounts_OAuth_Custom_([A-Za-z0-9]+)_(.+)/, 'Accounts_OAuth_Custom-$1-$2');
+			setting._id = setting._id.replace(/Accounts_OAuth_Custom_([A-Za-z0-9]+)/, 'Accounts_OAuth_Custom-$1');
+
+			RocketChat.models.Settings.remove({ _id: _id });
+			RocketChat.models.Settings.insert(setting);
+		}
+	}
+});
diff --git a/server/startup/migrations/v071.js b/server/startup/migrations/v071.js
new file mode 100644
index 0000000000000000000000000000000000000000..b9dc8259ab9c7edd567dc28716115d53adbfd748
--- /dev/null
+++ b/server/startup/migrations/v071.js
@@ -0,0 +1,9 @@
+RocketChat.Migrations.add({
+	version: 71,
+	up: function() {
+		//Removes the reactions on messages which are the system type "rm" ;)
+		RocketChat.models.Messages.find({ 't': 'rm', 'reactions': { $exists: true, $not: {$size: 0} } }, { t: 1 }).forEach(function(message) {
+			RocketChat.models.Messages.update({ _id: message._id }, { $set: { reactions: [] }});
+		});
+	}
+});
diff --git a/server/startup/migrations/v072.js b/server/startup/migrations/v072.js
new file mode 100644
index 0000000000000000000000000000000000000000..01f298b18be7dd118d186a508bc9bbaf070c4e65
--- /dev/null
+++ b/server/startup/migrations/v072.js
@@ -0,0 +1,15 @@
+RocketChat.Migrations.add({
+	version: 72,
+	up: function() {
+		RocketChat.models.Users.find({ type: 'visitor', 'emails.address': { $exists: true } }, { emails: 1 }).forEach(function(visitor) {
+			RocketChat.models.Users.update({ _id: visitor._id }, {
+				$set: {
+					visitorEmails: visitor.emails
+				},
+				$unset: {
+					emails: 1
+				}
+			});
+		});
+	}
+});
diff --git a/server/startup/migrations/v073.js b/server/startup/migrations/v073.js
new file mode 100644
index 0000000000000000000000000000000000000000..e279a0b65ae233b288a4e4db5703c3c38a447524
--- /dev/null
+++ b/server/startup/migrations/v073.js
@@ -0,0 +1,15 @@
+RocketChat.Migrations.add({
+	version: 73,
+	up: function() {
+		RocketChat.models.Users.find({ 'oauth.athorizedClients': { $exists: true } }, { oauth: 1 }).forEach(function(user) {
+			RocketChat.models.Users.update({ _id: user._id }, {
+				$set: {
+					'oauth.authorizedClients': user.oauth.athorizedClients
+				},
+				$unset: {
+					'oauth.athorizedClients': 1
+				}
+			});
+		});
+	}
+});
diff --git a/server/startup/migrations/v074.js b/server/startup/migrations/v074.js
new file mode 100644
index 0000000000000000000000000000000000000000..656b226c4efccac8f6ca5232ab9a05e0dfd2b35f
--- /dev/null
+++ b/server/startup/migrations/v074.js
@@ -0,0 +1,16 @@
+RocketChat.Migrations.add({
+	version: 74,
+	up: function() {
+		if (RocketChat && RocketChat.models && RocketChat.models.Settings) {
+			RocketChat.models.Settings.remove({_id: 'Assets_favicon_64'});
+			RocketChat.models.Settings.remove({_id: 'Assets_favicon_96'});
+			RocketChat.models.Settings.remove({_id: 'Assets_favicon_128'});
+			RocketChat.models.Settings.remove({_id: 'Assets_favicon_256'});
+			RocketChat.models.Settings.update({_id: 'Assets_favicon_192'}, {
+				$set: {
+					i18nLabel: 'android-chrome 192x192 (png)'
+				}
+			});
+		}
+	}
+});
diff --git a/server/startup/migrations/v075.js b/server/startup/migrations/v075.js
new file mode 100644
index 0000000000000000000000000000000000000000..aaf3ba9b74fed44338763405956f72450d6b5554
--- /dev/null
+++ b/server/startup/migrations/v075.js
@@ -0,0 +1,14 @@
+RocketChat.Migrations.add({
+	version: 71.1,
+	up: function() {
+		ServiceConfiguration.configurations.remove({});
+	}
+});
+
+RocketChat.Migrations.add({
+	version: 75,
+	up: function() {
+		ServiceConfiguration.configurations.remove({});
+	}
+});
+
diff --git a/server/startup/migrations/v076.js b/server/startup/migrations/v076.js
new file mode 100644
index 0000000000000000000000000000000000000000..4c19f9aaeee7d7a063156c172b9ccabe0212c534
--- /dev/null
+++ b/server/startup/migrations/v076.js
@@ -0,0 +1,10 @@
+RocketChat.Migrations.add({
+	version: 76,
+	up: function() {
+		if (RocketChat && RocketChat.models && RocketChat.models.Settings) {
+			RocketChat.models.Settings.find({section: 'Colors (alphas)'}).forEach((setting) => {
+				RocketChat.models.Settings.remove({ _id: setting._id });
+			});
+		}
+	}
+});
diff --git a/server/startup/migrations/v077.js b/server/startup/migrations/v077.js
new file mode 100644
index 0000000000000000000000000000000000000000..6e757ccb23d51247aa07fa7a81e13d352cb52627
--- /dev/null
+++ b/server/startup/migrations/v077.js
@@ -0,0 +1,23 @@
+RocketChat.Migrations.add({
+	version: 77,
+	up: function() {
+		if (RocketChat && RocketChat.models && RocketChat.models.Rooms) {
+			RocketChat.models.Rooms.find({
+				t: 'l',
+				'v._id': { $exists: true },
+				'v.username': { $exists: false }
+			}, { fields: { 'v._id': 1 } }).forEach(function(room) {
+				const user = RocketChat.models.Users.findOne({ _id: room.v._id }, { username: 1 });
+
+				RocketChat.models.Rooms.update({
+					_id: room._id
+				}, {
+					$set: {
+						'v.username': user.username
+					}
+				});
+			});
+		}
+	}
+});
+
diff --git a/server/startup/migrations/v078.js b/server/startup/migrations/v078.js
new file mode 100644
index 0000000000000000000000000000000000000000..41f5dbb4a5a7179da2aae24ead3b162a61ad9314
--- /dev/null
+++ b/server/startup/migrations/v078.js
@@ -0,0 +1,6 @@
+RocketChat.Migrations.add({
+	version: 78,
+	up: function() {
+		RocketChat.models.Permissions.update({ _id: { $in: ['create-c', 'create-d', 'create-p'] }}, { $addToSet: { roles: 'bot' }}, { multi: true });
+	}
+});
diff --git a/server/startup/migrations/v079.js b/server/startup/migrations/v079.js
new file mode 100644
index 0000000000000000000000000000000000000000..a3e4571bab9cf91c0d4e42f6a5aa120b55531099
--- /dev/null
+++ b/server/startup/migrations/v079.js
@@ -0,0 +1,16 @@
+RocketChat.Migrations.add({
+	version: 79,
+	up: function() {
+		const integrations = RocketChat.models.Integrations.find({type: 'webhook-incoming'}).fetch();
+
+		for (const integration of integrations) {
+			if (typeof integration.channel === 'string') {
+				RocketChat.models.Integrations.update({_id: integration._id}, {
+					$set: {
+						channel: integration.channel.split(',').map(channel => channel.trim())
+					}
+				});
+			}
+		}
+	}
+});
diff --git a/server/startup/roomPublishes.coffee b/server/startup/roomPublishes.coffee
index c1c1c7397210f41154bc4c706a21bcd5c58c4fdb..b80504eeebbccc5a2757d3084384d85172b17fb9 100644
--- a/server/startup/roomPublishes.coffee
+++ b/server/startup/roomPublishes.coffee
@@ -11,6 +11,7 @@ Meteor.startup ->
 				muted: 1
 				archived: 1
 				ro: 1
+				reactWhenReadOnly: 1
 				jitsiTimeout: 1
 				description: 1
 				sysMes: 1
@@ -20,10 +21,12 @@ Meteor.startup ->
 			options.fields.joinCode = 1
 
 		if RocketChat.authz.hasPermission(this.userId, 'view-c-room')
+			# CACHE: can we stop using publications here?
 			return RocketChat.models.Rooms.findByTypeAndName 'c', identifier, options
 		else if RocketChat.authz.hasPermission(this.userId, 'view-joined-room')
 			roomId = RocketChat.models.Subscriptions.findByTypeNameAndUserId('c', identifier, this.userId).fetch()
 			if roomId.length > 0
+				# CACHE: can we stop using publications here?
 				return RocketChat.models.Rooms.findById(roomId[0]?.rid, options)
 
 		return this.ready()
@@ -40,11 +43,13 @@ Meteor.startup ->
 				muted: 1
 				archived: 1
 				ro: 1
+				reactWhenReadOnly: 1
 				jitsiTimeout: 1
 				description: 1
 				sysMes: 1
 
 		user = RocketChat.models.Users.findOneById this.userId, fields: username: 1
+		# CACHE: can we stop using publications here?
 		return RocketChat.models.Rooms.findByTypeAndNameContainingUsername 'p', identifier, user.username, options
 
 	RocketChat.roomTypes.setPublish 'd', (identifier) ->
@@ -60,5 +65,6 @@ Meteor.startup ->
 
 		user = RocketChat.models.Users.findOneById this.userId, fields: username: 1
 		if RocketChat.authz.hasAtLeastOnePermission(this.userId, ['view-d-room', 'view-joined-room'])
-			return RocketChat.models.Rooms.findByTypeContainigUsernames 'd', [user.username, identifier], options
+			# CACHE: can we stop using publications here?
+			return RocketChat.models.Rooms.findByTypeContainingUsernames 'd', [user.username, identifier], options
 		return this.ready()
diff --git a/server/startup/serverRunning.coffee b/server/startup/serverRunning.coffee
index 4852c80c4e1ef8dc554d21ac75060ed5198278b7..4eb537553d3648eecbcd439efb1b9d76cf33cfa9 100644
--- a/server/startup/serverRunning.coffee
+++ b/server/startup/serverRunning.coffee
@@ -1,14 +1,16 @@
 Meteor.startup ->
-	isOplogState = 'Enabled'
-	if not MongoInternals.defaultRemoteCollectionDriver().mongo._oplogHandle?
-		isOplogState = 'Disabled'
+	oplogState = 'Disabled'
+	if MongoInternals.defaultRemoteCollectionDriver().mongo._oplogHandle?.onOplogEntry?
+		oplogState = 'Enabled'
+		if RocketChat.settings.get('Force_Disable_OpLog_For_Cache') is true
+			oplogState += ' (Disabled for Cache Sync)'
 
 	Meteor.setTimeout ->
 		msg = [
 			"     Version: #{RocketChat.Info.version}"
 			"Process Port: #{process.env.PORT}"
 			"    Site URL: #{RocketChat.settings.get('Site_Url')}"
-			"       OpLog: #{isOplogState}"
+			"       OpLog: #{oplogState}"
 		].join('\n')
 
 		SystemLogger.startup_box msg, 'SERVER RUNNING'
diff --git a/server/stream/messages.coffee b/server/stream/messages.coffee
index 45cd8cf9688d64aa98af2cbfbd1545fca01cf65b..6141449dd368d4ea4e0223a01e1188d0f1b382ef 100644
--- a/server/stream/messages.coffee
+++ b/server/stream/messages.coffee
@@ -37,10 +37,25 @@ Meteor.startup ->
 	if not RocketChat.settings.get 'Message_ShowEditedStatus'
 		fields = { 'editedAt': 0 }
 
-	RocketChat.models.Messages.on 'change', (type, args...) ->
-		records = RocketChat.models.Messages.getChangedRecords type, args[0], fields
-
-		for record in records
-			if record._hidden isnt true and not record.imported?
-				msgStream.emit '__my_messages__', record, {}
-				msgStream.emit record.rid, record
+	publishMessage = (type, record) ->
+		if record._hidden isnt true and not record.imported?
+			msgStream.emitWithoutBroadcast '__my_messages__', record, {}
+			msgStream.emitWithoutBroadcast record.rid, record
+
+	query =
+		collection: RocketChat.models.Messages.collectionName
+
+	RocketChat.models.Messages._db.on 'change', ({action, id, data, oplog}) =>
+		switch action
+			when 'insert'
+				data._id = id;
+				publishMessage 'inserted', data
+				break;
+
+			when 'update:record'
+				publishMessage 'updated', data;
+				break;
+
+			when 'update:diff'
+				publishMessage 'updated', RocketChat.models.Messages.findOne({_id: id})
+				break;
diff --git a/server/stream/streamBroadcast.coffee b/server/stream/streamBroadcast.coffee
index 4ac497ea5826020d30ccbd619f0ea88f9c222159..1afaa9f1b1e993e0285486f0b2dafd86b811f9ca 100644
--- a/server/stream/streamBroadcast.coffee
+++ b/server/stream/streamBroadcast.coffee
@@ -33,7 +33,7 @@ startMatrixBroadcast = ->
 				logger.auth.info "prevent self connect", instance
 				return
 
-			if record.extraInformation.host is process.env.INSTANCE_IP
+			if record.extraInformation.host is process.env.INSTANCE_IP and RocketChat.isDocker() is false
 				instance = "localhost:#{record.extraInformation.port}"
 
 			if connections[instance]?.instanceRecord?
@@ -53,7 +53,7 @@ startMatrixBroadcast = ->
 		removed: (record) ->
 			instance = "#{record.extraInformation.host}:#{record.extraInformation.port}"
 
-			if record.extraInformation.host is process.env.INSTANCE_IP
+			if record.extraInformation.host is process.env.INSTANCE_IP and RocketChat.isDocker() is false
 				instance = "localhost:#{record.extraInformation.port}"
 
 			if connections[instance]? and not InstanceStatus.getCollection().findOne({'extraInformation.host': record.extraInformation.host, 'extraInformation.port': record.extraInformation.port})?
@@ -61,32 +61,32 @@ startMatrixBroadcast = ->
 				connections[instance].disconnect()
 				delete connections[instance]
 
-	Meteor.methods
-		broadcastAuth: (remoteId, selfId) ->
-			check selfId, String
-			check remoteId, String
+Meteor.methods
+	broadcastAuth: (remoteId, selfId) ->
+		check selfId, String
+		check remoteId, String
 
-			@unblock()
-			if selfId is InstanceStatus.id() and remoteId isnt InstanceStatus.id() and InstanceStatus.getCollection().findOne({_id: remoteId})?
-				@connection.broadcastAuth = true
+		@unblock()
+		if selfId is InstanceStatus.id() and remoteId isnt InstanceStatus.id() and InstanceStatus.getCollection().findOne({_id: remoteId})?
+			@connection.broadcastAuth = true
 
-			return @connection.broadcastAuth is true
+		return @connection.broadcastAuth is true
 
-		stream: (streamName, eventName, args) ->
-			# Prevent call from self and client
-			if not @connection?
-				return 'self-not-authorized'
+	stream: (streamName, eventName, args) ->
+		# Prevent call from self and client
+		if not @connection?
+			return 'self-not-authorized'
 
-			# Prevent call from unauthrorized connections
-			if @connection.broadcastAuth isnt true
-				return 'not-authorized'
+		# Prevent call from unauthrorized connections
+		if @connection.broadcastAuth isnt true
+			return 'not-authorized'
 
-			if not Meteor.StreamerCentral.instances[streamName]?
-				return 'stream-not-exists'
+		if not Meteor.StreamerCentral.instances[streamName]?
+			return 'stream-not-exists'
 
-			Meteor.StreamerCentral.instances[streamName]._emit(eventName, args)
+		Meteor.StreamerCentral.instances[streamName]._emit(eventName, args)
 
-			return undefined
+		return undefined
 
 startStreamCastBroadcast = (value) ->
 	instance = 'StreamCast'
diff --git a/tests/chimp-config.js b/tests/chimp-config.js
index 56b10394416a73a07d4c34f53c2e8f47bd6b2196..93821020e4db8be1b2b6944e4bb06fe744d6de16 100644
--- a/tests/chimp-config.js
+++ b/tests/chimp-config.js
@@ -1,138 +1,153 @@
+// import path from 'path';
+// import {isCI} from '../lib/ci';
+
 module.exports = {
-	// - - - - CHIMP - - - -
-	watch: false,
-	watchTags: '@watch,@focus',
-	domainSteps: null,
-	e2eSteps: null,
-	fullDomain: false,
-	domainOnly: false,
-	e2eTags: '@e2e',
-	watchWithPolling: false,
-	server: false,
-	serverPort: 8060,
-	serverHost: 'localhost',
-	sync: true,
-	offline: false,
-	showXolvioMessages: true,
+// 	// - - - - CHIMP - - - -
+// 	watch: false,
+// 	watchTags: '@watch,@focus',
+// 	domainSteps: null,
+// 	e2eSteps: null,
+// 	fullDomain: false,
+// 	domainOnly: false,
+// 	e2eTags: '@e2e',
+// 	watchWithPolling: false,
+// 	server: false,
+// 	serverPort: 8060,
+// 	serverHost: 'localhost',
+// 	sync: true,
+// 	offline: false,
+// 	showXolvioMessages: true,
 
-	// - - - - CUCUMBER - - - -
-	// path: './features',
-	format: 'pretty',
-	tags: '~@ignore',
-	singleSnippetPerFile: true,
-	recommendedFilenameSeparator: '_',
-	chai: false,
-	// screenshotsOnError: isCI(),
-	screenshotsPath: '.screenshots',
-	captureAllStepScreenshots: false,
-	saveScreenshotsToDisk: true,
-	// Note: With a large viewport size and captureAllStepScreenshots enabled,
-	// you may run out of memory. Use browser.setViewportSize to make the
-	// viewport size smaller.
-	saveScreenshotsToReport: false,
-	jsonOutput: null,
-	// compiler: 'js:' + path.resolve(__dirname, '../lib/babel-register.js'),
-	conditionOutput: true,
+// 	// - - - - CUCUMBER - - - -
+	path: 'tests/steps',
+// 	format: 'pretty',
+// 	tags: '~@ignore',
+// 	singleSnippetPerFile: true,
+// 	recommendedFilenameSeparator: '_',
+// 	chai: false,
+// 	screenshotsOnError: isCI(),
+// 	screenshotsPath: '.screenshots',
+// 	captureAllStepScreenshots: false,
+// 	saveScreenshotsToDisk: true,
+// 	// Note: With a large viewport size and captureAllStepScreenshots enabled,
+// 	// you may run out of memory. Use browser.setViewportSize to make the
+// 	// viewport size smaller.
+// 	saveScreenshotsToReport: false,
+// 	jsonOutput: null,
+// 	compiler: 'js:' + path.resolve(__dirname, '../lib/babel-register.js'),
+// 	conditionOutput: true,
 
-	// - - - - SELENIUM  - - - -
-	browser: 'chrome',
-	platform: 'ANY',
-	name: '',
-	user: '',
-	key: '',
-	port: null,
-	host: null,
-	// deviceName: null,
+// 	// - - - - SELENIUM  - - - -
+// 	browser: null,
+// 	platform: 'ANY',
+// 	name: '',
+// 	user: '',
+// 	key: '',
+// 	port: null,
+// 	host: null,
+// 	// deviceName: null,
 
-	// - - - - WEBDRIVER-IO  - - - -
-	webdriverio: {
-		desiredCapabilities: {},
-		logLevel: 'silent',
-		// logOutput: null,
-		host: '127.0.0.1',
-		port: 4444,
-		path: '/wd/hub',
-		baseUrl: null,
-		coloredLogs: true,
-		screenshotPath: null,
-		waitforTimeout: 500,
-		waitforInterval: 250
-	},
+// 	// - - - - WEBDRIVER-IO  - - - -
+// 	webdriverio: {
+// 		desiredCapabilities: {},
+// 		logLevel: 'silent',
+// 		// logOutput: null,
+// 		host: '127.0.0.1',
+// 		port: 4444,
+// 		path: '/wd/hub',
+// 		baseUrl: null,
+// 		coloredLogs: true,
+// 		screenshotPath: null,
+// 		waitforTimeout: 500,
+// 		waitforInterval: 250,
+// 	},
 
-	// - - - - SELENIUM-STANDALONE
-	seleniumStandaloneOptions: {
-		// check for more recent versions of selenium here:
-		// http://selenium-release.storage.googleapis.com/index.html
-		version: '2.53.1',
-		baseURL: 'https://selenium-release.storage.googleapis.com',
-		drivers: {
-			chrome: {
-				// check for more recent versions of chrome driver here:
-				// http://chromedriver.storage.googleapis.com/index.html
-				version: '2.22',
-				arch: process.arch,
-				baseURL: 'https://chromedriver.storage.googleapis.com'
-			},
-			ie: {
-				// check for more recent versions of internet explorer driver here:
-				// http://selenium-release.storage.googleapis.com/index.html
-				version: '2.50.0',
-				arch: 'ia32',
-				baseURL: 'https://selenium-release.storage.googleapis.com'
-			}
-		}
-	},
+// 	// - - - - SELENIUM-STANDALONE
+// 	seleniumStandaloneOptions: {
+// 		// check for more recent versions of selenium here:
+// 		// http://selenium-release.storage.googleapis.com/index.html
+// 		version: '2.53.1',
+// 		baseURL: 'https://selenium-release.storage.googleapis.com',
+// 		drivers: {
+// 			chrome: {
+// 				// check for more recent versions of chrome driver here:
+// 				// http://chromedriver.storage.googleapis.com/index.html
+// 				version: '2.25',
+// 				arch: process.arch,
+// 				baseURL: 'https://chromedriver.storage.googleapis.com'
+// 			},
+// 			ie: {
+// 				// check for more recent versions of internet explorer driver here:
+// 				// http://selenium-release.storage.googleapis.com/index.html
+// 				version: '2.50.0',
+// 				arch: 'ia32',
+// 				baseURL: 'https://selenium-release.storage.googleapis.com'
+// 			},
+// 			firefox: {
+// 				// check for more recent versions of gecko  driver here:
+// 				// https://github.com/mozilla/geckodriver/releases
+// 				version: '0.11.1',
+// 				arch: process.arch,
+// 				baseURL: 'https://github.com/mozilla/geckodriver/releases/download'
+// 			}
+// 		}
+// 	},
 
-	// - - - - SESSION-MANAGER  - - - -
-	noSessionReuse: false,
+// 	// - - - - SESSION-MANAGER  - - - -
+// 	noSessionReuse: false,
 
-	// - - - - SIMIAN  - - - -
-	simianResultEndPoint: 'api.simian.io/v1.0/result',
-	simianAccessToken: false,
-	simianResultBranch: null,
-	simianRepositoryId: null,
+// 	// - - - - SIMIAN  - - - -
+// 	simianResultEndPoint: 'api.simian.io/v1.0/result',
+// 	simianAccessToken: false,
+// 	simianResultBranch: null,
+// 	simianRepositoryId: null,
 
-	// - - - - MOCHA  - - - -
+// 	// - - - - MOCHA  - - - -
 	mocha: true,
-	// mochaTags and mochaGrep only work when watch is false (disabled)
-	mochaTags: '',
-	mochaGrep: null,
-	path: './tests/steps',
-	mochaTimeout: 60000,
-	mochaReporter: 'spec',
-	mochaSlow: 0,
-
-	// - - - - JASMINE  - - - -
-	jasmine: false,
-	jasmineConfig: {
-		specDir: '.',
-		specFiles: [
-			'**/*@(_spec|-spec|Spec).@(js|jsx)'
-		],
-		helpers: [
-			'support/**/*.@(js|jsx)'
-		],
-		stopSpecOnExpectationFailure: true,
-		random: false
-	},
-	jasmineReporterConfig: {
-		// This options are passed to jasmine.configureDefaultReporter(...)
-		// See: http://jasmine.github.io/2.4/node.html#section-Reporters
+	mochaCommandLineOptions: ['--color'],
+	mochaConfig: {
+		// tags and grep only work when watch mode is false
+		tags: '',
+		grep: null,
+		timeout: 60000,
+		reporter: 'spec',
+		slow: 100,
+		bail: false // bail after first test failure
 	},
 
-	// - - - - METEOR  - - - -
-	ddp: false,
+// 	// - - - - JASMINE  - - - -
+// 	jasmine: false,
+// 	jasmineConfig: {
+// 		specDir: '.',
+// 		specFiles: [
+// 			'**/*@(_spec|-spec|Spec).@(js|jsx)',
+// 		],
+// 		helpers: [
+// 			'support/**/*.@(js|jsx)',
+// 		],
+// 		stopSpecOnExpectationFailure: false,
+// 		random: false,
+// 	},
+// 	jasmineReporterConfig: {
+// 		// This options are passed to jasmine.configureDefaultReporter(...)
+// 		// See: http://jasmine.github.io/2.4/node.html#section-Reporters
+// 	},
+
+// 	// - - - - METEOR  - - - -
+	ddp: 'http://localhost:3000'
+// 	serverExecuteTimeout: 10000,
 
-	// - - - - PHANTOM  - - - -
-	phantom_w: 1280,
-	phantom_h: 1024,
+// 	// - - - - PHANTOM  - - - -
+// 	phantom_w: 1280,
+// 	phantom_h: 1024,
+// 	phantom_ignoreSSLErrors: false,
 
-	// - - - - DEBUGGING  - - - -
-	log: 'info',
-	debug: false,
-	seleniumDebug: null,
-	debugCucumber: null,
-	debugBrkCucumber: null,
-	debugMocha: null,
-	debugBrkMocha: null
+// 	// - - - - DEBUGGING  - - - -
+// 	log: 'info',
+// 	debug: false,
+// 	seleniumDebug: null,
+// 	debugCucumber: null,
+// 	debugBrkCucumber: null,
+// 	debugMocha: null,
+// 	debugBrkMocha: null,
 };
diff --git a/tests/test-data/channel.js b/tests/data/channel.js
similarity index 100%
rename from tests/test-data/channel.js
rename to tests/data/channel.js
diff --git a/tests/data/checks.js b/tests/data/checks.js
new file mode 100644
index 0000000000000000000000000000000000000000..f29b68081f1f20200fd59a10e7f65399bd09130d
--- /dev/null
+++ b/tests/data/checks.js
@@ -0,0 +1,84 @@
+import loginPage from '../pageobjects/login.page';
+import mainContent from '../pageobjects/main-content.page';
+import sideNav from '../pageobjects/side-nav.page';
+
+export var publicChannelCreated = false;
+export var privateChannelCreated = false;
+export var directMessageCreated = false;
+
+export function setPublicChannelCreated(status) {
+	publicChannelCreated = status;
+}
+
+export function setPrivateChannelCreated(status) {
+	privateChannelCreated = status;
+}
+
+export function setDirectMessageCreated(status) {
+	directMessageCreated = status;
+}
+
+export function checkIfUserIsValid(username, email, password) {
+	if (!sideNav.accountBoxUserName.isVisible()) {
+		//if the user is not logged in.
+		console.log('	User not logged. logging in...');
+		loginPage.open();
+		loginPage.login({email, password});
+		try {
+			mainContent.mainContent.waitForExist(5000);
+		} catch (e) {
+			//if the user dont exist.
+			console.log('	User dont exist. Creating user...');
+			loginPage.gotToRegister();
+			loginPage.registerNewUser({username, email, password});
+			browser.waitForExist('form#login-card input#username', 5000);
+			browser.click('.submit > button');
+			mainContent.mainContent.waitForExist(5000);
+		}
+	} else if (sideNav.accountBoxUserName.getText() !== username) {
+		//if the logged user is not the right one
+		console.log('	Wrong logged user. Changing user...');
+		sideNav.accountBoxUserName.waitForVisible(5000);
+		sideNav.accountBoxUserName.click();
+		sideNav.logout.waitForVisible(5000);
+		sideNav.logout.click();
+
+		loginPage.open();
+		loginPage.login({email, password});
+		mainContent.mainContent.waitForExist(5000);
+	} else {
+		console.log('	User already logged');
+	}
+}
+
+export function checkIfUserIsAdmin(username, email, password) {
+	if (!sideNav.accountBoxUserName.isVisible()) {
+		//if the user is not logged in.
+		console.log('	User not logged. logging in...');
+		loginPage.open();
+		loginPage.login({email, password});
+		try {
+			mainContent.mainContent.waitForExist(5000);
+		} catch (e) {
+			//if the user dont exist.
+			console.log('	Admin User dont exist. Creating user...');
+			loginPage.gotToRegister();
+			loginPage.registerNewUser({username, email, password});
+			browser.waitForExist('form#login-card input#username', 5000);
+			browser.click('.submit > button');
+			mainContent.mainContent.waitForExist(5000);
+		}
+	} else if (sideNav.accountBoxUserName.getText() !== username) {
+		//if the logged user is not the right one
+		console.log('	Wrong logged user. Changing user...');
+		sideNav.accountBoxUserName.waitForVisible(5000);
+		sideNav.accountBoxUserName.click();
+		sideNav.logout.waitForVisible(5000);
+		sideNav.logout.click();
+
+		loginPage.open();
+		loginPage.login({email, password});
+	} else {
+		console.log('	User already logged');
+	}
+}
diff --git a/tests/test-data/interactions.js b/tests/data/interactions.js
similarity index 100%
rename from tests/test-data/interactions.js
rename to tests/data/interactions.js
diff --git a/tests/data/user.js b/tests/data/user.js
new file mode 100644
index 0000000000000000000000000000000000000000..3693d2244fc72afbb00187ede741c0149efa5960
--- /dev/null
+++ b/tests/data/user.js
@@ -0,0 +1,7 @@
+export const username = 'user.test.'+Date.now();
+export const email = username+'@rocket.chat';
+export const password = 'rocket.chat';
+
+export const adminUsername = 'rocketchat.internal.admin.test';
+export const adminEmail = adminUsername+'@rocket.chat';
+export const adminPassword = adminUsername;
diff --git a/tests/pageobjects/administration.page.js b/tests/pageobjects/administration.page.js
new file mode 100644
index 0000000000000000000000000000000000000000..2e337b314fa5bb496e447af3a9733af438682ff3
--- /dev/null
+++ b/tests/pageobjects/administration.page.js
@@ -0,0 +1,120 @@
+import Page from './Page';
+
+class Administration extends Page {
+	get flexNav() { return browser.element('.flex-nav'); }
+	get flexNavContent() { return browser.element('.flex-nav .content'); }
+	get layoutLink() { return browser.element('.flex-nav .content [href="/admin/Layout"]'); }
+	get infoLink() { return browser.element('.flex-nav .content [href="/admin/info"]'); }
+	get roomsLink() { return browser.element('.flex-nav .content [href="/admin/rooms"]'); }
+	get usersLink() { return browser.element('.flex-nav .content [href="/admin/users"]'); }
+	get generalLink() { return browser.element('.flex-nav .content [href="/admin/General"]'); }
+	get permissionsLink() { return browser.element('.flex-nav .content [href="/admin/permissions"]'); }
+	get customScriptBtn() { return browser.element('.section:nth-of-type(6) .collapse'); }
+	get customScriptLoggedOutTextArea() { return browser.element('.section:nth-of-type(6) .CodeMirror-scroll'); }
+	get customScriptLoggedInTextArea() { return browser.element('.CodeMirror.cm-s-default:nth-of-type(2)'); }
+	get infoRocketChatTableTitle() { return browser.element('.content h3'); }
+	get infoRocketChatTable() { return browser.element('.content .statistics-table'); }
+	get infoCommitTableTitle() { return browser.element('.content h3:nth-of-type(2)'); }
+	get infoCommitTable() { return browser.element('.content .statistics-table:nth-of-type(2)'); }
+	get infoRuntimeTableTitle() { return browser.element('.content h3:nth-of-type(3)'); }
+	get infoRuntimeTable() { return browser.element('.content .statistics-table:nth-of-type(3)'); }
+	get infoBuildTableTitle() { return browser.element('.content h3:nth-of-type(4)'); }
+	get infoBuildTable() { return browser.element('.content .statistics-table:nth-of-type(4)'); }
+	get infoUsageTableTitle() { return browser.element('.content h3:nth-of-type(5)'); }
+	get infoUsageTable() { return browser.element('.content .statistics-table:nth-of-type(5)'); }
+	get roomsSearchForm() { return browser.element('.content .search'); }
+	get roomsFilter() { return browser.element('#rooms-filter'); }
+	get roomsChannelsCheckbox() { return browser.element('label:nth-of-type(1) input[name="room-type"]'); }
+	get roomsDirectCheckbox() { return browser.element('label:nth-of-type(2) input[name="room-type"]'); }
+	get roomsPrivateCheckbox() { return browser.element('label:nth-of-type(3) input[name="room-type"]'); }
+	get roomsGeneralChannel() { return browser.element('td=general'); }
+	get usersRocketCat() { return browser.element('td=Rocket.Cat'); }
+	get usersInternalAdmin() { return browser.element('td=rocketchat.internal.admin.test'); }
+	get usersFilter() { return browser.element('#users-filter'); }
+	get rolesNewRolesButton() { return browser.element('.button.new-role'); }
+	get rolesPermissionGrid() { return browser.element('.permission-grid'); }
+	get rolesAdmin() { return browser.element('[title="Admin"]'); }
+	get rolesModerator() { return browser.element('[title="Moderator"]'); }
+	get rolesOwner() { return browser.element('[title="Owner"]'); }
+	get rolesReturnLink() { return browser.element('[href="/admin/permissions"]'); }
+	get rolesNewRoleName() { return browser.element('[name="name"]'); }
+	get rolesNewRoleDesc() { return browser.element('[name="description"]'); }
+	get rolesNewRoleScope() { return browser.element('[name="scope"]'); }
+	get rolesAddBtn() { return browser.element('button.add'); }
+	get rolesRoomsSearchForm() { return browser.element('.search [name="room"]'); }
+
+	//permissions grids checkboxes
+
+	get rolesUserCreateC() { return browser.element('[name="perm[user][create-c]"]'); }
+	get rolesUserCreateP() { return browser.element('[name="perm[user][create-p]"]'); }
+	get rolesUserCreateD() { return browser.element('[name="perm[user][create-d]"]'); }
+	get rolesUserMentionAll() { return browser.element('[name="perm[user][mention-all]"]'); }
+	get rolesUserPreviewC() { return browser.element('[name="perm[user][preview-c-room]"]'); }
+	get rolesUserViewC() { return browser.element('[name="perm[user][view-c-room]"]'); }
+	get rolesUserViewD() { return browser.element('[name="perm[user][view-d-room]"]'); }
+	get rolesUserViewP() { return browser.element('[name="perm[user][view-p-room]"]'); }
+	get rolesUserHistory() { return browser.element('[name="perm[user][view-history]"]'); }
+	get rolesOwnerDeleteMessage() { return browser.element('[name="perm[owner][delete-message]"]'); }
+	get rolesOwnerEditMessage() { return browser.element('[name="perm[owner][edit-message]"]'); }
+
+
+	get emojiFilter() { return browser.element('#emoji-filter'); }
+
+	//settings
+	get generalButtonExpandIframe() { return browser.element('.section:nth-of-type(2) .button.expand'); }
+	get generalButtonExpandNotifications() { return browser.element('.section:nth-of-type(3) .button.expand'); }
+	get generalButtonExpandRest() { return browser.element('.section:nth-of-type(4) .button.expand'); }
+	get generalButtonExpandReporting() { return browser.element('.section:nth-of-type(5) .button.expand'); }
+	get generalButtonExpandStreamCast() { return browser.element('.section:nth-of-type(6) .button.expand'); }
+	get generalButtonExpandTranslations() { return browser.element('.section:nth-of-type(7) .button.expand'); }
+	get generalButtonExpandUTF8() { return browser.element('.section:nth-of-type(8) .button.expand'); }
+
+	get generalSiteUrl() { return browser.element('[name="Site_Url"]'); }
+	get generalSiteUrlReset() { return browser.element('.reset-setting[data-setting="Site_Url"]'); }
+	get generalSiteName() { return browser.element('[name="Site_Name"]'); }
+	get generalSiteNameReset() { return browser.element('.reset-setting[data-setting="Site_Name"]'); }
+	get generalLanguage() { return browser.element('[name="Language"]'); }
+	get generalLanguagePtOption() { return browser.element('[value="pt"]'); }
+	get generalLanguageReset() { return browser.element('.reset-setting[data-setting="Language"]'); }
+	get generalSelfSignedCertsTrue() { return browser.element('label:nth-of-type(1) [name="Allow_Invalid_SelfSigned_Certs"]'); }
+	get generalSelfSignedCertsFalse() { return browser.element('label:nth-of-type(2) [name="Allow_Invalid_SelfSigned_Certs"]'); }
+	get generalSelfSignedCertsReset() { return browser.element('.reset-setting[data-setting="Allow_Invalid_SelfSigned_Certs"]'); }
+	get generalFavoriteRoomTrue() { return browser.element('label:nth-of-type(1) [name="Favorite_Rooms"]'); }
+	get generalFavoriteRoomFalse() { return browser.element('label:nth-of-type(2) [name="Favorite_Rooms"]'); }
+	get generalFavoriteRoomReset() { return browser.element('.reset-setting[data-setting="Favorite_Rooms"]'); }
+	get generalCdnPrefix() { return browser.element('[name="CDN_PREFIX"]'); }
+	get generalCdnPrefixReset() { return browser.element('.reset-setting[data-setting="CDN_PREFIX"]'); }
+	get generalForceSSLTrue() { return browser.element('label:nth-of-type(1) [name="Force_SSL"]'); }
+	get generalForceSSLFalse() { return browser.element('label:nth-of-type(2) [name="Force_SSL"]'); }
+	get generalForceSSLReset() { return browser.element('.reset-setting[data-setting="Force_SSL"]'); }
+	get generalGoogleTagId() { return browser.element('[name="GoogleTagManager_id"]'); }
+	get generalGoogleTagIdReset() { return browser.element('.reset-setting[data-setting="GoogleTagManager_id"]'); }
+	get generalBugsnagKey() { return browser.element('[name="Bugsnag_api_key"]'); }
+	get generalBugsnagKeyReset() { return browser.element('.reset-setting[data-setting="Bugsnag_api_key"]'); }
+	get generalIframeSendTrue() { return browser.element('label:nth-of-type(1) [name="Iframe_Integration_send_enable"]'); }
+	get generalIframeSendFalse() { return browser.element('label:nth-of-type(2) [name="Iframe_Integration_send_enable"]'); }
+	get generalIframeSendReset() { return browser.element('.reset-setting[data-setting="Iframe_Integration_send_enable"]'); }
+	get generalIframeSendTargetOrigin() { return browser.element('[name="Iframe_Integration_send_target_origin"]'); }
+	get generalIframeSendTargetOriginReset() { return browser.element('.reset-setting[data-setting="Iframe_Integration_send_target_origin"]'); }
+	get generalIframeRecieveTrue() { return browser.element('label:nth-of-type(1) [name="Iframe_Integration_receive_enable"]'); }
+	get generalIframeRecieveFalse() { return browser.element('label:nth-of-type(2) [name="Iframe_Integration_receive_enable"]'); }
+	get generalIframeRecieveFalseReset() { return browser.element('.reset-setting[data-setting="Iframe_Integration_receive_enable"]'); }
+	get generalIframeRecieveOrigin() { return browser.element('[name="Iframe_Integration_receive_origin"]'); }
+	get generalIframeRecieveOriginReset() { return browser.element('.reset-setting[data-setting="Iframe_Integration_receive_origin"]'); }
+	get generalNotificationDuration() { return browser.element('[name="Desktop_Notifications_Duration"]'); }
+	get generalNotificationDurationReset() { return browser.element('.reset-setting[data-setting="Desktop_Notifications_Duration"]'); }
+	get generalRestApiUserLimit() { return browser.element('[name="API_User_Limit"]'); }
+	get generalRestApiUserLimitReset() { return browser.element('.reset-setting[data-setting="API_User_Limit"]'); }
+	get generalReportingTrue() { return browser.element('label:nth-of-type(1) [name="Statistics_reporting"]'); }
+	get generalReportingFalse() { return browser.element('label:nth-of-type(2) [name="Statistics_reporting"]'); }
+	get generalReportingReset() { return browser.element('.reset-setting[data-setting="Statistics_reporting"]'); }
+	get generalStreamCastAdress() { return browser.element('[name="Stream_Cast_Address"]'); }
+	get generalStreamCastAdressReset() { return browser.element('.reset-setting[data-setting="Stream_Cast_Address"]'); }
+	get generalUTF8Regex() { return browser.element('[name="UTF8_Names_Validation"]'); }
+	get generalUTF8RegexReset() { return browser.element('.reset-setting[data-setting="UTF8_Names_Validation"]'); }
+	get generalUTF8NamesSlugTrue() { return browser.element('label:nth-of-type(1) [name="UTF8_Names_Slugify"]'); }
+	get generalUTF8NamesSlugFalse() { return browser.element('label:nth-of-type(2) [name="UTF8_Names_Slugify"]'); }
+	get generalUTF8NamesSlugReset() { return browser.element('.reset-setting[data-setting="UTF8_Names_Slugify"]'); }
+}
+
+module.exports = new Administration();
diff --git a/tests/pageobjects/flex-tab.page.js b/tests/pageobjects/flex-tab.page.js
index c31a12a0ecadba1670d7bbbda35c5b9d7b06da12..4ddb165e3f6a6b45aa9a347db96112ca6b9774f5 100644
--- a/tests/pageobjects/flex-tab.page.js
+++ b/tests/pageobjects/flex-tab.page.js
@@ -67,14 +67,36 @@ class FlexTab extends Page {
 	get sweetAlertOverlay() { return browser.element('.sweet-overlay'); }
 	get toastAlert() { return browser.element('.toast'); }
 
+	//admin view flextab items
+	get usersSendInvitationTab() { return browser.element('[aria-label="Invite Users"] .icon-paper-plane'); }
+	get usersAddUserTab() { return browser.element('[aria-label="Add User"] .icon-plus'); }
+	get usersSendInvitationTextArea() { return browser.element('#inviteEmails'); }
+	get usersButtonCancel() { return browser.element('button.cancel'); }
+	get usersSendInvitationSend() { return browser.element('button.send'); }
+	get usersButtonSave() { return browser.element('button.save'); }
+	get usersAddUserName() { return browser.element('#name'); }
+	get usersAddUserUsername() { return browser.element('#username'); }
+	get usersAddUserEmail() { return browser.element('#email'); }
+	get usersAddUserPassword() { return browser.element('#password'); }
+	get usersAddUserRole() { return browser.element('#role'); }
+	get usersAddUserVerifiedCheckbox() { return browser.element('#verified'); }
+	get usersAddUserChangePasswordCheckbox() { return browser.element('#changePassword'); }
+	get usersAddUserDefaultChannelCheckbox() { return browser.element('#joinDefaultChannels'); }
+	get usersAddUserWelcomeEmailCheckbox() { return browser.element('#sendWelcomeEmail'); }
+	get usersAddUserRandomPassword() { return browser.element('#randomPassword'); }
+	get emojiNewAliases() { return browser.element('#aliases'); }
+	get emojiNewImageInput() { return browser.element('#image'); }
+
+	getUserEl(username) { return browser.element(`.flex-tab button[title="${username}"] > p`); }
+
 	confirmPopup() {
+		this.confirmBtn.waitForVisible(5000);
 		this.confirmBtn.click();
 		this.sweetAlertOverlay.waitForVisible(5000, true);
 	}
 
 	dismissToast() {
 		this.toastAlert.click();
-		browser.pause(4000);
 	}
 
 	archiveChannel() {
@@ -93,38 +115,43 @@ class FlexTab extends Page {
 	}
 
 	removePeopleFromChannel(user) {
-		const userEl = browser.element('.flex-tab button[title="'+user+'"]');
+		const userEl = this.getUserEl(user);
 		userEl.waitForVisible();
 		userEl.click();
-		browser.pause(300);
 		this.removeUserBtn.click();
 	}
 
 	setUserOwner(user) {
-		const userEl = browser.element('.flex-tab button[title="'+user+'"]');
+		const userEl = this.getUserEl(user);
 		userEl.waitForVisible();
 		userEl.click();
-		browser.pause(300);
 		this.setOwnerBtn.waitForVisible(5000);
 		this.setOwnerBtn.click();
 		this.viewAllBtn.click();
+		browser.pause(100);
 	}
 
 	setUserModerator(user) {
-		const userEl = browser.element('.flex-tab button[title="'+user+'"]');
+		const userEl = this.getUserEl(user);
 		userEl.waitForVisible();
 		userEl.click();
-		browser.pause(300);
+		this.setModeratorBtn.waitForVisible();
 		this.setModeratorBtn.click();
 		this.viewAllBtn.click();
+		browser.pause(100);
 	}
 
 	muteUser(user) {
-		const userEl = browser.element('.flex-tab button[title="'+user+'"]');
-		userEl.waitForVisible();
-		userEl.click();
-		browser.pause(300);
-		this.muteUserBtn.click();
+		const userEl = this.getUserEl(user);
+		if (this.showAll.isVisible()) {
+			this.muteUserBtn.waitForVisible(5000);
+			this.muteUserBtn.click();
+		} else {
+			userEl.waitForVisible(5000);
+			userEl.click();
+			this.muteUserBtn.waitForVisible(5000);
+			this.muteUserBtn.click();
+		}
 	}
 }
 
diff --git a/tests/pageobjects/login.page.js b/tests/pageobjects/login.page.js
index 79280a9ca9eeb39ea337e16f8773ceb0acb92f54..c5790391f55b749b0a05d491bbd68319c879c39f 100644
--- a/tests/pageobjects/login.page.js
+++ b/tests/pageobjects/login.page.js
@@ -39,6 +39,15 @@ class LoginPage extends Page {
 		this.submit();
 	}
 
+	registerNewAdmin({adminUsername, adminEmail, adminPassword}) {
+		this.nameField.setValue(adminUsername);
+		this.emailField.setValue(adminEmail);
+		this.passwordField.setValue(adminPassword);
+		this.confirmPasswordField.setValue(adminPassword);
+
+		this.submit();
+	}
+
 	login({email, password}) {
 		this.emailOrUsernameField.setValue(email);
 		this.passwordField.setValue(password);
diff --git a/tests/pageobjects/main-content.page.js b/tests/pageobjects/main-content.page.js
index 3eb80336d21a59fd456ef66bfcd0c84090e251b7..5433da362a50ec93c9beb2bffd58732571fb7cfa 100644
--- a/tests/pageobjects/main-content.page.js
+++ b/tests/pageobjects/main-content.page.js
@@ -14,11 +14,17 @@ class MainContent extends Page {
 	get emojiBtn() { return browser.element('.inner-left-toolbar .emoji-picker-icon'); }
 	get channelTitle() { return browser.element('.room-title'); }
 	get popupFileConfirmBtn() { return browser.element('.sa-confirm-button-container .confirm'); }
+	get popupFileName() { return browser.element('#file-name'); }
+	get popupFileDescription() { return browser.element('#file-description'); }
+	get popupFileConfirmBtn() { return browser.element('.sa-confirm-button-container .confirm'); }
 	get popupFilePreview() { return browser.element('.upload-preview-file'); }
 	get popupFileTitle() { return browser.element('.upload-preview-title'); }
 	get popupFileCancelBtn() { return browser.element('.sa-button-container .cancel'); }
 	get lastMessageUser() { return browser.element('.message:last-child .user-card-message:nth-of-type(2)'); }
 	get lastMessage() { return browser.element('.message:last-child .body'); }
+	get lastMessageImg() { return browser.element('.message:last-child .body .inline-image'); }
+	get lastMessageDesc() { return browser.element('.message:last-child .body .attachment-description p'); }
+	get lastMessageRoleAdded() { return browser.element('.message:last-child.subscription-role-added .body'); }
 	get beforeLastMessage() { return browser.element('.message:nth-last-child(2) .body'); }
 	get lastMessageUserTag() { return browser.element('.message:last-child .role-tag'); }
 	get lastMessageImg() { return browser.element('.message:last-child .attachment-image img'); }
@@ -57,9 +63,7 @@ class MainContent extends Page {
 	get messagePopUpTitle() { return browser.element('.message-popup-title'); }
 	get messagePopUpItems() { return browser.element('.message-popup-items'); }
 	get messagePopUpFirstItem() { return browser.element('.popup-item.selected'); }
-	get settingLanguageSelect() { return browser.element('#language '); }
-	get settingLanguageEnglish() { return browser.element('[value="en"]'); }
-	get settingSaveBtn() { return browser.element('.button.save'); }
+	get mentionAllPopUp() { return browser.element('.popup-item[data-id="all"]'); }
 
 	sendMessage(text) {
 		this.setTextToInput(text);
@@ -83,20 +87,18 @@ class MainContent extends Page {
 	fileUpload(filePath) {
 		this.sendMessage('Prepare for the file');
 		this.fileAttachment.chooseFile(filePath);
-		browser.pause(1000);
 	}
 
 	openMessageActionMenu() {
 		this.lastMessage.moveToObject();
+		this.messageOptionsBtn.waitForVisible(5000);
 		this.messageOptionsBtn.click();
 		this.messageActionMenu.waitForVisible(5000);
 	}
 
 	setLanguageToEnglish() {
 		this.settingLanguageSelect.click();
-		browser.pause(500);
 		this.settingLanguageEnglish.click();
-		browser.pause(300);
 		this.settingSaveBtn.click();
 	}
 
@@ -106,13 +108,11 @@ class MainContent extends Page {
 			case 'edit':
 				this.messageEdit.waitForVisible(5000);
 				this.messageEdit.click();
-				browser.pause(1000);
 				this.messageInput.addValue('this message was edited');
 				break;
 			case 'reply':
 				this.messageReply.waitForVisible(5000);
 				this.messageReply.click();
-				browser.pause(1000);
 				this.messageInput.addValue(' this is a reply message');
 				break;
 			case 'delete':
@@ -130,7 +130,6 @@ class MainContent extends Page {
 			case 'quote':
 				this.messageQuote.waitForVisible(5000);
 				this.messageQuote.click();
-				browser.pause(1000);
 				this.messageInput.addValue(' this is a quote message');
 				break;
 			case 'star':
@@ -157,4 +156,4 @@ class MainContent extends Page {
 	}
 }
 
-module.exports = new MainContent();
\ No newline at end of file
+module.exports = new MainContent();
diff --git a/tests/pageobjects/side-nav.page.js b/tests/pageobjects/side-nav.page.js
index c1fadddc73b907f51cf3459799a874ee1d700f8c..bc0ccb47a7ac8f70480be755002690cf59d1eb74 100644
--- a/tests/pageobjects/side-nav.page.js
+++ b/tests/pageobjects/side-nav.page.js
@@ -4,8 +4,8 @@ class SideNav extends Page {
 	get directMessageTarget() { return browser.element('.flex-nav input#who'); }
 	get saveDirectMessageBtn() { return browser.element('.save-direct-message'); }
 
-	get channelType() { return browser.element('#channel-type'); }
-	get channelReadOnly() { return browser.element('#channel-ro'); }
+	get channelType() { return browser.element('label[for="channel-type"]'); }
+	get channelReadOnly() { return browser.element('label[for="channel-ro"]'); }
 	get channelName() { return browser.element('#channel-name'); }
 	get saveChannelBtn() { return browser.element('.save-channel'); }
 
@@ -31,9 +31,9 @@ class SideNav extends Page {
 	get statusBusy() { return browser.element('.busy'); }
 	get statusOffline() { return browser.element('.offline'); }
 	get account() { return browser.element('#account'); }
+	get admin() { return browser.element('#admin'); }
 	get logout() { return browser.element('#logout'); }
 	get sideNavBar() { return browser.element('.side-nav '); }
-	get sideNavBtn() { return browser.element('.fixed-title .burger'); }
 
 	get preferences() { return browser.element('.account-link:nth-of-type(1)'); }
 	get profile() { return browser.element('.account-link:nth-of-type(2)'); }
@@ -42,7 +42,10 @@ class SideNav extends Page {
 
 	openChannel(channelName) {
 		browser.click('.rooms-list > .wrapper > ul [title="'+channelName+'"]');
-		this.messageInput.waitForExist();
+		this.messageInput.waitForExist(5000);
+		browser.waitUntil(function() {
+			return browser.getText('.room-title') === channelName;
+		}, 5000);
 	}
 
 	getChannelFromList(channelName) {
@@ -50,6 +53,7 @@ class SideNav extends Page {
 	}
 
 	createChannel(channelName, isPrivate, isReadOnly) {
+		this.newChannelBtn.waitForVisible(10000);
 		this.newChannelBtn.click();
 		this.channelType.waitForVisible(10000);
 		this.channelName.setValue(channelName);
@@ -59,8 +63,11 @@ class SideNav extends Page {
 		if (isReadOnly) {
 			this.channelReadOnly.click();
 		}
+		browser.pause(500);
 		this.saveChannelBtn.click();
+		browser.pause(500);
 		browser.waitForExist('[title="'+channelName+'"]', 1000);
+		this.channelType.waitForVisible(500, true);
 	}
 
 	addPeopleToChannel(user) {
@@ -79,13 +86,13 @@ class SideNav extends Page {
 	}
 
 	startDirectMessage(user) {
+		this.newDirectMessageBtn.waitForVisible(3000);
 		this.newDirectMessageBtn.click();
-		browser.pause(1000);
 		this.directMessageTarget.waitForVisible(3000);
 		this.directMessageTarget.setValue(user);
 		browser.waitForVisible('.-autocomplete-item', 3000);
-		browser.pause(500);
 		browser.click('.-autocomplete-item');
+		browser.pause(200);
 		this.saveDirectMessageBtn.click();
 		browser.waitForExist('[title="'+user+'"]');
 	}
diff --git a/tests/steps/0-login.js b/tests/steps/00-login.js
similarity index 69%
rename from tests/steps/0-login.js
rename to tests/steps/00-login.js
index 3c54c70c9df00bd91b40d956e735155e4d21b1c6..d61805039ee169921bf1486b9139c7b578e2ef1c 100644
--- a/tests/steps/0-login.js
+++ b/tests/steps/00-login.js
@@ -3,7 +3,7 @@
 import loginPage from '../pageobjects/login.page';
 
 describe('login', () => {
-	it('load page', () => {
+	before(()=>{
 		loginPage.open();
 	});
 
@@ -45,19 +45,23 @@ describe('login', () => {
 		});
 	});
 
-	describe('email / username', () => {
-		it('it should be required', () => {
+	describe('required fields', () => {
+		before(() => {
 			loginPage.submit();
-			loginPage.emailOrUsernameField.getAttribute('class').should.contain('error');
-			loginPage.emailOrUsernameInvalidText.getText().should.not.be.empty;
 		});
-	});
 
-	describe('password', () => {
-		it('it should be required', () => {
-			loginPage.submit();
-			loginPage.passwordField.getAttribute('class').should.contain('error');
-			loginPage.passwordInvalidText.getText().should.not.be.empty;
+		describe('email / username', () => {
+			it('should be required', () => {
+				loginPage.emailOrUsernameField.getAttribute('class').should.contain('error');
+				loginPage.emailOrUsernameInvalidText.getText().should.not.be.empty;
+			});
+		});
+
+		describe('password', () => {
+			it('should be required', () => {
+				loginPage.passwordField.getAttribute('class').should.contain('error');
+				loginPage.passwordInvalidText.getText().should.not.be.empty;
+			});
 		});
 	});
 });
diff --git a/tests/steps/1-register.js b/tests/steps/01-register.js
similarity index 99%
rename from tests/steps/1-register.js
rename to tests/steps/01-register.js
index 8c187ef656438cd5aa1cfce81f2353351645986a..599d600881d5280ea17db97ce347aed43beac041 100644
--- a/tests/steps/1-register.js
+++ b/tests/steps/01-register.js
@@ -3,7 +3,7 @@
 import loginPage from '../pageobjects/login.page';
 
 describe('register', () => {
-	it('load page', () => {
+	before(() => {
 		loginPage.open();
 		loginPage.gotToRegister();
 	});
diff --git a/tests/steps/2-forgot-password.js b/tests/steps/02-forgot-password.js
similarity index 97%
rename from tests/steps/2-forgot-password.js
rename to tests/steps/02-forgot-password.js
index 3a6454843faa29ecfe0d7677a8d332db6e15c56e..f9af855e443e1fe83e4d360218c78ca9ac450d21 100644
--- a/tests/steps/2-forgot-password.js
+++ b/tests/steps/02-forgot-password.js
@@ -2,8 +2,8 @@
 
 import loginPage from '../pageobjects/login.page';
 
-describe('register', () => {
-	it('load page', () => {
+describe.skip('register', () => {
+	before(() => {
 		loginPage.open();
 		loginPage.gotToForgotPassword();
 	});
diff --git a/tests/steps/03-user-creation.js b/tests/steps/03-user-creation.js
new file mode 100644
index 0000000000000000000000000000000000000000..1d146c8cdff7c036b93ab3887c357d6c50f839ab
--- /dev/null
+++ b/tests/steps/03-user-creation.js
@@ -0,0 +1,59 @@
+/* eslint-env mocha */
+/* eslint-disable func-names, prefer-arrow-callback */
+
+import loginPage from '../pageobjects/login.page';
+import mainContent from '../pageobjects/main-content.page';
+import sideNav from '../pageobjects/side-nav.page';
+
+//test data imports
+import {username, email, password, adminUsername, adminEmail, adminPassword} from '../data/user.js';
+
+
+
+//Basic usage test start
+describe('User Creation', function() {
+	this.retries(2);
+
+	before(() => {
+		loginPage.open();
+	});
+
+	/*If you are using a clean database dont pass any environment variables
+	if you have an existing database please pass the username (ADMIN_USERNAME) and password (ADMIN_PASS) of the admin as environment variables.*/
+
+	if (process.env.ADMIN_USERNAME && process.env.ADMIN_PASS) {
+		console.log('Admin login and password provided, skipping admin creation.');
+	} else {
+		it.skip('create the admin user', () => {
+			loginPage.gotToRegister();
+
+			loginPage.registerNewAdmin({adminUsername, adminEmail, adminPassword});
+
+			browser.waitForExist('form#login-card input#username', 5000);
+
+			browser.click('.submit > button');
+
+			mainContent.mainContent.waitForExist(5000);
+		});
+
+		it.skip('logout', () => {
+			sideNav.accountBoxUserName.waitForVisible(5000);
+			sideNav.accountBoxUserName.click();
+
+			sideNav.logout.waitForVisible(5000);
+			sideNav.logout.click();
+		});
+	}
+
+	it('create user', () => {
+		loginPage.gotToRegister();
+
+		loginPage.registerNewUser({username, email, password});
+
+		browser.waitForExist('form#login-card input#username', 5000);
+
+		browser.click('.submit > button');
+
+		mainContent.mainContent.waitForExist(5000);
+	});
+});
diff --git a/tests/steps/04-main-elements-render.js b/tests/steps/04-main-elements-render.js
new file mode 100644
index 0000000000000000000000000000000000000000..31ad15b49b08ab58e0d5b93fde96b80d8b8a460b
--- /dev/null
+++ b/tests/steps/04-main-elements-render.js
@@ -0,0 +1,356 @@
+/* eslint-env mocha */
+/* eslint-disable func-names, prefer-arrow-callback */
+
+import flexTab from '../pageobjects/flex-tab.page';
+import mainContent from '../pageobjects/main-content.page';
+import sideNav from '../pageobjects/side-nav.page';
+
+//test data imports
+import {checkIfUserIsValid} from '../data/checks';
+import {username, email, password} from '../data/user.js';
+
+describe('Main Elements Render', function() {
+	before(()=>{
+		checkIfUserIsValid(username, email, password);
+		sideNav.getChannelFromList('general').waitForExist(5000);
+		sideNav.openChannel('general');
+	});
+
+	describe('side nav bar', () => {
+		describe('render', () => {
+			it('should show the logged username', () => {
+				sideNav.accountBoxUserName.isVisible().should.be.true;
+			});
+
+			it('should show the logged user avatar', () => {
+				sideNav.accountBoxUserAvatar.isVisible().should.be.true;
+			});
+
+			it('should show the new channel button', () => {
+				sideNav.newChannelBtn.isVisible().should.be.true;
+			});
+
+			it('should show the plus icon', () => {
+				sideNav.newChannelIcon.isVisible().should.be.true;
+			});
+
+			it('should show the "More Channels" button', () => {
+				sideNav.moreChannels.isVisible().should.be.true;
+			});
+
+			it('should show the new direct message button', () => {
+				sideNav.newDirectMessageBtn.isVisible().should.be.true;
+			});
+
+			it('should show the plus icon', () => {
+				sideNav.newDirectMessageIcon.isVisible().should.be.true;
+			});
+
+			it('should show the "More Direct Messages" button', () => {
+				sideNav.moreDirectMessages.isVisible().should.be.true;
+			});
+
+			it('should show "general" channel', () => {
+				sideNav.general.isVisible().should.be.true;
+			});
+
+			it.skip('should not show eye icon on general', () => {
+				sideNav.channelHoverIcon.isVisible().should.be.true;
+			});
+		});
+	});
+
+	describe('user options', () => {
+		describe('render', () => {
+			before(() => {
+				sideNav.accountBoxUserName.click();
+				sideNav.userOptions.waitForVisible(5000);
+			});
+
+			after(() => {
+				sideNav.accountBoxUserName.click();
+			});
+
+			it('should show user options', () => {
+				sideNav.userOptions.isVisible().should.be.true;
+			});
+
+			it('should show online button', () => {
+				sideNav.statusOnline.isVisible().should.be.true;
+			});
+
+			it('should show away button', () => {
+				sideNav.statusAway.isVisible().should.be.true;
+			});
+
+			it('should show busy button', () => {
+				sideNav.statusBusy.isVisible().should.be.true;
+			});
+
+			it('should show offline button', () => {
+				sideNav.statusOffline.isVisible().should.be.true;
+			});
+
+			it('should show settings button', () => {
+				sideNav.account.isVisible().should.be.true;
+			});
+
+			it('should show logout button', () => {
+				sideNav.logout.isVisible().should.be.true;
+			});
+		});
+	});
+
+	describe('main content', () => {
+		describe('render', () => {
+			before(()=> {
+				sideNav.logout.waitForVisible(5000, true);
+				sideNav.getChannelFromList('general').waitForVisible(5000);
+				sideNav.openChannel('general');
+			});
+
+			it('should show the title of the channel', () => {
+				mainContent.channelTitle.isVisible().should.be.true;
+			});
+
+			it('should show the empty favorite star', () => {
+				mainContent.emptyFavoriteStar.isVisible().should.be.true;
+			});
+
+			it('clicks the star', () => {
+				mainContent.emptyFavoriteStar.click();
+			});
+
+			it('should not show the empty favorite star', () => {
+				mainContent.favoriteStar.isVisible().should.be.true;
+			});
+
+			it('clicks the star', () => {
+				mainContent.favoriteStar.click();
+			});
+
+			it('should show the message input bar', () => {
+				mainContent.messageInput.isVisible().should.be.true;
+			});
+
+			it('should show the file attachment button', () => {
+				mainContent.fileAttachmentBtn.isVisible().should.be.true;
+			});
+
+			it('should show the audio recording button', () => {
+				mainContent.recordBtn.isVisible().should.be.true;
+			});
+
+			it('should show the video call button', () => {
+				mainContent.videoCamBtn.isVisible().should.be.true;
+			});
+
+			it('should not show the send button', () => {
+				mainContent.sendBtn.isVisible().should.be.false;
+			});
+
+			it('should show the emoji button', () => {
+				mainContent.emojiBtn.isVisible().should.be.true;
+			});
+
+			it('adds some text to the input', () => {
+				mainContent.addTextToInput('Some Text');
+			});
+
+			it('should show the send button', () => {
+				mainContent.sendBtn.isVisible().should.be.true;
+			});
+
+			it('should not show the file attachment button', () => {
+				mainContent.fileAttachmentBtn.isVisible().should.be.false;
+			});
+
+			it('should not show the audio recording button', () => {
+				mainContent.recordBtn.isVisible().should.be.false;
+			});
+
+			it('should not show the video call button', () => {
+				mainContent.videoCamBtn.isVisible().should.be.false;
+			});
+
+			it('should show the last message', () => {
+				mainContent.lastMessage.isVisible().should.be.true;
+			});
+
+			it('the last message should be from the loged user', () => {
+				mainContent.lastMessageUser.getText().should.equal(username);
+			});
+
+			it('should not show the Admin tag', () => {
+				mainContent.lastMessageUserTag.isVisible().should.be.false;
+			});
+		});
+	});
+
+	describe('flextab usage', () => {
+		describe('render', () => {
+			before(()=> {
+				sideNav.getChannelFromList('general').waitForVisible(5000);
+				sideNav.openChannel('general');
+			});
+			describe('Room Info Tab', () => {
+				before(()=> {
+					flexTab.channelTab.click();
+				});
+
+				after(()=> {
+					flexTab.channelTab.click();
+				});
+
+				it('should show the room info button', () => {
+					flexTab.channelTab.isVisible().should.be.true;
+				});
+
+				it('should show the room info tab content', () => {
+					flexTab.channelSettings.waitForVisible(5000);
+					flexTab.channelSettings.isVisible().should.be.true;
+				});
+
+				it('should show the room name', ()=> {
+					flexTab.firstSetting.waitForVisible();
+					flexTab.firstSetting.getText().should.equal('general');
+				});
+
+			});
+
+			describe('Search Tab', () => {
+				before(()=> {
+					flexTab.searchTab.click();
+				});
+
+				after(()=> {
+					flexTab.searchTab.click();
+				});
+
+				it('should show the message search  button', () => {
+					flexTab.searchTab.isVisible().should.be.true;
+				});
+
+				it('should show the message tab content', () => {
+					flexTab.searchTabContent.isVisible().should.be.true;
+				});
+			});
+
+			describe('Members Tab', () => {
+				before(()=> {
+					flexTab.membersTab.click();
+				});
+
+				after(()=> {
+					flexTab.membersTab.click();
+				});
+
+				it('should show the members tab button', () => {
+					flexTab.membersTab.isVisible().should.be.true;
+				});
+
+				it('should show the members content', () => {
+					flexTab.membersTabContent.isVisible().should.be.true;
+				});
+
+				it.skip('should show the members search bar', () => {
+					flexTab.userSearchBar.isVisible().should.be.true;
+				});
+
+				it.skip('should show the show all link', () => {
+					flexTab.showAll.isVisible().should.be.true;
+				});
+			});
+
+			describe('Notifications Tab', () => {
+				before(()=> {
+					flexTab.notificationsTab.click();
+				});
+
+				after(()=> {
+					flexTab.notificationsTab.click();
+				});
+
+				it('should show the notifications button', () => {
+					flexTab.notificationsTab.isVisible().should.be.true;
+				});
+
+				it('should show the notifications Tab content', () => {
+					flexTab.notificationsSettings.isVisible().should.be.true;
+				});
+			});
+
+			describe('Files Tab', () => {
+				before(()=> {
+					flexTab.filesTab.click();
+				});
+
+				after(()=> {
+					flexTab.filesTab.click();
+				});
+
+				it('should show the files button', () => {
+					flexTab.filesTab.isVisible().should.be.true;
+				});
+
+				it('should show the files Tab content', () => {
+					flexTab.filesTabContent.isVisible().should.be.true;
+				});
+			});
+
+			describe('Mentions Tab', () => {
+				before(()=> {
+					flexTab.mentionsTab.click();
+				});
+
+				after(()=> {
+					flexTab.mentionsTab.click();
+				});
+
+				it('should show the mentions button', () => {
+					flexTab.mentionsTab.isVisible().should.be.true;
+				});
+
+				it('should show the mentions Tab content', () => {
+					flexTab.mentionsTabContent.isVisible().should.be.true;
+				});
+			});
+
+			describe('Starred Messages Tab', () => {
+				before(()=> {
+					flexTab.starredTab.click();
+				});
+
+				after(()=> {
+					flexTab.starredTab.click();
+				});
+
+				it('should show the starred messages button', () => {
+					flexTab.starredTab.isVisible().should.be.true;
+				});
+
+				it('should show the starred messages Tab content', () => {
+					flexTab.starredTabContent.isVisible().should.be.true;
+				});
+			});
+
+			describe('Pinned Messages Tab', () => {
+				before(()=> {
+					flexTab.pinnedTab.click();
+				});
+
+				after(()=> {
+					flexTab.pinnedTab.click();
+				});
+
+				it('should show the pinned button', () => {
+					flexTab.pinnedTab.isVisible().should.be.true;
+				});
+
+				it('should show the pinned messages Tab content', () => {
+					flexTab.pinnedTabContent.isVisible().should.be.true;
+				});
+			});
+		});
+	});
+});
diff --git a/tests/steps/05-channel-creation.js b/tests/steps/05-channel-creation.js
new file mode 100644
index 0000000000000000000000000000000000000000..7d34fdc934adf0a97e7cb5573cadee7c2d898dc8
--- /dev/null
+++ b/tests/steps/05-channel-creation.js
@@ -0,0 +1,64 @@
+/* eslint-env mocha */
+/* eslint-disable func-names, prefer-arrow-callback */
+
+import sideNav from '../pageobjects/side-nav.page';
+import {publicChannelName, privateChannelName} from '../data/channel.js';
+import {targetUser} from '../data/interactions.js';
+
+//test data imports
+import {checkIfUserIsValid, setPublicChannelCreated, setPrivateChannelCreated, setDirectMessageCreated} from '../data/checks';
+import {username, email, password} from '../data/user.js';
+//Basic usage test start
+describe('Channel creation', function() {
+	before(()=>{
+		checkIfUserIsValid(username, email, password);
+		sideNav.getChannelFromList('general').waitForExist(5000);
+		sideNav.openChannel('general');
+	});
+
+	beforeEach(()=>{
+		sideNav.getChannelFromList('general').waitForVisible(5000);
+		sideNav.openChannel('general');
+	});
+
+	afterEach(function() {
+		if (this.currentTest.state !== 'passed') {
+			setPublicChannelCreated(false);
+			switch (this.currentTest.title) {
+				case 'create a public channel':
+					setPublicChannelCreated(false);
+					console.log('Public channel Not Created!');
+					break;
+				case 'create a private channel':
+					setPrivateChannelCreated(false);
+					console.log('Private channel Not Created!');
+					break;
+				case 'start a direct message with rocket.cat':
+					setDirectMessageCreated(false);
+					console.log('Direct Message Not Created!');
+					break;
+			}
+		}
+	});
+
+	describe('create a public channel', function() {
+		it('create a public channel', function() {
+			sideNav.createChannel(publicChannelName, false, false);
+			setPublicChannelCreated(true);
+		});
+	});
+
+	describe('create a private channel', function() {
+		it('create a private channel', function() {
+			sideNav.createChannel(privateChannelName, true, false);
+			setPrivateChannelCreated(true);
+		});
+	});
+
+	describe('direct channel', function() {
+		it('start a direct message with rocket.cat', function() {
+			sideNav.startDirectMessage(targetUser);
+			setDirectMessageCreated(true);
+		});
+	});
+});
diff --git a/tests/steps/06-messaging.js b/tests/steps/06-messaging.js
new file mode 100644
index 0000000000000000000000000000000000000000..3b29f6a7aaba759ca0be51e9ebded200300c5cea
--- /dev/null
+++ b/tests/steps/06-messaging.js
@@ -0,0 +1,322 @@
+/* eslint-env mocha */
+/* eslint-disable func-names, prefer-arrow-callback */
+
+import mainContent from '../pageobjects/main-content.page';
+import sideNav from '../pageobjects/side-nav.page';
+
+//test data imports
+import {username, email, password} from '../data/user.js';
+import {publicChannelName, privateChannelName} from '../data/channel.js';
+import {targetUser, imgURL} from '../data/interactions.js';
+import {checkIfUserIsValid, publicChannelCreated, privateChannelCreated, directMessageCreated, setPublicChannelCreated, setPrivateChannelCreated, setDirectMessageCreated} from '../data/checks';
+
+
+//Test data
+const message = 'message from '+username;
+var currentTest = 'none';
+
+function messagingTest() {
+	describe('Normal message', ()=> {
+		it('send a message', () => {
+			mainContent.sendMessage(message);
+		});
+
+		it('should show the last message', () => {
+			mainContent.lastMessage.isVisible().should.be.true;
+		});
+
+		if (!currentTest === 'direct') {
+			it('the last message should be from the loged user', () => {
+				mainContent.lastMessageUser.getText().should.equal(username);
+			});
+		}
+
+		if (currentTest === 'general') {
+			it('should not show the Admin tag', () => {
+				mainContent.lastMessageUserTag.isVisible().should.be.false;
+			});
+		}
+	});
+
+	describe('fileUpload', ()=> {
+		after(() => {
+		});
+		it('send a attachment', () => {
+			mainContent.fileUpload(imgURL);
+		});
+
+		it('should show the confirm button', () => {
+			mainContent.popupFileConfirmBtn.isVisible().should.be.true;
+		});
+
+		it('should show the cancel button', () => {
+			mainContent.popupFileCancelBtn.isVisible().should.be.true;
+		});
+
+		it('should show the file preview', () => {
+			mainContent.popupFilePreview.isVisible().should.be.true;
+		});
+
+		it('should show the confirm button', () => {
+			mainContent.popupFileConfirmBtn.isVisible().should.be.true;
+		});
+
+		it('should show the file title', () => {
+			mainContent.popupFileTitle.isVisible().should.be.true;
+		});
+
+		it('should show the file name input', () => {
+			mainContent.popupFileName.isVisible().should.be.true;
+		});
+
+		it('should fill the file name input', () => {
+			mainContent.popupFileName.setValue('File Name');
+		});
+
+		it('should show the file name input', () => {
+			mainContent.popupFileDescription.isVisible().should.be.true;
+		});
+
+		it('should fill the file name input', () => {
+			mainContent.popupFileDescription.setValue('File Description');
+		});
+
+		it('click the confirm', () => {
+			mainContent.popupFileConfirmBtn.click();
+			mainContent.popupFileConfirmBtn.waitForVisible(5000, true);
+		});
+
+		it('should show the file in the message', () => {
+			mainContent.lastMessageDesc.waitForVisible(10000);
+			mainContent.lastMessageDesc.getText().should.equal('File Description');
+		});
+	});
+}
+
+function messageActionsTest() {
+	describe('Message actions', ()=> {
+		before(() => {
+			mainContent.sendMessage('Message for Message Actions Tests');
+		});
+		describe('Message Actions Render', ()=> {
+			before(() => {
+				mainContent.openMessageActionMenu();
+			});
+
+			after(() => {
+				browser.pause(100);
+				mainContent.selectAction('close');
+				mainContent.messageActionMenu.waitForVisible(5000, true);
+			});
+
+			it('should show the message action menu', () => {
+				mainContent.messageActionMenu.isVisible().should.be.true;
+			});
+
+			it('should show the reply action', () => {
+				mainContent.messageReply.isVisible().should.be.true;
+			});
+
+			it('should show the edit action', () => {
+				mainContent.messageEdit.isVisible().should.be.true;
+			});
+
+			it('should show the delete action', () => {
+				mainContent.messageDelete.isVisible().should.be.true;
+			});
+
+			it('should show the permalink action', () => {
+				mainContent.messagePermalink.isVisible().should.be.true;
+			});
+
+			it('should show the copy action', () => {
+				mainContent.messageCopy.isVisible().should.be.true;
+			});
+
+			it('should show the quote the action', () => {
+				mainContent.messageQuote.isVisible().should.be.true;
+			});
+
+			it('should show the star action', () => {
+				mainContent.messageStar.isVisible().should.be.true;
+			});
+
+			it('should show the reaction action', () => {
+				mainContent.messageReaction.isVisible().should.be.true;
+			});
+
+			it('should show the close action', () => {
+				mainContent.messageClose.isVisible().should.be.true;
+			});
+
+			if (currentTest === 'general') {
+				it('should not show the pin action', () => {
+					mainContent.messagePin.isVisible().should.be.false;
+				});
+			}
+
+			it('should not show the mark as unread action', () => {
+				mainContent.messageUnread.isVisible().should.be.false;
+			});
+		});
+
+		describe('Message Actions usage', () => {
+			describe('Message Reply', () => {
+				before(() => {
+					mainContent.openMessageActionMenu();
+				});
+				it('reply the message', () => {
+					mainContent.selectAction('reply');
+					mainContent.sendBtn.click();
+				});
+
+				it.skip('checks if the message was replied', () => {
+					mainContent.lastMessageTextAttachment.waitForExist(5000);
+					mainContent.lastMessageTextAttachment.getText().should.equal(mainContent.beforeLastMessage.getText());
+				});
+			});
+
+
+			describe('Message edit', () => {
+				before(() => {
+					mainContent.sendMessage('Message for Message edit Tests');
+					mainContent.openMessageActionMenu();
+				});
+
+				it('edit the message', () => {
+					mainContent.selectAction('edit');
+					mainContent.sendBtn.click();
+				});
+			});
+
+
+			describe('Message delete', () => {
+				before(() => {
+					mainContent.sendMessage('Message for Message Delete Tests');
+					mainContent.openMessageActionMenu();
+				});
+
+				it('delete the message', () => {
+					mainContent.selectAction('delete');
+					mainContent.popupFileConfirmBtn.click();
+					browser.waitForVisible('.sweet-overlay', 3000, true);
+				});
+
+				it('should not show the deleted message', () => {
+					mainContent.lastMessage.should.not.equal('Message for Message Delete Tests');
+				});
+			});
+
+			describe('Message quote', () => {
+				const message = 'Message for quote Tests - ' + Date.now();
+
+				before(() => {
+					mainContent.sendMessage(message);
+					mainContent.openMessageActionMenu();
+				});
+
+				it('quote the message', () => {
+					mainContent.selectAction('quote');
+					mainContent.sendBtn.click();
+
+					browser.waitUntil(function() {
+						return browser.getText(mainContent.lastMessageTextAttachment.selector) === message;
+					}, 2000);
+				});
+			});
+
+			describe('Message star', () => {
+				before(() => {
+					mainContent.sendMessage('Message for star Tests');
+					mainContent.openMessageActionMenu();
+				});
+
+				it('star the message', () => {
+					mainContent.selectAction('star');
+				});
+			});
+
+			describe('Message copy', () => {
+				before(() => {
+					mainContent.sendMessage('Message for copy Tests');
+					mainContent.openMessageActionMenu();
+				});
+
+				it('copy the message', () => {
+					mainContent.selectAction('copy');
+				});
+			});
+
+			describe('Message Permalink', () => {
+				before(() => {
+					mainContent.sendMessage('Message for permalink Tests');
+					mainContent.openMessageActionMenu();
+				});
+
+
+				it('permalink the message', () => {
+					mainContent.selectAction('permalink');
+				});
+			});
+		});
+	});
+}
+
+describe('Messaging in different channels', () => {
+	before(()=>{
+		checkIfUserIsValid(username, email, password);
+		sideNav.getChannelFromList('general').waitForExist(5000);
+		sideNav.openChannel('general');
+	});
+
+
+	describe('Messaging in GENERAL channel', () => {
+		before(()=>{
+			sideNav.openChannel('general');
+			currentTest = 'general';
+		});
+		messagingTest();
+		messageActionsTest();
+	});
+
+	describe('Messaging in created public channel', () => {
+		before(()=>{
+			if (!publicChannelCreated) {
+				sideNav.createChannel(publicChannelName, false, false);
+				setPublicChannelCreated(true);
+				console.log('	public channel not found, creating one...');
+			}
+			currentTest = 'public';
+			sideNav.openChannel(publicChannelName);
+		});
+		messagingTest();
+		messageActionsTest();
+	});
+
+	describe('Messaging in created private channel', () => {
+		before(()=>{
+			if (!privateChannelCreated) {
+				sideNav.createChannel(privateChannelName, true, false);
+				setPrivateChannelCreated(true);
+				console.log('	private channel not found, creating one...');
+			}
+			currentTest = 'private';
+			sideNav.openChannel(privateChannelName);
+		});
+		messagingTest();
+		messageActionsTest();
+	});
+
+	describe('Messaging in created direct message', () => {
+		before(()=>{
+			if (!directMessageCreated) {
+				sideNav.startDirectMessage(targetUser);
+				setDirectMessageCreated(true);
+				console.log('	Direct message not found, creating one...');
+			}
+			currentTest = 'direct';
+			sideNav.openChannel(publicChannelName);
+		});
+		messagingTest();
+	});
+});
diff --git a/tests/steps/5-emoji.js b/tests/steps/07-emoji.js
similarity index 72%
rename from tests/steps/5-emoji.js
rename to tests/steps/07-emoji.js
index 344d2d4e8c41d463c881dd0be9b260dcf0002cbc..604d70b155754ef97c9878d96f70c8ae4a16896b 100644
--- a/tests/steps/5-emoji.js
+++ b/tests/steps/07-emoji.js
@@ -4,16 +4,27 @@
 import mainContent from '../pageobjects/main-content.page';
 import sideNav from '../pageobjects/side-nav.page';
 
+import {username, email, password} from '../data/user.js';
+import {checkIfUserIsValid} from '../data/checks';
+
 describe('emoji', ()=> {
-	it('opens general', ()=> {
+	before(()=>{
+		checkIfUserIsValid(username, email, password);
+		sideNav.getChannelFromList('general').waitForExist(5000);
 		sideNav.openChannel('general');
 	});
 
-	it('opens emoji menu', ()=> {
-		mainContent.emojiBtn.click();
-	});
 
 	describe('render', ()=> {
+		before(()=> {
+			mainContent.emojiBtn.click();
+		});
+
+		after(() => {
+			mainContent.emojiSmile.click();
+			mainContent.setTextToInput('');
+		});
+
 		it('should show the emoji picker menu', ()=> {
 			mainContent.emojiPickerMainScreen.isVisible().should.be.true;
 		});
@@ -65,24 +76,36 @@ describe('emoji', ()=> {
 		it('should show the emoji picker search bar', ()=> {
 			mainContent.emojiPickerFilter.isVisible().should.be.true;
 		});
+	});
 
-		it('send a smile emoji', ()=> {
-			mainContent.emojiSmile.click();
-		});
+	describe('usage', ()=> {
+		describe('send emoji via screen', ()=> {
+			before(()=> {
+				mainContent.emojiBtn.click();
+				mainContent.emojiPickerPeopleIcon.click();
+			});
 
-		it('the value on the message input should be the same as the emoji clicked', ()=> {
-			mainContent.messageInput.getValue().should.equal(':smile:');
-		});
+			it('select a grinning emoji', ()=> {
+				mainContent.emojiGrinning.waitForVisible(5000);
+				mainContent.emojiGrinning.click();
+			});
 
-		it('send the emoji', ()=> {
-			mainContent.addTextToInput(' ');
-			mainContent.sendBtn.click();
-		});
+			it('the value on the message input should be the same as the emoji clicked', ()=> {
+				mainContent.messageInput.getValue().should.equal(':grinning:');
+			});
 
-		it('the value on the message should be the same as the emoji clicked', ()=> {
-			mainContent.lastMessage.getText().should.equal('😄');
+			it('send the emoji', ()=> {
+				mainContent.addTextToInput(' ');
+				mainContent.sendBtn.click();
+			});
+
+			it('the value on the message should be the same as the emoji clicked', ()=> {
+				mainContent.lastMessage.getText().should.equal('😀');
+			});
 		});
+	});
 
+	describe('send emoji via text', ()=> {
 		it('adds emoji text to the message input', ()=> {
 			mainContent.addTextToInput(':smile');
 		});
diff --git a/tests/steps/08-resolutions.js b/tests/steps/08-resolutions.js
new file mode 100644
index 0000000000000000000000000000000000000000..a810e8c596578286570342e52ad4ba75369acf45
--- /dev/null
+++ b/tests/steps/08-resolutions.js
@@ -0,0 +1,105 @@
+/* eslint-env mocha */
+/* eslint-disable func-names, prefer-arrow-callback */
+
+import mainContent from '../pageobjects/main-content.page';
+import sideNav from '../pageobjects/side-nav.page';
+
+import {username, email, password} from '../data/user.js';
+import {checkIfUserIsValid} from '../data/checks';
+
+describe.skip('resolutions tests', ()=> {
+	describe('mobile render', ()=> {
+		before(()=> {
+			checkIfUserIsValid(username, email, password);
+			sideNav.getChannelFromList('general').waitForExist(5000);
+			sideNav.openChannel('general');
+			browser.windowHandleSize({
+				width: 650,
+				height: 800
+			});
+		});
+
+		after(()=> {
+			browser.windowHandleSize({
+				width: 1450,
+				height: 900
+			});
+		});
+
+		describe('moving elements ', () => {
+			it('should close de sidenav', () => {
+				mainContent.mainContent.getLocation().should.deep.equal({x:0, y:0});
+			});
+
+			it('press the navbar button', () => {
+				sideNav.sideNavBtn.click();
+			});
+
+			it('should open de sidenav', () => {
+				mainContent.mainContent.getLocation().should.not.deep.equal({x:0, y:0});
+			});
+
+			it('open general channel', () => {
+				sideNav.openChannel('general');
+			});
+
+			it('should close de sidenav', () => {
+				mainContent.mainContent.getLocation().should.deep.equal({x:0, y:0});
+			});
+
+			it('press the navbar button', () => {
+				sideNav.sideNavBtn.click();
+			});
+
+			it('opens the user preferences screen', () => {
+				sideNav.accountBoxUserName.waitForVisible();
+				sideNav.accountBoxUserName.click();
+				sideNav.account.waitForVisible();
+				sideNav.account.click();
+			});
+
+			it('press the preferences link', () => {
+				sideNav.preferences.waitForVisible();
+				sideNav.preferences.click();
+			});
+
+			it('should close de sidenav', () => {
+				mainContent.mainContent.getLocation().should.deep.equal({x:0, y:0});
+			});
+
+			it('press the navbar button', () => {
+				sideNav.sideNavBtn.click();
+			});
+
+			it('press the profile link', () => {
+				sideNav.profile.waitForVisible();
+				sideNav.profile.click();
+			});
+
+			it('should close de sidenav', () => {
+				mainContent.mainContent.getLocation().should.deep.equal({x:0, y:0});
+			});
+
+			it('press the navbar button', () => {
+				sideNav.sideNavBtn.click();
+			});
+
+			it('press the avatar link', () => {
+				sideNav.avatar.waitForVisible();
+				sideNav.avatar.click();
+			});
+
+			it('should close de sidenav', () => {
+				mainContent.mainContent.getLocation().should.deep.equal({x:0, y:0});
+			});
+
+			it('press the navbar button', () => {
+				sideNav.sideNavBtn.click();
+			});
+
+			it('close the preferences menu', () => {
+				sideNav.preferencesClose.click();
+			});
+		});
+	});
+});
diff --git a/tests/steps/09-channel.js b/tests/steps/09-channel.js
new file mode 100644
index 0000000000000000000000000000000000000000..32a45a47c09b2e8d4708d6a01050669e362d6efd
--- /dev/null
+++ b/tests/steps/09-channel.js
@@ -0,0 +1,264 @@
+/* eslint-env mocha */
+/* eslint-disable func-names, prefer-arrow-callback */
+
+import flexTab from '../pageobjects/flex-tab.page';
+import mainContent from '../pageobjects/main-content.page';
+import sideNav from '../pageobjects/side-nav.page';
+
+import {username, email, password} from '../data/user.js';
+import {checkIfUserIsValid, publicChannelCreated, setPublicChannelCreated} from '../data/checks';
+import {publicChannelName} from '../data/channel.js';
+import {targetUser} from '../data/interactions.js';
+
+describe('channel usage', ()=> {
+	before(() => {
+		checkIfUserIsValid(username, email, password);
+		if (!publicChannelCreated) {
+			sideNav.createChannel(publicChannelName, false, false);
+			setPublicChannelCreated(true);
+			console.log('public channel not found, creating one...');
+		}
+		sideNav.openChannel(publicChannelName);
+	});
+
+	describe('Adding a user to the room', () => {
+		before(()=> {
+			if (flexTab.toastAlert.isVisible()) {
+				flexTab.dismissToast();
+				flexTab.toastAlert.waitForVisible(5000, true);
+			}
+			flexTab.membersTab.waitForVisible();
+			flexTab.membersTab.click();
+		});
+
+		after(()=> {
+			if (flexTab.toastAlert.isVisible()) {
+				flexTab.dismissToast();
+				flexTab.toastAlert.waitForVisible(5000, true);
+			}
+			flexTab.membersTab.waitForVisible();
+			flexTab.membersTab.click();
+		});
+
+		it('add people to the room', () => {
+			flexTab.addPeopleToChannel(targetUser);
+		});
+
+	});
+
+	describe('Channel settings', ()=> {
+		describe('Channel name edit', ()=> {
+			before(()=> {
+				if (flexTab.toastAlert.isVisible()) {
+					flexTab.dismissToast();
+					flexTab.toastAlert.waitForVisible(5000, true);
+				}
+				flexTab.channelTab.waitForVisible();
+				flexTab.channelTab.click();
+			});
+
+			after(()=> {
+				if (flexTab.toastAlert.isVisible()) {
+					flexTab.dismissToast();
+					flexTab.toastAlert.waitForVisible(5000, true);
+				}
+				flexTab.channelTab.waitForVisible(5000);
+				flexTab.channelTab.click();
+				browser.pause(400);
+			});
+
+			it('should show the old name', ()=> {
+				flexTab.firstSetting.waitForVisible();
+				flexTab.firstSetting.getText().should.equal(publicChannelName);
+			});
+
+			it('click the edit name', ()=> {
+				flexTab.editNameBtn.waitForVisible();
+				flexTab.editNameBtn.click();
+			});
+
+			it('edit the name input', ()=> {
+				flexTab.editNameTextInput.waitForVisible();
+				flexTab.editNameTextInput.setValue('NAME-EDITED-'+publicChannelName);
+			});
+
+			it('save the name', ()=> {
+				flexTab.editNameSave.click();
+
+			});
+
+			it('should show the new name', ()=> {
+				var channelName = sideNav.getChannelFromList('NAME-EDITED-'+publicChannelName);
+				channelName.getText().should.equal('NAME-EDITED-'+publicChannelName);
+			});
+		});
+
+		describe('Channel topic edit', ()=> {
+			before(()=> {
+				flexTab.channelTab.waitForVisible();
+				flexTab.channelTab.click();
+			});
+
+			after(()=> {
+				if (flexTab.toastAlert.isVisible()) {
+					flexTab.dismissToast();
+					flexTab.toastAlert.waitForVisible(5000, true);
+				}
+				flexTab.channelTab.waitForVisible();
+				flexTab.channelTab.click();
+			});
+
+			it('click the edit topic', ()=> {
+				flexTab.editTopicBtn.waitForVisible(5000);
+				flexTab.editTopicBtn.click();
+			});
+
+			it('edit the topic input', ()=> {
+				flexTab.editTopicTextInput.waitForVisible(5000);
+				flexTab.editTopicTextInput.setValue('TOPIC EDITED');
+			});
+
+			it('save the topic', ()=> {
+				flexTab.editNameSave.click();
+			});
+
+			it('should show the new topic', ()=> {
+				flexTab.secondSetting.getText().should.equal('TOPIC EDITED');
+			});
+		});
+
+		describe('Channel description edit', ()=> {
+			before(()=> {
+				flexTab.channelTab.waitForVisible();
+				flexTab.channelTab.click();
+			});
+
+			after(()=> {
+				if (flexTab.toastAlert.isVisible()) {
+					flexTab.dismissToast();
+					flexTab.toastAlert.waitForVisible(5000, true);
+				}
+				flexTab.channelTab.waitForVisible();
+				flexTab.channelTab.click();
+			});
+
+			it('click the edit description', ()=> {
+				flexTab.editDescriptionBtn.waitForVisible();
+				flexTab.editDescriptionBtn.click();
+			});
+
+			it('edit the description input', ()=> {
+				flexTab.editDescriptionTextInput.waitForVisible(5000);
+				flexTab.editDescriptionTextInput.setValue('DESCRIPTION EDITED');
+			});
+
+			it('save the description', ()=> {
+				flexTab.editNameSave.click();
+			});
+
+			it('should show the new description', ()=> {
+				flexTab.thirdSetting.getText().should.equal('DESCRIPTION EDITED');
+			});
+		});
+	});
+
+	describe('Members tab usage', () => {
+		describe('Owner added', () => {
+			before(()=> {
+				if (flexTab.toastAlert.isVisible()) {
+					flexTab.dismissToast();
+					flexTab.toastAlert.waitForVisible(5000, true);
+				}
+				flexTab.membersTab.waitForVisible();
+				flexTab.membersTab.click();
+			});
+
+			after(()=> {
+				if (flexTab.toastAlert.isVisible()) {
+					flexTab.dismissToast();
+					flexTab.toastAlert.waitForVisible(5000, true);
+				}
+				flexTab.membersTab.waitForVisible();
+				flexTab.membersTab.click();
+			});
+
+			it('sets rocket cat as owner', ()=> {
+				flexTab.setUserOwner(targetUser);
+			});
+
+			it('dismiss the toast', ()=> {
+				if (flexTab.toastAlert.isVisible()) {
+					flexTab.dismissToast();
+					flexTab.toastAlert.waitForVisible(5000, true);
+				}
+			});
+
+			it('the last message should be a subscription role added', ()=> {
+				mainContent.lastMessageRoleAdded.isVisible().should.be.true;
+			});
+
+			it('should show the target username in owner add message', ()=> {
+				mainContent.lastMessage.getText().should.have.string(targetUser);
+			});
+		});
+
+		describe('Moderator added', () => {
+			before(()=> {
+				if (flexTab.toastAlert.isVisible()) {
+					flexTab.dismissToast();
+					flexTab.toastAlert.waitForVisible(5000, true);
+				}
+				flexTab.membersTab.waitForVisible();
+				flexTab.membersTab.click();
+			});
+
+			after(()=> {
+				if (flexTab.toastAlert.isVisible()) {
+					flexTab.dismissToast();
+					flexTab.toastAlert.waitForVisible(5000, true);
+				}
+				flexTab.membersTab.waitForVisible();
+				flexTab.membersTab.click();
+			});
+
+			it('sets rocket cat as moderator', ()=> {
+				flexTab.setUserModerator(targetUser);
+			});
+
+			it('dismiss the toast', ()=> {
+				if (flexTab.toastAlert.isVisible()) {
+					flexTab.dismissToast();
+					flexTab.toastAlert.waitForVisible(5000, true);
+				}
+			});
+
+			it('the last message should be a subscription role added', ()=> {
+				mainContent.lastMessageRoleAdded.isVisible().should.be.true;
+			});
+
+			it('should show the target username in moderator add message', ()=> {
+				mainContent.lastMessage.getText().should.have.string(targetUser);
+			});
+		});
+
+		describe.skip('User muted', () => {
+			before(()=> {
+				flexTab.membersTab.waitForVisible(5000);
+				flexTab.membersTab.click();
+			});
+
+			after(()=> {
+				flexTab.membersTab.waitForVisible();
+				flexTab.membersTab.click();
+			});
+
+			it('mute rocket cat', ()=> {
+				flexTab.muteUser(targetUser);
+			});
+
+			it('confirms the popup', ()=> {
+				flexTab.confirmPopup();
+			});
+		});
+	});
+});
diff --git a/tests/steps/7-user-preferences.js b/tests/steps/10-user-preferences.js
similarity index 90%
rename from tests/steps/7-user-preferences.js
rename to tests/steps/10-user-preferences.js
index 5bc466194c811900ad510586d1886908707a52c1..f662c41df0c6be256a4c4d1c4da9df0f5ec49ec1 100644
--- a/tests/steps/7-user-preferences.js
+++ b/tests/steps/10-user-preferences.js
@@ -6,17 +6,22 @@ import mainContent from '../pageobjects/main-content.page';
 import sideNav from '../pageobjects/side-nav.page';
 import preferencesMainContent from '../pageobjects/preferences-main-content.page';
 
-import {username, password} from '../test-data/user.js';
-import {imgURL} from '../test-data/interactions.js';
+import {username, password, email} from '../data/user.js';
+import {imgURL} from '../data/interactions.js';
 
-describe('user preferences', ()=> {
+import {checkIfUserIsValid} from '../data/checks';
+
+
+describe.skip('user preferences', ()=> {
+	before(() => {
+		checkIfUserIsValid(username, email, password);
+		sideNav.getChannelFromList('general').waitForExist(5000);
+		sideNav.openChannel('general');
 
-	it('opens the user preferences screen', () => {
 		sideNav.accountBoxUserName.waitForVisible();
 		sideNav.accountBoxUserName.click();
 		sideNav.account.waitForVisible();
 		sideNav.account.click();
-		browser.pause(1000);
 	});
 
 	describe('render', ()=> {
@@ -34,7 +39,6 @@ describe('user preferences', ()=> {
 
 		it('click on the profile link', ()=> {
 			sideNav.profile.click();
-			browser.pause(1000);
 		});
 
 		it('should show the username input', ()=> {
@@ -62,7 +66,6 @@ describe('user preferences', ()=> {
 	describe.skip('user info change', ()=> {
 		it('click on the profile link', ()=> {
 			sideNav.profile.click();
-			browser.pause(1000);
 		});
 
 		it('change the name field', ()=> {
@@ -95,7 +98,6 @@ describe('user preferences', ()=> {
 
 		it('close the preferences menu', () => {
 			sideNav.preferencesClose.click();
-			browser.pause(3000);
 		});
 
 		it('open GENERAL', () => {
@@ -130,4 +132,4 @@ describe('user preferences', ()=> {
 			flexTab.membersTab.click();
 		});
 	});
-});
\ No newline at end of file
+});
diff --git a/tests/steps/11-admin.js b/tests/steps/11-admin.js
new file mode 100644
index 0000000000000000000000000000000000000000..3f3fd0b24f44277826edb3a8243a13a582fa8a1c
--- /dev/null
+++ b/tests/steps/11-admin.js
@@ -0,0 +1,686 @@
+/* eslint-env mocha */
+/* eslint-disable func-names, prefer-arrow-callback */
+
+import sideNav from '../pageobjects/side-nav.page';
+import flexTab from '../pageobjects/flex-tab.page';
+import admin from '../pageobjects/administration.page';
+
+//test data imports
+import {checkIfUserIsAdmin} from '../data/checks';
+import {adminUsername, adminEmail, adminPassword} from '../data/user.js';
+
+describe('Admin Login', () => {
+	before(() => {
+		checkIfUserIsAdmin(adminUsername, adminEmail, adminPassword);
+		sideNav.getChannelFromList('general').waitForExist(5000);
+		sideNav.openChannel('general');
+	});
+
+	after(() => {
+		sideNav.preferencesClose.waitForVisible(5000);
+		sideNav.preferencesClose.click();
+		sideNav.getChannelFromList('general').waitForExist(5000);
+		sideNav.openChannel('general');
+	});
+
+	describe('Admin view', () => {
+		before(() => {
+			sideNav.accountBoxUserName.click();
+			sideNav.admin.waitForVisible(5000);
+		});
+
+		it('Enter the admin view', () => {
+			sideNav.admin.click();
+			admin.flexNavContent.waitForVisible(5000);
+		});
+
+		describe('info', () => {
+			before(() =>{
+				admin.infoLink.waitForVisible(5000);
+				admin.infoLink.click();
+				admin.infoRocketChatTable.waitForVisible(5000);
+			});
+			it('the first title should be Rocket.Chat', () => {
+				admin.infoRocketChatTableTitle.getText().should.equal('Rocket.Chat');
+			});
+
+			it('should show the rocket chat table', () => {
+				admin.infoRocketChatTable.isVisible().should.be.true;
+			});
+
+			it('the second title should be Commit', () => {
+				admin.infoCommitTableTitle.getText().should.equal('Commit');
+			});
+
+			it('should show the Commit table', () => {
+				admin.infoCommitTable.isVisible().should.be.true;
+			});
+
+			it('the first title should be Runtime_Environment', () => {
+				admin.infoRuntimeTableTitle.getText().should.equal('Runtime_Environment');
+			});
+
+			it('should show the Runtime_Environment table', () => {
+				admin.infoRuntimeTable.isVisible().should.be.true;
+			});
+
+			it('the first title should be Build_Environment', () => {
+				admin.infoBuildTableTitle.getText().should.equal('Build_Environment');
+			});
+
+			it('should show the Build_Environment table', () => {
+				admin.infoBuildTable.isVisible().should.be.true;
+			});
+		});
+
+		describe('rooms', () => {
+			before(() => {
+				admin.roomsLink.waitForVisible(5000);
+				admin.roomsLink.click();
+				admin.roomsFilter.waitForVisible(5000);
+			});
+
+			after(() => {
+				admin.infoLink.click();
+			});
+
+			describe('render', () => {
+				it('should show the search form', () => {
+					admin.roomsSearchForm.isVisible().should.be.true;
+				});
+
+				it('should show the rooms Filter', () => {
+					admin.roomsFilter.isVisible().should.be.true;
+				});
+
+				it('should show the channel checkbox', () => {
+					admin.roomsChannelsCheckbox.isVisible().should.be.true;
+				});
+
+				it('should show the direct messsage checkbox', () => {
+					admin.roomsDirectCheckbox.isVisible().should.be.true;
+				});
+
+				it('should show the Private channel checkbox', () => {
+					admin.roomsPrivateCheckbox.isVisible().should.be.true;
+				});
+
+				it('should show the general channel', () => {
+					admin.roomsGeneralChannel.isVisible().should.be.true;
+				});
+			});
+
+			describe('filter text', () => {
+				before(() => {
+					admin.roomsFilter.click();
+					admin.roomsFilter.setValue('general');
+				});
+
+				after(() => {
+					admin.roomsFilter.click();
+					admin.roomsFilter.setValue('');
+				});
+
+				it('should show the general channel', () => {
+					admin.roomsGeneralChannel.isVisible().should.be.true;
+				});
+			});
+
+			describe('filter text with wrong channel', () => {
+				before(() => {
+					admin.roomsFilter.click();
+					browser.pause(5000);
+					admin.roomsFilter.setValue('something else');
+				});
+
+				after(() => {
+					admin.roomsFilter.click();
+					admin.roomsFilter.setValue('');
+				});
+
+				it('should not show the general channel', () => {
+					admin.roomsGeneralChannel.isVisible().should.be.false;
+				});
+			});
+
+			describe('filter checkbox', () => {
+				var checkbox = 1;
+				before(() => {
+					admin.roomsFilter.setValue('');
+					//add value triggers a key event that changes search±±±±±±±±±
+					admin.roomsFilter.addValue(' ');
+					admin.roomsGeneralChannel.waitForVisible(5000);
+				});
+				beforeEach(() => {
+					switch (checkbox) {
+						case 1:
+							admin.roomsChannelsCheckbox.click();
+							break;
+						case 2:
+							admin.roomsDirectCheckbox.click();
+							break;
+						case 3:
+							admin.roomsPrivateCheckbox.click();
+							break;
+					}
+				});
+
+				afterEach(() => {
+					switch (checkbox) {
+						case 1:
+							admin.roomsChannelsCheckbox.click();
+							checkbox ++;
+							break;
+						case 2:
+							admin.roomsDirectCheckbox.click();
+							checkbox ++;
+							break;
+						case 3:
+							admin.roomsPrivateCheckbox.click();
+							break;
+					}
+				});
+
+				it('should show the general channel', () => {
+					admin.roomsGeneralChannel.isVisible().should.be.true;
+				});
+
+				it('should not show the general channel', () => {
+					admin.roomsGeneralChannel.isVisible().should.be.false;
+				});
+
+				it('should not show the general channel', () => {
+					admin.roomsGeneralChannel.isVisible().should.be.false;
+				});
+			});
+		});
+
+		describe('users', () => {
+			before(() => {
+				admin.usersLink.waitForVisible(5000);
+				admin.usersLink.click();
+				admin.usersFilter.waitForVisible(5000);
+			});
+
+			after(() => {
+				admin.infoLink.click();
+			});
+
+			it('should show the search form', () => {
+				admin.usersFilter.isVisible().should.be.true;
+			});
+
+
+			it('should show rocket.cat', () => {
+				admin.usersRocketCat.isVisible().should.be.true;
+			});
+
+			describe('filter text', () => {
+				before(() => {
+					admin.usersFilter.click();
+					browser.pause(5000);
+					admin.usersFilter.setValue('Rocket.Cat');
+				});
+
+				after(() => {
+					admin.usersFilter.click();
+					admin.usersFilter.setValue('');
+				});
+
+				it('should show rocket.cat', () => {
+					admin.usersRocketCat.waitForVisible();
+					admin.usersRocketCat.isVisible().should.be.true;
+				});
+			});
+
+			describe('filter text with wrong user', () => {
+				before(() => {
+					admin.usersFilter.click();
+					browser.pause(5000);
+					admin.usersFilter.setValue('something else');
+				});
+
+				after(() => {
+					admin.usersFilter.click();
+					admin.usersFilter.setValue('');
+				});
+
+				it('should not show rocket.cat', () => {
+					admin.usersRocketCat.isVisible().should.be.false;
+				});
+			});
+
+			describe('users flex tab ', () => {
+				describe('send invitation', () => {
+					before(() => {
+						flexTab.usersSendInvitationTab.waitForVisible(5000);
+						flexTab.usersSendInvitationTab.click();
+						flexTab.usersSendInvitationTextArea.waitForVisible(5000);
+					});
+
+					after(() => {
+						flexTab.usersSendInvitationTab.waitForVisible(5000);
+						flexTab.usersSendInvitationTab.click();
+						flexTab.usersSendInvitationTextArea.waitForVisible(5000, true);
+					});
+
+					it('should show the send invitation text area', () => {
+						flexTab.usersSendInvitationTextArea.isVisible().should.be.true;
+					});
+
+					it('should show the cancel button', () => {
+						flexTab.usersButtonCancel.isVisible().should.be.true;
+					});
+
+					it('should show the send button', () => {
+						flexTab.usersSendInvitationSend.isVisible().should.be.true;
+					});
+				});
+
+				describe('create user ', () => {
+					before(() => {
+						flexTab.usersAddUserTab.waitForVisible(5000);
+						flexTab.usersAddUserTab.click();
+						flexTab.usersAddUserName.waitForVisible(5000);
+					});
+
+					after(() => {
+						flexTab.usersAddUserTab.waitForVisible(5000);
+						flexTab.usersAddUserTab.click();
+						flexTab.usersAddUserName.waitForVisible(5000, true);
+					});
+
+					it('should show the name field', () => {
+						flexTab.usersAddUserName.isVisible().should.be.true;
+					});
+
+					it('should show the username field', () => {
+						flexTab.usersAddUserUsername.isVisible().should.be.true;
+					});
+
+					it('should show the email field', () => {
+						flexTab.usersAddUserEmail.isVisible().should.be.true;
+					});
+
+					it('should show the verified checkbox', () => {
+						flexTab.usersAddUserVerifiedCheckbox.isVisible().should.be.true;
+					});
+
+					it('should show the password field', () => {
+						flexTab.usersAddUserPassword.isVisible().should.be.true;
+					});
+
+					it('should show the random password button', () => {
+						flexTab.usersAddUserRandomPassword.isVisible().should.be.true;
+					});
+
+					it('should show the require password change button', () => {
+						flexTab.usersAddUserChangePasswordCheckbox.isVisible().should.be.true;
+					});
+
+					it('should show the role dropdown', () => {
+						flexTab.usersAddUserRole.isVisible().should.be.true;
+					});
+
+					it('should show the join default channel checkbox', () => {
+						flexTab.usersAddUserDefaultChannelCheckbox.isVisible().should.be.true;
+					});
+
+					it('should show the send welcome checkbox', () => {
+						flexTab.usersAddUserWelcomeEmailCheckbox.isVisible().should.be.true;
+					});
+
+					it('should show the save button', () => {
+						flexTab.usersButtonSave.isVisible().should.be.true;
+					});
+
+					it('should show the cancel button', () => {
+						flexTab.usersButtonCancel.isVisible().should.be.true;
+					});
+				});
+			});
+		});
+
+		describe('roles', () => {
+			before(() =>{
+				admin.permissionsLink.waitForVisible(5000);
+				admin.permissionsLink.click();
+				admin.rolesPermissionGrid.waitForVisible(5000);
+			});
+
+			after(() => {
+				admin.infoLink.click();
+			});
+
+			it('should show the permissions grid', () => {
+				admin.rolesPermissionGrid.isVisible().should.be.true;
+			});
+
+			it('should show the new role button', () => {
+				admin.rolesNewRolesButton.isVisible().should.be.true;
+			});
+
+			it('should show the admin link', () => {
+				admin.rolesAdmin.isVisible().should.be.true;
+			});
+
+			describe('new role', () => {
+				before(() => {
+					admin.rolesNewRolesButton.waitForVisible(5000);
+					admin.rolesNewRolesButton.click();
+					admin.rolesReturnLink.waitForVisible(5000);
+				});
+
+				after(() => {
+					admin.rolesReturnLink.click();
+				});
+
+				it('should show the return to permissions', () => {
+					admin.rolesReturnLink.isVisible().should.be.true;
+				});
+
+				it('should show the new role name field', () => {
+					admin.rolesNewRoleName.isVisible().should.be.true;
+				});
+
+				it('should show the new role description field', () => {
+					admin.rolesNewRoleDesc.isVisible().should.be.true;
+				});
+
+				it('should show the new role scope', () => {
+					admin.rolesNewRoleScope.isVisible().should.be.true;
+				});
+			});
+
+			describe('admin role', () => {
+				before(() => {
+					admin.rolesAdmin.waitForVisible(5000);
+					admin.rolesAdmin.click();
+					admin.usersInternalAdmin.waitForVisible(5000);
+				});
+
+				after(() => {
+					admin.rolesReturnLink.click();
+				});
+
+				it('should show internal admin', () => {
+					admin.usersInternalAdmin.isVisible().should.be.true;
+				});
+			});
+		});
+
+		describe('general settings', () => {
+			before(() => {
+				admin.generalLink.waitForVisible(5000);
+				admin.generalLink.click();
+				admin.generalSiteUrl.waitForVisible(5000);
+			});
+
+			describe('general', () => {
+				it('should show site url field', () => {
+					admin.generalSiteUrl.isVisible().should.be.true;
+				});
+
+				it('should change site url field', () => {
+					admin.generalSiteUrl.setValue('something');
+				});
+
+				it('should show the reset button', () => {
+					admin.generalSiteUrlReset.waitForVisible(5000);
+					admin.generalSiteUrlReset.isVisible().should.be.true;
+				});
+
+				it('should click the reset button', () => {
+					admin.generalSiteUrlReset.click();
+				});
+
+				it('the site url field should be different from the last input', () => {
+					admin.generalSiteUrl.getText().should.not.equal('something');
+				});
+
+				it('should show site name field', () => {
+					admin.generalSiteName.isVisible().should.be.true;
+				});
+
+				it('should change site name field', () => {
+					admin.generalSiteName.setValue('something');
+				});
+
+				it('should show the reset button', () => {
+					admin.generalSiteNameReset.waitForVisible(5000);
+					admin.generalSiteNameReset.isVisible().should.be.true;
+				});
+
+				it('should click the reset button', () => {
+					admin.generalSiteNameReset.click();
+				});
+
+				it('the name field should be different from the last input', () => {
+					admin.generalSiteName.getText().should.not.equal('something');
+				});
+
+				it('should show language field', () => {
+					admin.generalLanguage.isVisible().should.be.true;
+				});
+
+				it('should change the language ', () => {
+					admin.generalLanguage.click();
+					admin.generalLanguagePtOption.waitForVisible(5000);
+					admin.generalLanguagePtOption.click();
+				});
+
+				it('should show the reset button', () => {
+					admin.generalLanguageReset.waitForVisible(5000);
+					admin.generalLanguageReset.isVisible().should.be.true;
+				});
+
+				it('should click the reset button', () => {
+					admin.generalLanguageReset.click();
+				});
+
+				it('should show invalid self signed certs checkboxes', () => {
+					admin.generalSelfSignedCertsFalse.isVisible().should.be.true;
+					admin.generalSelfSignedCertsTrue.isVisible().should.be.true;
+				});
+
+				it('should change the invalid self signed certs checkboxes', () => {
+					admin.generalSelfSignedCertsTrue.click();
+				});
+
+				it('should show the reset button', () => {
+					admin.generalSelfSignedCertsReset.waitForVisible(5000);
+					admin.generalSelfSignedCertsReset.isVisible().should.be.true;
+				});
+
+				it('should click the reset button', () => {
+					admin.generalSelfSignedCertsReset.click();
+				});
+
+				it('should show favorite rooms checkboxes', () => {
+					admin.generalFavoriteRoomFalse.isVisible().should.be.true;
+					admin.generalFavoriteRoomTrue.isVisible().should.be.true;
+				});
+
+				it('should change the favorite rooms checkboxes', () => {
+					admin.generalFavoriteRoomFalse.click();
+				});
+
+				it('should show the reset button', () => {
+					admin.generalFavoriteRoomReset.waitForVisible(5000);
+					admin.generalFavoriteRoomReset.isVisible().should.be.true;
+				});
+
+				it('should click the reset button', () => {
+					admin.generalFavoriteRoomReset.click();
+				});
+
+				it('should show cdn prefix field', () => {
+					admin.generalCdnPrefix.isVisible().should.be.true;
+				});
+
+				it('should change site url field', () => {
+					admin.generalCdnPrefix.setValue('something');
+				});
+
+				it('should show the reset button', () => {
+					admin.generalCdnPrefixReset.waitForVisible(5000);
+					admin.generalCdnPrefixReset.isVisible().should.be.true;
+				});
+
+				it('should click the reset button', () => {
+					admin.generalCdnPrefixReset.click();
+				});
+
+				it('should show the force SSL checkboxes', () => {
+					admin.generalForceSSLTrue.isVisible().should.be.true;
+					admin.generalForceSSLFalse.isVisible().should.be.true;
+				});
+
+				it('should change the force ssl checkboxes', () => {
+					admin.generalForceSSLTrue.click();
+				});
+
+				it('should show the reset button', () => {
+					admin.generalForceSSLReset.waitForVisible(5000);
+					admin.generalForceSSLReset.isVisible().should.be.true;
+				});
+
+				it('should click the reset button', () => {
+					admin.generalForceSSLReset.click();
+				});
+
+				it('should show google tag id field', () => {
+					admin.generalGoogleTagId.isVisible().should.be.true;
+				});
+
+				it('should change google tag id field', () => {
+					admin.generalGoogleTagId.setValue('something');
+				});
+
+				it('should show the reset button', () => {
+					admin.generalGoogleTagIdReset.waitForVisible(5000);
+					admin.generalGoogleTagIdReset.isVisible().should.be.true;
+				});
+
+				it('should click the reset button', () => {
+					admin.generalGoogleTagIdReset.click();
+				});
+
+				it('should show bugsnag key field', () => {
+					admin.generalBugsnagKey.isVisible().should.be.true;
+				});
+
+				it('should change bugsnag key id field', () => {
+					admin.generalBugsnagKey.setValue('something');
+				});
+
+				it('should show the reset button', () => {
+					admin.generalBugsnagKeyReset.waitForVisible(5000);
+					admin.generalBugsnagKeyReset.isVisible().should.be.true;
+				});
+
+				it('should click the reset button', () => {
+					admin.generalBugsnagKeyReset.click();
+				});
+			});
+
+			describe('iframe', () => {
+				before(() => {
+					admin.generalButtonExpandIframe.waitForVisible(5000);
+					admin.generalButtonExpandIframe.click();
+					admin.generalIframeSendTrue.waitForVisible(5000);
+					admin.generalIframeSendTrue.scroll();
+				});
+
+				it('should show iframe send checkboxes', () => {
+					admin.generalIframeSendTrue.isVisible().should.be.true;
+					admin.generalIframeSendFalse.isVisible().should.be.true;
+				});
+
+				it('should show send origin field', () => {
+					admin.generalIframeSendTargetOrigin.isVisible().should.be.true;
+				});
+
+				it('should show iframe send checkboxes', () => {
+					admin.generalIframeRecieveFalse.isVisible().should.be.true;
+					admin.generalIframeRecieveTrue.isVisible().should.be.true;
+				});
+
+				it('should show send origin field', () => {
+					admin.generalIframeRecieveOrigin.isVisible().should.be.true;
+				});
+			});
+
+			describe('notifications', () => {
+				before(() => {
+					admin.generalButtonExpandNotifications.waitForVisible(5000);
+					admin.generalButtonExpandNotifications.click();
+					admin.generalNotificationDuration.waitForVisible(5000);
+					admin.generalNotificationDuration.scroll();
+				});
+
+				it('should show the notifications durations field', () => {
+					admin.generalNotificationDuration.isVisible().should.be.true;
+				});
+			});
+
+			describe('rest api', () => {
+				before(() => {
+					admin.generalButtonExpandRest.waitForVisible(5000);
+					admin.generalButtonExpandRest.click();
+					admin.generalRestApiUserLimit.waitForVisible(5000);
+					admin.generalRestApiUserLimit.scroll();
+				});
+
+				it('should show the API user add limit field', () => {
+					admin.generalRestApiUserLimit.isVisible().should.be.true;
+				});
+			});
+
+			describe('reporting', () => {
+				before(() => {
+					admin.generalButtonExpandReporting.waitForVisible(5000);
+					admin.generalButtonExpandReporting.click();
+					admin.generalReportingTrue.waitForVisible(5000);
+					admin.generalReportingTrue.scroll();
+				});
+
+				it('should show the report to rocket.chat checkboxes', () => {
+					admin.generalReportingTrue.isVisible().should.be.true;
+					admin.generalReportingFalse.isVisible().should.be.true;
+				});
+			});
+
+			describe('stream cast', () => {
+				before(() => {
+					admin.generalButtonExpandStreamCast.waitForVisible(5000);
+					admin.generalButtonExpandStreamCast.click();
+					admin.generalStreamCastAdress.waitForVisible(5000);
+					admin.generalStreamCastAdress.scroll();
+				});
+
+				it('should show the stream cast adress field', () => {
+					admin.generalStreamCastAdress.isVisible().should.be.true;
+				});
+			});
+
+			describe('stream cast', () => {
+				before(() => {
+					admin.generalButtonExpandUTF8.waitForVisible(5000);
+					admin.generalButtonExpandUTF8.click();
+					admin.generalUTF8Regex.waitForVisible(5000);
+					admin.generalUTF8Regex.scroll();
+				});
+
+				it('should show the utf8 regex field', () => {
+					admin.generalUTF8Regex.isVisible().should.be.true;
+				});
+
+				it('should show the utf8 names slug checkboxes', () => {
+					admin.generalUTF8NamesSlugTrue.isVisible().should.be.true;
+					admin.generalUTF8NamesSlugFalse.isVisible().should.be.true;
+				});
+			});
+		});
+	});
+});
\ No newline at end of file
diff --git a/tests/steps/12-admin-settings.js b/tests/steps/12-admin-settings.js
new file mode 100644
index 0000000000000000000000000000000000000000..5184efb7275b745d86cb88e2303fb33c3dfe517f
--- /dev/null
+++ b/tests/steps/12-admin-settings.js
@@ -0,0 +1,161 @@
+/* eslint-env mocha */
+/* eslint-disable func-names, prefer-arrow-callback */
+
+import sideNav from '../pageobjects/side-nav.page';
+import flexTab from '../pageobjects/flex-tab.page';
+import admin from '../pageobjects/administration.page';
+import mainContent from '../pageobjects/main-content.page';
+import {checkIfUserIsValid} from '../data/checks';
+
+//test data imports
+import {checkIfUserIsAdmin} from '../data/checks';
+import {username, email, password, adminUsername, adminEmail, adminPassword} from '../data/user.js';
+
+describe('Admin settings', () => {
+	before(() => {
+		checkIfUserIsAdmin(adminUsername, adminEmail, adminPassword);
+		sideNav.getChannelFromList('general').waitForExist(5000);
+		sideNav.openChannel('general');
+		sideNav.accountBoxUserName.waitForVisible(5000);
+		sideNav.accountBoxUserName.click();
+		sideNav.admin.waitForVisible(5000);
+		sideNav.admin.click();
+	});
+
+	describe('user creation via admin view', () => {
+		before(() => {
+			admin.usersLink.waitForVisible(5000);
+			admin.usersLink.click();
+			admin.usersFilter.waitForVisible(5000);
+			flexTab.usersAddUserTab.waitForVisible(5000);
+			flexTab.usersAddUserTab.click();
+			flexTab.usersAddUserName.waitForVisible(5000);
+		});
+
+		after(() => {
+			admin.infoLink.waitForVisible(5000);
+			admin.infoLink.click();
+		});
+
+		it('create a user', () => {
+			flexTab.usersAddUserName.setValue('adminCreated'+username);
+			flexTab.usersAddUserUsername.setValue('adminCreated'+username);
+			flexTab.usersAddUserEmail.setValue('adminCreated'+email);
+			flexTab.usersAddUserVerifiedCheckbox.click();
+			flexTab.usersAddUserPassword.setValue(password);
+			flexTab.usersAddUserChangePasswordCheckbox.click();
+			flexTab.usersButtonSave.click();
+		});
+
+		it('should show the user in the list', () => {
+			browser.pause(200);
+			var element = browser.element('td=adminCreated'+username);
+			element.isVisible().should.be.visible;
+		});
+	});
+
+	describe('permissions', () => {
+		before(() => {
+			admin.permissionsLink.waitForVisible(5000);
+			admin.permissionsLink.click();
+			admin.rolesPermissionGrid.waitForVisible(5000);
+		});
+
+		describe('changing the permissions', () => {
+			it('should change the create c room permission', () => {
+				if (admin.rolesUserCreateC.isSelected()) {
+					admin.rolesUserCreateC.waitForVisible(5000);
+					admin.rolesUserCreateC.scroll();
+					admin.rolesUserCreateC.click();
+				}
+			});
+
+			it('should change the create d room permission', () => {
+				if (admin.rolesUserCreateD.isSelected()) {
+					admin.rolesUserCreateD.waitForVisible(5000);
+					admin.rolesUserCreateD.scroll();
+					admin.rolesUserCreateD.click();
+				}
+			});
+
+			it('should change the create p room permission', () => {
+				if (admin.rolesUserCreateP.isSelected()) {
+					admin.rolesUserCreateP.waitForVisible(5000);
+					admin.rolesUserCreateP.scroll();
+					admin.rolesUserCreateP.click();
+				}
+			});
+
+			it('should change the mention all permission', () => {
+				if (admin.rolesUserMentionAll.isSelected()) {
+					admin.rolesUserMentionAll.waitForVisible(5000);
+					admin.rolesUserMentionAll.scroll();
+					admin.rolesUserMentionAll.click();
+				}
+			});
+
+			it('should change the delete message all permission for owners', () => {
+				if (admin.rolesOwnerDeleteMessage.isSelected()) {
+					admin.rolesOwnerDeleteMessage.waitForVisible(5000);
+					admin.rolesOwnerDeleteMessage.scroll();
+					admin.rolesOwnerDeleteMessage.click();
+				}
+			});
+
+			it('should change the edit message all permission for owners', () => {
+				if (admin.rolesOwnerEditMessage.isSelected()) {
+					admin.rolesOwnerEditMessage.waitForVisible(5000);
+					admin.rolesOwnerEditMessage.scroll();
+					admin.rolesOwnerEditMessage.click();
+				}
+			});
+		});
+	});
+	describe('test the permissions', () => {
+		before(() => {
+			sideNav.preferencesClose.waitForVisible(5000);
+			sideNav.preferencesClose.click();
+
+			checkIfUserIsValid('adminCreated'+username, 'adminCreated'+email, password);
+		});
+
+		it('should not show the plus icon on channels ', () => {
+			sideNav.newChannelIcon.isVisible().should.be.false;
+		});
+
+		it('when clicked should not show the new channel name input ', () => {
+			sideNav.newChannelBtn.click();
+			sideNav.channelName.isVisible().should.be.false;
+		});
+
+		it('should not show the plus icon on direct messages ', () => {
+			sideNav.newDirectMessageIcon.isVisible().should.be.false;
+		});
+
+		it('when clicked should not show the new direct message user input ', () => {
+			sideNav.newDirectMessageBtn.click();
+			sideNav.directMessageTarget.isVisible().should.be.false;
+		});
+
+		it('go to general', () => {
+			sideNav.getChannelFromList('general').waitForExist(5000);
+			sideNav.openChannel('general');
+		});
+
+		it('try to use @all and should be warned by rocket.cat ', () => {
+			mainContent.addTextToInput('@all');
+			mainContent.mentionAllPopUp.waitForVisible(5000);
+			mainContent.mentionAllPopUp.click();
+			mainContent.sendBtn.click();
+			mainContent.lastMessage.getText().should.equal('Notify all in this room is not allowed');
+		});
+
+		it.skip('should not be able to delete own message ', () => {
+			//waiting for changes in the delete-message permission
+		});
+
+		it.skip('should not be able to edit own message ', () => {
+			//waiting for changes in the edit-message permission
+		});
+	});
+});
\ No newline at end of file
diff --git a/tests/steps/3-basic-usage.js b/tests/steps/3-basic-usage.js
deleted file mode 100644
index 76530743bd30979f86dc4d57c4c5ea3d8beded71..0000000000000000000000000000000000000000
--- a/tests/steps/3-basic-usage.js
+++ /dev/null
@@ -1,975 +0,0 @@
-/* eslint-env mocha */
-/* eslint-disable func-names, prefer-arrow-callback */
-
-import loginPage from '../pageobjects/login.page';
-import flexTab from '../pageobjects/flex-tab.page';
-import mainContent from '../pageobjects/main-content.page';
-import sideNav from '../pageobjects/side-nav.page';
-
-//test data imports
-import {username, email, password} from '../test-data/user.js';
-import {publicChannelName, privateChannelName} from '../test-data/channel.js';
-import {targetUser, imgURL} from '../test-data/interactions.js';
-
-//Test data
-const message = 'message from '+username;
-
-
-//Basic usage test start
-describe('Basic usage', function() {
-	this.retries(2);
-
-	it('load page', () => {
-		loginPage.open();
-	});
-
-	it('create user', () => {
-		loginPage.gotToRegister();
-
-		loginPage.registerNewUser({username, email, password});
-
-		browser.waitForExist('form#login-card input#username', 5000);
-
-		browser.click('.submit > button');
-
-		mainContent.mainContent.waitForExist(5000);
-	});
-
-	it('logout', () => {
-		sideNav.accountBoxUserName.waitForVisible(5000);
-		sideNav.accountBoxUserName.click();
-		browser.pause(200);
-
-		sideNav.logout.waitForVisible(5000);
-		sideNav.logout.click();
-	});
-
-	it('login', () => {
-		loginPage.login({email, password});
-		mainContent.mainContent.waitForExist(5000);
-	});
-
-	describe('side nav bar', () => {
-		describe('render', () => {
-			it('should show the logged username', () => {
-				sideNav.accountBoxUserName.isVisible().should.be.true;
-			});
-
-			it('should show the logged user avatar', () => {
-				sideNav.accountBoxUserAvatar.isVisible().should.be.true;
-			});
-
-			it('should show the new channel button', () => {
-				sideNav.newChannelBtn.isVisible().should.be.true;
-			});
-
-			it('should show the plus icon', () => {
-				sideNav.newChannelIcon.isVisible().should.be.true;
-			});
-
-			it('should show the "More Channels" button', () => {
-				sideNav.moreChannels.isVisible().should.be.true;
-			});
-
-			it('should show the new direct message button', () => {
-				sideNav.newDirectMessageBtn.isVisible().should.be.true;
-			});
-
-			it('should show the plus icon', () => {
-				sideNav.newDirectMessageIcon.isVisible().should.be.true;
-			});
-
-			it('should show the "More Direct Messages" button', () => {
-				sideNav.moreDirectMessages.isVisible().should.be.true;
-			});
-
-			it('should show "general" channel', () => {
-				sideNav.general.isVisible().should.be.true;
-			});
-
-			it('should not show eye icon on general', () => {
-				sideNav.channelHoverIcon.isVisible().should.be.false;
-			});
-		});
-
-		describe('user options', () => {
-			describe('render', () => {
-				before(() => {
-					sideNav.accountBoxUserName.click();
-				});
-
-				after(() => {
-					sideNav.accountBoxUserName.click();
-				});
-
-				it('should show user options', () => {
-					sideNav.userOptions.waitForVisible();
-					sideNav.userOptions.isVisible().should.be.true;
-				});
-
-				it('should show online button', () => {
-					sideNav.statusOnline.isVisible().should.be.true;
-				});
-
-				it('should show away button', () => {
-					sideNav.statusAway.isVisible().should.be.true;
-				});
-
-				it('should show busy button', () => {
-					sideNav.statusBusy.isVisible().should.be.true;
-				});
-
-				it('should show offline button', () => {
-					sideNav.statusOffline.isVisible().should.be.true;
-				});
-
-				it('should show settings button', () => {
-					sideNav.account.isVisible().should.be.true;
-				});
-
-				it('should show logout button', () => {
-					sideNav.logout.isVisible().should.be.true;
-				});
-			});
-		});
-	});
-
-	describe('Setting the tests Preferences', () => {
-		it('opens the user preferences screen', () => {
-			sideNav.accountBoxUserName.waitForVisible();
-			sideNav.accountBoxUserName.click();
-			sideNav.account.waitForVisible();
-			sideNav.account.click();
-		});
-
-		it('Sets the language to english', () => {
-			mainContent.setLanguageToEnglish();
-			browser.pause(10000);
-		});
-
-		it('close the preferences menu', () => {
-			sideNav.preferencesClose.click();
-		});
-	});
-
-	describe('general channel', () => {
-		it('open GENERAL', () => {
-			sideNav.getChannelFromList('general').waitForExist(5000);
-			sideNav.openChannel('general');
-		});
-
-		it('send a message', () => {
-			mainContent.sendMessage(message);
-		});
-
-		describe('main content usage', () => {
-			describe('render', () => {
-				it('should show the title of the channel', () => {
-					mainContent.channelTitle.isVisible().should.be.true;
-				});
-
-				it('should show the empty favorite star', () => {
-					mainContent.emptyFavoriteStar.isVisible().should.be.true;
-				});
-
-				it('clicks the star', () => {
-					mainContent.emptyFavoriteStar.click();
-				});
-
-				it('should not show the empty favorite star', () => {
-					mainContent.favoriteStar.isVisible().should.be.true;
-				});
-
-				it('clicks the star', () => {
-					mainContent.favoriteStar.click();
-				});
-
-				it('should show the message input bar', () => {
-					mainContent.messageInput.isVisible().should.be.true;
-				});
-
-				it('should show the file attachment button', () => {
-					mainContent.fileAttachmentBtn.isVisible().should.be.true;
-				});
-
-				it('should show the audio recording button', () => {
-					mainContent.recordBtn.isVisible().should.be.true;
-				});
-
-				it('should show the video call button', () => {
-					mainContent.videoCamBtn.isVisible().should.be.true;
-				});
-
-				it('should not show the send button', () => {
-					mainContent.sendBtn.isVisible().should.be.false;
-				});
-
-				it('should show the emoji button', () => {
-					mainContent.emojiBtn.isVisible().should.be.true;
-				});
-
-				it('adds some text to the input', () => {
-					mainContent.addTextToInput('Some Text');
-				});
-
-				it('should show the send button', () => {
-					mainContent.sendBtn.isVisible().should.be.true;
-				});
-
-				it('should not show the file attachment button', () => {
-					mainContent.fileAttachmentBtn.isVisible().should.be.false;
-				});
-
-				it('should not show the audio recording button', () => {
-					mainContent.recordBtn.isVisible().should.be.false;
-				});
-
-				it('should not show the video call button', () => {
-					mainContent.videoCamBtn.isVisible().should.be.false;
-				});
-
-				it('should show the last message', () => {
-					mainContent.lastMessage.isVisible().should.be.true;
-				});
-
-				it('the last message should be from the loged user', () => {
-					mainContent.lastMessageUser.getText().should.equal(username);
-				});
-
-				it('should not show the Admin tag', () => {
-					mainContent.lastMessageUserTag.isVisible().should.be.false;
-				});
-			});
-
-			describe('fileUpload', ()=> {
-				it('send a attachment', () => {
-					mainContent.fileUpload(imgURL);
-				});
-
-				it('should show the confirm button', () => {
-					mainContent.popupFileConfirmBtn.isVisible().should.be.true;
-				});
-
-				it('should show the cancel button', () => {
-					mainContent.popupFileCancelBtn.isVisible().should.be.true;
-				});
-
-				it('should show the file preview', () => {
-					mainContent.popupFilePreview.isVisible().should.be.true;
-				});
-
-				it('should show the confirm button', () => {
-					mainContent.popupFileConfirmBtn.isVisible().should.be.true;
-				});
-
-				it('should show the file title', () => {
-					mainContent.popupFileTitle.isVisible().should.be.true;
-				});
-
-				it('click the confirm', () => {
-					mainContent.popupFileConfirmBtn.click();
-				});
-			});
-
-			describe('messages actions in general room', ()=> {
-				describe('render', () => {
-					it('open GENERAL', () => {
-						sideNav.openChannel('general');
-					});
-
-					it('send a message to be tested', () => {
-						mainContent.sendMessage('Message for Message Actions Tests');
-					});
-
-					it('open the message action menu', () => {
-						mainContent.openMessageActionMenu();
-					});
-
-					it('should show the message action menu', () => {
-						mainContent.messageActionMenu.isVisible().should.be.true;
-					});
-
-					it('should show the reply action', () => {
-						mainContent.messageReply.isVisible().should.be.true;
-					});
-
-					it('should show the edit action', () => {
-						mainContent.messageEdit.isVisible().should.be.true;
-					});
-
-					it('should show the delete action', () => {
-						mainContent.messageDelete.isVisible().should.be.true;
-					});
-
-					it('should show the permalink action', () => {
-						mainContent.messagePermalink.isVisible().should.be.true;
-					});
-
-					it('should show the copy action', () => {
-						mainContent.messageCopy.isVisible().should.be.true;
-					});
-
-					it('should show the quote the action', () => {
-						mainContent.messageQuote.isVisible().should.be.true;
-					});
-
-					it('should show the star action', () => {
-						mainContent.messageStar.isVisible().should.be.true;
-					});
-
-					it('should show the reaction action', () => {
-						mainContent.messageReaction.isVisible().should.be.true;
-					});
-
-					it('should show the close action', () => {
-						mainContent.messageClose.isVisible().should.be.true;
-					});
-
-					it('should not show the pin action', () => {
-						mainContent.messagePin.isVisible().should.be.false;
-					});
-
-					it('should not show the mark as unread action', () => {
-						mainContent.messageUnread.isVisible().should.be.false;
-					});
-
-					it('close the action menu', () => {
-						mainContent.selectAction('close');
-					});
-				});
-
-				describe('usage', () => {
-					it('send a message to test the reply', () => {
-						mainContent.sendMessage('Message for reply Tests');
-					});
-
-					it('open the message action menu', () => {
-						mainContent.openMessageActionMenu();
-					});
-
-					it('reply the message', () => {
-						mainContent.selectAction('reply');
-						mainContent.sendBtn.click();
-					});
-
-					it('checks if the message was replied', () => {
-						mainContent.lastMessageTextAttachment.getText().should.equal(mainContent.beforeLastMessage.getText());
-					});
-
-					it('send a message to test the edit', () => {
-						mainContent.addTextToInput('Message for Message edit Tests ');
-						mainContent.sendBtn.click();
-					});
-
-					it('open the message action menu', () => {
-						mainContent.openMessageActionMenu();
-					});
-
-					it('edit the message', () => {
-						mainContent.selectAction('edit');
-						mainContent.sendBtn.click();
-					});
-
-					it('send a message to test the delete', () => {
-						mainContent.sendMessage('Message for Message Delete Tests');
-					});
-
-					it('open the message action menu', () => {
-						mainContent.openMessageActionMenu();
-					});
-
-					it('delete the message', () => {
-						mainContent.selectAction('delete');
-						mainContent.popupFileConfirmBtn.click();
-					});
-
-					it('should not show the deleted message', () => {
-						mainContent.lastMessage.should.not.equal('Message for Message Delete Tests');
-					});
-
-					it('send a message to test the quote', () => {
-						mainContent.sendMessage('Message for quote Tests');
-					});
-
-					it('open the message action menu', () => {
-						mainContent.openMessageActionMenu();
-					});
-
-					it('quote the message', () => {
-						mainContent.selectAction('quote');
-						mainContent.sendBtn.click();
-					});
-
-					it('checks if the message was quoted', () => {
-						mainContent.lastMessageTextAttachment.getText().should.equal(mainContent.beforeLastMessage.getText());
-					});
-
-					it('send a message to test the star', () => {
-						mainContent.sendMessage('Message for star Tests');
-					});
-
-					it('open the message action menu', () => {
-						mainContent.openMessageActionMenu();
-					});
-
-					it('star the message', () => {
-						mainContent.selectAction('star');
-					});
-
-					it('send a message to test the copy', () => {
-						mainContent.sendMessage('Message for copy Tests');
-					});
-
-					it('open the message action menu', () => {
-						mainContent.openMessageActionMenu();
-					});
-
-					it('copy the message', () => {
-						mainContent.selectAction('copy');
-					});
-
-					it('send a message to test the permalink', () => {
-						mainContent.sendMessage('Message for permalink Tests');
-					});
-
-					it('open the message action menu', () => {
-						mainContent.openMessageActionMenu();
-					});
-
-					it('permalink the message', () => {
-						mainContent.selectAction('permalink');
-					});
-				});
-			});
-		});
-	});
-
-	describe('flextab usage', () => {
-		describe('render', () => {
-			it('should show the room info button', () => {
-				flexTab.channelTab.isVisible().should.be.true;
-			});
-
-			it('should show the room info tab content', () => {
-				browser.pause(7000);
-				flexTab.channelTab.click();
-				flexTab.channelSettings.isVisible().should.be.true;
-			});
-
-			it('should show the message search  button', () => {
-				flexTab.searchTab.isVisible().should.be.true;
-			});
-
-			it('should show the message tab content', () => {
-				browser.pause(5000);
-				flexTab.searchTab.click();
-				flexTab.searchTabContent.isVisible().should.be.true;
-			});
-
-			it('should show the members tab button', () => {
-				flexTab.membersTab.isVisible().should.be.true;
-			});
-
-			it('should show the members content', () => {
-				flexTab.membersTab.click();
-				flexTab.membersTabContent.isVisible().should.be.true;
-			});
-
-			it.skip('should show the members search bar', () => {
-				flexTab.userSearchBar.isVisible().should.be.true;
-			});
-
-			it('should show the show all link', () => {
-				flexTab.showAll.isVisible().should.be.true;
-			});
-
-			it('should show the notifications button', () => {
-				flexTab.notificationsTab.isVisible().should.be.true;
-			});
-
-			it('should show the notifications Tab content', () => {
-				flexTab.notificationsTab.click();
-				flexTab.notificationsSettings.isVisible().should.be.true;
-			});
-
-			it('should show the files button', () => {
-				flexTab.filesTab.isVisible().should.be.true;
-			});
-
-			it('should show the files Tab content', () => {
-				flexTab.filesTab.click();
-				flexTab.filesTabContent.isVisible().should.be.true;
-			});
-
-			it('should show the mentions button', () => {
-				flexTab.mentionsTab.isVisible().should.be.true;
-			});
-
-			it('should show the mentions Tab content', () => {
-				flexTab.mentionsTab.click();
-				flexTab.mentionsTabContent.isVisible().should.be.true;
-			});
-
-			it('should show the starred button', () => {
-				flexTab.starredTab.isVisible().should.be.true;
-			});
-
-			it('should show the starred Tab content', () => {
-				flexTab.starredTab.click();
-				flexTab.starredTabContent.isVisible().should.be.true;
-			});
-
-			it('should show the pinned button', () => {
-				flexTab.pinnedTab.isVisible().should.be.true;
-			});
-
-			it('should show the pinned messages Tab content', () => {
-				flexTab.pinnedTab.click();
-				flexTab.pinnedTabContent.isVisible().should.be.true;
-			});
-		});
-	});
-
-	describe('direct channel', () => {
-		it('start a direct message with rocket.cat', () => {
-			sideNav.startDirectMessage(targetUser);
-		});
-
-		it('open the direct message', () => {
-			sideNav.openChannel(targetUser);
-		});
-
-		it('send a direct message', () => {
-			mainContent.sendMessage(message);
-		});
-
-		it('should show the last message', () => {
-			mainContent.lastMessage.isVisible().should.be.true;
-		});
-
-		it('the last message should be from the loged user', () => {
-			mainContent.lastMessageUser.getText().should.equal(username);
-		});
-
-		it('should not show the Admin tag', () => {
-			mainContent.lastMessageUserTag.isVisible().should.be.false;
-		});
-
-		describe('messages actions in direct messages', ()=> {
-			describe('render', () => {
-				it('open GENERAL', () => {
-					sideNav.openChannel('general');
-				});
-
-				it('send a message to be tested', () => {
-					mainContent.sendMessage('Message for Message Actions Tests');
-				});
-
-				it('open the message action menu', () => {
-					mainContent.openMessageActionMenu();
-				});
-
-				it('should show the message action menu', () => {
-					mainContent.messageActionMenu.isVisible().should.be.true;
-				});
-
-				it('should show the reply action', () => {
-					mainContent.messageReply.isVisible().should.be.true;
-				});
-
-				it('should show the edit action', () => {
-					mainContent.messageEdit.isVisible().should.be.true;
-				});
-
-				it('should show the delete action', () => {
-					mainContent.messageDelete.isVisible().should.be.true;
-				});
-
-				it('should show the permalink action', () => {
-					mainContent.messagePermalink.isVisible().should.be.true;
-				});
-
-				it('should show the copy action', () => {
-					mainContent.messageCopy.isVisible().should.be.true;
-				});
-
-				it('should show the quote the action', () => {
-					mainContent.messageQuote.isVisible().should.be.true;
-				});
-
-				it('should show the star action', () => {
-					mainContent.messageStar.isVisible().should.be.true;
-				});
-
-				it('should show the reaction action', () => {
-					mainContent.messageReaction.isVisible().should.be.true;
-				});
-
-				it('should show the close action', () => {
-					mainContent.messageClose.isVisible().should.be.true;
-				});
-
-				it('should not show the pin action', () => {
-					mainContent.messagePin.isVisible().should.be.false;
-				});
-
-				it('should not show the mark as unread action', () => {
-					mainContent.messageUnread.isVisible().should.be.false;
-				});
-
-				it('close the action menu', () => {
-					mainContent.selectAction('close');
-				});
-			});
-
-			describe('usage', () => {
-				it('send a message to test the reply', () => {
-					mainContent.sendMessage('Message for reply Tests');
-				});
-
-				it('open the message action menu', () => {
-					mainContent.openMessageActionMenu();
-				});
-
-				it('reply the message', () => {
-					mainContent.selectAction('reply');
-					mainContent.sendBtn.click();
-				});
-
-				it('checks if the message was replied', () => {
-					mainContent.lastMessageTextAttachment.getText().should.equal(mainContent.beforeLastMessage.getText());
-				});
-
-				it('send a message to test the edit', () => {
-					mainContent.addTextToInput('Message for Message edit Tests ');
-					mainContent.sendBtn.click();
-				});
-
-				it('open the message action menu', () => {
-					mainContent.openMessageActionMenu();
-				});
-
-				it('edit the message', () => {
-					mainContent.selectAction('edit');
-					mainContent.sendBtn.click();
-				});
-
-				it('send a message to test the delete', () => {
-					mainContent.sendMessage('Message for Message Delete Tests');
-				});
-
-				it('open the message action menu', () => {
-					mainContent.openMessageActionMenu();
-				});
-
-				it('delete the message', () => {
-					mainContent.selectAction('delete');
-					mainContent.popupFileConfirmBtn.click();
-				});
-
-				it('should not show the deleted message', () => {
-					mainContent.lastMessage.should.not.equal('Message for Message Delete Tests');
-				});
-
-				it('send a message to test the quote', () => {
-					mainContent.sendMessage('Message for quote Tests');
-				});
-
-				it('open the message action menu', () => {
-					mainContent.openMessageActionMenu();
-				});
-
-				it('quote the message', () => {
-					mainContent.selectAction('quote');
-					mainContent.sendBtn.click();
-				});
-
-				it('checks if the message was quoted', () => {
-					mainContent.lastMessageTextAttachment.getText().should.equal(mainContent.beforeLastMessage.getText());
-				});
-
-				it('send a message to test the star', () => {
-					mainContent.sendMessage('Message for star Tests');
-				});
-
-				it('open the message action menu', () => {
-					mainContent.openMessageActionMenu();
-				});
-
-				it('star the message', () => {
-					mainContent.selectAction('star');
-				});
-
-				it('send a message to test the copy', () => {
-					mainContent.sendMessage('Message for copy Tests');
-				});
-
-				it('open the message action menu', () => {
-					mainContent.openMessageActionMenu();
-				});
-
-				it('copy the message', () => {
-					mainContent.selectAction('copy');
-				});
-
-				it('send a message to test the permalink', () => {
-					mainContent.sendMessage('Message for permalink Tests');
-				});
-
-				it('open the message action menu', () => {
-					mainContent.openMessageActionMenu();
-				});
-
-				it('permalink the message', () => {
-					mainContent.selectAction('permalink');
-				});
-			});
-		});
-	});
-
-	describe('public channel', () => {
-		it('create a public channel', () => {
-			sideNav.createChannel(publicChannelName, false, false);
-		});
-
-		it('open the public channel', () => {
-			sideNav.openChannel(publicChannelName);
-			browser.pause(3000);
-		});
-
-		it('send a message in the public channel', () => {
-			mainContent.sendMessage(message);
-		});
-
-		it('should show the last message', () => {
-			mainContent.lastMessage.isVisible().should.be.true;
-		});
-
-		it('the last message should be from the loged user', () => {
-			mainContent.lastMessageUser.getText().should.equal(username);
-		});
-
-		it('should not show the Admin tag', () => {
-			var messageTag = mainContent.lastMessageUserTag.getText();
-			messageTag.should.not.equal('Admin');
-		});
-
-		it('should show the Owner tag', () => {
-			var messageTag = mainContent.lastMessageUserTag.getText();
-			messageTag.should.equal('Owner');
-		});
-
-		it('add people to the room', () => {
-			flexTab.membersTab.click();
-			flexTab.addPeopleToChannel(targetUser);
-		});
-
-		it('remove people from room', () => {
-			flexTab.removePeopleFromChannel(targetUser);
-			flexTab.confirmPopup();
-		});
-
-		it.skip('archive the room', () => {
-			flexTab.channelTab.click();
-			flexTab.archiveChannel();
-			flexTab.channelTab.click();
-		});
-
-		it('open GENERAL', () => {
-			sideNav.openChannel('general');
-		});
-	});
-
-	describe('private channel', () => {
-		it('create a private channel', () => {
-			sideNav.createChannel(privateChannelName, true, false);
-		});
-
-		it('send a message in the private channel', () => {
-			mainContent.sendMessage(message);
-		});
-
-		describe('messages actions in private room', ()=> {
-			describe('render', () => {
-				it('send a message to be tested', () => {
-					mainContent.sendMessage('Message for Message Actions Tests');
-				});
-
-				it('open the message action menu', () => {
-					mainContent.openMessageActionMenu();
-				});
-
-				it('should show the message action menu', () => {
-					mainContent.messageActionMenu.isVisible().should.be.true;
-				});
-
-				it('should show the reply action', () => {
-					mainContent.messageReply.isVisible().should.be.true;
-				});
-
-				it('should show the edit action', () => {
-					mainContent.messageEdit.isVisible().should.be.true;
-				});
-
-				it('should show the delete action', () => {
-					mainContent.messageDelete.isVisible().should.be.true;
-				});
-
-				it('should show the permalink action', () => {
-					mainContent.messagePermalink.isVisible().should.be.true;
-				});
-
-				it('should show the copy action', () => {
-					mainContent.messageCopy.isVisible().should.be.true;
-				});
-
-				it('should show the quote the action', () => {
-					mainContent.messageQuote.isVisible().should.be.true;
-				});
-
-				it('should show the star action', () => {
-					mainContent.messageStar.isVisible().should.be.true;
-				});
-
-				it('should show the reaction action', () => {
-					mainContent.messageReaction.isVisible().should.be.true;
-				});
-
-				it('should show the close action', () => {
-					mainContent.messageClose.isVisible().should.be.true;
-				});
-
-				it('should show show the pin action', () => {
-					mainContent.messagePin.isVisible().should.be.true;
-				});
-
-				it('should not show the mark as unread action', () => {
-					mainContent.messageUnread.isVisible().should.be.false;
-				});
-
-				it('close the action menu', () => {
-					mainContent.selectAction('close');
-				});
-			});
-
-			describe('usage', () => {
-				it('send a message to test the reply', () => {
-					mainContent.sendMessage('Message for reply Tests');
-				});
-
-				it('open the message action menu', () => {
-					mainContent.openMessageActionMenu();
-				});
-
-				it('reply the message', () => {
-					mainContent.selectAction('reply');
-					mainContent.sendBtn.click();
-				});
-
-				it('checks if the message was replied', () => {
-					mainContent.lastMessageTextAttachment.getText().should.equal(mainContent.beforeLastMessage.getText());
-				});
-
-				it('send a message to test the edit', () => {
-					mainContent.addTextToInput('Message for Message edit Tests ');
-					mainContent.sendBtn.click();
-				});
-
-				it('open the message action menu', () => {
-					mainContent.openMessageActionMenu();
-				});
-
-				it('edit the message', () => {
-					mainContent.selectAction('edit');
-					mainContent.sendBtn.click();
-				});
-
-				it('send a message to test the delete', () => {
-					mainContent.sendMessage('Message for Message Delete Tests');
-				});
-
-				it('open the message action menu', () => {
-					mainContent.openMessageActionMenu();
-				});
-
-				it('delete the message', () => {
-					mainContent.selectAction('delete');
-					mainContent.popupFileConfirmBtn.click();
-				});
-
-				it('should not show the deleted message', () => {
-					mainContent.lastMessage.should.not.equal('Message for Message Delete Tests');
-				});
-
-				it('send a message to test the quote', () => {
-					mainContent.sendMessage('Message for quote Tests');
-				});
-
-				it('open the message action menu', () => {
-					mainContent.openMessageActionMenu();
-				});
-
-				it('quote the message', () => {
-					mainContent.selectAction('quote');
-					mainContent.sendBtn.click();
-				});
-
-				it('checks if the message was quoted', () => {
-					mainContent.lastMessageTextAttachment.getText().should.equal(mainContent.beforeLastMessage.getText());
-				});
-
-				it('send a message to test the star', () => {
-					mainContent.sendMessage('Message for star Tests');
-				});
-
-				it('open the message action menu', () => {
-					mainContent.openMessageActionMenu();
-				});
-
-				it('star the message', () => {
-					mainContent.selectAction('star');
-				});
-
-				it('send a message to test the copy', () => {
-					mainContent.sendMessage('Message for copy Tests');
-				});
-
-				it('open the message action menu', () => {
-					mainContent.openMessageActionMenu();
-				});
-
-				it('copy the message', () => {
-					mainContent.selectAction('copy');
-				});
-
-				it('send a message to test the permalink', () => {
-					mainContent.sendMessage('Message for permalink Tests');
-				});
-
-				it('open the message action menu', () => {
-					mainContent.openMessageActionMenu();
-				});
-
-				it('permalink the message', () => {
-					mainContent.selectAction('permalink');
-				});
-			});
-		});
-
-		it('add people to the room', () => {
-			flexTab.membersTab.click();
-			flexTab.addPeopleToChannel(targetUser);
-		});
-
-		it('remove people from room', () => {
-			flexTab.removePeopleFromChannel(targetUser);
-			flexTab.confirmPopup();
-		});
-
-		it('archive the room', () => {
-			flexTab.channelTab.click();
-			flexTab.archiveChannel();
-			flexTab.channelTab.click();
-		});
-	});
-});
diff --git a/tests/steps/4-resolutions.js b/tests/steps/4-resolutions.js
deleted file mode 100644
index 893f4ccaf0fb240520c2fefef1e509e6a0fa7e02..0000000000000000000000000000000000000000
--- a/tests/steps/4-resolutions.js
+++ /dev/null
@@ -1,102 +0,0 @@
-/* eslint-env mocha */
-/* eslint-disable func-names, prefer-arrow-callback */
-
-import mainContent from '../pageobjects/main-content.page';
-import sideNav from '../pageobjects/side-nav.page';
-
-describe('resolutions tests', ()=> {
-	describe('mobile render', ()=> {
-		it('change the resolution', ()=> {
-			browser.windowHandleSize({
-				width: 650,
-				height: 800
-			});
-		});
-
-		it('should close de sidenav', () => {
-			mainContent.mainContent.getLocation().should.deep.equal({x:0, y:0});
-		});
-
-		it('press the navbar button', () => {
-			sideNav.sideNavBtn.click();
-		});
-
-		it('should open de sidenav', () => {
-			browser.pause(1000);
-			mainContent.mainContent.getLocation().should.not.deep.equal({x:0, y:0});
-		});
-
-		it('open general channel', () => {
-			sideNav.openChannel('general');
-		});
-
-		it('should close de sidenav', () => {
-			browser.pause(1000);
-			mainContent.mainContent.getLocation().should.deep.equal({x:0, y:0});
-		});
-
-		it('press the navbar button', () => {
-			sideNav.sideNavBtn.click();
-		});
-
-		it('opens the user preferences screen', () => {
-			sideNav.accountBoxUserName.waitForVisible();
-			sideNav.accountBoxUserName.click();
-			sideNav.account.waitForVisible();
-			sideNav.account.click();
-		});
-
-		it('press the preferences link', () => {
-			sideNav.preferences.waitForVisible();
-			sideNav.preferences.click();
-		});
-
-		it('should close de sidenav', () => {
-			browser.pause(1000);
-			mainContent.mainContent.getLocation().should.deep.equal({x:0, y:0});
-		});
-
-		it('press the navbar button', () => {
-			sideNav.sideNavBtn.click();
-		});
-
-		it('press the profile link', () => {
-			sideNav.profile.waitForVisible();
-			sideNav.profile.click();
-		});
-
-		it('should close de sidenav', () => {
-			browser.pause(1000);
-			mainContent.mainContent.getLocation().should.deep.equal({x:0, y:0});
-		});
-
-		it('press the navbar button', () => {
-			sideNav.sideNavBtn.click();
-		});
-
-		it('press the avatar link', () => {
-			sideNav.avatar.waitForVisible();
-			sideNav.avatar.click();
-		});
-
-		it('should close de sidenav', () => {
-			browser.pause(1000);
-			mainContent.mainContent.getLocation().should.deep.equal({x:0, y:0});
-		});
-
-		it('press the navbar button', () => {
-			sideNav.sideNavBtn.click();
-		});
-
-		it('change the resolution', ()=> {
-			browser.windowHandleSize({
-				width: 1450,
-				height: 900
-			});
-		});
-
-		it('close the preferences menu', () => {
-			sideNav.preferencesClose.click();
-		});
-	});
-});
\ No newline at end of file
diff --git a/tests/steps/6-channel.js b/tests/steps/6-channel.js
deleted file mode 100644
index 879c6eea2b99e8b1c092d95ae5dbc4254b8f1376..0000000000000000000000000000000000000000
--- a/tests/steps/6-channel.js
+++ /dev/null
@@ -1,132 +0,0 @@
-/* eslint-env mocha */
-/* eslint-disable func-names, prefer-arrow-callback */
-
-import flexTab from '../pageobjects/flex-tab.page';
-import mainContent from '../pageobjects/main-content.page';
-import sideNav from '../pageobjects/side-nav.page';
-
-import {username} from '../test-data/user.js';
-import {publicChannelName} from '../test-data/channel.js';
-import {targetUser} from '../test-data/interactions.js';
-
-describe('channel settings', ()=> {
-
-	describe('channel info tab', ()=> {
-		it('open the channel', ()=> {
-			sideNav.openChannel(publicChannelName);
-		});
-
-		it('open the channel info tab', ()=> {
-			flexTab.channelTab.waitForVisible();
-			flexTab.channelTab.click();
-		});
-
-		it('should show the old name', ()=> {
-			flexTab.firstSetting.waitForVisible();
-			flexTab.firstSetting.getText().should.equal(publicChannelName);
-		});
-
-		it('click the edit name', ()=> {
-			flexTab.editNameBtn.waitForVisible();
-			flexTab.editNameBtn.click();
-		});
-
-		it('edit the name input', ()=> {
-			flexTab.editNameTextInput.waitForVisible();
-			flexTab.editNameTextInput.setValue('NAME-EDITED-'+publicChannelName);
-		});
-
-		it('save the name', ()=> {
-			flexTab.editNameSave.click();
-
-		});
-
-		it('should show the new name', ()=> {
-			//gives timeout errors
-			var channelName = sideNav.getChannelFromList('NAME-EDITED-'+publicChannelName);
-			channelName.getText().should.equal('NAME-EDITED-'+publicChannelName);
-		});
-
-		it('click the edit topic', ()=> {
-			browser.pause(500);
-			flexTab.editTopicBtn.waitForVisible(5000);
-			flexTab.editTopicBtn.click();
-		});
-
-		it('edit the topic input', ()=> {
-			flexTab.editTopicTextInput.waitForVisible(5000);
-			flexTab.editTopicTextInput.setValue('TOPIC EDITED');
-		});
-
-		it('save the topic', ()=> {
-			flexTab.editNameSave.click();
-		});
-
-		it('should show the new topic', ()=> {
-			flexTab.secondSetting.getText().should.equal('TOPIC EDITED');
-		});
-
-		it('click the edit description', ()=> {
-			flexTab.editDescriptionBtn.waitForVisible();
-			flexTab.editDescriptionBtn.click();
-		});
-
-		it('edit the description input', ()=> {
-			flexTab.editDescriptionTextInput.waitForVisible();
-			flexTab.editDescriptionTextInput.setValue('DESCRIPTION EDITED');
-		});
-
-		it('save the description', ()=> {
-			flexTab.editNameSave.click();
-		});
-
-		it('should show the new description', ()=> {
-			flexTab.thirdSetting.getText().should.equal('DESCRIPTION EDITED');
-		});
-
-		it('dismiss the toast', ()=> {
-			flexTab.dismissToast();
-		});
-
-		it('open the users tab', ()=> {
-			flexTab.membersTab.waitForVisible();
-			flexTab.membersTab.click();
-
-		});
-
-		it('sets rocket cat as owner', ()=> {
-			flexTab.setUserOwner(targetUser);
-		});
-
-		it('dismiss the toast', ()=> {
-			flexTab.dismissToast();
-		});
-
-		it('should show the owner add message', ()=> {
-			mainContent.lastMessage.getText().should.equal(targetUser+' was set owner by '+username);
-		});
-
-		it('sets rocket cat as moderator', ()=> {
-			browser.pause(1000);
-			flexTab.setUserModerator(targetUser);
-		});
-
-		it('should show the moderator add message', ()=> {
-			mainContent.lastMessage.getText().should.equal(targetUser+' was set moderator by '+username);
-		});
-
-		it('mute rocket cat', ()=> {
-			browser.pause(5000);
-			flexTab.muteUser(targetUser);
-		});
-
-		it('confirms the popup', ()=> {
-			flexTab.confirmPopup();
-		});
-
-		it('close the user screen', ()=> {
-			browser.pause(5000);
-			flexTab.viewAllBtn.click();
-		});
-	});
-});
\ No newline at end of file
diff --git a/tests/steps/API.js b/tests/steps/API.js
new file mode 100644
index 0000000000000000000000000000000000000000..c5baf7da129a2c0f8f98b1a559a002c2d037749a
--- /dev/null
+++ b/tests/steps/API.js
@@ -0,0 +1,88 @@
+/* eslint-env mocha */
+/* globals expect */
+/* eslint no-unused-vars: 0 */
+
+import supertest from 'supertest';
+const request = supertest('http://localhost:3000');
+const prefix = '/api/v1/';
+
+import {adminUsername, adminEmail, adminPassword} from '../data/user.js';
+
+function api(path) {
+	return prefix + path;
+}
+
+function log(res) {
+	console.log(res.req.path);
+	console.log({
+		body: res.body,
+		headers: res.headers
+	});
+}
+
+const credentials = {
+	['X-Auth-Token']: undefined,
+	['X-User-Id']: undefined
+};
+
+const login = {
+	user: adminUsername,
+	password: adminPassword
+};
+
+describe('API default', () => {
+	// Required by mobile apps
+	it('/info', (done) => {
+		request.get('/api/info')
+			.expect('Content-Type', 'application/json')
+			.expect(200)
+			.expect((res) => {
+				expect(res.body).to.have.property('version');
+				expect(res.body).to.have.deep.property('build.date');
+				expect(res.body).to.have.deep.property('build.nodeVersion');
+				expect(res.body).to.have.deep.property('build.arch');
+				expect(res.body).to.have.deep.property('build.platform');
+				expect(res.body).to.have.deep.property('build.osRelease');
+				expect(res.body).to.have.deep.property('build.totalMemory');
+				expect(res.body).to.have.deep.property('build.freeMemory');
+				expect(res.body).to.have.deep.property('build.cpus');
+			})
+			.end(done);
+	});
+});
+
+describe('API v1', () => {
+	before((done) => {
+		request.post(api('login'))
+			.send(login)
+			.expect('Content-Type', 'application/json')
+			.expect(200)
+			.expect((res) => {
+				credentials['X-Auth-Token'] = res.body.data.authToken;
+				credentials['X-User-Id'] = res.body.data.userId;
+			})
+			.end(done);
+	});
+
+	it('/login', () => {
+		expect(credentials).to.have.property('X-Auth-Token').with.length.at.least(1);
+		expect(credentials).to.have.property('X-User-Id').with.length.at.least(1);
+	});
+
+	it('/me', (done) => {
+		request.get(api('me'))
+			.set(credentials)
+			.expect('Content-Type', 'application/json')
+			.expect(200)
+			.expect((res) => {
+				expect(res.body).to.have.property('success', true);
+				expect(res.body).to.have.property('_id', credentials['X-User-Id']);
+				expect(res.body).to.have.property('username', login.user);
+				expect(res.body).to.have.property('active');
+				expect(res.body).to.have.property('name');
+				expect(res.body).to.have.deep.property('emails[0].address', adminEmail);
+			})
+			.end(done);
+	});
+
+});
diff --git a/tests/test-data/user.js b/tests/test-data/user.js
deleted file mode 100644
index 0b8032fff1831d876ea570f0d1fa79a02efcddc2..0000000000000000000000000000000000000000
--- a/tests/test-data/user.js
+++ /dev/null
@@ -1,3 +0,0 @@
-export const username = 'user.test.'+Date.now();
-export const email = username+'@rocket.chat';
-export const password = 'rocket.chat';
\ No newline at end of file