Repository: mapbox/batfish
Pull request #127 (2017-07-30 21:54:02)

New CSS system that bypasses Webpack
@jfurrow: This is a bit of a beast, but please bear with me. I'm wide open to feedback about the approach.

While looking into the dev server's problem of reloading multiple times on the first build, I dug a little deeper into extract-text-webpack-plugin — and I didn't like what I found. It was the cause of the reloading problem. And it significantly slows down performance. Work on it is stalling while the Webpack team addresses the more fundamental architectural problems that make its use-cases so difficult to address. Basically: everyone admits that it's a flawed and temporary hack. It does the job for a lot of projects — but I wanted to experiment with something that would be faster and less mysterious.

So the main idea of this PR is to *bypass Webpack for the CSS build*. Instead, we can do our own CSS build that is faster, less hacky, more transparent.

The configuration option `externalStylesheets` is renamed `stylesheets`, because it is now *where you list all your styleseets* — whether they're URLs or files. At first I felt a little bit uneasy giving up the `import` syntax for CSS; but on second thought, I think this way is better because it maps more directly to what is actually happening: all your CSS is getting concatenated, in the order you specify, into one stylesheet for the site. (If at some point we can make a good system for component- or page-specific CSS, we will adjust.) `stylesheets` accepts URLs, files, and globs (e.g. `src/**/*.css`).

Other details:
- Demos are adjusted to the new reality.
- `start` and `build` now compile CSS outside of the Webpack build. They use the new `compileStylesheets` function.
- `compileStylesheets` is the complicated part, where the custom CSS build happens. It reads stylesheets, processes them with PostCSS, puts them in the specified order, concatenates them, (in production) minifies and hashes the output file, and threads source map support for files (not for URLs) through all of that. It writes the CSS file (and its source map) directory to the directory where Webpack is writing other assets.
- `start` watches Webpack files and CSS files in parallel. If CSS changes, only the CSS is rebuilt, and the new stylesheet is injected by Browsersync *without a page refresh*.
- All the Webpack-CSS-related dependencies are gone (css-loader, postcss-loader, style-loader, extract-text-webpack-plugin).
- While working I added a few new constants and created a `joinUrlParts` utility function to solve repeated problems.
- I reorganized `start.js` a bit.
- In order to load the non-Webpack CSS on the development server, I created `html-webpack-template.ejs` — a template for html-webpack-plugin to read. Another advantage of using this template is that we could add the `#batfish-content` element to the page and remove some unnecessary JS.
- Updated documentation. Hopefully it explains what the end user has to know about all the above.


davidtheclark: How to double-check this:

- Ensure the demos work, for the dev server and the build.
- Ensure the production build hashes the CSS file correctly.
- Ensure sourcemaps work.
- Ensure the documentation is coherent.
davidtheclark: Thanks @jfurrow. I will make the fixes you noted before merging.

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9cd225c..2db2800 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,10 @@
 
 ## Head
 
--   [Breaking change] Changed `wrapperPath` option to `applicationWrapperPath`.
+-   [Breaking change] Renamed `externalStylesheets` option to `stylesheets`.
+-   [Breaking change] CSS is no longer `import`ed or `require`d via Webpack.
+    All stylesheets should be listed in the `stylesheets` configuration array.
+-   [Breaking change] Renamed `wrapperPath` option to `applicationWrapperPath`.
 -   [Breaking change] Removed `notFoundPath` option.
     Instead, 404 pages always live as `404.(js|md)` in the `pagesDirectory`.
 -   [Breaking change] 404 pages are no longer `index.html` files inside directories, e.g. `404/index.html`.
diff --git a/README.md b/README.md
index 4bc33a3..735d36b 100644
--- a/README.md
+++ b/README.md
@@ -268,14 +268,17 @@ prefixUrl.absolute('engineer') // -> 'https://mydomain.com/about/jobs/engineer'
 
 ## CSS
 
-You can import CSS via `import` or `require` statements.
-Webpack will bundle all the imported CSS together.
+Add stylesheets to your site with the [`stylesheets`] configuration option.
+List all your stylesheets, URLs or filepaths, in the order you'd like, and Batfish will concatenate them together and add them to the build.
+You can also pass them through whatever [PostCSS] plugins you'd like.
 
 **During the static build, each page has its relevant CSS injected inline, and the complete stylesheet is loaded lazily, after the rest of the page is rendered.**
 This optimization ensures that the loading of an external stylesheet does not block rendering, and your page content is visible as quickly as possible.
 (This is accomplished with [postcss-html-filter].)
 
-You can also include stylesheets referenced by URL using the [`externalStylesheets`] configuration option.
+_Why not use a Webpack loader and allow `import` or `require` for CSS?_
+We've found that getting CSS to load in the way we want it to (for both the development server and the static build) has been messy, buggy, and slow enough via existing Webpack patterns that we decided to step outside of Webpack for this part of the build.
+However, you can add more Webpack loaders and plugins to accomplish this in your preferred way, if you'd like, using the [`webpackLoaders`] and [`webpackPlugins`] configuration options.
 
 ## Document `<head>`
 
@@ -319,6 +322,12 @@ Additional documentation can be found in [`docs/advanced-usage.md`](docs/advance
 
 [`production`]: docs/configuration.md#production
 
+[`stylesheets`]: docs/configuration.md#stylesheets
+
+[`webpackloaders`]: docs/configuration.md#webpackloaders
+
+[`webpackplugins`]: docs/configuration.md#webpackplugins
+
 [jsxtreme-markdown]: https://github.com/mapbox/jsxtreme-markdown
 
 [link-hijacker]: https://github.com/mapbox/link-hijacker
@@ -333,4 +342,4 @@ Additional documentation can be found in [`docs/advanced-usage.md`](docs/advance
 
 [postcss-html-filter]: https://github.com/mapbox/postcss-html-filter
 
-[`externalstylesheets`]: docs/configuration.md#externalstylesheets
+[postcss]: http://postcss.org/
diff --git a/docs/configuration.md b/docs/configuration.md
index 65e9932..4f61cbd 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -24,7 +24,7 @@ You can specify an alternate location.
     -   [siteBasePath](#sitebasepath)
     -   [siteOrigin](#siteorigin)
     -   [applicationWrapperPath](#applicationwrapperpath)
-    -   [externalStylesheets](#externalstylesheets)
+    -   [stylesheets](#stylesheets)
     -   [browserslist](#browserslist)
     -   [pagesDirectory](#pagesdirectory)
     -   [staticDirectory](#staticdirectory)
@@ -83,12 +83,17 @@ The component must be exported with `export default = YourWrapperComponent` or `
 
 This component will mount only once, wrapping Batfish's `Router` component, which in turn wraps your pages.
 
-### externalStylesheets
+### stylesheets
 
 `Array<string>` - Optional.
 
-An array of URLs to external stylesheets that you want to include in your site.
-These stylesheets need to be publicly available at the designated URL so Batfish can download them and work them into the CSS optimizations.
+An array of **URLs, filenames, or globs** pointing to stylesheets that you want to include in your site.
+
+If an item is a URL, it must start with `http(s)` and must be publicly available, so Batfish can download it and work it into the CSS optimizations.
+If using filenames and globs, provide absolute paths.
+
+If you need to control the order of your stylesheets, avoid globs.
+Batfish cannot guarantee the order in which files matching your glob will be concatenated.
 
 ### browserslist
 
@@ -193,14 +198,12 @@ You'll need to use this if, for example, you use a library that includes ES2015
 
 `Array<Function> | Function` - Optional. Default: Autoprefixer only.
 
-All of the CSS you load via Webpack is run through [PostCSS](http://postcss.org/), so you can apply any [PostCSS plugins](https://github.com/postcss/postcss/blob/master/docs/plugins.md) to it.
+All of the CSS you load via [`stylesheets`] is run through [PostCSS](http://postcss.org/), so you can apply any [PostCSS plugins](https://github.com/postcss/postcss/blob/master/docs/plugins.md) to it.
 By default, only [Autoprefixer] is applied.
 
 If a function is provided, it will receive the default array as an argument and should return a new array.
 A transform function is probably preferable if you only need to add or remove an item or two from the default array.
 
-This value is passed directly to [postcss-loader](https://github.com/postcss/postcss-loader#plugins).
-
 ### fileLoaderExtensions
 
 `Array<string> | Function` - Options. Default: `['jpeg', 'jpg', 'png', 'gif', 'webp', 'mp4', 'webm', 'woff', 'woff2']`
@@ -290,4 +293,6 @@ If the specified port is unavailable, another port is used.
 
 [`outputdirectory`]: #outputdirectory
 
+[`stylesheets`]: #stylesheets
+
 ["injecting data"]: ./advanced-usage.md#injecting-data
diff --git a/examples/basic/batfish.config.js b/examples/basic/batfish.config.js
index f3b9027..ee64e4d 100644
--- a/examples/basic/batfish.config.js
+++ b/examples/basic/batfish.config.js
@@ -1,9 +1,12 @@
+const path = require('path');
+
 module.exports = () => {
   return {
     siteBasePath: '/example',
     siteOrigin: 'https://www.mapbox.com',
-    externalStylesheets: [
-      'https://api.mapbox.com/mapbox-assembly/v0.15.0/assembly.min.css'
+    stylesheets: [
+      'https://api.mapbox.com/mapbox-assembly/v0.15.0/assembly.min.css',
+      path.join(__dirname, './src/style.css')
     ]
   };
 };
diff --git a/examples/basic/src/components/wrapper.js b/examples/basic/src/components/wrapper.js
index 7b8daaa..e258b01 100644
--- a/examples/basic/src/components/wrapper.js
+++ b/examples/basic/src/components/wrapper.js
@@ -1,5 +1,5 @@
 import React, { PureComponent } from 'react';
-import '../style.css';
+
 export default class Wrapper extends PureComponent {
   render() {
     return (
diff --git a/examples/initial-experiments/batfish.config.js b/examples/initial-experiments/batfish.config.js
index a7ba20f..7baaaba 100644
--- a/examples/initial-experiments/batfish.config.js
+++ b/examples/initial-experiments/batfish.config.js
@@ -6,8 +6,9 @@ module.exports = () => {
     applicationWrapperPath: path.join(__dirname, './src/components/wrapper.js'),
     siteOrigin: 'https://www.mapbox.com',
     siteBasePath: '/demo',
-    externalStylesheets: [
-      'https://api.mapbox.com/mapbox-assembly/v0.13.0/assembly.min.css'
+    stylesheets: [
+      'https://api.mapbox.com/mapbox-assembly/v0.16.0/assembly.min.css',
+      path.join(__dirname, './src/*.css')
     ],
     dataSelectors: {
       posts: data => {
diff --git a/examples/initial-experiments/package.json b/examples/initial-experiments/package.json
index 41df487..fb98b36 100644
--- a/examples/initial-experiments/package.json
+++ b/examples/initial-experiments/package.json
@@ -4,6 +4,6 @@
     "batfish": "../../bin/batfish.js"
   },
   "dependencies": {
-    "source-map-support": "^0.4.15"
+    "source-map": "^0.5.6"
   }
 }
diff --git a/examples/initial-experiments/src/components/page-shell.js b/examples/initial-experiments/src/components/page-shell.js
index a9e07e1..fe3006f 100644
--- a/examples/initial-experiments/src/components/page-shell.js
+++ b/examples/initial-experiments/src/components/page-shell.js
@@ -13,10 +13,10 @@ class PageShell extends React.Component {
             src="https://api.mapbox.com/mapbox-assembly/v0.13.0/assembly.js"
           />
         </Helmet>
-        <div className="wmax480 mx-auto mt72">
+        <div className="wmax600 mx-auto mt60">
           {this.props.children}
 
-          <div className="mt72 p24 bg-gray-faint">
+          <div className="mt60 px24 py24 bg-gray-faint">
             <a className="link inline-block mr24" href={prefixUrl('/')}>
               home
             </a>
diff --git a/examples/initial-experiments/src/components/wrapper.js b/examples/initial-experiments/src/components/wrapper.js
index c6f1e14..63dddbd 100644
--- a/examples/initial-experiments/src/components/wrapper.js
+++ b/examples/initial-experiments/src/components/wrapper.js
@@ -3,7 +3,6 @@ import {
   addRouteChangeStartListener,
   addRouteChangeEndListener
 } from '@mapbox/batfish/modules/route-change-listeners';
-import '../test.css';
 
 addRouteChangeStartListener(() => {
   console.log('starting the route change');
diff --git a/examples/markdown-world/batfish.config.js b/examples/markdown-world/batfish.config.js
index 96d5a35..064f813 100644
--- a/examples/markdown-world/batfish.config.js
+++ b/examples/markdown-world/batfish.config.js
@@ -1,9 +1,10 @@
 module.exports = () => {
   return {
     port: 9999,
-    externalStylesheets: [
+    stylesheets: [
       'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css',
-      'https://api.mapbox.com/mapbox-assembly/v0.14.0/assembly.min.css'
+      'https://api.mapbox.com/mapbox-assembly/v0.14.0/assembly.min.css',
+      'src/**/*.css'
     ],
     jsxtremeMarkdownOptions: {
       remarkPlugins: [require('remark-emoji')],
diff --git a/examples/markdown-world/src/pages/markdown-react/index.js b/examples/markdown-world/src/pages/markdown-react/index.js
index 0600f2a..e4e1e7d 100644
--- a/examples/markdown-world/src/pages/markdown-react/index.js
+++ b/examples/markdown-world/src/pages/markdown-react/index.js
@@ -9,7 +9,7 @@ const PageShell = require('../../components/page-shell');
 const PageHero = require('../../components/page-hero');
 const prefixUrl = require('@mapbox/batfish/modules/prefix-url').prefixUrl;
 const Helmet = require('react-helmet').Helmet;
-require('./unique.css');
+
 class MarkdownReactPage extends React.Component {
   render() {
     return (
diff --git a/examples/react-component-pages/batfish.config.js b/examples/react-component-pages/batfish.config.js
index d99519c..a2ff7a3 100644
--- a/examples/react-component-pages/batfish.config.js
+++ b/examples/react-component-pages/batfish.config.js
@@ -2,8 +2,9 @@ const path = require('path');
 
 module.exports = () => {
   return {
-    externalStylesheets: [
-      'https://api.mapbox.com/mapbox-assembly/v0.13.0/assembly.min.css'
+    stylesheets: [
+      'https://api.mapbox.com/mapbox-assembly/v0.13.0/assembly.min.css',
+      path.join(__dirname, './src/blog.css')
     ],
     applicationWrapperPath: path.join(__dirname, './src/components/wrapper.js')
   };
diff --git a/examples/react-component-pages/src/pages/blog.css b/examples/react-component-pages/src/blog.css
similarity index 100%
rename from examples/react-component-pages/src/pages/blog.css
rename to examples/react-component-pages/src/blog.css
diff --git a/examples/react-component-pages/src/pages/blog.js b/examples/react-component-pages/src/pages/blog.js
index 12ad0cb..a3c16f4 100644
--- a/examples/react-component-pages/src/pages/blog.js
+++ b/examples/react-component-pages/src/pages/blog.js
@@ -21,7 +21,6 @@ blogPosts:
 ---*/
 
 const React = require('react');
-require('./blog.css');
 
 class BlogPage extends React.Component {
   renderBlogPost(blogPost, index) {
diff --git a/examples/using-siteOrigin/batfish.config.js b/examples/using-siteOrigin/batfish.config.js
index 93b884c..5a6288e 100644
--- a/examples/using-siteOrigin/batfish.config.js
+++ b/examples/using-siteOrigin/batfish.config.js
@@ -2,8 +2,9 @@ const path = require('path');
 
 module.exports = () => {
   return {
-    externalStylesheets: [
-      'https://api.mapbox.com/mapbox-assembly/v0.13.0/assembly.min.css'
+    stylesheets: [
+      'https://api.mapbox.com/mapbox-assembly/v0.13.0/assembly.min.css',
+      path.join(__dirname, './src/*.css')
     ],
     siteOrigin: '//localhost:8080',
     applicationWrapperPath: path.join(__dirname, './src/components/wrapper.js')
diff --git a/examples/using-siteOrigin/src/components/wrapper.js b/examples/using-siteOrigin/src/components/wrapper.js
index 8bd2e97..50408f3 100644
--- a/examples/using-siteOrigin/src/components/wrapper.js
+++ b/examples/using-siteOrigin/src/components/wrapper.js
@@ -1,6 +1,5 @@
 import React, { Component } from 'react';
 import { prefixUrlAbsolute } from '@mapbox/batfish/modules/prefix-url';
-import '../wrapper.css';
 
 export default class Wrapper extends Component {
   render() {
diff --git a/lib/build.js b/lib/build.js
index 5641f18..4c7be09 100644
--- a/lib/build.js
+++ b/lib/build.js
@@ -7,6 +7,7 @@ const chalk = require('chalk');
 const fs = require('fs');
 const del = require('del');
 const cpy = require('cpy');
+const _ = require('lodash');
 const UglifyJs = require('uglify-js');
 const createWebpackConfigClient = require('./create-webpack-config-client');
 const createWebpackConfigStatic = require('./create-webpack-config-static');
@@ -14,6 +15,9 @@ const timelog = require('./timelog');
 const validateConfig = require('./validate-config');
 const inlineCss = require('./inline-css');
 const generateSitemap = require('./generate-sitemap');
+const compileStylesheets = require('./compile-stylesheets');
+const joinUrlParts = require('./join-url-parts');
+const constants = require('./constants');
 
 /**
  * Build static pages and assets, ready for deployment.
@@ -30,8 +34,12 @@ function build(rawConfig, projectDirectory) {
     rawConfig
   );
   const batfishConfig = validateConfig(rawConfig, projectDirectory);
+  const stylesheetsIsEmpty = _.isEmpty(batfishConfig.stylesheets);
   const outputDirectory = batfishConfig.outputDirectory;
-  const assetsDirectory = path.join(outputDirectory, 'assets');
+  const assetsDirectory = path.join(
+    outputDirectory,
+    constants.PUBLIC_PATH_ASSETS
+  );
 
   const getAssetFilePath = assetPath => {
     const pathWithoutBase = assetPath.replace(
@@ -84,18 +92,31 @@ function build(rawConfig, projectDirectory) {
   const start = batfishConfig.clearOutputDirectory
     ? del(outputDirectory, { force: true })
     : Promise.resolve();
+  let cssFilename;
   return start
     .then(() => {
-      timelog('Bundling for client');
+      if (stylesheetsIsEmpty) return;
+      timelog('Compiling CSS');
+      return compileStylesheets(
+        batfishConfig,
+        assetsDirectory
+      ).then(filename => {
+        cssFilename = filename;
+      });
+    })
+    .then(() => {
+      timelog('Creating the client bundle');
       return buildClient();
     })
     .then(() => {
-      timelog('Bundling for static pages');
+      timelog('Creating the static-page-rendering bundle');
       return buildStatic();
     })
-    .then(() => Promise.all([copyNonPages(), copyStatic()]))
     .then(() => {
-      timelog('Successful Webpack bundling');
+      timelog('Copying files');
+      return Promise.all([copyNonPages(), copyStatic()]);
+    })
+    .then(() => {
       return pify(fs.readFile)(
         path.join(assetsDirectory, 'assets.json'),
         'utf8'
@@ -103,45 +124,53 @@ function build(rawConfig, projectDirectory) {
     })
     .then(rawAssets => {
       const assets = JSON.parse(rawAssets);
-      // Asset filenames in assets JSON are relative to the outputDirectory
-      return pify(fs.readFile)(getAssetFilePath(assets.manifest.js), 'utf8')
-        .then(manifestJs => {
-          timelog('Starting static HTML build');
-          const uglifiedManifestJs = UglifyJs.minify(manifestJs, {
-            fromString: true
-          }).code;
+      const manifestJs = fs.readFileSync(
+        getAssetFilePath(assets.manifest.js),
+        'utf8'
+      );
+
+      timelog('Starting static HTML build');
+      const uglifiedManifestJs = UglifyJs.minify(manifestJs, {
+        fromString: true
+      }).code;
 
-          let staticRenderPages;
-          try {
-            staticRenderPages = require(path.join(
-              assetsDirectory,
-              'static-render-pages.js'
-            )).default;
-            return staticRenderPages(
-              batfishConfig,
-              assets,
-              uglifiedManifestJs
-            ).catch(error => {
-              timelog(
-                `${chalk.red.bold(
-                  'Error executing static-render-pages.js.'
-                )} You may be importing a JS file that cannot run in Node.`
-              );
-              throw error;
-            });
-          } catch (requireError) {
-            timelog(
-              `${chalk.red.bold('Error parsing static-render-pages.js')}`
-            );
-            throw requireError;
-          }
-        })
-        .then(() => {
-          if (!batfishConfig.production) return;
-          return inlineCss(outputDirectory, getAssetFilePath(assets.app.css), {
-            verbose: batfishConfig.verbose
-          });
+      const cssUrl = stylesheetsIsEmpty
+        ? undefined
+        : joinUrlParts(
+            batfishConfig.siteBasePath,
+            constants.PUBLIC_PATH_ASSETS,
+            path.basename(cssFilename)
+          );
+
+      let staticRenderPages;
+      try {
+        staticRenderPages = require(path.join(
+          assetsDirectory,
+          'static-render-pages.js'
+        )).default;
+        return staticRenderPages(
+          batfishConfig,
+          assets,
+          uglifiedManifestJs,
+          cssUrl
+        ).catch(error => {
+          timelog(
+            `${chalk.red.bold(
+              'Error executing static-render-pages.js.'
+            )} You may be importing a JS file that cannot run in Node.`
+          );
+          throw error;
         });
+      } catch (requireError) {
+        timelog(`${chalk.red.bold('Error parsing static-render-pages.js')}`);
+        throw requireError;
+      }
+    })
+    .then(() => {
+      if (!batfishConfig.production || stylesheetsIsEmpty) return;
+      return inlineCss(outputDirectory, cssFilename, {
+        verbose: batfishConfig.verbose
+      });
     })
     .then(() => {
       if (batfishConfig.siteOrigin) {
diff --git a/lib/compile-stylesheets.js b/lib/compile-stylesheets.js
new file mode 100644
index 0000000..b4ac715
--- /dev/null
+++ b/lib/compile-stylesheets.js
@@ -0,0 +1,179 @@
+'use strict';
+
+const got = require('got');
+const path = require('path');
+const fs = require('fs');
+const _ = require('lodash');
+const pify = require('pify');
+const globby = require('globby');
+const postcss = require('postcss');
+const mkdirp = require('mkdirp');
+const csso = require('csso');
+const hasha = require('hasha');
+const Concat = require('concat-with-sourcemaps');
+const SourceMapConsumer = require('source-map').SourceMapConsumer;
+const constants = require('./constants');
+const postcssAbsoluteUrls = require('./postcss-absolute-urls');
+
+const FAKE_CSS_TARGET = 'concat.css';
+const urlCache = new Map();
+
+// Special logging for PostCSS errors. Makes them very easy to understand.
+function handlePostcssError(error) {
+  if (error.name === 'CssSyntaxError') {
+    console.log(error.message);
+    console.log(error.showSourceCode());
+  } else {
+    throw error;
+  }
+}
+
+/**
+ * Fetch and concatenate stylesheets, with source maps.
+ *
+ * @param {BatfishConfig} batfishConfig
+ * @param {string} [cssOutputDirectory] - Defaults to batfishConfig.outputDirectory.
+ * @return {Promise<string>} - Resolves with the absolute path to the written file.
+ */
+function compileStylesheets(batfishConfig, cssOutputDirectory) {
+  if (_.isEmpty(batfishConfig.stylesheets)) return Promise.resolve();
+  cssOutputDirectory = cssOutputDirectory || batfishConfig.outputDirectory;
+
+  // Ensure the stylesheets are concatenated in the order specified.
+  // Each item will be an object with locator, css, and map properties.
+  // After all are accumulated, we'll concatenate them together in that order.
+  const stylesheetContents = [];
+
+  // Get a CSS from a URL and insert it into stylesheetContents
+  // at the specified index.
+  const getStylesheetFromUrl = (url, index) => {
+    const cached = urlCache.get(url);
+    if (cached) {
+      stylesheetContents[index] = cached;
+      return Promise.resolve();
+    }
+
+    return got(url)
+      .then(response => {
+        return (
+          postcss()
+            // Make all the URLs in the stylesheet absolute so the new local
+            // stylesheet can fetch assets like fonts and images.
+            .use(postcssAbsoluteUrls({ stylesheetUrl: url }))
+            .process(response.body, { from: url, to: FAKE_CSS_TARGET })
+            .catch(handlePostcssError)
+        );
+      })
+      .then(result => {
+        const contentsItem = { locator: url, css: result.css };
+        urlCache.set(url, contentsItem);
+        stylesheetContents[index] = contentsItem;
+      });
+  };
+
+  const processSingleStylesheetFromFs = filename => {
+    return pify(fs.readFile)(filename, 'utf8').then(css => {
+      return postcss(batfishConfig.postcssPlugins)
+        .process(css, {
+          from: filename,
+          to: FAKE_CSS_TARGET,
+          map: {
+            inline: false,
+            sourcesContent: true,
+            annotation: false
+          }
+        })
+        .then(result => {
+          return {
+            locator: filename,
+            css: result.css,
+            map: result.map.toString()
+          };
+        })
+        .catch(handlePostcssError);
+    });
+  };
+
+  // input could be a filename or a glob or an array of those.
+  // Get the CSS from each file and insert it into stylesheetContents
+  // at the specified index. If input is array, that item in stylesheetContents
+  // will be an array.
+  const getStylesheetFromFs = (input, index) => {
+    return globby(input, { absolute: true })
+      .then(filenames => {
+        return Promise.all(filenames.map(processSingleStylesheetFromFs));
+      })
+      .then(contents => {
+        stylesheetContents[index] = contents;
+      });
+  };
+
+  // Runs after stylesheetContents has been populated. Concatenates the CSS
+  // in that order, with source maps. Outputs new CSS and and a new source map.
+  const concatStylesheetContents = () => {
+    const concatenator = new Concat(
+      true,
+      path.join(cssOutputDirectory, constants.BATFISH_CSS_BASENAME, '\n')
+    );
+    // Since items in stylesheets can be an array, we need to be recursive here.
+    const addItems = list => {
+      list.forEach(item => {
+        if (Array.isArray(item)) return addItems(item);
+        concatenator.add(item.locator, item.css, item.map);
+      });
+    };
+    addItems(stylesheetContents);
+    return {
+      css: concatenator.content,
+      map: concatenator.sourceMap
+    };
+  };
+
+  return Promise.all(
+    batfishConfig.stylesheets.map((locator, index) => {
+      if (/^http/.test(locator)) {
+        return getStylesheetFromUrl(locator, index);
+      }
+      return getStylesheetFromFs(locator, index);
+    })
+  )
+    .then(() => pify(mkdirp)(cssOutputDirectory))
+    .then(() => {
+      const concatenated = concatStylesheetContents();
+
+      let finalCss = concatenated.css;
+      let finalMap = concatenated.map;
+
+      // Minify for production. csso's source map integration is awkward but
+      // seems to work ok.
+      if (batfishConfig.production) {
+        const cssoOutput = csso.minify(finalCss, {
+          filename: FAKE_CSS_TARGET,
+          sourceMap: true
+        });
+        finalCss = cssoOutput.css;
+        cssoOutput.map.applySourceMap(
+          new SourceMapConsumer(finalMap),
+          FAKE_CSS_TARGET
+        );
+        finalMap = cssoOutput.map.toString();
+      }
+
+      // Add a md5 hash to the filename for production.
+      let basename = constants.BATFISH_CSS_BASENAME;
+      if (batfishConfig.production) {
+        const hash = hasha(finalCss, { algorithm: 'md5' });
+        basename = basename.replace(/\.css$/, `-${hash}.css`);
+      }
+
+      const finalCssWithSourcemapAnnotation = `${finalCss}/*# sourceMappingURL=${basename}.map */`;
+      const cssFilePath = path.join(cssOutputDirectory, basename);
+      const mapFilePath = `${cssFilePath}.map`;
+      return Promise.all([
+        pify(fs.writeFile)(cssFilePath, finalCssWithSourcemapAnnotation),
+        pify(fs.writeFile)(mapFilePath, finalMap)
+      ]).then(() => cssFilePath);
+    });
+}
+
+module.exports = compileStylesheets;
diff --git a/lib/concat-external-stylesheets.js b/lib/concat-external-stylesheets.js
deleted file mode 100644
index b7e9aa1..0000000
--- a/lib/concat-external-stylesheets.js
+++ /dev/null
@@ -1,44 +0,0 @@
-'use strict';
-
-const got = require('got');
-const path = require('path');
-const fs = require('fs');
-const pify = require('pify');
-const postcss = require('postcss');
-const postcssAbsoluteUrls = require('./postcss-absolute-urls');
-
-/**
- * Fetch and concatenate external stylesheets.
- *
- * @param {BatfishConfig} batfishConfig
- * @return {Promise<string>} - Resolves with the absolute path to the written file.
- */
-function concatExternalStylesheets(batfishConfig) {
-  const filePath = path.join(
-    batfishConfig.temporaryDirectory,
-    'external-stylesheets.css'
-  );
-
-  const getStylesheet = url => {
-    return got(url)
-      .then(response => {
-        const css = response.body;
-        return postcss()
-          .use(postcssAbsoluteUrls({ stylesheetUrl: url }))
-          .process(css);
-      })
-      .then(result => result.css);
-  };
-
-  // Ensure the stylesheets are concatenated in the order specified.
-  const stylesheetContents = [];
-  return Promise.all(
-    batfishConfig.externalStylesheets.map((url, i) => {
-      return getStylesheet(url).then(css => (stylesheetContents[i] = css));
-    })
-  )
-    .then(() => pify(fs.writeFile)(filePath, stylesheetContents.join('\n')))
-    .then(() => filePath);
-}
-
-module.exports = concatExternalStylesheets;
diff --git a/lib/constants.js b/lib/constants.js
index 31a2ae6..2121a34 100644
--- a/lib/constants.js
+++ b/lib/constants.js
@@ -1,5 +1,7 @@
 'use strict';
 
 module.exports = {
-  INLINE_CSS_MARKER: '<!-- INLINE CSS HERE, BATFISH -->'
+  INLINE_CSS_MARKER: '<!-- INLINE CSS HERE, BATFISH -->',
+  BATFISH_CSS_BASENAME: 'batfish-styles.css',
+  PUBLIC_PATH_ASSETS: 'assets'
 };
diff --git a/lib/create-batfish-context.js b/lib/create-batfish-context.js
index 19b8a9e..a359b91 100644
--- a/lib/create-batfish-context.js
+++ b/lib/create-batfish-context.js
@@ -8,7 +8,6 @@ const slugg = require('slugg');
 const prettier = require('prettier');
 const getPagesData = require('./get-pages-data');
 const createPageModule = require('./create-page-module');
-const concatExternalStylesheets = require('./concat-external-stylesheets');
 
 /**
  * Create a JS module that can be used during Webpack compilation,
@@ -27,6 +26,9 @@ const concatExternalStylesheets = require('./concat-external-stylesheets');
  * The file is written to the temporaryDirectory and made available with a
  * Webpack alias. **Intended for internal use only.**
  *
+ * Looking at a generated batfish-context.js file will help a lot if you're
+ * trying to understand how this works.
+ *
  * @param {BatfishConfig} batfishConfig
  * @return {Promise<string>} - Resolves with the absolute path to the written
  *   module file.
@@ -37,13 +39,9 @@ function createBatfishContext(batfishConfig) {
     'batfish-context.js'
   );
 
-  return Promise.all([
-    getPagesData(batfishConfig),
-    concatExternalStylesheets(batfishConfig)
-  ])
+  return Promise.all([getPagesData(batfishConfig)])
     .then(results => {
       const pagesData = results[0];
-      const externalStylesheetsPath = results[1];
 
       // Construct a data object for the entire site.
       // Pages can load this data with siteData front-matter
@@ -90,9 +88,7 @@ function createBatfishContext(batfishConfig) {
         Object.keys(pagesData).map(stringifyPageRoute)
       ).then(() => {
         const stringifiedRoutesArray = `[${stringifiedRoutes.join(',')}]`;
-        // Import the CSS here, so it's processed by the text extract plugin.
         const content = `
-          import '${externalStylesheetsPath}';
           export const batfishContext = {
             selectedConfig: {
               siteBasePath: '${batfishConfig.siteBasePath}',
diff --git a/lib/create-webpack-config-base.js b/lib/create-webpack-config-base.js
index 214c83c..7e4164b 100644
--- a/lib/create-webpack-config-base.js
+++ b/lib/create-webpack-config-base.js
@@ -4,8 +4,9 @@ const _ = require('lodash');
 const path = require('path');
 const webpack = require('webpack');
 const WebpackChunkHash = require('webpack-chunk-hash');
-const ExtractTextPlugin = require('extract-text-webpack-plugin');
 const createBatfishContext = require('./create-batfish-context');
+const joinUrlParts = require('./join-url-parts');
+const constants = require('./constants');
 
 // Cache it to ensure we don't do unnecessary work within one process.
 let cachedConfig;
@@ -76,23 +77,6 @@ function createWebpackConfigBase(batfishConfig) {
       }
     };
 
-    const cssLoaderConfig = {
-      loader: 'css-loader',
-      options: {
-        minimize: batfishConfig.production,
-        sourceMap: !batfishConfig.production
-      }
-    };
-
-    const postcssLoaderConfig = {
-      loader: 'postcss-loader',
-      options: {
-        plugins() {
-          return batfishConfig.postcssPlugins;
-        }
-      }
-    };
-
     const aliases = {
       'batfish-internal/context': batfishContextPath,
       'batfish-internal/application-wrapper':
@@ -109,7 +93,11 @@ function createWebpackConfigBase(batfishConfig) {
     const config = {
       output: {
         path: batfishConfig.outputDirectory,
-        publicPath: `${batfishConfig.siteBasePath}/assets/`,
+        publicPath: joinUrlParts(
+          batfishConfig.siteBasePath,
+          constants.PUBLIC_PATH_ASSETS,
+          ''
+        ),
         pathinfo: batfishConfig.verbose,
         filename: '[name].js'
       },
@@ -130,7 +118,6 @@ function createWebpackConfigBase(batfishConfig) {
         rules: [
           {
             test: /\.jsx?$/,
-            enforce: 'pre',
             exclude: batfishConfig.babelExclude,
             use: [babelLoaderConfig]
           },
@@ -138,7 +125,6 @@ function createWebpackConfigBase(batfishConfig) {
             test: new RegExp(
               _.escapeRegExp(batfishConfig.pagesDirectory) + '.*.md$'
             ),
-            enforce: 'pre',
             use: [
               babelLoaderConfig,
               {
@@ -147,27 +133,18 @@ function createWebpackConfigBase(batfishConfig) {
               }
             ]
           },
-          // style-loader breaks server-rendering. So instead we
-          // extract the CSS text into a file, styles.css, which gets
-          // loaded in the document head. Works in tandem with the plugin below.
-          {
-            test: /\.css$/,
-            use: ExtractTextPlugin.extract({
-              fallback: 'style-loader',
-              use: [cssLoaderConfig, postcssLoaderConfig]
-            })
-          },
           // Static assets are copied into assets/ with an added hash,
           // and when you require() them you'll get the proper
           // filename (with hash).
           {
             test: fileLoaderTest,
             loader: 'file-loader',
-            enforce: 'post',
             options: {
               hash: 'sha512',
               digest: 'hex',
-              name: '[name]-[hash].[ext]'
+              name: batfishConfig.production
+                ? '[name]-[hash].[ext]'
+                : '[name].[ext]'
             }
           },
           // JSON!
@@ -186,13 +163,6 @@ function createWebpackConfigBase(batfishConfig) {
             ? '"development"'
             : '"production"'
         }),
-        // Extract imported CSS into one file to be cached. Works in tandem with the loader above.
-        new ExtractTextPlugin({
-          filename: !batfishConfig.production
-            ? 'styles.css'
-            : 'styles-[chunkhash].css',
-          allChunks: true
-        }),
         // Determine hashes with file content, not random strings. This allows for long-term caching.
         new WebpackChunkHash()
       ],
diff --git a/lib/join-url-parts.js b/lib/join-url-parts.js
new file mode 100644
index 0000000..ab9b109
--- /dev/null
+++ b/lib/join-url-parts.js
@@ -0,0 +1,23 @@
+'use strict';
+
+/**
+ * Determine if a slash has to be added between the parts you're combining.
+ * And combine the parts.
+ *
+ * @param {...string} parts - Pass an empty string as the last argument if you
+ *   want the returned URL to end with a slash.
+ * @return {string}
+ */
+function joinUrlParts() {
+  let result = '';
+  for (let i = 0, l = arguments.length; i < l; i++) {
+    const arg = arguments[i];
+    if (i !== 0 && !/\/$/.test(result) && !/^\//.test(arg)) {
+      result += '/';
+    }
+    result += arg;
+  }
+  return result;
+}
+
+module.exports = joinUrlParts;
diff --git a/lib/start.js b/lib/start.js
index 6b860f4..b30147b 100644
--- a/lib/start.js
+++ b/lib/start.js
@@ -5,6 +5,8 @@ const chalk = require('chalk');
 const del = require('del');
 const fs = require('fs');
 const path = require('path');
+const _ = require('lodash');
+const chokidar = require('chokidar');
 const getPort = require('get-port');
 const browserSync = require('browser-sync');
 const historyApiFallback = require('connect-history-api-fallback');
@@ -12,8 +14,15 @@ const HtmlWebpackPlugin = require('html-webpack-plugin');
 const webpackMerge = require('webpack-merge');
 const createWebpackConfigClient = require('./create-webpack-config-client');
 const timelog = require('./timelog');
+const constants = require('./constants');
 const validateConfig = require('./validate-config');
 const logServerInit = require('./log-server-init');
+const compileStylesheets = require('./compile-stylesheets');
+const joinUrlParts = require('./join-url-parts');
+
+const webpackWatchOptions = {
+  ignored: /node_modules/
+};
 
 /**
  * Start the development server and Webpack watcher.
@@ -24,19 +33,24 @@ const logServerInit = require('./log-server-init');
 function start(rawConfig, projectDirectory) {
   rawConfig = rawConfig || {};
   const batfishConfig = validateConfig(rawConfig, projectDirectory);
+  const stylesheetsIsEmpty = _.isEmpty(batfishConfig.stylesheets);
   const server = browserSync.create();
   const exit = () => {
     server.exit();
     process.exit();
   };
   const statsFilename = path.join(batfishConfig.outputDirectory, 'stats.json');
+  const htmlWebpackPluginOptions = {
+    template: path.join(__dirname, '../src/html-webpack-template.ejs'),
+    cssBasename: stylesheetsIsEmpty ? '' : constants.BATFISH_CSS_BASENAME
+  };
 
   createWebpackConfigClient(batfishConfig, {
     devServer: true
   }).then(clientConfig => {
     // Create an HTML file to load the assets in the browser.
     const config = webpackMerge(clientConfig, {
-      plugins: [new HtmlWebpackPlugin()]
+      plugins: [new HtmlWebpackPlugin(htmlWebpackPluginOptions)]
     });
     config.stats = 'normal';
 
@@ -49,7 +63,10 @@ function start(rawConfig, projectDirectory) {
     const startServer = () => {
       process.on('SIGINT', exit);
 
-      const serveAssetsDir = batfishConfig.siteBasePath + '/assets';
+      const serveAssetsDir = joinUrlParts(
+        batfishConfig.siteBasePath,
+        constants.PUBLIC_PATH_ASSETS
+      );
       const serveStaticDir = batfishConfig.siteBasePath + '/static';
       // This allows us to serve static files within the pages directory.
       const servePagesDir = batfishConfig.siteBasePath;
@@ -70,7 +87,19 @@ function start(rawConfig, projectDirectory) {
           open: false,
           logLevel: 'silent',
           reloadDebounce: 500,
-          offline: true
+          offline: true,
+          injectChanges: true
+        });
+      });
+    };
+
+    const startCssWatcher = () => {
+      if (stylesheetsIsEmpty) return;
+      const cssWatcher = chokidar.watch(batfishConfig.stylesheets);
+      cssWatcher.on('change', () => {
+        compileStylesheets(batfishConfig).then(compiledFilename => {
+          timelog('Recompiled CSS');
+          server.reload(compiledFilename);
         });
       });
     };
@@ -89,54 +118,60 @@ function start(rawConfig, projectDirectory) {
       });
     };
 
-    timelog('Starting your batfish development server');
-    timelog(chalk.yellow.bold('Wait ...'));
-    const start = batfishConfig.clearOutputDirectory
-      ? del(batfishConfig.outputDirectory, { force: true })
-      : Promise.resolve();
-    return start.then(() => {
+    const startWebpackWatcher = () => {
       const compiler = webpack(config);
-      startServer();
       let lastHash;
       let hasCompiled = false;
-      compiler.watch(
-        {
-          ignored: /node_modules/
-        },
-        (fatalError, stats) => {
-          if (!hasCompiled) {
-            hasCompiled = true;
-            timelog(chalk.green.bold('Go!'));
-            getServerInstance.then(serverInstance => {
-              logServerInit(serverInstance, batfishConfig);
-            });
-          }
-          if (fatalError) {
-            logFatalError(fatalError);
-            return exit();
-          }
-          logStatsErrors(stats);
-          fs.writeFile(statsFilename, JSON.stringify(stats.toJson()), err => {
-            if (err) {
-              console.error('Error writing stats.json');
-              console.error(err);
-            }
+      compiler.watch(webpackWatchOptions, (fatalError, stats) => {
+        if (!hasCompiled) {
+          hasCompiled = true;
+          timelog(chalk.green.bold('Go!'));
+          getServerInstance.then(serverInstance => {
+            logServerInit(serverInstance, batfishConfig);
           });
-          if (batfishConfig.verbose) {
-            console.log(
-              stats.toString({
-                chunks: false,
-                colors: true
-              })
-            );
+        }
+        if (fatalError) {
+          logFatalError(fatalError);
+          return exit();
+        }
+        logStatsErrors(stats);
+        const statsString = JSON.stringify(stats.toJson());
+        fs.writeFile(statsFilename, statsString, err => {
+          if (err) {
+            console.error('Error writing stats.json');
+            console.error(err);
           }
-          if (stats.hash === lastHash) return;
-          lastHash = stats.hash;
-          timelog('Webpack finished compiling');
-          server.reload();
+        });
+        if (batfishConfig.verbose) {
+          console.log(
+            stats.toString({
+              chunks: false,
+              colors: true
+            })
+          );
         }
-      );
-    });
+        if (stats.hash === lastHash) return;
+        lastHash = stats.hash;
+        timelog('Webpack finished compiling');
+        server.reload();
+      });
+    };
+
+    timelog('Starting your batfish development server');
+    timelog(chalk.yellow.bold('Wait ...'));
+    const clearTheWay = batfishConfig.clearOutputDirectory
+      ? del(batfishConfig.outputDirectory, { force: true })
+      : Promise.resolve();
+    return clearTheWay
+      .then(() => compileStylesheets(batfishConfig))
+      .then(() => {
+        startServer();
+        startCssWatcher();
+        startWebpackWatcher();
+      })
+      .catch(error => {
+        console.error(error.stack);
+      });
   });
 }
 
diff --git a/lib/validate-config.js b/lib/validate-config.js
index b942440..6a9c8c4 100644
--- a/lib/validate-config.js
+++ b/lib/validate-config.js
@@ -12,7 +12,7 @@ const validConfigProperties = [
   'siteBasePath',
   'siteOrigin',
   'applicationWrapperPath',
-  'externalStylesheets',
+  'stylesheets',
   'browserslist',
   'pagesDirectory',
   'staticDirectory',
@@ -70,7 +70,7 @@ function validateConfig(config, configPath) {
       __dirname,
       '../src/empty-application-wrapper.js'
     ),
-    externalStylesheets: [],
+    stylesheets: [],
     babelExclude: /node_modules\/!(@mapbox\/batfish\/)/,
     siteBasePath: '',
     browserslist: ['> 5%', 'last 2 versions'],
diff --git a/package-lock.json b/package-lock.json
index 4874b0f..2110eb0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -234,11 +234,6 @@
         "repeat-string": "1.6.1"
       }
     },
-    "alphanum-sort": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz",
-      "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM="
-    },
     "amdefine": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
@@ -1636,33 +1631,6 @@
         "map-obj": "1.0.1"
       }
     },
-    "caniuse-api": {
-      "version": "1.6.1",
-      "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz",
-      "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=",
-      "requires": {
-        "browserslist": "1.7.7",
-        "caniuse-db": "1.0.30000706",
-        "lodash.memoize": "4.1.2",
-        "lodash.uniq": "4.5.0"
-      },
-      "dependencies": {
-        "browserslist": {
-          "version": "1.7.7",
-          "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz",
-          "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=",
-          "requires": {
-            "caniuse-db": "1.0.30000706",
-            "electron-to-chromium": "1.3.16"
-          }
-        }
-      }
-    },
-    "caniuse-db": {
-      "version": "1.0.30000706",
-      "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000706.tgz",
-      "integrity": "sha1-4rXwRgVzy8yIoJhfXM7QjxYXxvU="
-    },
     "caniuse-lite": {
       "version": "1.0.30000706",
       "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000706.tgz",
@@ -1800,28 +1768,6 @@
       "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==",
       "dev": true
     },
-    "clap": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.0.tgz",
-      "integrity": "sha1-WckP4+E3EEdG/xlGmiemNP9oyFc=",
-      "requires": {
-        "chalk": "1.1.3"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          }
-        }
-      }
-    },
     "clean-css": {
       "version": "4.1.7",
       "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.7.tgz",
@@ -1878,24 +1824,11 @@
         "wrap-ansi": "2.1.0"
       }
     },
-    "clone": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz",
-      "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk="
-    },
     "co": {
       "version": "4.6.0",
       "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
       "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
     },
-    "coa": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz",
-      "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=",
-      "requires": {
-        "q": "1.5.0"
-      }
-    },
     "code-point-at": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
@@ -1906,16 +1839,6 @@
       "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.3.tgz",
       "integrity": "sha1-S5BvZw5aljqHt2sOFolkM0G2Ajw="
     },
-    "color": {
-      "version": "0.11.4",
-      "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz",
-      "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=",
-      "requires": {
-        "clone": "1.0.2",
-        "color-convert": "1.9.0",
-        "color-string": "0.3.0"
-      }
-    },
     "color-convert": {
       "version": "1.9.0",
       "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz",
@@ -1929,29 +1852,6 @@
       "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
       "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
     },
-    "color-string": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz",
-      "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=",
-      "requires": {
-        "color-name": "1.1.3"
-      }
-    },
-    "colormin": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz",
-      "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=",
-      "requires": {
-        "color": "0.11.4",
-        "css-color-names": "0.0.4",
-        "has": "1.0.1"
-      }
-    },
-    "colors": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
-      "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM="
-    },
     "combined-stream": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz",
@@ -2025,6 +1925,21 @@
         "typedarray": "0.0.6"
       }
     },
+    "concat-with-sourcemaps": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.4.tgz",
+      "integrity": "sha1-9Vs74q60dgGxCi1SWcz7cP0vHdY=",
+      "requires": {
+        "source-map": "0.5.6"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.5.6",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
+          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
+        }
+      }
+    },
     "connect": {
       "version": "3.5.0",
       "resolved": "https://registry.npmjs.org/connect/-/connect-3.5.0.tgz",
@@ -2095,32 +2010,6 @@
       "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
       "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
     },
-    "cosmiconfig": {
-      "version": "2.2.2",
-      "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-2.2.2.tgz",
-      "integrity": "sha512-GiNXLwAFPYHy25XmTPpafYvn3CLAkJ8FLsscq78MQd1Kh0OU6Yzhn4eV2MVF4G9WEQZoWEGltatdR+ntGPMl5A==",
-      "requires": {
-        "is-directory": "0.3.1",
-        "js-yaml": "3.9.0",
-        "minimist": "1.2.0",
-        "object-assign": "4.1.1",
-        "os-homedir": "1.0.2",
-        "parse-json": "2.2.0",
-        "require-from-string": "1.2.1"
-      },
-      "dependencies": {
-        "minimist": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
-          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
-        },
-        "object-assign": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-          "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
-        }
-      }
-    },
     "cp-file": {
       "version": "4.2.0",
       "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-4.2.0.tgz",
@@ -2258,82 +2147,6 @@
       "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz",
       "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4="
     },
-    "css-color-names": {
-      "version": "0.0.4",
-      "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz",
-      "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA="
-    },
-    "css-loader": {
-      "version": "0.28.4",
-      "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.28.4.tgz",
-      "integrity": "sha1-bPNXkZLONV6LONX0Ldeh8uyJjQ8=",
-      "requires": {
-        "babel-code-frame": "6.22.0",
-        "css-selector-tokenizer": "0.7.0",
-        "cssnano": "3.10.0",
-        "icss-utils": "2.1.0",
-        "loader-utils": "1.1.0",
-        "lodash.camelcase": "4.3.0",
-        "object-assign": "4.1.1",
-        "postcss": "5.2.17",
-        "postcss-modules-extract-imports": "1.1.0",
-        "postcss-modules-local-by-default": "1.2.0",
-        "postcss-modules-scope": "1.1.0",
-        "postcss-modules-values": "1.3.0",
-        "postcss-value-parser": "3.3.0",
-        "source-list-map": "0.1.8"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "object-assign": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-          "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
-          "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
     "css-select": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
@@ -2356,28 +2169,6 @@
         }
       }
     },
-    "css-selector-tokenizer": {
-      "version": "0.7.0",
-      "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz",
-      "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=",
-      "requires": {
-        "cssesc": "0.1.0",
-        "fastparse": "1.1.1",
-        "regexpu-core": "1.0.0"
-      },
-      "dependencies": {
-        "regexpu-core": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz",
-          "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=",
-          "requires": {
-            "regenerate": "1.3.2",
-            "regjsgen": "0.2.0",
-            "regjsparser": "0.1.5"
-          }
-        }
-      }
-    },
     "css-tree": {
       "version": "1.0.0-alpha19",
       "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha19.tgz",
@@ -2398,122 +2189,6 @@
       "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz",
       "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0="
     },
-    "cssesc": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz",
-      "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q="
-    },
-    "cssnano": {
-      "version": "3.10.0",
-      "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz",
-      "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=",
-      "requires": {
-        "autoprefixer": "6.7.7",
-        "decamelize": "1.2.0",
-        "defined": "1.0.0",
-        "has": "1.0.1",
-        "object-assign": "4.1.1",
-        "postcss": "5.2.17",
-        "postcss-calc": "5.3.1",
-        "postcss-colormin": "2.2.2",
-        "postcss-convert-values": "2.6.1",
-        "postcss-discard-comments": "2.0.4",
-        "postcss-discard-duplicates": "2.1.0",
-        "postcss-discard-empty": "2.1.0",
-        "postcss-discard-overridden": "0.1.1",
-        "postcss-discard-unused": "2.2.3",
-        "postcss-filter-plugins": "2.0.2",
-        "postcss-merge-idents": "2.1.7",
-        "postcss-merge-longhand": "2.0.2",
-        "postcss-merge-rules": "2.1.2",
-        "postcss-minify-font-values": "1.0.5",
-        "postcss-minify-gradients": "1.0.5",
-        "postcss-minify-params": "1.2.2",
-        "postcss-minify-selectors": "2.1.1",
-        "postcss-normalize-charset": "1.1.1",
-        "postcss-normalize-url": "3.0.8",
-        "postcss-ordered-values": "2.2.3",
-        "postcss-reduce-idents": "2.4.0",
-        "postcss-reduce-initial": "1.0.1",
-        "postcss-reduce-transforms": "1.0.4",
-        "postcss-svgo": "2.1.6",
-        "postcss-unique-selectors": "2.0.2",
-        "postcss-value-parser": "3.3.0",
-        "postcss-zindex": "2.2.0"
-      },
-      "dependencies": {
-        "autoprefixer": {
-          "version": "6.7.7",
-          "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz",
-          "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=",
-          "requires": {
-            "browserslist": "1.7.7",
-            "caniuse-db": "1.0.30000706",
-            "normalize-range": "0.1.2",
-            "num2fraction": "1.2.2",
-            "postcss": "5.2.17",
-            "postcss-value-parser": "3.3.0"
-          }
-        },
-        "browserslist": {
-          "version": "1.7.7",
-          "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz",
-          "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=",
-          "requires": {
-            "caniuse-db": "1.0.30000706",
-            "electron-to-chromium": "1.3.16"
-          }
-        },
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "object-assign": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-          "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
-          "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
     "csso": {
       "version": "3.1.1",
       "resolved": "https://registry.npmjs.org/csso/-/csso-3.1.1.tgz",
@@ -3621,27 +3296,6 @@
         "is-extglob": "1.0.0"
       }
     },
-    "extract-text-webpack-plugin": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/extract-text-webpack-plugin/-/extract-text-webpack-plugin-3.0.0.tgz",
-      "integrity": "sha1-kMqnkHvESfM1AF46x1MrQbAN5hI=",
-      "requires": {
-        "async": "2.5.0",
-        "loader-utils": "1.1.0",
-        "schema-utils": "0.3.0",
-        "webpack-sources": "1.0.1"
-      },
-      "dependencies": {
-        "async": {
-          "version": "2.5.0",
-          "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz",
-          "integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==",
-          "requires": {
-            "lodash": "4.17.4"
-          }
-        }
-      }
-    },
     "extsprintf": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz",
@@ -3658,11 +3312,6 @@
       "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
       "dev": true
     },
-    "fastparse": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz",
-      "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg="
-    },
     "fault": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.1.tgz",
@@ -4768,7 +4417,8 @@
     "function-bind": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz",
-      "integrity": "sha1-FhdnFMgBeY5Ojyz391KUZ7tKV3E="
+      "integrity": "sha1-FhdnFMgBeY5Ojyz391KUZ7tKV3E=",
+      "dev": true
     },
     "function.prototype.name": {
       "version": "1.0.3",
@@ -4994,6 +4644,7 @@
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz",
       "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=",
+      "dev": true,
       "requires": {
         "function-bind": "1.1.0"
       }
@@ -5061,6 +4712,14 @@
         "minimalistic-assert": "1.0.0"
       }
     },
+    "hasha": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz",
+      "integrity": "sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk=",
+      "requires": {
+        "is-stream": "1.1.0"
+      }
+    },
     "hast-to-hyperscript": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-3.0.0.tgz",
@@ -5226,11 +4885,6 @@
       "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz",
       "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg=="
     },
-    "html-comment-regex": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.1.tgz",
-      "integrity": "sha1-ZouTd26q5V696POtRkswekljYl4="
-    },
     "html-encoding-sniffer": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.1.tgz",
@@ -5399,19 +5053,6 @@
       "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz",
       "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA=="
     },
-    "icss-replace-symbols": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz",
-      "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0="
-    },
-    "icss-utils": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz",
-      "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=",
-      "requires": {
-        "postcss": "6.0.8"
-      }
-    },
     "ieee754": {
       "version": "1.1.8",
       "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz",
@@ -5627,11 +5268,6 @@
       "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.1.tgz",
       "integrity": "sha1-9ftqlJlq2ejjdh+/vQkfH8qMToI="
     },
-    "is-directory": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
-      "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE="
-    },
     "is-dotfile": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
@@ -5819,14 +5455,6 @@
       "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=",
       "dev": true
     },
-    "is-svg": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz",
-      "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=",
-      "requires": {
-        "html-comment-regex": "1.1.1"
-      }
-    },
     "is-symbol": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz",
@@ -7231,7 +6859,8 @@
     "lodash.camelcase": {
       "version": "4.3.0",
       "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
-      "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY="
+      "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=",
+      "dev": true
     },
     "lodash.chunk": {
       "version": "4.2.0",
@@ -7330,11 +6959,6 @@
       "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=",
       "dev": true
     },
-    "lodash.memoize": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
-      "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4="
-    },
     "lodash.merge": {
       "version": "3.3.2",
       "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-3.3.2.tgz",
@@ -7409,11 +7033,6 @@
         "lodash.keysin": "3.0.8"
       }
     },
-    "lodash.uniq": {
-      "version": "4.5.0",
-      "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
-      "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M="
-    },
     "lodash.upperfirst": {
       "version": "4.3.1",
       "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz",
@@ -7534,11 +7153,6 @@
         "yallist": "2.1.2"
       }
     },
-    "macaddress": {
-      "version": "0.2.8",
-      "resolved": "https://registry.npmjs.org/macaddress/-/macaddress-0.2.8.tgz",
-      "integrity": "sha1-WQTcU3w57G2+/q6QIycTX6hRHxI="
-    },
     "make-dir": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.0.0.tgz",
@@ -7593,11 +7207,6 @@
       "integrity": "sha1-Sz3ToTPRUYuO8NvHCb8qG0gkvIw=",
       "dev": true
     },
-    "math-expression-evaluator": {
-      "version": "1.2.17",
-      "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz",
-      "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw="
-    },
     "mdast-util-compact": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz",
@@ -7942,24 +7551,6 @@
       "resolved": "https://registry.npmjs.org/normalize-uri/-/normalize-uri-1.1.0.tgz",
       "integrity": "sha1-AftEDH/QWbnZvoZFqsFDQe/QWd0="
     },
-    "normalize-url": {
-      "version": "1.9.1",
-      "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz",
-      "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=",
-      "requires": {
-        "object-assign": "4.1.1",
-        "prepend-http": "1.0.4",
-        "query-string": "4.3.4",
-        "sort-keys": "1.1.2"
-      },
-      "dependencies": {
-        "object-assign": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-          "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
-        }
-      }
-    },
     "npm-path": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.3.tgz",
@@ -8499,1382 +8090,72 @@
       "requires": {
         "pinkie": "2.0.4"
       }
-    },
-    "pkg-conf": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-1.1.3.tgz",
-      "integrity": "sha1-N45W1v0T6Iv7b0ol33qD+qvduls=",
-      "requires": {
-        "find-up": "1.1.2",
-        "load-json-file": "1.1.0",
-        "object-assign": "4.1.1",
-        "symbol": "0.2.3"
-      },
-      "dependencies": {
-        "object-assign": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-          "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
-        }
-      }
-    },
-    "pkg-dir": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
-      "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
-      "requires": {
-        "find-up": "2.1.0"
-      },
-      "dependencies": {
-        "find-up": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
-          "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
-          "requires": {
-            "locate-path": "2.0.0"
-          }
-        }
-      }
-    },
-    "pluralize": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-4.0.0.tgz",
-      "integrity": "sha1-WbcIwcAZCi9pLxx2GMRGsFL9F2I=",
-      "dev": true
-    },
-    "portscanner": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.1.1.tgz",
-      "integrity": "sha1-6rtAnk3iSVD1oqUW01rnaTQ/u5Y=",
-      "requires": {
-        "async": "1.5.2",
-        "is-number-like": "1.0.8"
-      }
-    },
-    "postcss": {
-      "version": "6.0.8",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.8.tgz",
-      "integrity": "sha512-G6WnRmdTt2jvJvY+aY+M0AO4YlbxE+slKPZb+jG2P2U9Tyxi3h1fYZ/DgiFU6DC6bv3XIEJoZt+f/kNh8BrWFw==",
-      "requires": {
-        "chalk": "2.0.1",
-        "source-map": "0.5.6",
-        "supports-color": "4.2.1"
-      },
-      "dependencies": {
-        "has-flag": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
-          "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "4.2.1",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.1.tgz",
-          "integrity": "sha512-qxzYsob3yv6U+xMzPrv170y8AwGP7i74g+pbixCfD6rgso8BscLT2qXIuz6TpOaiJZ3mFgT5O9lyT9nMU4LfaA==",
-          "requires": {
-            "has-flag": "2.0.0"
-          }
-        }
-      }
-    },
-    "postcss-calc": {
-      "version": "5.3.1",
-      "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz",
-      "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=",
-      "requires": {
-        "postcss": "5.2.17",
-        "postcss-message-helpers": "2.0.0",
-        "reduce-css-calc": "1.3.0"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
-          "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
-    "postcss-colormin": {
-      "version": "2.2.2",
-      "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-2.2.2.tgz",
-      "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=",
-      "requires": {
-        "colormin": "1.1.2",
-        "postcss": "5.2.17",
-        "postcss-value-parser": "3.3.0"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
-          "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
-    "postcss-convert-values": {
-      "version": "2.6.1",
-      "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz",
-      "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=",
-      "requires": {
-        "postcss": "5.2.17",
-        "postcss-value-parser": "3.3.0"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
-          "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
-    "postcss-discard-comments": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz",
-      "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=",
-      "requires": {
-        "postcss": "5.2.17"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
-          "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
-    "postcss-discard-duplicates": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz",
-      "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=",
-      "requires": {
-        "postcss": "5.2.17"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
-          "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
-    "postcss-discard-empty": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz",
-      "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=",
-      "requires": {
-        "postcss": "5.2.17"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
-          "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
-    "postcss-discard-overridden": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz",
-      "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=",
-      "requires": {
-        "postcss": "5.2.17"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
-          "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
-    "postcss-discard-unused": {
-      "version": "2.2.3",
-      "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz",
-      "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=",
-      "requires": {
-        "postcss": "5.2.17",
-        "uniqs": "2.0.0"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
-          "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
-    "postcss-filter-plugins": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.2.tgz",
-      "integrity": "sha1-bYWGJTTXNaxCDkqFgG4fXUKG2Ew=",
-      "requires": {
-        "postcss": "5.2.17",
-        "uniqid": "4.1.1"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
-          "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
-    "postcss-load-config": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-1.2.0.tgz",
-      "integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=",
-      "requires": {
-        "cosmiconfig": "2.2.2",
-        "object-assign": "4.1.1",
-        "postcss-load-options": "1.2.0",
-        "postcss-load-plugins": "2.3.0"
-      },
-      "dependencies": {
-        "object-assign": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-          "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
-        }
-      }
-    },
-    "postcss-load-options": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/postcss-load-options/-/postcss-load-options-1.2.0.tgz",
-      "integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=",
-      "requires": {
-        "cosmiconfig": "2.2.2",
-        "object-assign": "4.1.1"
-      },
-      "dependencies": {
-        "object-assign": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-          "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
-        }
-      }
-    },
-    "postcss-load-plugins": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/postcss-load-plugins/-/postcss-load-plugins-2.3.0.tgz",
-      "integrity": "sha1-dFdoEWWZrKLwCfrUJrABdQSdjZI=",
-      "requires": {
-        "cosmiconfig": "2.2.2",
-        "object-assign": "4.1.1"
-      },
-      "dependencies": {
-        "object-assign": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-          "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
-        }
-      }
-    },
-    "postcss-loader": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-2.0.6.tgz",
-      "integrity": "sha512-HIq7yy1hh9KI472Y38iSRV4WupZUNy6zObkxQM/ZuInoaE2+PyX4NcO6jjP5HG5mXL7j5kcNEl0fAG4Kva7O9w==",
-      "requires": {
-        "loader-utils": "1.1.0",
-        "postcss": "6.0.8",
-        "postcss-load-config": "1.2.0",
-        "schema-utils": "0.3.0"
-      }
-    },
-    "postcss-merge-idents": {
-      "version": "2.1.7",
-      "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz",
-      "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=",
-      "requires": {
-        "has": "1.0.1",
-        "postcss": "5.2.17",
-        "postcss-value-parser": "3.3.0"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
-          "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
-    "postcss-merge-longhand": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz",
-      "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=",
-      "requires": {
-        "postcss": "5.2.17"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
-          "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
-    "postcss-merge-rules": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz",
-      "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=",
-      "requires": {
-        "browserslist": "1.7.7",
-        "caniuse-api": "1.6.1",
-        "postcss": "5.2.17",
-        "postcss-selector-parser": "2.2.3",
-        "vendors": "1.0.1"
-      },
-      "dependencies": {
-        "browserslist": {
-          "version": "1.7.7",
-          "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz",
-          "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=",
-          "requires": {
-            "caniuse-db": "1.0.30000706",
-            "electron-to-chromium": "1.3.16"
-          }
-        },
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
-          "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
-    "postcss-message-helpers": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz",
-      "integrity": "sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4="
-    },
-    "postcss-minify-font-values": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz",
-      "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=",
-      "requires": {
-        "object-assign": "4.1.1",
-        "postcss": "5.2.17",
-        "postcss-value-parser": "3.3.0"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "object-assign": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-          "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
-          "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
-    "postcss-minify-gradients": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz",
-      "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=",
-      "requires": {
-        "postcss": "5.2.17",
-        "postcss-value-parser": "3.3.0"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
-          "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
-    "postcss-minify-params": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz",
-      "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=",
-      "requires": {
-        "alphanum-sort": "1.0.2",
-        "postcss": "5.2.17",
-        "postcss-value-parser": "3.3.0",
-        "uniqs": "2.0.0"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
-          "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
-    "postcss-minify-selectors": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz",
-      "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=",
-      "requires": {
-        "alphanum-sort": "1.0.2",
-        "has": "1.0.1",
-        "postcss": "5.2.17",
-        "postcss-selector-parser": "2.2.3"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
-          "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
-    "postcss-modules-extract-imports": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz",
-      "integrity": "sha1-thTJcgvmgW6u41+zpfqh26agXds=",
-      "requires": {
-        "postcss": "6.0.8"
-      }
-    },
-    "postcss-modules-local-by-default": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz",
-      "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=",
-      "requires": {
-        "css-selector-tokenizer": "0.7.0",
-        "postcss": "6.0.8"
-      }
-    },
-    "postcss-modules-scope": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz",
-      "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=",
-      "requires": {
-        "css-selector-tokenizer": "0.7.0",
-        "postcss": "6.0.8"
-      }
-    },
-    "postcss-modules-values": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz",
-      "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=",
-      "requires": {
-        "icss-replace-symbols": "1.1.0",
-        "postcss": "6.0.8"
-      }
-    },
-    "postcss-normalize-charset": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz",
-      "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=",
-      "requires": {
-        "postcss": "5.2.17"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
-          "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
-    "postcss-normalize-url": {
-      "version": "3.0.8",
-      "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz",
-      "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=",
-      "requires": {
-        "is-absolute-url": "2.1.0",
-        "normalize-url": "1.9.1",
-        "postcss": "5.2.17",
-        "postcss-value-parser": "3.3.0"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
-          "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
-    "postcss-ordered-values": {
-      "version": "2.2.3",
-      "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz",
-      "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=",
-      "requires": {
-        "postcss": "5.2.17",
-        "postcss-value-parser": "3.3.0"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
-          "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
-    "postcss-reduce-idents": {
-      "version": "2.4.0",
-      "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz",
-      "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=",
-      "requires": {
-        "postcss": "5.2.17",
-        "postcss-value-parser": "3.3.0"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
-          "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
-    "postcss-reduce-initial": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz",
-      "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=",
-      "requires": {
-        "postcss": "5.2.17"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
-          "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "requires": {
-            "has-flag": "1.0.0"
-          }
+    },
+    "pkg-conf": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-1.1.3.tgz",
+      "integrity": "sha1-N45W1v0T6Iv7b0ol33qD+qvduls=",
+      "requires": {
+        "find-up": "1.1.2",
+        "load-json-file": "1.1.0",
+        "object-assign": "4.1.1",
+        "symbol": "0.2.3"
+      },
+      "dependencies": {
+        "object-assign": {
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+          "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
         }
       }
     },
-    "postcss-reduce-transforms": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz",
-      "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=",
+    "pkg-dir": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
+      "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
       "requires": {
-        "has": "1.0.1",
-        "postcss": "5.2.17",
-        "postcss-value-parser": "3.3.0"
+        "find-up": "2.1.0"
       },
       "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
+        "find-up": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+          "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
           "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
+            "locate-path": "2.0.0"
           }
+        }
+      }
+    },
+    "pluralize": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-4.0.0.tgz",
+      "integrity": "sha1-WbcIwcAZCi9pLxx2GMRGsFL9F2I=",
+      "dev": true
+    },
+    "portscanner": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.1.1.tgz",
+      "integrity": "sha1-6rtAnk3iSVD1oqUW01rnaTQ/u5Y=",
+      "requires": {
+        "async": "1.5.2",
+        "is-number-like": "1.0.8"
+      }
+    },
+    "postcss": {
+      "version": "6.0.8",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.8.tgz",
+      "integrity": "sha512-G6WnRmdTt2jvJvY+aY+M0AO4YlbxE+slKPZb+jG2P2U9Tyxi3h1fYZ/DgiFU6DC6bv3XIEJoZt+f/kNh8BrWFw==",
+      "requires": {
+        "chalk": "2.0.1",
+        "source-map": "0.5.6",
+        "supports-color": "4.2.1"
+      },
+      "dependencies": {
+        "has-flag": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+          "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
         },
         "source-map": {
           "version": "0.5.6",
@@ -9882,34 +8163,21 @@
           "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
         },
         "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.1.tgz",
+          "integrity": "sha512-qxzYsob3yv6U+xMzPrv170y8AwGP7i74g+pbixCfD6rgso8BscLT2qXIuz6TpOaiJZ3mFgT5O9lyT9nMU4LfaA==",
           "requires": {
-            "has-flag": "1.0.0"
+            "has-flag": "2.0.0"
           }
         }
       }
     },
-    "postcss-selector-parser": {
-      "version": "2.2.3",
-      "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz",
-      "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=",
-      "requires": {
-        "flatten": "1.0.2",
-        "indexes-of": "1.0.1",
-        "uniq": "1.0.1"
-      }
-    },
-    "postcss-svgo": {
-      "version": "2.1.6",
-      "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz",
-      "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=",
+    "postcss-discard-empty": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz",
+      "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=",
       "requires": {
-        "is-svg": "2.1.0",
-        "postcss": "5.2.17",
-        "postcss-value-parser": "3.3.0",
-        "svgo": "0.7.2"
+        "postcss": "5.2.17"
       },
       "dependencies": {
         "chalk": {
@@ -9957,12 +8225,11 @@
         }
       }
     },
-    "postcss-unique-selectors": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz",
-      "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=",
+    "postcss-discard-unused": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz",
+      "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=",
       "requires": {
-        "alphanum-sort": "1.0.2",
         "postcss": "5.2.17",
         "uniqs": "2.0.0"
       },
@@ -10046,61 +8313,6 @@
         "uniq": "1.0.1"
       }
     },
-    "postcss-zindex": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz",
-      "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=",
-      "requires": {
-        "has": "1.0.1",
-        "postcss": "5.2.17",
-        "uniqs": "2.0.0"
-      },
-      "dependencies": {
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          },
-          "dependencies": {
-            "supports-color": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-              "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
-            }
-          }
-        },
-        "postcss": {
-          "version": "5.2.17",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz",
-          "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=",
-          "requires": {
-            "chalk": "1.1.3",
-            "js-base64": "2.1.9",
-            "source-map": "0.5.6",
-            "supports-color": "3.2.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        },
-        "supports-color": {
-          "version": "3.2.3",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
-          "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
-          "requires": {
-            "has-flag": "1.0.0"
-          }
-        }
-      }
-    },
     "prelude-ls": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
@@ -10262,22 +8474,6 @@
       "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz",
       "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM="
     },
-    "query-string": {
-      "version": "4.3.4",
-      "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
-      "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=",
-      "requires": {
-        "object-assign": "4.1.1",
-        "strict-uri-encode": "1.1.0"
-      },
-      "dependencies": {
-        "object-assign": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-          "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
-        }
-      }
-    },
     "querystring": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
@@ -10562,38 +8758,6 @@
         }
       }
     },
-    "reduce-css-calc": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz",
-      "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=",
-      "requires": {
-        "balanced-match": "0.4.2",
-        "math-expression-evaluator": "1.2.17",
-        "reduce-function-call": "1.0.2"
-      },
-      "dependencies": {
-        "balanced-match": {
-          "version": "0.4.2",
-          "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
-          "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg="
-        }
-      }
-    },
-    "reduce-function-call": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.2.tgz",
-      "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=",
-      "requires": {
-        "balanced-match": "0.4.2"
-      },
-      "dependencies": {
-        "balanced-match": {
-          "version": "0.4.2",
-          "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
-          "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg="
-        }
-      }
-    },
     "regenerate": {
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.2.tgz",
@@ -10919,7 +9083,8 @@
     "require-from-string": {
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz",
-      "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg="
+      "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=",
+      "dev": true
     },
     "require-main-filename": {
       "version": "1.0.1",
@@ -11102,28 +9267,8 @@
     "sax": {
       "version": "1.2.4",
       "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
-      "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
-    },
-    "schema-utils": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz",
-      "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=",
-      "requires": {
-        "ajv": "5.2.2"
-      },
-      "dependencies": {
-        "ajv": {
-          "version": "5.2.2",
-          "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.2.2.tgz",
-          "integrity": "sha1-R8aNaehvXZUxA7AHSpQw3GPaXjk=",
-          "requires": {
-            "co": "4.6.0",
-            "fast-deep-equal": "1.0.0",
-            "json-schema-traverse": "0.3.1",
-            "json-stable-stringify": "1.0.1"
-          }
-        }
-      }
+      "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
+      "dev": true
     },
     "semver": {
       "version": "5.4.1",
@@ -11479,14 +9624,6 @@
         }
       }
     },
-    "sort-keys": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz",
-      "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=",
-      "requires": {
-        "is-plain-obj": "1.1.0"
-      }
-    },
     "source-list-map": {
       "version": "0.1.8",
       "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz",
@@ -11620,11 +9757,6 @@
       "integrity": "sha1-Rb8dny19wJvtgfHDB8Qw5ouEz/4=",
       "dev": true
     },
-    "strict-uri-encode": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
-      "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM="
-    },
     "string_decoder": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
@@ -11715,64 +9847,11 @@
       "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
       "dev": true
     },
-    "style-loader": {
-      "version": "0.18.2",
-      "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.18.2.tgz",
-      "integrity": "sha512-WPpJPZGUxWYHWIUMNNOYqql7zh85zGmr84FdTVWq52WTIkqlW9xSxD3QYWi/T31cqn9UNSsietVEgGn2aaSCzw==",
-      "requires": {
-        "loader-utils": "1.1.0",
-        "schema-utils": "0.3.0"
-      }
-    },
     "supports-color": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
       "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
     },
-    "svgo": {
-      "version": "0.7.2",
-      "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz",
-      "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=",
-      "requires": {
-        "coa": "1.0.4",
-        "colors": "1.1.2",
-        "csso": "2.3.2",
-        "js-yaml": "3.7.0",
-        "mkdirp": "0.5.1",
-        "sax": "1.2.4",
-        "whet.extend": "0.9.9"
-      },
-      "dependencies": {
-        "csso": {
-          "version": "2.3.2",
-          "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz",
-          "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=",
-          "requires": {
-            "clap": "1.2.0",
-            "source-map": "0.5.6"
-          }
-        },
-        "esprima": {
-          "version": "2.7.3",
-          "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
-          "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE="
-        },
-        "js-yaml": {
-          "version": "3.7.0",
-          "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz",
-          "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=",
-          "requires": {
-            "argparse": "1.0.9",
-            "esprima": "2.7.3"
-          }
-        },
-        "source-map": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
-          "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
-        }
-      }
-    },
     "symbol": {
       "version": "0.2.3",
       "resolved": "https://registry.npmjs.org/symbol/-/symbol-0.2.3.tgz",
@@ -12285,14 +10364,6 @@
       "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz",
       "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8="
     },
-    "uniqid": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/uniqid/-/uniqid-4.1.1.tgz",
-      "integrity": "sha1-iSIN32t1GuUrX3JISGNShZa7hME=",
-      "requires": {
-        "macaddress": "0.2.8"
-      }
-    },
     "uniqs": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz",
@@ -12500,11 +10571,6 @@
         "spdx-expression-parse": "1.0.4"
       }
     },
-    "vendors": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.1.tgz",
-      "integrity": "sha1-N61zyO5Bf7PVgOeFMSMH0nSEfyI="
-    },
     "verror": {
       "version": "1.3.6",
       "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz",
@@ -12955,11 +11021,6 @@
         }
       }
     },
-    "whet.extend": {
-      "version": "0.9.9",
-      "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz",
-      "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE="
-    },
     "which": {
       "version": "1.2.14",
       "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz",
diff --git a/package.json b/package.json
index 279bcf2..59f7c73 100644
--- a/package.json
+++ b/package.json
@@ -85,21 +85,22 @@
     "babel-register": "^6.24.1",
     "browser-sync": "^2.18.12",
     "chalk": "^2.0.0",
+    "chokidar": "^1.7.0",
+    "concat-with-sourcemaps": "^1.0.4",
     "connect-history-api-fallback": "^1.3.0",
     "cpy": "^5.0.0",
-    "css-loader": "^0.28.4",
     "csso": "^3.1.1",
     "date-time": "^2.0.0",
     "debounce": "^1.0.2",
     "dedent": "^0.7.0",
     "del": "^3.0.0",
     "es6-promise": "^4.1.0",
-    "extract-text-webpack-plugin": "^3.0.0",
     "file-loader": "^0.11.2",
     "get-port": "^3.1.0",
     "globby": "^6.1.0",
     "got": "^7.0.0",
     "gray-matter": "^3.0.2",
+    "hasha": "^3.0.0",
     "html-webpack-plugin": "^2.28.0",
     "ignore-loader": "^0.1.2",
     "json-loader": "^0.5.4",
@@ -108,7 +109,6 @@
     "mkdirp": "^0.5.1",
     "pify": "^3.0.0",
     "postcss": "^6.0.1",
-    "postcss-loader": "^2.0.5",
     "postcss-url": "^7.0.0",
     "postcss-values-parser": "^1.2.2",
     "prop-types": "^15.5.10",
@@ -117,7 +117,6 @@
     "sitemap-static": "^0.4.2",
     "slugg": "^1.2.1",
     "source-map-support": "^0.4.15",
-    "style-loader": "^0.18.2",
     "tempy": "^0.1.0",
     "uglify-js": "^2.8.29",
     "webpack": "^3.4.0",
diff --git a/src/batfish-app.js b/src/batfish-app.js
index 7b08fbf..b9cd014 100644
--- a/src/batfish-app.js
+++ b/src/batfish-app.js
@@ -29,14 +29,5 @@ matchingRoute.getPage().then(pageModule => {
     }
   }
 
-  let container = document.getElementById('batfish-content');
-  // On the development server, this container element will not yet exist.
-  // In the static HTML build, though, it will.
-  if (!container) {
-    container = document.createElement('div');
-    container.id = 'batfish-content';
-    document.body.appendChild(container);
-  }
-
-  ReactDOM.render(<App />, container);
+  ReactDOM.render(<App />, document.getElementById('batfish-content'));
 });
diff --git a/src/html-webpack-template.ejs b/src/html-webpack-template.ejs
new file mode 100644
index 0000000..bbfb9fc
--- /dev/null
+++ b/src/html-webpack-template.ejs
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <title>Hello Batfish</title>
+    <% if (htmlWebpackPlugin.options.cssBasename) { %>
+    <link rel="stylesheet" href="<%= webpackConfig.output.publicPath %><%= htmlWebpackPlugin.options.cssBasename %>" />
+    <% } %>
+  </head>
+  <body>
+    <div id="batfish-content"></div>
+  </body>
+</html>
diff --git a/src/static-render-pages.js b/src/static-render-pages.js
index f692aa2..b2fb617 100644
--- a/src/static-render-pages.js
+++ b/src/static-render-pages.js
@@ -26,9 +26,10 @@ import timelog from '../lib/timelog';
  * @param {BatfishConfig} batfishConfig
  * @param {Object} assets - JSON output by Webpack that locates assets.
  * @param {string} manifestJs - JS output by Webpack that locates chunks.
+ * @param {string} [cssUrl] - URL to load the CSS file from.
  * @return {Promise<void>} - Resolves when all HTML pages have been rendered and written.
  */
-function staticRenderPages(batfishConfig, assets, manifestJs) {
+function staticRenderPages(batfishConfig, assets, manifestJs, cssUrl) {
   const renderPage = route => {
     let inlineJs;
     if (batfishConfig.production && batfishConfig.inlineJs) {
@@ -65,10 +66,13 @@ function staticRenderPages(batfishConfig, assets, manifestJs) {
         throw renderError;
       }
 
-      const cssUrl = assets.app.css;
       // Load the full stylesheet lazily, after DOMContentLoaded. The page will
       // still render quickly because it will have its own CSS injected inline.
-      const loadCssScript = `document.addEventListener('DOMContentLoaded',function(){var s=document.createElement('link');s.rel='stylesheet';s.href='${cssUrl}';document.head.insertBefore(s, document.getElementById('loadCss')); });`;
+      let loadCssScript = '';
+      if (cssUrl) {
+        const loadCssJs = `document.addEventListener('DOMContentLoaded',function(){var s=document.createElement('link');s.rel='stylesheet';s.href='${cssUrl}';document.head.insertBefore(s, document.getElementById('loadCss')); });`;
+        loadCssScript = `<script id="loadCss">${loadCssJs}</script>`;
+      }
       const head = Helmet.rewind();
       const reactDocument = (
         <StaticHtmlPage
@@ -83,7 +87,7 @@ function staticRenderPages(batfishConfig, assets, manifestJs) {
             inlineJs,
             head.script.toString(),
             constants.INLINE_CSS_MARKER,
-            `<script id="loadCss">${loadCssScript}</script>`,
+            loadCssScript,
             // This comes after the inlined and dynamically loaded CSS
             // so it will override regular stylesheets
             head.style.toString()


Test patch:
diff --git a/examples/initial-experiments/src/test.css b/examples/initial-experiments/src/test.css
index 6d0cb16..b3d166e 100644
--- a/examples/initial-experiments/src/test.css
+++ b/examples/initial-experiments/src/test.css
@@ -1,3 +1,4 @@
+/* foo */
 body {
   background: lightblue;
 }
diff --git a/test/__snapshots__/validate-config.test.js.snap b/test/__snapshots__/validate-config.test.js.snap
index 7911cee..5d306ee 100644
--- a/test/__snapshots__/validate-config.test.js.snap
+++ b/test/__snapshots__/validate-config.test.js.snap
@@ -10,7 +10,6 @@ Object {
   ],
   "clearOutputDirectory": true,
   "developmentDevtool": "source-map",
-  "externalStylesheets": Array [],
   "fileLoaderExtensions": Array [
     "jpeg",
     "jpg",
@@ -33,6 +32,7 @@ Object {
   "productionDevtool": false,
   "siteBasePath": "",
   "staticDirectory": "/my-project/src/static",
+  "stylesheets": Array [],
   "temporaryDirectory": "/my-project/_batfish_tmp",
   "verbose": false,
 }
diff --git a/test/join-url-parts.test.js b/test/join-url-parts.test.js
new file mode 100644
index 0000000..b476397
--- /dev/null
+++ b/test/join-url-parts.test.js
@@ -0,0 +1,27 @@
+'use strict';
+
+const joinUrlParts = require('../lib/join-url-parts');
+
+describe('joinUrlParts', () => {
+  test('with no arguments returns empty string', () => {
+    expect(joinUrlParts()).toBe('');
+  });
+
+  test('concatenates with slashes between arguments', () => {
+    expect(joinUrlParts('foo', 'bar', 'baz')).toBe('foo/bar/baz');
+  });
+
+  test('does not duplicate slashes if arguments end with them', () => {
+    expect(joinUrlParts('foo/', 'bar/', 'baz')).toBe('foo/bar/baz');
+  });
+
+  test('does not duplicate slashes if arguments being with them', () => {
+    expect(joinUrlParts('/foo', '/bar', '/baz', '/pit')).toBe(
+      '/foo/bar/baz/pit'
+    );
+  });
+
+  test('ends with a slash if last argument is an empty string', () => {
+    expect(joinUrlParts('/baz', '')).toBe('/baz/');
+  });
+});