diff --git a/client/less/main.less b/client/less/main.less index db9a804e05..bbf9249e6b 100644 --- a/client/less/main.less +++ b/client/less/main.less @@ -35,14 +35,46 @@ pre.wrappable { word-wrap: break-word; /* IE 5+ */ } -//input[type=checkbox] { -// /* Double-sized Checkboxes */ -// -ms-transform: scale(2); /* IE */ -// -moz-transform: scale(2); /* FF */ -// -webkit-transform: scale(2); /* Safari and Chrome */ -// -o-transform: scale(2); /* Opera */ -// padding: 10px; -//} +.checkbox label:after { + content: ''; + display: table; + clear: both; +} + +.checkbox .cr { + position: relative; + display: inline-block; + border: 1px solid #a9a9a9; + border-radius: .25em; + width: 1.3em; + height: 1.3em; + float: left; + margin-right: .5em; +} + +.checkbox .cr .cr-icon { + position: absolute; + font-size: .8em; + line-height: 0; + top: 50%; + left: 15%; +} + +.checkbox label input[type="checkbox"] { + display: none; +} + +.checkbox label input[type="checkbox"]+.cr>.cr-icon { + opacity: 0; +} + +.checkbox label input[type="checkbox"]:checked+.cr>.cr-icon { + opacity: 1; +} + +.checkbox label input[type="checkbox"]:disabled+.cr { + opacity: .5; +} .btn-group { border-color: @brand-primary; diff --git a/common/models/User-Identity.js b/common/models/User-Identity.js index 3fb7c30a40..eeaa59f6a6 100644 --- a/common/models/User-Identity.js +++ b/common/models/User-Identity.js @@ -4,8 +4,7 @@ import dedent from 'dedent'; import { getSocialProvider, - getUsernameFromProvider, - createUserUpdatesFromProfile + getUsernameFromProvider } from '../../server/utils/auth'; import { observeMethod, observeQuery } from '../../server/utils/rx'; import { wrapHandledError } from '../../server/utils/create-handled-error.js'; @@ -48,84 +47,100 @@ export default function(UserIdent) { }, include: 'user' }; - return UserIdent.findOne$(query) - .flatMap(identity => { - if (!identity) { - throw wrapHandledError( - new Error('user identity account not found'), - { - message: dedent` - New accounts can only be created using an email address. - Please create an account below - `, - type: 'info', - redirectTo: '/signup' - } - ); - } - const modified = new Date(); - const user = identity.user(); - if (!user) { - const username = getUsernameFromProvider(provider, profile); - return observeQuery( + + if (provider === 'auth0') { + + const email = profile.emails[0].value; + return User.findOne$({ where: { email } }) + .flatMap(user => { + if (!user) { + return User.create$({ email }); + } + return Observable.of(user); + }) + .subscribe( + ( user ) => cb(null, user, null, null), + cb + ); + + } else { + + return UserIdent.findOne$(query) + .flatMap(identity => { + if (!identity) { + throw wrapHandledError( + new Error('user identity account not found'), + { + message: dedent` + New accounts can only be created using an email address. + Please create an account below + `, + type: 'info', + redirectTo: '/signup' + } + ); + } + const modified = new Date(); + const user = identity.user(); + if (!user) { + const username = getUsernameFromProvider(provider, profile); + return observeQuery( + identity, + 'updateAttributes', + { + isOrphaned: username || true + } + ) + .do(() => { + throw wrapHandledError( + new Error('user identity is not associated with a user'), + { + type: 'info', + redirectTo: '/signup', + message: dedent` + The user account associated with the ${provider} user ${username || 'Anon'} + no longer exists. + ` + } + ); + }); + } + + // identity already exists + // find user and log them in + identity.credentials = credentials; + const attributes = { + // we no longer want to keep the profile + // this is information we do not need or use + profile: null, + credentials: credentials, + modified + }; + const updateIdentity = observeQuery( identity, 'updateAttributes', + attributes + ); + const createToken = observeQuery( + AccessToken, + 'create', { - isOrphaned: username || true + userId: user.id, + created: new Date(), + ttl: user.constructor.settings.ttl } - ) - .do(() => { - throw wrapHandledError( - new Error('user identity is not associated with a user'), - { - type: 'info', - redirectTo: '/signup', - message: dedent` - The user account associated with the ${provider} user ${username || 'Anon'} - no longer exists. - ` - } - ); - }); - } - const updateUser = User.update$( - { id: user.id }, - createUserUpdatesFromProfile(provider, profile) - ).map(() => user); - // identity already exists - // find user and log them in - identity.credentials = credentials; - const attributes = { - // we no longer want to keep the profile - // this is information we do not need or use - profile: null, - credentials: credentials, - modified - }; - const updateIdentity = observeQuery( - identity, - 'updateAttributes', - attributes + ); + return Observable.combineLatest( + Observable.of(user), + updateIdentity, + createToken, + (user, identity, token) => ({ user, identity, token }) + ); + }) + .subscribe( + ({ user, identity, token }) => cb(null, user, identity, token), + cb ); - const createToken = observeQuery( - AccessToken, - 'create', - { - userId: user.id, - created: new Date(), - ttl: user.constructor.settings.ttl - } - ); - return Observable.combineLatest( - updateUser, - updateIdentity, - createToken, - (user, identity, token) => ({ user, identity, token }) - ); - }) - .subscribe( - ({ user, identity, token }) => cb(null, user, identity, token), - cb - ); + } }; } diff --git a/hosted-templates/hosted-pages/login.html b/hosted-templates/hosted-pages/login.html new file mode 100644 index 0000000000..4d1b4e6381 --- /dev/null +++ b/hosted-templates/hosted-pages/login.html @@ -0,0 +1,462 @@ + + + + + + + + + Sign in to freeCodeCamp + + + + + + + + + + + +
+
+
+ +
+
+

Sign up (or sign in with your existing account)

+
+
+ +
+
+
+ + + +
+
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+ + + + + +
+
+
+ + + + + +
+
+
+ + + + + + + + + + + + + diff --git a/package-lock.json b/package-lock.json index 4710aa2848..a5233aa023 100644 --- a/package-lock.json +++ b/package-lock.json @@ -721,6 +721,32 @@ "integrity": "sha1-lfE2KbEsOlGl0hWr3OKqnzL4B3M=", "dev": true }, + "auth0-js": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/auth0-js/-/auth0-js-9.5.1.tgz", + "integrity": "sha1-NN6msPEbXl7hOWBWEfSbHA8V27E=", + "requires": { + "base64-js": "1.3.0", + "idtoken-verifier": "1.2.0", + "js-cookie": "2.2.0", + "qs": "6.5.1", + "superagent": "3.8.3", + "url-join": "1.1.0", + "winchan": "0.2.0" + }, + "dependencies": { + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" + }, + "url-join": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz", + "integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg=" + } + } + }, "aws-sdk": { "version": "2.141.0", "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.141.0.tgz", @@ -3889,6 +3915,11 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, + "cookiejar": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.1.tgz", + "integrity": "sha1-Qa1XsbVVlR7BcUEqgZQrHoIA00o=" + }, "copy-concurrently": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", @@ -4225,6 +4256,11 @@ "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-1.0.9.tgz", "integrity": "sha1-zFRJaF37hesRyYKKzHy4erW7/MA=" }, + "crypto-js": { + "version": "3.1.9-1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.9-1.tgz", + "integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg=" + }, "crypto-random-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", @@ -8806,6 +8842,30 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" }, + "idtoken-verifier": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/idtoken-verifier/-/idtoken-verifier-1.2.0.tgz", + "integrity": "sha512-8jmmFHwdPz8L73zGNAXHHOV9yXNC+Z0TUBN5rafpoaFaLFltlIFr1JkQa3FYAETP23eSsulVw0sBiwrE8jqbUg==", + "requires": { + "base64-js": "1.3.0", + "crypto-js": "3.1.9-1", + "jsbn": "0.1.1", + "superagent": "3.8.3", + "url-join": "1.1.0" + }, + "dependencies": { + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" + }, + "url-join": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz", + "integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg=" + } + } + }, "ieee754": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", @@ -9628,6 +9688,11 @@ "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.1.1.tgz", "integrity": "sha1-NHwcIcfgBBFeCk2jLOzgQfrTyKM=" }, + "js-cookie": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.0.tgz", + "integrity": "sha1-Gywnmm7s44ChIWi5JIUmWzWx7/s=" + }, "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", @@ -9656,8 +9721,7 @@ "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "optional": true + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "jschardet": { "version": "1.6.0", @@ -13935,6 +13999,16 @@ "pause": "0.0.1" } }, + "passport-auth0": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/passport-auth0/-/passport-auth0-0.6.1.tgz", + "integrity": "sha512-JJzb7BhR7eH19h9awD1+rZQbo0FCPMH1Wf6cGcSnw+boGYaIWc+A3ID0KDd6A8eFwqDEZgy+NEuYhIGOpngFuA==", + "requires": { + "passport-oauth": "1.0.0", + "request": "2.83.0", + "xtend": "4.0.1" + } + }, "passport-facebook": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/passport-facebook/-/passport-facebook-2.1.1.tgz", @@ -18143,6 +18217,70 @@ "chalk": "1.1.3" } }, + "superagent": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", + "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", + "requires": { + "component-emitter": "1.2.1", + "cookiejar": "2.1.1", + "debug": "3.1.0", + "extend": "3.0.1", + "form-data": "2.3.1", + "formidable": "1.2.1", + "methods": "1.1.2", + "mime": "1.4.1", + "qs": "6.5.1", + "readable-stream": "2.3.6" + }, + "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "formidable": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz", + "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==" + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -20339,6 +20477,11 @@ "semver": "5.4.1" } }, + "winchan": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/winchan/-/winchan-0.2.0.tgz", + "integrity": "sha1-OGMCjn+XSw2hQS8oQXukJJcqvZQ=" + }, "window-size": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", diff --git a/package.json b/package.json index e3099a89b8..f9cfb30183 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "dependencies": { "@freecodecamp/loopback-component-passport": "^1.0.0", "accepts": "^1.3.0", + "auth0-js": "^9.5.1", "babel-core": "^6.18.1", "babel-preset-es2015": "^6.3.13", "babel-preset-react": "^6.3.13", @@ -101,6 +102,7 @@ "normalizr": "2.2.1", "opbeat": "^4.14.0", "passport": "^0.4.0", + "passport-auth0": "^0.6.1", "passport-facebook": "^2.0.0", "passport-github": "^1.0.0", "passport-google-oauth2": "~0.1.6", diff --git a/public/css/Vimeo.css b/public/css/Vimeo.css deleted file mode 100644 index 1bdb4b99bd..0000000000 --- a/public/css/Vimeo.css +++ /dev/null @@ -1,97 +0,0 @@ -.vimeo-image, -.vimeo-image:after, -.vimeo-embed { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; -} -.vimeo { - position: relative; - padding-bottom: 56.25%; - background: #e2e2e2; -} -.vimeo iframe { - border: 0; -} -.vimeo-image { - background-position: center center; - background-size: 100% auto; -} -.vimeo-image:after { - z-index: 1; - display: block; - content: ''; - background: rgba(0,0,0,0.3); -} -.vimeo-play-button, -.vimeo-loading { - top: 50%; - left: 50%; - transform: translateX(-50%) translateY(-50%); -} -.vimeo-play-button { - z-index: 2; - position: absolute; - padding: 0; - width: 70px; - border: 0; - background: none; -} -.vimeo-play-button:focus { - outline: none; -} -.vimeo-play-button svg { - fill: #fff; - -webkit-filter: drop-shadow(0 1px 1px rgba(0,0,0,0.8)); - filter: drop-shadow(0 1px 1px rgba(0,0,0,0.8)); -} -.vimeo-loading { - z-index: 4; - position: absolute; - width: 32px; - height: 32px; -} -.vimeo-loading svg { - fill: #000; - transform-origin: 50% 50%; - -webkit-animation: spinner 0.8s infinite linear; - animation: spinner 0.8s infinite linear; -} -.vimeo-embed iframe { - width: 100%; - height: 100%; -} -@-moz-keyframes spinner { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} -@-webkit-keyframes spinner { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} -@-o-keyframes spinner { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} -@keyframes spinner { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} diff --git a/public/css/themes/flatly.less b/public/css/themes/flatly.less deleted file mode 100644 index 41eb6e716c..0000000000 --- a/public/css/themes/flatly.less +++ /dev/null @@ -1,1167 +0,0 @@ -// Flatly 3.3.0 -// Variables -// -------------------------------------------------- - -//== Colors -// -//## Gray and brand colors for use across Bootstrap. - -@gray-base: #000; -@gray-darker: lighten(@gray-base, 13.5%); // #222 -@gray-dark: #7b8a8b; // #333 -@gray: #95a5a6; // #555 -@gray-light: #b4bcc2; // #999 -@gray-lighter: #ecf0f1; // #eee - -@brand-primary: #2C3E50; -@brand-success: #18BC9C; -@brand-info: #3498DB; -@brand-warning: #F39C12; -@brand-danger: #E74C3C; - - -//== Scaffolding -// -//## Settings for some of the most global styles. - -//** Background color for ``. -@body-bg: #fff; -//** Global text color on ``. -@text-color: @brand-primary; - -//** Global textual link color. -@link-color: @brand-success; -//** Link hover color set via `darken()` function. -@link-hover-color: @link-color; -//** Link hover decoration. -@link-hover-decoration: underline; - - -//== Typography -// -//## Font, line-height, and color for body text, headings, and more. - -@font-family-sans-serif: "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif; -@font-family-serif: Georgia, "Times New Roman", Times, serif; -//** Default monospace fonts for ``, ``, and `
`.
-@font-family-monospace:   Menlo, Monaco, Consolas, "Courier New", monospace;
-@font-family-base:        @font-family-sans-serif;
-
-@font-size-base:          15px;
-@font-size-large:         ceil((@font-size-base * 1.25)); // ~18px
-@font-size-small:         ceil((@font-size-base * 0.85)); // ~12px
-
-@font-size-h1:            floor((@font-size-base * 2.6)); // ~36px
-@font-size-h2:            floor((@font-size-base * 2.15)); // ~30px
-@font-size-h3:            ceil((@font-size-base * 1.7)); // ~24px
-@font-size-h4:            ceil((@font-size-base * 1.25)); // ~18px
-@font-size-h5:            @font-size-base;
-@font-size-h6:            ceil((@font-size-base * 0.85)); // ~12px
-
-//** Unit-less `line-height` for use in components like buttons.
-@line-height-base:        1.428571429; // 20/14
-//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
-@line-height-computed:    floor((@font-size-base * @line-height-base)); // ~20px
-
-//** By default, this inherits from the ``.
-@headings-font-family:    @font-family-base;
-@headings-font-weight:    400;
-@headings-line-height:    1.1;
-@headings-color:          inherit;
-
-
-//== Iconography
-//
-//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via npm.
-
-//** Load fonts from this directory.
-@icon-font-path:          "../fonts/";
-//** File name for all font files.
-@icon-font-name:          "glyphicons-halflings-regular";
-//** Element ID within SVG icon file.
-@icon-font-svg-id:        "glyphicons_halflingsregular";
-
-
-//== Components
-//
-//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
-
-@padding-base-vertical:     10px;
-@padding-base-horizontal:   15px;
-
-@padding-large-vertical:    18px;
-@padding-large-horizontal:  27px;
-
-@padding-small-vertical:    6px;
-@padding-small-horizontal:  9px;
-
-@padding-xs-vertical:       1px;
-@padding-xs-horizontal:     5px;
-
-@line-height-large:         1.33;
-@line-height-small:         1.5;
-
-@border-radius-base:        4px;
-@border-radius-large:       6px;
-@border-radius-small:       3px;
-
-//** Global color for active items (e.g., navs or dropdowns).
-@component-active-color:    #fff;
-//** Global background color for active items (e.g., navs or dropdowns).
-@component-active-bg:       @brand-primary;
-
-//** Width of the `border` for generating carets that indicator dropdowns.
-@caret-width-base:          4px;
-//** Carets increase slightly in size for larger components.
-@caret-width-large:         5px;
-
-
-//== Tables
-//
-//## Customizes the `.table` component with basic values, each used across all table variations.
-
-//** Padding for ``s and ``s.
-@table-cell-padding:            8px;
-//** Padding for cells in `.table-condensed`.
-@table-condensed-cell-padding:  5px;
-
-//** Default background color used for all tables.
-@table-bg:                      transparent;
-//** Background color used for `.table-striped`.
-@table-bg-accent:               #f9f9f9;
-//** Background color used for `.table-hover`.
-@table-bg-hover:                @gray-lighter;
-@table-bg-active:               @table-bg-hover;
-
-//** Border color for table and cell borders.
-@table-border-color:            @gray-lighter;
-
-
-//== Buttons
-//
-//## For each of Bootstrap's buttons, define text, background and border color.
-
-@btn-font-weight:                normal;
-
-@btn-default-color:              #fff;
-@btn-default-bg:                 @gray;
-@btn-default-border:             @btn-default-bg;
-
-@btn-primary-color:              @btn-default-color;
-@btn-primary-bg:                 @brand-primary;
-@btn-primary-border:             @btn-primary-bg;
-
-@btn-success-color:              @btn-default-color;
-@btn-success-bg:                 @brand-success;
-@btn-success-border:             @btn-success-bg;
-
-@btn-info-color:                 @btn-default-color;
-@btn-info-bg:                    @brand-info;
-@btn-info-border:                @btn-info-bg;
-
-@btn-warning-color:              @btn-default-color;
-@btn-warning-bg:                 @brand-warning;
-@btn-warning-border:             @btn-warning-bg;
-
-@btn-danger-color:               @btn-default-color;
-@btn-danger-bg:                  @brand-danger;
-@btn-danger-border:              @btn-danger-bg;
-
-@btn-link-disabled-color:        @gray-light;
-
-
-//== Forms
-//
-//##
-
-//** `` background color
-@input-bg:                       #fff;
-//** `` background color
-@input-bg-disabled:              @gray-lighter;
-
-//** Text color for ``s
-@input-color:                    @text-color;
-//** `` border color
-@input-border:                   #dce4ec;
-
-// TODO: Rename `@input-border-radius` to `@input-border-radius-base` in v4
-//** Default `.form-control` border radius
-@input-border-radius:            @border-radius-base;
-//** Large `.form-control` border radius
-@input-border-radius-large:      @border-radius-large;
-//** Small `.form-control` border radius
-@input-border-radius-small:      @border-radius-small;
-
-//** Border color for inputs on focus
-@input-border-focus:             @brand-primary;
-
-//** Placeholder text color
-@input-color-placeholder:        #acb6c0;
-
-//** Default `.form-control` height
-@input-height-base:              (@line-height-computed + (@padding-base-vertical * 2) + 2);
-//** Large `.form-control` height
-@input-height-large:             (ceil(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2);
-//** Small `.form-control` height
-@input-height-small:             (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2);
-
-@legend-color:                   @text-color;
-@legend-border-color:            transparent;
-
-//** Background color for textual input addons
-@input-group-addon-bg:           @gray-lighter;
-//** Border color for textual input addons
-@input-group-addon-border-color: @input-border;
-
-//** Disabled cursor for form controls and buttons.
-@cursor-disabled:                not-allowed;
-
-
-//== Dropdowns
-//
-//## Dropdown menu container and contents.
-
-//** Background for the dropdown menu.
-@dropdown-bg:                    #fff;
-//** Dropdown menu `border-color`.
-@dropdown-border:                rgba(0,0,0,.15);
-//** Dropdown menu `border-color` **for IE8**.
-@dropdown-fallback-border:       #ccc;
-//** Divider color for between dropdown items.
-@dropdown-divider-bg:            #e5e5e5;
-
-//** Dropdown link text color.
-@dropdown-link-color:            @gray-dark;
-//** Hover color for dropdown links.
-@dropdown-link-hover-color:      #fff;
-//** Hover background for dropdown links.
-@dropdown-link-hover-bg:         @dropdown-link-active-bg;
-
-//** Active dropdown menu item text color.
-@dropdown-link-active-color:     #fff;
-//** Active dropdown menu item background color.
-@dropdown-link-active-bg:        @component-active-bg;
-
-//** Disabled dropdown menu item background color.
-@dropdown-link-disabled-color:   @text-muted;
-
-//** Text color for headers within dropdown menus.
-@dropdown-header-color:          @text-muted;
-
-//** Deprecated `@dropdown-caret-color` as of v3.1.0
-@dropdown-caret-color:           #000;
-
-
-//-- Z-index master list
-//
-// Warning: Avoid customizing these values. They're used for a bird's eye view
-// of components dependent on the z-axis and are designed to all work together.
-//
-// Note: These variables are not generated into the Customizer.
-
-@zindex-navbar:            1000;
-@zindex-dropdown:          1000;
-@zindex-popover:           1060;
-@zindex-tooltip:           1070;
-@zindex-navbar-fixed:      1030;
-@zindex-modal:             1040;
-
-
-//== Media queries breakpoints
-//
-//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
-
-// Extra small screen / phone
-//** Deprecated `@screen-xs` as of v3.0.1
-@screen-xs:                  480px;
-//** Deprecated `@screen-xs-min` as of v3.2.0
-@screen-xs-min:              @screen-xs;
-//** Deprecated `@screen-phone` as of v3.0.1
-@screen-phone:               @screen-xs-min;
-
-// Small screen / tablet
-//** Deprecated `@screen-sm` as of v3.0.1
-@screen-sm:                  768px;
-@screen-sm-min:              @screen-sm;
-//** Deprecated `@screen-tablet` as of v3.0.1
-@screen-tablet:              @screen-sm-min;
-
-// Medium screen / desktop
-//** Deprecated `@screen-md` as of v3.0.1
-@screen-md:                  992px;
-@screen-md-min:              @screen-md;
-//** Deprecated `@screen-desktop` as of v3.0.1
-@screen-desktop:             @screen-md-min;
-
-// Large screen / wide desktop
-//** Deprecated `@screen-lg` as of v3.0.1
-@screen-lg:                  1200px;
-@screen-lg-min:              @screen-lg;
-//** Deprecated `@screen-lg-desktop` as of v3.0.1
-@screen-lg-desktop:          @screen-lg-min;
-
-// So media queries don't overlap when required, provide a maximum
-@screen-xs-max:              (@screen-sm-min - 1);
-@screen-sm-max:              (@screen-md-min - 1);
-@screen-md-max:              (@screen-lg-min - 1);
-
-
-//== Grid system
-//
-//## Define your custom responsive grid.
-
-//** Number of columns in the grid.
-@grid-columns:              12;
-//** Padding between columns. Gets divided in half for the left and right.
-@grid-gutter-width:         30px;
-// Navbar collapse
-//** Point at which the navbar becomes uncollapsed.
-@grid-float-breakpoint:     @screen-sm-min;
-//** Point at which the navbar begins collapsing.
-@grid-float-breakpoint-max: (@grid-float-breakpoint - 1);
-
-
-//== Container sizes
-//
-//## Define the maximum width of `.container` for different screen sizes.
-
-// Small screen / tablet
-@container-tablet:             (720px + @grid-gutter-width);
-//** For `@screen-sm-min` and up.
-@container-sm:                 @container-tablet;
-
-// Medium screen / desktop
-@container-desktop:            (940px + @grid-gutter-width);
-//** For `@screen-md-min` and up.
-@container-md:                 @container-desktop;
-
-// Large screen / wide desktop
-@container-large-desktop:      (1140px + @grid-gutter-width);
-//** For `@screen-lg-min` and up.
-@container-lg:                 @container-large-desktop;
-
-
-//== Navbar
-//
-//##
-
-// Basics of a navbar
-@navbar-height:                    60px;
-@navbar-margin-bottom:             @line-height-computed;
-@navbar-border-radius:             @border-radius-base;
-@navbar-padding-horizontal:        floor((@grid-gutter-width / 2));
-@navbar-padding-vertical:          ((@navbar-height - @line-height-computed) / 2);
-@navbar-collapse-max-height:       340px;
-
-@navbar-default-color:             #777;
-@navbar-default-bg:                @brand-primary;
-@navbar-default-border:            transparent;
-
-// Navbar links
-@navbar-default-link-color:                #fff;
-@navbar-default-link-hover-color:          @brand-success;
-@navbar-default-link-hover-bg:             transparent;
-@navbar-default-link-active-color:         #fff;
-@navbar-default-link-active-bg:            darken(@navbar-default-bg, 10%);
-@navbar-default-link-disabled-color:       #ccc;
-@navbar-default-link-disabled-bg:          transparent;
-
-// Navbar brand label
-@navbar-default-brand-color:               @navbar-default-link-color;
-@navbar-default-brand-hover-color:         @navbar-default-link-hover-color;
-@navbar-default-brand-hover-bg:            transparent;
-
-// Navbar toggle
-@navbar-default-toggle-hover-bg:           darken(@navbar-default-bg, 10%);
-@navbar-default-toggle-icon-bar-bg:        #fff;
-@navbar-default-toggle-border-color:       darken(@navbar-default-bg, 10%);
-
-
-// Inverted navbar
-// Reset inverted navbar basics
-@navbar-inverse-color:                      #fff;
-@navbar-inverse-bg:                         @brand-success;
-@navbar-inverse-border:                     transparent;
-
-// Inverted navbar links
-@navbar-inverse-link-color:                 #fff;
-@navbar-inverse-link-hover-color:           @brand-primary;
-@navbar-inverse-link-hover-bg:              transparent;
-@navbar-inverse-link-active-color:          #fff;
-@navbar-inverse-link-active-bg:             darken(@navbar-inverse-bg, 5%);
-@navbar-inverse-link-disabled-color:        #ccc;
-@navbar-inverse-link-disabled-bg:           transparent;
-
-// Inverted navbar brand label
-@navbar-inverse-brand-color:                @navbar-inverse-link-color;
-@navbar-inverse-brand-hover-color:          @navbar-inverse-link-hover-color;
-@navbar-inverse-brand-hover-bg:             transparent;
-
-// Inverted navbar toggle
-@navbar-inverse-toggle-hover-bg:            darken(@navbar-inverse-bg, 10%);
-@navbar-inverse-toggle-icon-bar-bg:         #fff;
-@navbar-inverse-toggle-border-color:        darken(@navbar-inverse-bg, 10%);
-
-
-//== Navs
-//
-//##
-
-//=== Shared nav styles
-@nav-link-padding:                          10px 15px;
-@nav-link-hover-bg:                         @gray-lighter;
-
-@nav-disabled-link-color:                   @gray-light;
-@nav-disabled-link-hover-color:             @gray-light;
-
-//== Tabs
-@nav-tabs-border-color:                     @gray-lighter;
-
-@nav-tabs-link-hover-border-color:          @gray-lighter;
-
-@nav-tabs-active-link-hover-bg:             @body-bg;
-@nav-tabs-active-link-hover-color:          @brand-primary;
-@nav-tabs-active-link-hover-border-color:   @gray-lighter;
-
-@nav-tabs-justified-link-border-color:            @gray-lighter;
-@nav-tabs-justified-active-link-border-color:     @body-bg;
-
-//== Pills
-@nav-pills-border-radius:                   @border-radius-base;
-@nav-pills-active-link-hover-bg:            @component-active-bg;
-@nav-pills-active-link-hover-color:         @component-active-color;
-
-
-//== Pagination
-//
-//##
-
-@pagination-color:                     #fff;
-@pagination-bg:                        @brand-success;
-@pagination-border:                    transparent;
-
-@pagination-hover-color:               #fff;
-@pagination-hover-bg:                  darken(@brand-success, 15%);
-@pagination-hover-border:              transparent;
-
-@pagination-active-color:              #fff;
-@pagination-active-bg:                 darken(@brand-success, 15%);
-@pagination-active-border:             transparent;
-
-@pagination-disabled-color:            @gray-lighter;
-@pagination-disabled-bg:               lighten(@brand-success, 15%);;
-@pagination-disabled-border:           transparent;
-
-
-//== Pager
-//
-//##
-
-@pager-bg:                             @pagination-bg;
-@pager-border:                         @pagination-border;
-@pager-border-radius:                  15px;
-
-@pager-hover-bg:                       @pagination-hover-bg;
-
-@pager-active-bg:                      @pagination-active-bg;
-@pager-active-color:                   @pagination-active-color;
-
-@pager-disabled-color:                 #fff;
-
-
-//== Jumbotron
-//
-//##
-
-@jumbotron-padding:              30px;
-@jumbotron-color:                inherit;
-@jumbotron-bg:                   @gray-lighter;
-@jumbotron-heading-color:        inherit;
-@jumbotron-font-size:            ceil((@font-size-base * 1.5));
-
-
-//== Form states and alerts
-//
-//## Define colors for form feedback states and, by default, alerts.
-
-@state-success-text:             #fff;
-@state-success-bg:               @brand-success;
-@state-success-border:           @brand-success;
-
-@state-info-text:                #fff;
-@state-info-bg:                  @brand-info;
-@state-info-border:              @brand-info;
-
-@state-warning-text:             #fff;
-@state-warning-bg:               @brand-warning;
-@state-warning-border:           @brand-warning;
-
-@state-danger-text:              #fff;
-@state-danger-bg:                @brand-danger;
-@state-danger-border:            @brand-danger;
-
-
-//== Tooltips
-//
-//##
-
-//** Tooltip max width
-@tooltip-max-width:           200px;
-//** Tooltip text color
-@tooltip-color:               #fff;
-//** Tooltip background color
-@tooltip-bg:                  rgba(0,0,0,.9);
-@tooltip-opacity:             .9;
-
-//** Tooltip arrow width
-@tooltip-arrow-width:         5px;
-//** Tooltip arrow color
-@tooltip-arrow-color:         @tooltip-bg;
-
-
-//== Popovers
-//
-//##
-
-//** Popover body background color
-@popover-bg:                          #fff;
-//** Popover maximum width
-@popover-max-width:                   276px;
-//** Popover border color
-@popover-border-color:                rgba(0,0,0,.2);
-//** Popover fallback border color
-@popover-fallback-border-color:       #ccc;
-
-//** Popover title background color
-@popover-title-bg:                    darken(@popover-bg, 3%);
-
-//** Popover arrow width
-@popover-arrow-width:                 10px;
-//** Popover arrow color
-@popover-arrow-color:                 @popover-bg;
-
-//** Popover outer arrow width
-@popover-arrow-outer-width:           (@popover-arrow-width + 1);
-//** Popover outer arrow color
-@popover-arrow-outer-color:           fadein(@popover-border-color, 5%);
-//** Popover outer arrow fallback color
-@popover-arrow-outer-fallback-color:  darken(@popover-fallback-border-color, 20%);
-
-
-//== Labels
-//
-//##
-
-//** Default label background color
-@label-default-bg:            @btn-default-bg;
-//** Primary label background color
-@label-primary-bg:            @brand-primary;
-//** Success label background color
-@label-success-bg:            @brand-success;
-//** Info label background color
-@label-info-bg:               @brand-info;
-//** Warning label background color
-@label-warning-bg:            @brand-warning;
-//** Danger label background color
-@label-danger-bg:             @brand-danger;
-
-//** Default label text color
-@label-color:                 #fff;
-//** Default text color of a linked label
-@label-link-hover-color:      #fff;
-
-
-//== Modals
-//
-//##
-
-//** Padding applied to the modal body
-@modal-inner-padding:         20px;
-
-//** Padding applied to the modal title
-@modal-title-padding:         15px;
-//** Modal title line-height
-@modal-title-line-height:     @line-height-base;
-
-//** Background color of modal content area
-@modal-content-bg:                             #fff;
-//** Modal content border color
-@modal-content-border-color:                   rgba(0,0,0,.2);
-//** Modal content border color **for IE8**
-@modal-content-fallback-border-color:          #999;
-
-//** Modal backdrop background color
-@modal-backdrop-bg:           #000;
-//** Modal backdrop opacity
-@modal-backdrop-opacity:      .5;
-//** Modal header border color
-@modal-header-border-color:   #e5e5e5;
-//** Modal footer border color
-@modal-footer-border-color:   @modal-header-border-color;
-
-@modal-lg:                    900px;
-@modal-md:                    600px;
-@modal-sm:                    300px;
-
-
-//== Alerts
-//
-//## Define alert colors, border radius, and padding.
-
-@alert-padding:               15px;
-@alert-border-radius:         @border-radius-base;
-@alert-link-font-weight:      bold;
-
-@alert-success-bg:            @state-success-bg;
-@alert-success-text:          @state-success-text;
-@alert-success-border:        @state-success-border;
-
-@alert-info-bg:               @state-info-bg;
-@alert-info-text:             @state-info-text;
-@alert-info-border:           @state-info-border;
-
-@alert-warning-bg:            @state-warning-bg;
-@alert-warning-text:          @state-warning-text;
-@alert-warning-border:        @state-warning-border;
-
-@alert-danger-bg:             @state-danger-bg;
-@alert-danger-text:           @state-danger-text;
-@alert-danger-border:         @state-danger-border;
-
-
-//== Progress bars
-//
-//##
-
-//** Background color of the whole progress component
-@progress-bg:                 @gray-lighter;
-//** Progress bar text color
-@progress-bar-color:          #fff;
-//** Variable for setting rounded corners on progress bar.
-@progress-border-radius:      @border-radius-base;
-
-//** Default progress bar color
-@progress-bar-bg:             @brand-primary;
-//** Success progress bar color
-@progress-bar-success-bg:     @brand-success;
-//** Warning progress bar color
-@progress-bar-warning-bg:     @brand-warning;
-//** Danger progress bar color
-@progress-bar-danger-bg:      @brand-danger;
-//** Info progress bar color
-@progress-bar-info-bg:        @brand-info;
-
-
-//== List group
-//
-//##
-
-//** Background color on `.list-group-item`
-@list-group-bg:                 #fff;
-//** `.list-group-item` border color
-@list-group-border:             @gray-lighter;
-//** List group border radius
-@list-group-border-radius:      @border-radius-base;
-
-//** Background color of single list items on hover
-@list-group-hover-bg:           @gray-lighter;
-//** Text color of active list items
-@list-group-active-color:       @component-active-color;
-//** Background color of active list items
-@list-group-active-bg:          @component-active-bg;
-//** Border color of active list elements
-@list-group-active-border:      @list-group-active-bg;
-//** Text color for content within active list items
-@list-group-active-text-color:  lighten(@list-group-active-bg, 40%);
-
-//** Text color of disabled list items
-@list-group-disabled-color:      @gray-light;
-//** Background color of disabled list items
-@list-group-disabled-bg:         @gray-lighter;
-//** Text color for content within disabled list items
-@list-group-disabled-text-color: @list-group-disabled-color;
-
-@list-group-link-color:         #555;
-@list-group-link-hover-color:   @list-group-link-color;
-@list-group-link-heading-color: #333;
-
-
-//== Panels
-//
-//##
-
-@panel-bg:                    #fff;
-@panel-body-padding:          15px;
-@panel-heading-padding:       10px 15px;
-@panel-footer-padding:        @panel-heading-padding;
-@panel-border-radius:         @border-radius-base;
-
-//** Border color for elements within panels
-@panel-inner-border:          @gray-lighter;
-@panel-footer-bg:             @gray-lighter;
-
-@panel-default-text:          @text-color;
-@panel-default-border:        @gray-lighter;
-@panel-default-heading-bg:    @gray-lighter;
-
-@panel-primary-text:          #fff;
-@panel-primary-border:        @brand-primary;
-@panel-primary-heading-bg:    @brand-primary;
-
-@panel-success-text:          @state-success-text;
-@panel-success-border:        @state-success-border;
-@panel-success-heading-bg:    @state-success-bg;
-
-@panel-info-text:             @state-info-text;
-@panel-info-border:           @state-info-border;
-@panel-info-heading-bg:       @state-info-bg;
-
-@panel-warning-text:          @state-warning-text;
-@panel-warning-border:        @state-warning-border;
-@panel-warning-heading-bg:    @state-warning-bg;
-
-@panel-danger-text:           @state-danger-text;
-@panel-danger-border:         @state-danger-border;
-@panel-danger-heading-bg:     @state-danger-bg;
-
-
-//== Thumbnails
-//
-//##
-
-//** Padding around the thumbnail image
-@thumbnail-padding:           4px;
-//** Thumbnail background color
-@thumbnail-bg:                @body-bg;
-//** Thumbnail border color
-@thumbnail-border:            @gray-lighter;
-//** Thumbnail border radius
-@thumbnail-border-radius:     @border-radius-base;
-
-//** Custom text color for thumbnail captions
-@thumbnail-caption-color:     @text-color;
-//** Padding around the thumbnail caption
-@thumbnail-caption-padding:   9px;
-
-
-//== Wells
-//
-//##
-
-@well-bg:                     @gray-lighter;
-@well-border:                 transparent;
-
-
-//== Badges
-//
-//##
-
-@badge-color:                 #fff;
-//** Linked badge text color on hover
-@badge-link-hover-color:      #fff;
-@badge-bg:                    @brand-primary;
-
-//** Badge text color in active nav link
-@badge-active-color:          @brand-primary;
-//** Badge background color in active nav link
-@badge-active-bg:             #fff;
-
-@badge-font-weight:           bold;
-@badge-line-height:           1;
-@badge-border-radius:         10px;
-
-
-//== Breadcrumbs
-//
-//##
-
-@breadcrumb-padding-vertical:   8px;
-@breadcrumb-padding-horizontal: 15px;
-//** Breadcrumb background color
-@breadcrumb-bg:                 @gray-lighter;
-//** Breadcrumb text color
-@breadcrumb-color:              #ccc;
-//** Text color of current page in the breadcrumb
-@breadcrumb-active-color:       @gray;
-//** Textual separator for between breadcrumb elements
-@breadcrumb-separator:          "/";
-
-
-//== Carousel
-//
-//##
-
-@carousel-text-shadow:                        0 1px 2px rgba(0,0,0,.6);
-
-@carousel-control-color:                      #fff;
-@carousel-control-width:                      15%;
-@carousel-control-opacity:                    .5;
-@carousel-control-font-size:                  20px;
-
-@carousel-indicator-active-bg:                #fff;
-@carousel-indicator-border-color:             #fff;
-
-@carousel-caption-color:                      #fff;
-
-
-//== Close
-//
-//##
-
-@close-font-weight:           bold;
-@close-color:                 #000;
-@close-text-shadow:           none;
-
-
-//== Code
-//
-//##
-
-@code-color:                  #c7254e;
-@code-bg:                     #f9f2f4;
-
-@kbd-color:                   #fff;
-@kbd-bg:                      #333;
-
-@pre-bg:                      @gray-lighter;
-@pre-color:                   @gray-dark;
-@pre-border-color:            #ccc;
-@pre-scrollable-max-height:   340px;
-
-
-//== Type
-//
-//##
-
-//** Horizontal offset for forms and lists.
-@component-offset-horizontal: 180px;
-//** Text muted color
-@text-muted:                  @gray-light;
-//** Abbreviations and acronyms border color
-@abbr-border-color:           @gray-light;
-//** Headings small color
-@headings-small-color:        @gray-light;
-//** Blockquote small color
-@blockquote-small-color:      @gray-light;
-//** Blockquote font size
-@blockquote-font-size:        (@font-size-base * 1.25);
-//** Blockquote border color
-@blockquote-border-color:     @gray-lighter;
-//** Page header border color
-@page-header-border-color:    transparent;
-//** Width of horizontal description list titles
-@dl-horizontal-offset:        @component-offset-horizontal;
-//** Horizontal line color.
-@hr-border:                   @gray-lighter;
-
-// Flatly 3.3.0
-// Bootswatch
-// -----------------------------------------------------
-
-@import url("https://fonts.googleapis.com/css?family=Lato:400,700,400italic");
-
-// Navbar =====================================================================
-
-.navbar {
-  border-width: 0;
-
-  &-default {
-
-    .badge {
-      background-color: #fff;
-      color: @navbar-default-bg;
-    }
-  }
-
-  &-inverse {
-
-    .badge {
-      background-color: #fff;
-      color: @navbar-inverse-bg;
-    }
-  }
-
-  &-brand {
-    padding: 18.5px 15px 20.5px;
-  }
-}
-
-// Buttons ====================================================================
-
-.btn:active {
-  .box-shadow(none);
-}
-
-.btn-group.open .dropdown-toggle {
-  .box-shadow(none);
-}
-
-// Typography =================================================================
-
-.text-primary,
-.text-primary:hover {
-  color: @brand-primary;
-}
-
-.text-success,
-.text-success:hover {
-  color: @brand-success;
-}
-
-.text-danger,
-.text-danger:hover {
-  color: @brand-danger;
-}
-
-.text-warning,
-.text-warning:hover {
-  color: @brand-warning;
-}
-
-.text-info,
-.text-info:hover {
-  color: @brand-info;
-}
-
-// Tables =====================================================================
-
-table,
-.table {
-
-  a:not(.btn) {
-    text-decoration: underline;
-  }
-
-  .dropdown-menu a {
-    text-decoration: none;
-  }
-
-  .success,
-  .warning,
-  .danger,
-  .info {
-    color: #fff;
-
-    a {
-      color: #fff;
-    }
-  }
-
-  > thead > tr > th,
-  > tbody > tr > th,
-  > tfoot > tr > th,
-  > thead > tr > td,
-  > tbody > tr > td,
-  > tfoot > tr > td {
-    border: none;
-  }
-
-  &-bordered > thead > tr > th,
-  &-bordered > tbody > tr > th,
-  &-bordered > tfoot > tr > th,
-  &-bordered > thead > tr > td,
-  &-bordered > tbody > tr > td,
-  &-bordered > tfoot > tr > td {
-    border: 1px solid @table-border-color;
-  }
-}
-
-// Forms ======================================================================
-
-.form-control,
-input, {
-  border-width: 2px;
-  .box-shadow(none);
-
-  &:focus {
-    .box-shadow(none);
-  }
-}
-
-.has-warning {
-  .help-block,
-  .control-label,
-  .radio,
-  .checkbox,
-  .radio-inline,
-  .checkbox-inline,
-  .form-control-feedback {
-    color: @brand-warning;
-  }
-
-  .form-control,
-  .form-control:focus {
-    border: 2px solid @brand-warning;
-  }
-
-  .input-group-addon {
-    border-color: @brand-warning;
-  }
-}
-
-.has-error {
-  .help-block,
-  .control-label,
-  .radio,
-  .checkbox,
-  .radio-inline,
-  .checkbox-inline,
-  .form-control-feedback {
-    color: @brand-danger;
-  }
-
-  .form-control,
-  .form-control:focus {
-    border: 2px solid @brand-danger;
-  }
-
-  .input-group-addon {
-    border-color: @brand-danger;
-  }
-}
-
-.has-success {
-  .help-block,
-  .control-label,
-  .radio,
-  .checkbox,
-  .radio-inline,
-  .checkbox-inline,
-  .form-control-feedback {
-    color: @brand-success;
-  }
-
-  .form-control,
-  .form-control:focus {
-    border: 2px solid @brand-success;
-  }
-
-  .input-group-addon {
-    border-color: @brand-success;
-  }
-}
-
-// Navs =======================================================================
-
-.nav {
-  .open > a,
-  .open > a:hover,
-  .open > a:focus {
-    border-color: transparent;
-  }
-}
-
-.pager {
-  a,
-  a:hover {
-    color: #fff;
-  }
-
-  .disabled {
-    &>a,
-    &>a:hover,
-    &>a:focus,
-    &>span {
-      background-color: @pagination-disabled-bg;
-    }
-  }
-}
-
-// Indicators =================================================================
-
-.close {
-  color: #fff;
-  text-decoration: none;
-  opacity: 0.4;
-
-  &:hover,
-  &:focus {
-    color: #fff;
-    opacity: 1;
-  }
-}
-
-.alert {
-
-  .alert-link {
-    color: #fff;
-    text-decoration: underline;
-  }
-}
-
-// Progress bars ==============================================================
-
-.progress {
-  height: 10px;
-  .box-shadow(none);
-  .progress-bar {
-    font-size: 10px;
-    line-height: 10px;
-  }
-}
-
-// Containers =================================================================
-
-.well {
-  .box-shadow(none);
-}
-
-a.list-group-item {
-
-  &.active,
-  &.active:hover,
-  &.active:focus {
-    border-color: @list-group-border;
-  }
-
-  &-success {
-    &.active {
-      background-color: @state-success-bg;
-    }
-
-    &.active:hover,
-    &.active:focus {
-      background-color: darken(@state-success-bg, 5%);
-    }
-  }
-
-  &-warning {
-    &.active {
-      background-color: @state-warning-bg;
-    }
-
-    &.active:hover,
-    &.active:focus {
-      background-color: darken(@state-warning-bg, 5%);
-    }
-  }
-
-  &-danger {
-    &.active {
-      background-color: @state-danger-bg;
-    }
-
-    &.active:hover,
-    &.active:focus {
-      background-color: darken(@state-danger-bg, 5%);
-    }
-  }
-}
-
-.panel {
-  &-default {
-    .close {
-      color: @text-color;
-    }
-  }
-}
-
-.modal {
-  .close {
-    color: @text-color;
-  }
-}
-
-.popover {
-  color: @text-color;
-}
diff --git a/public/css/themes/modern.less b/public/css/themes/modern.less
deleted file mode 100644
index f9e6d8b25f..0000000000
--- a/public/css/themes/modern.less
+++ /dev/null
@@ -1,151 +0,0 @@
-@import url("http://fonts.googleapis.com/css?family=Montserrat:400,700");
-@import url("http://fonts.googleapis.com/css?family=Raleway:400,300");
-
-// Colors
-// -------------------------
-
-@gray-lighter: #f5f5f5;
-@gray-light: #e0e0e0;
-@gray: #737373;
-@gray-dark: #404040;
-@gray-darker: #121212;
-
-@brand-primary: #2ac5ee;
-@brand-success: #0f9d58;
-@brand-warning: #f4b400;
-@brand-danger: #d80017;
-@brand-info: #5bc0dd;
-
-// Footer
-// -------------------------
-
-footer {
-  color: #fff;
-  background-color: @gray-darker;
-
-  a:hover {
-    color: #fff;
-  }
-}
-
-// Typography
-// -------------------------
-
-@font-size-base: 13px;
-@font-family-base: 'Montserrat', sans-serif;
-@headings-font-family: 'Montserrat', sans-serif;
-@headings-font-weight: 700;
-@text-color: @gray-darker;
-@link-color: @brand-primary;
-@link-hover-color: @gray-darker;
-
-a {
-  transition: all .4s cubic-bezier(.24,.45,.46,.92);
-
-  &:hover {
-    text-decoration: none;
-  }
-}
-
-ul,
-p {
-  font-family: 'Raleway', sans-serif;
-  font-size: 14px;
-  font-weight: 300;
-}
-
-.text-danger {
-  color: @brand-danger;
-}
-
-// Dropdowns
-// -------------------------
-
-@dropdown-link-color: @gray-darker;
-
-.dropdown-menu > li > a {
-  font-weight: 300;
-}
-
-// Buttons
-// -------------------------
-
-@btn-default-bg: @gray-lighter;
-@btn-default-color: @gray-darker;
-
-.btn {
-  padding: 10px 16px;
-  border: 0;
-  border-radius: 3px;
-  transition: all .4s cubic-bezier(.24,.45,.46,.92);
-
-  &:hover {
-    color: #fff;
-    background-color: @gray-darker;
-  }
-}
-
-.btn-social {
-  padding: 10px 50px;
-
-  :first-child {
-    width: 38px;
-    line-height: 38px;
-  }
-}
-
-.btn-link {
-
-  &:hover {
-    color: @gray-darker;
-    text-decoration: none;
-    background-color: transparent;
-  }
-}
-
-// Forms
-// -------------------------
-
-@input-border-radius: 2px;
-@input-border-focus: #999;
-@input-border: #f0f0f0;
-@input-color: #444;
-@input-color-placeholder: #999;
-@input-height-base: 44px;
-
-// Form states and alerts
-// -------------------------
-
-@state-success-bg: @brand-success;
-@state-info-bg: @brand-primary;
-@state-warning-bg: @brand-warning;
-@state-danger-bg: @brand-danger;
-
-.alert {
-  font-family: 'Raleway', sans-serif;
-  color: #fff;
-}
-
-// Navbar
-// -------------------------
-
-@navbar-height: 50px;
-@navbar-default-bg: rgba(255,255,255,0.95);
-@navbar-default-link-color: @gray-darker;
-@navbar-default-link-active-color: @brand-primary;
-@navbar-default-link-active-bg: transparent;
-@navbar-default-link-hover-color: @brand-primary;
-@navbar-default-link-hover-bg: transparent;
-@navbar-default-brand-color: @gray-darker;
-@navbar-default-brand-hover-color: @brand-primary;
-
-.navbar-default {
-  border: 0;
-  box-shadow: 0 1px 5px rgba(0,0,0,.15);
-
-  .navbar-nav {
-    > li > a {
-      transition: color .4s cubic-bezier(.24,.45,.46,.92);
-    }
-  }
-}
\ No newline at end of file
diff --git a/public/favicon.ico b/public/favicon.ico
index 3ec62dd50c..60054e1992 100644
Binary files a/public/favicon.ico and b/public/favicon.ico differ
diff --git a/public/favicons.html b/public/favicons.html
deleted file mode 100644
index ba348ed7db..0000000000
--- a/public/favicons.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/public/images/freeCodeCamp-puck.svg b/public/images/freeCodeCamp-puck.svg
new file mode 100644
index 0000000000..f2572ed38b
--- /dev/null
+++ b/public/images/freeCodeCamp-puck.svg
@@ -0,0 +1,37 @@
+
+
+
+
+Created by potrace 1.15, written by Peter Selinger 2001-2017
+
+
+
+
+
diff --git a/public/images/freecodecamp_logo.svg b/public/images/freecodecamp_logo.svg
deleted file mode 100644
index 2c24007979..0000000000
--- a/public/images/freecodecamp_logo.svg
+++ /dev/null
@@ -1,199 +0,0 @@
-
-
-
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	
-	
-
-
-
-
\ No newline at end of file
diff --git a/server/boot/authentication.js b/server/boot/authentication.js
index 100880e0a4..546bf6c755 100644
--- a/server/boot/authentication.js
+++ b/server/boot/authentication.js
@@ -29,25 +29,26 @@ module.exports = function enableAuthentication(app) {
   const api = app.loopback.Router();
   const { AuthToken, User } = app.models;
 
-  router.get('/login', (req, res) => res.redirect(301, '/signin'));
-  router.get('/logout', (req, res) => res.redirect(301, '/signout'));
-  router.get('/signup', (req, res) => res.redirect(301, '/signin'));
-  router.get('/email-signin', (req, res) => res.redirect(301, '/signin'));
+  router.get('/email-signin', (req, res) => res.redirect(301, '/login'));
+  router.get('/signin', (req, res) => res.redirect(301, '/signup'));
+  router.get('/signout', (req, res) => res.redirect(301, '/logout'));
 
-  function getEmailSignin(req, res) {
+  function getLegacySignUp(req, res) {
     if (isSignUpDisabled) {
       return res.render('account/beta', {
         title: 'New sign ups are disabled'
       });
     }
-    return res.render('account/email-signin', {
+    return res.render('account/deprecated-signup', {
       title: 'Sign in to freeCodeCamp using your Email Address'
     });
   }
+  router.get('/signup', ifUserRedirect, getLegacySignUp);
+  router.get('/login',
+  ifUserRedirect,
+  (req, res) => res.redirect(301, '/auth/auth0'));
 
-  router.get('/signin', ifUserRedirect, getEmailSignin);
-
-  router.get('/signout', (req, res) => {
+  router.get('/logout', (req, res) => {
     req.logout();
     res.redirect('/');
   });
diff --git a/server/component-passport.js b/server/component-passport.js
index f08305a4f2..63104737ff 100644
--- a/server/component-passport.js
+++ b/server/component-passport.js
@@ -2,6 +2,7 @@ import passport from 'passport';
 import { PassportConfigurator } from
  '@freecodecamp/loopback-component-passport';
 import passportProviders from './passport-providers';
+import url from 'url';
 
 const passportOptions = {
   emailOptional: true,
@@ -90,8 +91,58 @@ export default function setupPassport(app) {
   configurator.init();
 
   Object.keys(passportProviders).map(function(strategy) {
-    var config = passportProviders[strategy];
+    let config = passportProviders[strategy];
     config.session = config.session !== false;
+
+    // https://stackoverflow.com/q/37430452
+    let successRedirect = (req) => {
+      if (!!req && req.session && req.session.returnTo) {
+        let returnTo = req.session.returnTo;
+        delete req.session.returnTo;
+        return returnTo;
+      }
+      return config.successRedirect || '';
+    };
+
+    config.customCallback = !config.useCustomCallback
+      ? null
+      : (req, res, next) => {
+
+        passport.authenticate(
+          strategy,
+          { session: false },
+          (err, user) => {
+            if (err) {
+              return next(err);
+            }
+
+            if (!user) {
+              return res.redirect(config.failureRedirect);
+            }
+            let redirect = url.parse(successRedirect(req), true);
+
+            delete redirect.search;
+
+            req.flash(
+              'success',
+              'Success! You have signed in to your account. Happy Coding!'
+            );
+
+            // redirect.query = {
+            //   /* eslint-disable camelcase */
+            //   access_token: info.accessToken.id,
+            //   /* eslint-enable camelcase */
+            //   userId: user.id.toString()
+            // };
+
+            user.loginByRequest(req, res);
+
+            redirect = url.format(redirect);
+            return res.redirect(redirect);
+          }
+        )(req, res, next);
+    };
+
     configurator.configureProvider(
       strategy,
       {
diff --git a/server/middlewares/error-reporter.js b/server/middlewares/error-reporter.js
index 5b3aaba86b..2eb8455e2c 100644
--- a/server/middlewares/error-reporter.js
+++ b/server/middlewares/error-reporter.js
@@ -10,7 +10,7 @@ const log = debug('fcc:middlewares:error-reporter');
 
 const isOpbeatDisabled = !opbeat.appId;
 export default function errrorReporter() {
-  if (process.env.NODE_ENV !== 'production') {
+  if (process.env.NODE_ENV !== 'production' && process.env.ERROR_REPORTER) {
     return (err, req, res, next) => {
       if (isHandledError(err)) {
         // log out user messages in development
diff --git a/server/passport-providers.js b/server/passport-providers.js
index 733d1b845c..bab270396b 100644
--- a/server/passport-providers.js
+++ b/server/passport-providers.js
@@ -1,5 +1,5 @@
 const successRedirect = '/';
-const failureRedirect = '/signin';
+const failureRedirect = '/';
 const linkSuccessRedirect = '/settings';
 const linkFailureRedirect = '/settings';
 
@@ -165,5 +165,21 @@ export default {
       'We\'ve updated your profile based ',
       'on your your GitHub account.'
     ].join('')
+  },
+  'auth0-login': {
+    provider: 'auth0',
+    module: 'passport-auth0',
+    clientID: process.env.AUTH0_CLIENT_ID,
+    clientSecret: process.env.AUTH0_CLIENT_SECRET,
+    domain: process.env.AUTH0_DOMAIN,
+    cookieDomain: 'freeCodeCamp.org',
+    callbackURL: '/auth/auth0/callback',
+    authPath: '/auth/auth0',
+    callbackPath: '/auth/auth0/callback',
+    useCustomCallback: true,
+    successRedirect: successRedirect,
+    failureRedirect: failureRedirect,
+    scope: ['openid email'],
+    failureFlash: true
   }
 };
diff --git a/server/views/account/deprecated-signin.jade b/server/views/account/deprecated-signin.jade
index 0cb67ef558..9d51f4f018 100644
--- a/server/views/account/deprecated-signin.jade
+++ b/server/views/account/deprecated-signin.jade
@@ -1,26 +1,34 @@
 extends ../layout
 block content
-    .text-center
-        h2 If you originally signed up using one of these methods, you can sign in and add your email address to your account:
-        br
-        a.btn.btn-lg.btn-block.btn-social.btn-github(href='/auth/github')
-            i.fa.fa-github
-            | Sign in with GitHub
-        a.btn.btn-lg.btn-block.btn-social.btn-facebook(href='/auth/facebook')
-            i.fa.fa-facebook
-            | Sign in with Facebook
-        a.btn.btn-lg.btn-block.btn-social.btn-google(href='/auth/google')
-            i.fa.fa-google
-            | Sign in with Google
-        a.btn.btn-lg.btn-block.btn-social.btn-linkedin(href='/auth/linkedin')
-            i.fa.fa-linkedin
-            | Sign in with LinkedIn
-        a.btn.btn-lg.btn-block.btn-social.btn-twitter(href='/auth/twitter')
-            i.fa.fa-twitter
-            | Sign in with Twitter
-        br
-        p
-          a(href="/signin") Or click here to go back.
+  .container
+    .col-xs-12
+      .row
+        .text-center
+            h3 Sign in with one of these options if you used them as your original sign up methods :
+            br
+            a.btn.btn-lg.btn-block.btn-social.btn-github(href='/auth/github')
+                i.fa.fa-github
+                | Sign in with GitHub
+            a.btn.btn-lg.btn-block.btn-social.btn-facebook(href='/auth/facebook')
+                i.fa.fa-facebook
+                | Sign in with Facebook
+            a.btn.btn-lg.btn-block.btn-social.btn-google(href='/auth/google')
+                i.fa.fa-google
+                | Sign in with Google
+            a.btn.btn-lg.btn-block.btn-social.btn-linkedin(href='/auth/linkedin')
+                i.fa.fa-linkedin
+                | Sign in with LinkedIn
+            a.btn.btn-lg.btn-block.btn-social.btn-twitter(href='/auth/twitter')
+                i.fa.fa-twitter
+                | Sign in with Twitter
+            br
+            h3
+             | We are unable to create new accounts using these methods
+            h4 If you haven't updated your email with us, you should do that as soon as possible,
+             | after you login here, to avoid losing access to your account.
+            br
+            p
+              a(href="/signin") Or click here to go back.
 
     script.
       $(document).ready(function() {
diff --git a/server/views/account/deprecated-signup.jade b/server/views/account/deprecated-signup.jade
new file mode 100644
index 0000000000..b46594a565
--- /dev/null
+++ b/server/views/account/deprecated-signup.jade
@@ -0,0 +1,20 @@
+extends ../layout
+block content
+    .container
+      .col-xs-12
+        .row
+          .text-center
+            h2 Sign up (or sign in with your existing account)
+            br
+            br
+            br
+            a.btn.btn-lg.btn-primary(href='/auth/auth0')
+              | Continue with your email
+        .row
+          .text-center
+            br
+            br
+            br
+            br
+            a(href="/deprecated-signin")
+              | Continute with an old sign in method, that you used previously.
diff --git a/server/views/account/email-signin.jade b/server/views/account/email-signin.jade
deleted file mode 100644
index cf1fb37390..0000000000
--- a/server/views/account/email-signin.jade
+++ /dev/null
@@ -1,100 +0,0 @@
-extends ../layout
-block content
-    .container
-      .col-xs-12
-        .row
-          .col-sm-6.col-sm-offset-3.flashMessage.negative-30
-                #flash-board.alert.fade.in(style='display: none;')
-                    button.close(type='button', data-dismiss='alert')
-                        span.ion-close-circled#flash-close
-                    #flash-content
-        .row
-          .text-center
-            h2 Sign up (or sign in with your existing account)
-              .button-spacer
-          .col-sm-6.col-sm-offset-3
-              form(method='POST', action='/passwordless-auth')
-                  input(type='hidden', name='_csrf', value=_csrf)
-                  .form-group
-                      input.input-lg.form-control(type='email', name='email', id='email', placeholder='Enter your email address', autofocus=true, required, oninvalid="this.setCustomValidity('Enter your email address')", oninput="setCustomValidity('')")
-                  .button-spacer
-                  button#magic-btn.btn.btn-primary.btn-lg.btn-block(type='submit')
-                    | Get a sign in link
-        .row
-          .col-sm-6.col-sm-offset-3
-              br
-              p.text-center
-                br
-                br
-                a(href="/deprecated-signin") Try old sign in methods
-
-        script.
-          $(document).ready(function() {
-            function disableMagicButton (isDisabled) {
-                if (isDisabled) {
-                  $('#magic-btn')
-                    .prop('disabled', true)
-                    .html('OK - we\'re sending you an email. Open it and click sign in link.');
-                } else {
-                  $('#magic-btn')
-                    .prop('disabled', true)
-                    .html('If you didn\'t get the email, check your spam folder, or reload the page to try again.');
-                }
-            }
-
-            $('form').submit(function(event){
-              event.preventDefault();
-              $('#flash-board').hide();
-              disableMagicButton(true);
-              var $form = $(event.target);
-              $.ajax({
-                type        : 'POST',
-                url         : $form.attr('action'),
-                data        : $form.serialize(),
-                dataType    : 'json',
-                encode      : true,
-                xhrFields   : { withCredentials:  true }
-              })
-              .fail(error => {
-                if (error.responseText){
-                  var data = JSON.parse(error.responseText);
-                  if(data.error && data.error.message) {
-                    $('#flash-content').html(data.error.message);
-                    $('#flash-board')
-                      .removeClass('alert-success')
-                      .addClass('alert-info')
-                      .slideDown(400)
-                      .delay(800)
-                      .fadeIn();
-                    disableMagicButton(false);
-                  }
-                }
-              })
-              .done(data => {
-                if(data && data.message) {
-                  var alertType = 'alert-';
-                  switch (data.type) {
-                    case 'errors': {
-                      alertType += 'danger';
-                      break
-                    }
-                    case 'success': {
-                      alertType += 'success';
-                      break
-                    }
-                    default: {
-                      alertType += 'info';
-                    }
-                  }
-                  $('#flash-content').html(data.message);
-                  $('#flash-board')
-                    .removeClass('alert-info alert-success alert-danger')
-                    .addClass(alertType)
-                    .slideDown(400)
-                    .delay(800)
-                    .fadeIn();
-                  disableMagicButton(false);
-                }
-              });
-            });
-          });