[
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: tscanlin\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\nnpm-debug*\n.DS_Store\ntest/output\ndist/*\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\nnode_js:\n  - \"6.9\"\nsudo: false\nbranches:\n  only:\n    - master\ninstall:\n- npm install\nscript:\n- npm run test\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "### Unreleased\n...\n\n\n### 2.3.0\n\n#### Added\n- reportDetails option for all selectors to be listed\n- get travis-ci working\n- add webpages option\n\n#### Updated\n- rename config.js to defaultOptions.js\n- refactor tests\n- update readme\n- ignore option appends by default\n\n\n### 2.2.0\n\n#### Added\n- new overwriteCss option\n\n\n### 2.1.1\n\n#### Fixed\n- fix cli when no output file specified and report improvements\n\n\n### 2.1.0\n\n#### Added\n- More docs & examples\n- CHANGELOG.md\n- Support for passing glob patterns\n\n\n### 2.0.0\n\n#### Added\n- Added `report` option to display stats about used vs unused selectors\n\n#### Changed\n- Rewrite tests with lab and code\n- Parse args with yargs\n\n\n### 1.1.0\n\n#### Added\n- Got CLI working\n- Promise API\n- Tests\n- Core functionality\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2017 Tim Scanlin\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# css-razor\n\n![Build Status](https://travis-ci.org/tscanlin/css-razor.svg?branch=master)\n\ncss-razor is a fast way to remove unused selectors from css. Essentially, it accomplishes the same goal as [uncss](https://github.com/giakki/uncss). However, it accomplishes this goal differently. Rather than loading a webpage in phantomjs and using `document.querySelector` to determine if a selector is being used, css-razor uses [cheeriojs](https://github.com/cheeriojs/cheerio) to parse static html and css files to removed unused selectors.\n\n- Helps trim down CSS so you only keep the necessary parts\n- Built for speed using the amazing  [cheeriojs](https://github.com/cheeriojs/cheerio)\n- has an ignore list that can be added to\n- ignores common pseudo elements & pseudo selectors by default\n- Supports multiple files / globs\n- Supports raw html & css input\n- Supports html paths from URLs\n- Reporting stats detailing how many selectors are removed.\n\n\n## Getting Started\n\nInstall with npm\n\n```bash\nnpm install --save-dev css-razor\n```\n\nYou can then use the cli\n\n```bash\ncss-razor build/css/index.css build/index.html --stdout > build/css/index.min.css\n```\n\nAnd you can even pass globs\n\n```bash\ncss-razor build/css/*.css build/*.html --stdout > build/css/index.min.css\n```\n\nOr you can use the js api\n\n```js\nconst cssRazor = require('css-razor').default\n\ncssRazor({\n  html: ['build/index.html'],\n  css: ['build/css/index.css'],\n}, function(err, data) {\n  console.log(data.css)\n})\n```\n\n\n## Options\n\n```js\nmodule.exports = {\n  // Array of HTML file globs.\n  html: [],\n  // Array of CSS file globs.\n  css: [],\n  // Raw HTML string.\n  htmlRaw: '',\n  // Raw CSS string.\n  cssRaw: '',\n  // Array of webpages to add to HTML.\n  webpages: [],\n  // Strings in CSS classes to ignore. Pass `false`\n  // (or `--no-ignore` via cli) to not ignore these.\n  ignore: [\n    'html', // global element\n    'body', // global element\n    'button', // global element\n\n    'active', // state class\n    'inactive', // state class\n    'collapsed', // state class\n    'expanded', // state class\n    'show', // state class\n    'hide', // state class\n    'hidden', // state class\n    'is-', // state class\n  ],\n  // Where to output\n  outputFile: 'dist/index.css',\n  // Disable output via stdout w/ `--no-stdout`.\n  stdout: false,\n  // Report Stats about used vs unused selectors.\n  report: false,\n  // Detailed Report Stats including every selector used vs unused.\n  // Note: this also depends on the `report` option being true.\n  reportDetails: false,\n  // Overwrite the input css file if there is only one.\n  overwriteCss: false,\n}\n```\n\n\n## Usage with Postcss\n\n```js\nconst postcssRazor = require('css-razor').postcss\n\npostcss([\n    postcssRazor({\n      html: \"<html>your html string</html>\",\n    })\n  ])\n  .process(css, {\n    from: 'index.css',\n    to: 'output.css'\n  })\n```\n\n\n## React to HTML Example\n\nBelow is an example of building an html file from a react app created with `create-react-app`. The resulting HTML file can then be used for server rendering and detecting selectors with css-razor.\n\nindex.js:\n```js\nimport App from './components/App'\nimport './index.css'\n\nif (typeof window !== 'undefined') { // Web\n  ReactDOM.render(\n    <App />,\n    window.document.getElementById('root')\n  )\n} else { // Node / server render\n  global.appToRender = App\n}\n\n```\n\nbuildStatic.js:\n```js\nconst app = global.appToRender\nconst markup = ReactDOM.renderToString(ReactDOM.createElement(app));\n\nconst html = fs.readFileSync(HTML_FILE)\nconst newHtml = html.toString().split('<div id=\"root\"></div>').join(\n  '<div id=\"root\">' + markup + '</div>'\n)\n\nfs.writeFileSync(HTML_FILE, newHtml, 'utf8')\n```\n\n\n## Todo\n\n- html input via stdin?\n- more tests for raw and globs\n- test for postcss plugin usage\n"
  },
  {
    "path": "cli.js",
    "content": "#!/usr/bin/env node\n\nconst cssRazor = require('./index.js').default\nconst defaultOptions = require('./defaultOptions.js')\nconst argv = require('yargs')\n  .usage('Usage: $0 <command> [options]')\n  .argv\n\nif (process.argv && process.argv.length > 2) {\n  defaultOptions.outputFile = '' // Default to no output file over cli because of stdout.\n  const options = Object.assign({}, defaultOptions, argv)\n\n  options._.forEach((arg, i) => {\n    if (arg.indexOf('.html') === arg.length - 5) {\n      options.html.push(arg)\n    } else if (arg.indexOf('.css') === arg.length - 4) {\n      options.css.push(arg)\n    }\n    // TODO: Set more CLI options here.\n  })\n\n  cssRazor(options, (err, data) => {\n    if (err) {\n      process.stderr.write(err)\n      process.exit(1)\n    }\n    if (options.stdout) {\n      process.stdout.write(data.css)\n      process.exit(0)\n    }\n  })\n} else {\n  throw new Error('You need to pass arguments to css-razor')\n}\n"
  },
  {
    "path": "defaultOptions.js",
    "content": "module.exports = {\n  // Array of HTML file globs.\n  html: [],\n  // Array of CSS file globs.\n  css: [],\n  // Raw HTML string.\n  htmlRaw: '',\n  // Raw CSS string.\n  cssRaw: '',\n  // Array of webpages to add to HTML.\n  webpages: [],\n  // Strings in CSS classes to ignore. Pass `false`\n  // (or `--no-ignore` via cli) to not ignore these.\n  ignore: [\n    'html', // global element\n    'body', // global element\n    'button', // global element\n\n    'active', // state class\n    'inactive', // state class\n    'collapsed', // state class\n    'expanded', // state class\n    'show', // state class\n    'hide', // state class\n    'hidden', // state class\n    'is-' // state class\n  ],\n  // Where to output\n  outputFile: 'dist/index.css',\n  // Disable output via stdout w/ `--no-stdout`.\n  stdout: false,\n  // Report Stats about used vs unused selectors.\n  report: false,\n  // Detailed Report Stats including every selector used vs unused.\n  // Note: this also depends on the `report` option being true.\n  reportDetails: false,\n  // Overwrite the input css file if there is only one.\n  overwriteCss: false\n}\n"
  },
  {
    "path": "index.js",
    "content": "'use strict'\n\nconst cheerio = require('cheerio')\nconst postcss = require('postcss')\nconst fs = require('fs')\nconst path = require('path')\nconst globby = require('globby')\nconst mkdirp = require('mkdirp')\n\nrequire('es6-promise').polyfill()\nrequire('isomorphic-fetch')\n\nconst defaultOptions = require('./defaultOptions')\nconst DELIMITER = ' || '\n\nfunction cssRazor (options, callback) {\n  let ignoreList = []\n  if (typeof options.ignore === 'undefined') {\n    ignoreList = defaultOptions.ignore.concat(options.ignore)\n  }\n  options = Object.assign({}, defaultOptions, options)\n  options.ignore = ignoreList\n\n  if (!((options.htmlRaw || options.html.length || options.webpages.length) && (options.cssRaw || options.css.length))) {\n    throw new Error('You must include HTML and CSS for input.')\n  }\n\n  const p = new Promise(function (resolve, reject) {\n    let htmlRaw = options.htmlRaw\n    let cssRaw = options.cssRaw\n\n    Promise.all([\n      globby(options.html),\n      globby(options.css)\n    ]).then((pathsArray) => {\n      const htmlFiles = pathsArray[0]\n      const cssFiles = pathsArray[1]\n      getTextFromUrls(options.webpages, (webHtml) =>\n        getTextFromFiles(htmlFiles, (html) =>\n          getTextFromFiles(cssFiles, (css) => {\n            // TODO: Is there a better way to do this. I'd rather not nest it\n            // but I don't want to pass more args either.\n            function processInput (html, css) {\n              const outputFile = options.overwriteCss\n                ? cssFiles[0]\n                : options.outputFile\n              postcss([\n                postcssRazor({\n                  html: html,\n                  ignore: options.ignore,\n                  report: options.report\n                })\n              ])\n                .process(css, {\n                  from: options.inputCss,\n                  to: outputFile\n                })\n                .then((result) => {\n                  if (outputFile) {\n                    // Make sure the directory exists first.\n                    mkdirp(path.dirname(outputFile), (err, d1) => {\n                      if (err) {\n                        return reject(err)\n                      }\n                      fs.writeFile(outputFile, result.css, (err, d2) => {\n                        if (err) {\n                          return reject(err)\n                        }\n                        resolve(result)\n                      })\n                    })\n                  } else {\n                    resolve(result)\n                  }\n                })\n                .catch((e) => {\n                  reject(e)\n                })\n            }\n\n            return processInput(html + htmlRaw + webHtml, css + cssRaw)\n          })\n        )\n      )\n    })\n  })\n\n  // Enable callback support too.\n  if (callback) {\n    p.then((result) => {\n      callback(null, result)\n    }).catch(err => callback(err))\n  }\n\n  return p\n}\n\nconst postcssRazor = postcss.plugin('postcss-razor', (opt) => {\n  const html = opt.html\n  let keepCount = 0\n  let keepSelectors = ''\n  let removeCount = 0\n  let removeSelectors = ''\n  return (root) => {\n    const $ = cheerio.load(html)\n    root.walk((node) => {\n      if (node.type === 'rule') {\n        const exists = checkExists(node, $)\n        const ignore = opt.ignore.some((ignore) => {\n          return node.selector.indexOf(ignore) !== -1\n        })\n        if (!exists && !ignore) {\n          node.remove()\n          removeSelectors += node.selector + DELIMITER\n          removeCount++\n        } else {\n          keepSelectors += node.selector + DELIMITER\n          keepCount++\n        }\n      }\n    })\n\n    // Remove empty media queries.\n    root.walkAtRules((rule) => {\n      if (typeof rule.nodes === 'undefined' || rule.nodes.length === 0) {\n        rule.remove()\n      }\n    })\n\n    if (opt.report) {\n      const percent = ((removeCount / (keepCount + removeCount)) * 100).toFixed()\n      console.log('   Selectors kept: ' + keepCount)\n      console.log('Selectors removed: ' + removeCount)\n      console.log('  Percent removed: ' + percent + '%')\n      console.log(' ')\n      if (opt.reportDetails) {\n        console.log('Removed selectors: ' + removeSelectors)\n        console.log(' ')\n        console.log('   Kept selectors: ' + keepSelectors)\n      }\n    }\n  }\n})\n\nfunction getTextFromFiles (files, cb) {\n  let text = ''\n  if (files.length) {\n    files.forEach((file, i) => {\n      fs.readFile(file, (err, data) => {\n        if (err) {\n          console.error(err)\n        }\n        text += data.toString()\n\n        if (i === files.length - 1) {\n          cb(text)\n        }\n      })\n    })\n  } else {\n    cb(text)\n  }\n}\n\nfunction getTextFromUrls (urls, cb) {\n  let text = ''\n  if (urls.length) {\n    urls.forEach((file, i) => {\n      fetch(file).then(function (response) {\n        if (response.status >= 400) {\n          throw new Error('Bad response from server')\n        }\n        return response.text()\n      }).then(function (responseText) {\n        text += responseText\n\n        if (i === urls.length - 1) {\n          cb(text)\n        }\n      })\n    })\n  } else {\n    cb(text)\n  }\n}\n\nfunction checkExists (node, $) {\n  // Right now this try is needed because cheerio doesn't handle `pseudo-element` well.\n  // See: https://github.com/cheeriojs/cheerio/issues/979\n  try {\n    return $(removePseudoClasses(node.selector)).length > 0\n  } catch (e) {\n    return true\n  }\n}\n\nfunction removePseudoClasses (selector) {\n  return [\n    ':active',\n    ':focus',\n    ':hover',\n    ':visited',\n    '::before',\n    ':before',\n    '::after',\n    ':after'\n  ].reduce((p, c) => {\n    return p.split(c).join('')\n  }, selector)\n}\n\nmodule.exports = {\n  default: cssRazor,\n  postcss: postcssRazor\n}\n"
  },
  {
    "path": "index.test.js",
    "content": "const Code = require('code') // assertion library\nconst Lab = require('lab')\nconst lab = exports.lab = Lab.script()\n\nconst cssRazor = require('./index').default\nconst spawn = require('child_process').spawn\n\n// Test output\nconst testResults = require('./test/results.js')\n\nlab.experiment('css-razor', () => {\n  lab.test('returns promise with used CSS based on input HTML & CSS', (done) => {\n    cssRazor({\n      html: ['test/input/index.html'],\n      css: ['test/input/index.css'],\n      outputFile: 'test/output/index.css'\n    }).then((data) => {\n      Code.expect(data.css.split('\\r').join('')).to.equal(testResults.simpleCss)\n      done()\n    })\n  })\n\n  lab.test('calls callback with used CSS based on input HTML & CSS', (done) => {\n    cssRazor({\n      html: ['test/input/index.html'],\n      css: ['test/input/index.css'],\n      outputFile: 'test/output/index.css'\n    }, function (err, data) {\n      if (err) {\n        console.error(err)\n      }\n      Code.expect(data.css.split('\\r').join('')).to.equal(testResults.simpleCss)\n      done()\n    })\n  })\n\n  lab.test('returns promise with used CSS based on more complex input HTML & CSS', (done) => {\n    cssRazor({\n      html: ['test/input/tachyons.html'],\n      css: ['test/input/tachyons.min.css'],\n      outputFile: 'test/output/tachyons.css'\n    }).then((data) => {\n      Code.expect(data.css.split('\\r').join('')).to.equal(testResults.complexCss)\n      done()\n    })\n  })\n\n  lab.test('calls callback with used CSS based on more complex input webpage & CSS', (done) => {\n    cssRazor({\n      webpages: ['http://blog.timscanlin.net/'],\n      css: ['test/input/tachyons.min.css'],\n      outputFile: 'test/output/tachyons.css'\n    }, function (err, data) {\n      if (err) {\n        console.error(err)\n      }\n      Code.expect(data.css.split('\\r').join('')).to.equal(testResults.complexHttpCss)\n      done()\n    })\n  })\n\n  lab.test('CLI returns used CSS based on input HTML & CSS', (done) => {\n    const cli = spawn('node', [\n      './cli.js',\n      'test/input/index.html',\n      'test/input/index.css'\n    ])\n\n    cli.stdout.on('data', (data) => {\n      Code.expect(data.toString().split('\\r').join('')).to.equal(testResults.simpleCss)\n    })\n\n    cli.on('close', (code) => {\n      Code.expect(code).to.equal(0)\n      done()\n    })\n  })\n\n  // empty input\n  // no files\n\n  // multiple files\n  // raw\n  // postcss\n  // set output file\n})\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"css-razor\",\n  \"version\": \"2.4.4\",\n  \"description\": \"Remove unused selectors from CSS efficiently\",\n  \"main\": \"index.js\",\n  \"bin\": {\n    \"css-razor\": \"./cli.js\"\n  },\n  \"scripts\": {\n    \"lint\": \"standard --globals=fetch\",\n    \"test:unit\": \"lab ./index.test.js --ignore fetch,Response,Headers,Request,Base64\",\n    \"test\": \"npm run lint && npm run test:unit\",\n    \"v-patch\": \"npm version patch && git push --tags && npm publish && git push\",\n    \"v-minor\": \"npm version minor && git push --tags && npm publish && git push\",\n    \"v-major\": \"npm version major && git push --tags && npm publish && git push\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/tscanlin/css-razor.git\"\n  },\n  \"keywords\": [\n    \"css\",\n    \"razor\",\n    \"strip\",\n    \"cut\",\n    \"slim\",\n    \"cheerio\",\n    \"postcss\",\n    \"postcss-runner\"\n  ],\n  \"author\": \"Tim Scanlin\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/tscanlin/css-razor/issues\"\n  },\n  \"homepage\": \"https://github.com/tscanlin/css-razor#readme\",\n  \"dependencies\": {\n    \"cheerio\": \"^0.22.0\",\n    \"es6-promise\": \"^4.1.0\",\n    \"globby\": \"^6.1.0\",\n    \"isomorphic-fetch\": \"^2.2.1\",\n    \"mkdirp\": \"^0.5.1\",\n    \"postcss\": \"^5.2.13\",\n    \"yargs\": \"^6.6.0\"\n  },\n  \"devDependencies\": {\n    \"code\": \"^4.0.0\",\n    \"lab\": \"^12.1.0\",\n    \"standard\": \"^10.0.2\"\n  }\n}\n"
  },
  {
    "path": "test/input/index.css",
    "content": "body {\n  font-size: 20px;\n}\n\n.some-element {\n  margin: 20px;\n}\n\n.some-element .inner-element {\n  text-align: center;\n}\n\n.some-element > .inner-element {\n  color: blue;\n}\n\n.non-existent {\n  padding: 10px;\n}\n\n@media screen and (min-width > 200px) {\n  .nothing {\n    font-weight: bold;\n  }\n}\n"
  },
  {
    "path": "test/input/index.html",
    "content": "<div class=\"some-element\">\n  <span class=\"inner-element\">Foo Bar</span>\n</div>\n"
  },
  {
    "path": "test/input/tachyons.html",
    "content": "<article class=\"br2 ba dark-gray b--black-10 mv4 w-100 w-50-m w-25-l mw5 center\">\n  <img src=\"http://placekitten.com/g/600/300\" class=\"db w-100 br2 br--top\" alt=\"Photo of a kitten looking menacing.\">\n  <div class=\"pa2 ph3-ns pb3-ns\">\n    <div class=\"dt w-100 mt1\">\n      <div class=\"dtc\">\n        <h1 class=\"f5 f4-ns mv0\">Cat</h1>\n      </div>\n      <div class=\"dtc tr\">\n        <h2 class=\"f5 mv0\">$1,000</h2>\n      </div>\n    </div>\n    <p class=\"f6 lh-copy measure mt2 mid-gray\">\n      If it fits, i sits burrow under covers. Destroy couch leave hair everywhere,\n      and touch water with paw then recoil in horror.\n    </p>\n  </div>\n</article>\n"
  },
  {
    "path": "test/results.js",
    "content": "exports.simpleCss = 'body {\\n  font-size: 20px;\\n}\\n\\n.some-element {\\n  margin: 20px;\\n}\\n\\n.some-element .inner-element {\\n  text-align: center;\\n}\\n\\n.some-element > .inner-element {\\n  color: blue;\\n}\\n'\n\nexports.complexCss = '/*! TACHYONS v4.6.1 | http://tachyons.io */\\n/*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}a:active,a:hover{outline-width:0}img{border-style:none}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}/* 1 */ [type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}/* 1 */[hidden],template{display:none}.border-box,a,article,body,code,dd,div,dl,dt,fieldset,footer,form,h1,h2,h3,h4,h5,h6,header,html,input[type=email],input[type=number],input[type=password],input[type=tel],input[type=text],input[type=url],legend,li,main,ol,p,pre,section,table,td,textarea,th,tr,ul{box-sizing:border-box}img{max-width:100%}.ba{border-style:solid;border-width:1px}.b--black-10{border-color:rgba(0,0,0,.1)}.br2{border-radius:.25rem}.br--top{border-bottom-right-radius:0}.br--right,.br--top{border-bottom-left-radius:0}.db{display:block}.dt{display:table}.dtc{display:table-cell}.button-reset::-moz-focus-inner,.input-reset::-moz-focus-inner{border:0;padding:0}.lh-copy{line-height:1.5}.link,.link:active,.link:focus,.link:hover,.link:link,.link:visited{-webkit-transition:color .15s ease-in;transition:color .15s ease-in}.mw5{max-width:16rem}.w-100{width:100%}.overflow-hidden{overflow:hidden}.overflow-x-hidden{overflow-x:hidden}.overflow-y-hidden{overflow-y:hidden}.dark-gray{color:#333}.mid-gray{color:#555}.pa2{padding:.5rem}.mt1{margin-top:.25rem}.mt2{margin-top:.5rem}.mv0{margin-top:0;margin-bottom:0}.mv4{margin-top:2rem;margin-bottom:2rem}.tr{text-align:right}.f5{font-size:1rem}.f6{font-size:.875rem}.measure{max-width:30em}.center{margin-right:auto;margin-left:auto}.dim:active{opacity:.8;-webkit-transition:opacity .15s ease-out;transition:opacity .15s ease-out}.hide-child .child{opacity:0;-webkit-transition:opacity .15s ease-in;transition:opacity .15s ease-in}.hide-child:active .child,.hide-child:focus .child,.hide-child:hover .child{opacity:1;-webkit-transition:opacity .15s ease-in;transition:opacity .15s ease-in}.grow:active{-webkit-transform:scale(.9);transform:scale(.9)}.grow-large:active{-webkit-transform:scale(.95);transform:scale(.95)}@media screen and (min-width:30em){.overflow-hidden-ns{overflow:hidden}.overflow-x-hidden-ns{overflow-x:hidden}.overflow-y-hidden-ns{overflow-y:hidden}.pb3-ns{padding-bottom:1rem}.ph3-ns{padding-left:1rem;padding-right:1rem}.f4-ns{font-size:1.25rem}}@media screen and (min-width:30em) and (max-width:60em){.w-50-m{width:50%}.overflow-hidden-m{overflow:hidden}.overflow-x-hidden-m{overflow-x:hidden}.overflow-y-hidden-m{overflow-y:hidden}}@media screen and (min-width:60em){.w-25-l{width:25%}.overflow-hidden-l{overflow:hidden}.overflow-x-hidden-l{overflow-x:hidden}.overflow-y-hidden-l{overflow-y:hidden}}\\n'\n\nexports.complexHttpCss = '/*! TACHYONS v4.6.1 | http://tachyons.io */\\n/*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}small{font-size:80%}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}/* 1 */ [type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}/* 1 */[hidden],template{display:none}.border-box,a,article,body,code,dd,div,dl,dt,fieldset,footer,form,h1,h2,h3,h4,h5,h6,header,html,input[type=email],input[type=number],input[type=password],input[type=tel],input[type=text],input[type=url],legend,li,main,ol,p,pre,section,table,td,textarea,th,tr,ul{box-sizing:border-box}.bb{border-bottom-style:solid;border-bottom-width:1px}.b--light-gray{border-color:#eee}.top-0{top:0}.right-0{right:0}.db{display:block}.dib{display:inline-block}.normal{font-weight:400}.b{font-weight:700}.button-reset::-moz-focus-inner,.input-reset::-moz-focus-inner{border:0;padding:0}.lh-solid{line-height:1}.lh-title{line-height:1.25}.lh-copy{line-height:1.5}.link,.link:active,.link:focus,.link:hover,.link:link,.link:visited{-webkit-transition:color .15s ease-in;transition:color .15s ease-in}.mw6{max-width:32rem}.mw7{max-width:48rem}.w5{width:16rem}.overflow-hidden{overflow:hidden}.overflow-x-hidden{overflow-x:hidden}.overflow-y-hidden{overflow-y:hidden}.relative{position:relative}.absolute{position:absolute}.o-80{opacity:.8}.o-70{opacity:.7}.o-60{opacity:.6}.o-40{opacity:.4}.black{color:#000}.white{color:#fff}.bg-mid-gray{background-color:#555}.pa0{padding:0}.pa1{padding:.25rem}.pa3{padding:1rem}.pb2{padding-bottom:.5rem}.pb3{padding-bottom:1rem}.pt2{padding-top:.5rem}.pv4{padding-top:2rem;padding-bottom:2rem}.ph1{padding-left:.25rem;padding-right:.25rem}.ma0{margin:0}.ma1{margin:.25rem}.mb4{margin-bottom:2rem}.mt4{margin-top:2rem}.mv1{margin-top:.25rem;margin-bottom:.25rem}.no-underline{text-decoration:none}.tc{text-align:center}.ttu{text-transform:uppercase}.f1{font-size:3rem}.f3{font-size:1.5rem}.f6{font-size:.875rem}.center{margin-right:auto;margin-left:auto}.dim:active{opacity:.8;-webkit-transition:opacity .15s ease-out;transition:opacity .15s ease-out}.glow,.glow:focus,.glow:hover{-webkit-transition:opacity .15s ease-in;transition:opacity .15s ease-in}.glow:focus,.glow:hover{opacity:1}.hide-child .child{opacity:0;-webkit-transition:opacity .15s ease-in;transition:opacity .15s ease-in}.hide-child:active .child,.hide-child:focus .child,.hide-child:hover .child{opacity:1;-webkit-transition:opacity .15s ease-in;transition:opacity .15s ease-in}.grow:active{-webkit-transform:scale(.9);transform:scale(.9)}.grow-large:active{-webkit-transform:scale(.95);transform:scale(.95)}@media screen and (min-width:30em){.overflow-hidden-ns{overflow:hidden}.overflow-x-hidden-ns{overflow-x:hidden}.overflow-y-hidden-ns{overflow-y:hidden}.pa4-ns{padding:2rem}}@media screen and (min-width:30em) and (max-width:60em){.overflow-hidden-m{overflow:hidden}.overflow-x-hidden-m{overflow-x:hidden}.overflow-y-hidden-m{overflow-y:hidden}}@media screen and (min-width:60em){.overflow-hidden-l{overflow:hidden}.overflow-x-hidden-l{overflow-x:hidden}.overflow-y-hidden-l{overflow-y:hidden}}\\n'\n"
  }
]