UNPKG

vite

Version:

Native-ESM powered web dev build tool

12,275 lines • 355 kB
'use strict';

var require$$0 = require('os');
var require$$0$1 = require('http');
var require$$1 = require('https');
var require$$0$2 = require('url');
var path$8 = require('path');
var build = require('./dep-cc49d7be.js');
var fs$3 = require('fs');

function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e['default'] : e; }

var require$$0__default = /*#__PURE__*/_interopDefaultLegacy(require$$0);
var require$$0__default$1 = /*#__PURE__*/_interopDefaultLegacy(require$$0$1);
var require$$1__default = /*#__PURE__*/_interopDefaultLegacy(require$$1);
var require$$0__default$2 = /*#__PURE__*/_interopDefaultLegacy(require$$0$2);
var path__default = /*#__PURE__*/_interopDefaultLegacy(path$8);
var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs$3);

var clean = {exports: {}};

function level0Optimize$1(tokens) {
  // noop as level 0 means no optimizations!
  return tokens;
}

var optimize$4 = level0Optimize$1;

// adapted from http://nedbatchelder.com/blog/200712.html#e20071211T054956

var NUMBER_PATTERN = /([0-9]+)/;

function naturalCompare$1(value1, value2) {
  var keys1 = ('' + value1).split(NUMBER_PATTERN).map(tryParseInt);
  var keys2 = ('' + value2).split(NUMBER_PATTERN).map(tryParseInt);
  var key1;
  var key2;
  var compareFirst = Math.min(keys1.length, keys2.length);
  var i, l;

  for (i = 0, l = compareFirst; i < l; i++) {
    key1 = keys1[i];
    key2 = keys2[i];

    if (key1 != key2) {
      return key1 > key2 ? 1 : -1;
    }
  }

  return keys1.length > keys2.length ? 1 : (keys1.length == keys2.length ? 0 : -1);
}

function tryParseInt(value) {
  return ('' + parseInt(value)) == value ?
    parseInt(value) :
    value;
}

var naturalCompare_1 = naturalCompare$1;

var naturalCompare = naturalCompare_1;

function naturalSorter$1(scope1, scope2) {
  return naturalCompare(scope1[1], scope2[1]);
}

function standardSorter(scope1, scope2) {
  return scope1[1] > scope2[1] ? 1 : -1;
}

function sortSelectors$3(selectors, method) {
  switch (method) {
    case 'natural':
      return selectors.sort(naturalSorter$1);
    case 'standard':
      return selectors.sort(standardSorter);
    case 'none':
    case false:
      return selectors;
  }
}

var sortSelectors_1 = sortSelectors$3;

function override$7(source1, source2) {
  var target = {};
  var key1;
  var key2;
  var item;

  for (key1 in source1) {
    item = source1[key1];

    if (Array.isArray(item)) {
      target[key1] = item.slice(0);
    } else if (typeof item == 'object' && item !== null) {
      target[key1] = override$7(item, {});
    } else {
      target[key1] = item;
    }
  }

  for (key2 in source2) {
    item = source2[key2];

    if (key2 in target && Array.isArray(item)) {
      target[key2] = item.slice(0);
    } else if (key2 in target && typeof item == 'object' && item !== null) {
      target[key2] = override$7(target[key2], item);
    } else {
      target[key2] = item;
    }
  }

  return target;
}

var override_1 = override$7;

var systemLineBreak = require$$0__default.EOL;

var override$6 = override_1;

var Breaks$1 = {
  AfterAtRule: 'afterAtRule',
  AfterBlockBegins: 'afterBlockBegins',
  AfterBlockEnds: 'afterBlockEnds',
  AfterComment: 'afterComment',
  AfterProperty: 'afterProperty',
  AfterRuleBegins: 'afterRuleBegins',
  AfterRuleEnds: 'afterRuleEnds',
  BeforeBlockEnds: 'beforeBlockEnds',
  BetweenSelectors: 'betweenSelectors'
};

var BreakWith = {
  CarriageReturnLineFeed: '\r\n',
  LineFeed: '\n',
  System: systemLineBreak
};

var IndentWith = {
  Space: ' ',
  Tab: '\t'
};

var Spaces$2 = {
  AroundSelectorRelation: 'aroundSelectorRelation',
  BeforeBlockBegins: 'beforeBlockBegins',
  BeforeValue: 'beforeValue'
};

var DEFAULTS$2 = {
  breaks: breaks(false),
  breakWith: BreakWith.System,
  indentBy: 0,
  indentWith: IndentWith.Space,
  spaces: spaces(false),
  wrapAt: false,
  semicolonAfterLastProperty: false
};

var BEAUTIFY_ALIAS = 'beautify';
var KEEP_BREAKS_ALIAS = 'keep-breaks';

var OPTION_SEPARATOR$1 = ';';
var OPTION_NAME_VALUE_SEPARATOR = ':';
var HASH_VALUES_OPTION_SEPARATOR = ',';
var HASH_VALUES_NAME_VALUE_SEPARATOR = '=';

var FALSE_KEYWORD_1$1 = 'false';
var FALSE_KEYWORD_2$1 = 'off';
var TRUE_KEYWORD_1$1 = 'true';
var TRUE_KEYWORD_2$1 = 'on';

function breaks(value) {
  var breakOptions = {};

  breakOptions[Breaks$1.AfterAtRule] = value;
  breakOptions[Breaks$1.AfterBlockBegins] = value;
  breakOptions[Breaks$1.AfterBlockEnds] = value;
  breakOptions[Breaks$1.AfterComment] = value;
  breakOptions[Breaks$1.AfterProperty] = value;
  breakOptions[Breaks$1.AfterRuleBegins] = value;
  breakOptions[Breaks$1.AfterRuleEnds] = value;
  breakOptions[Breaks$1.BeforeBlockEnds] = value;
  breakOptions[Breaks$1.BetweenSelectors] = value;

  return breakOptions;
}

function spaces(value) {
  var spaceOptions = {};

  spaceOptions[Spaces$2.AroundSelectorRelation] = value;
  spaceOptions[Spaces$2.BeforeBlockBegins] = value;
  spaceOptions[Spaces$2.BeforeValue] = value;

  return spaceOptions;
}

function formatFrom$1(source) {
  if (source === undefined || source === false) {
    return false;
  }

  if (typeof source == 'object' && 'breakWith' in source) {
    source = override$6(source, { breakWith: mapBreakWith(source.breakWith) });
  }

  if (typeof source == 'object' && 'indentBy' in source) {
    source = override$6(source, { indentBy: parseInt(source.indentBy) });
  }

  if (typeof source == 'object' && 'indentWith' in source) {
    source = override$6(source, { indentWith: mapIndentWith(source.indentWith) });
  }

  if (typeof source == 'object') {
    return remapBreaks(override$6(DEFAULTS$2, source));
  }

  if (typeof source == 'string' && source == BEAUTIFY_ALIAS) {
    return remapBreaks(
      override$6(DEFAULTS$2, {
        breaks: breaks(true),
        indentBy: 2,
        spaces: spaces(true)
      })
    );
  }

  if (typeof source == 'string' && source == KEEP_BREAKS_ALIAS) {
    return remapBreaks(
      override$6(DEFAULTS$2, {
        breaks: {
          afterAtRule: true,
          afterBlockBegins: true,
          afterBlockEnds: true,
          afterComment: true,
          afterRuleEnds: true,
          beforeBlockEnds: true
        }
      })
    );
  }

  if (typeof source == 'string') {
    return remapBreaks(override$6(DEFAULTS$2, toHash(source)));
  }

  return DEFAULTS$2;
}

function toHash(string) {
  return string
    .split(OPTION_SEPARATOR$1)
    .reduce(function (accumulator, directive) {
      var parts = directive.split(OPTION_NAME_VALUE_SEPARATOR);
      var name = parts[0];
      var value = parts[1];

      if (name == 'breaks' || name == 'spaces') {
        accumulator[name] = hashValuesToHash(value);
      } else if (name == 'indentBy' || name == 'wrapAt') {
        accumulator[name] = parseInt(value);
      } else if (name == 'indentWith') {
        accumulator[name] = mapIndentWith(value);
      } else if (name == 'breakWith') {
        accumulator[name] = mapBreakWith(value);
      }

      return accumulator;
    }, {});
}

function hashValuesToHash(string) {
  return string
    .split(HASH_VALUES_OPTION_SEPARATOR)
    .reduce(function (accumulator, directive) {
      var parts = directive.split(HASH_VALUES_NAME_VALUE_SEPARATOR);
      var name = parts[0];
      var value = parts[1];

      accumulator[name] = normalizeValue$1(value);

      return accumulator;
    }, {});
}


function normalizeValue$1(value) {
  switch (value) {
    case FALSE_KEYWORD_1$1:
    case FALSE_KEYWORD_2$1:
      return false;
    case TRUE_KEYWORD_1$1:
    case TRUE_KEYWORD_2$1:
      return true;
    default:
      return value;
  }
}

function mapBreakWith(value) {
  switch (value) {
    case 'windows':
    case 'crlf':
    case BreakWith.CarriageReturnLineFeed:
      return BreakWith.CarriageReturnLineFeed;
    case 'unix':
    case 'lf':
    case BreakWith.LineFeed:
      return BreakWith.LineFeed;
    default:
      return systemLineBreak;
  }
}

function mapIndentWith(value) {
  switch (value) {
    case 'space':
      return IndentWith.Space;
    case 'tab':
      return IndentWith.Tab;
    default:
      return value;
  }
}

function remapBreaks(source) {
  for (var key in Breaks$1) {
    var breakName = Breaks$1[key];
    var breakValue = source.breaks[breakName];

    if (breakValue === true) {
      source.breaks[breakName] = source.breakWith;
    } else if (breakValue === false) {
      source.breaks[breakName] = '';
    } else {
      source.breaks[breakName] = source.breakWith.repeat(parseInt(breakValue));
    }
  }

  return source;
}

var format = {
  Breaks: Breaks$1,
  Spaces: Spaces$2,
  formatFrom: formatFrom$1
};

var Marker$g = {
  ASTERISK: '*',
  AT: '@',
  BACK_SLASH: '\\',
  CARRIAGE_RETURN: '\r',
  CLOSE_CURLY_BRACKET: '}',
  CLOSE_ROUND_BRACKET: ')',
  CLOSE_SQUARE_BRACKET: ']',
  COLON: ':',
  COMMA: ',',
  DOUBLE_QUOTE: '"',
  EXCLAMATION: '!',
  FORWARD_SLASH: '/',
  INTERNAL: '-clean-css-',
  NEW_LINE_NIX: '\n',
  OPEN_CURLY_BRACKET: '{',
  OPEN_ROUND_BRACKET: '(',
  OPEN_SQUARE_BRACKET: '[',
  SEMICOLON: ';',
  SINGLE_QUOTE: '\'',
  SPACE: ' ',
  TAB: '\t',
  UNDERSCORE: '_'
};

var marker = Marker$g;

function formatPosition$4(metadata) {
  var line = metadata[0];
  var column = metadata[1];
  var source = metadata[2];

  return source ?
    source + ':' + line + ':' + column :
    line + ':' + column;
}

var formatPosition_1 = formatPosition$4;

var Spaces$1 = format.Spaces;
var Marker$f = marker;
var formatPosition$3 = formatPosition_1;

var CASE_ATTRIBUTE_PATTERN = /[\s"'][iI]\s*\]/;
var CASE_RESTORE_PATTERN = /([\d\w])([iI])\]/g;
var DOUBLE_QUOTE_CASE_PATTERN = /="([a-zA-Z][a-zA-Z\d\-_]+)"([iI])/g;
var DOUBLE_QUOTE_PATTERN = /="([a-zA-Z][a-zA-Z\d\-_]+)"(\s|\])/g;
var HTML_COMMENT_PATTERN = /^(?:(?:<!--|-->)\s*)+/;
var SINGLE_QUOTE_CASE_PATTERN = /='([a-zA-Z][a-zA-Z\d\-_]+)'([iI])/g;
var SINGLE_QUOTE_PATTERN = /='([a-zA-Z][a-zA-Z\d\-_]+)'(\s|\])/g;
var RELATION_PATTERN$1 = /[>\+~]/;
var WHITESPACE_PATTERN$2 = /\s/;

var ASTERISK_PLUS_HTML_HACK = '*+html ';
var ASTERISK_FIRST_CHILD_PLUS_HTML_HACK = '*:first-child+html ';
var LESS_THAN = '<';

var PSEUDO_CLASSES_WITH_SELECTORS = [
  ':current',
  ':future',
  ':has',
  ':host',
  ':host-context',
  ':is',
  ':not',
  ':past',
  ':where'
];

function hasInvalidCharacters(value) {
  var isEscaped;
  var isInvalid = false;
  var character;
  var isQuote = false;
  var i, l;

  for (i = 0, l = value.length; i < l; i++) {
    character = value[i];

    if (isEscaped) ; else if (character == Marker$f.SINGLE_QUOTE || character == Marker$f.DOUBLE_QUOTE) {
      isQuote = !isQuote;
    } else if (!isQuote && (character == Marker$f.CLOSE_CURLY_BRACKET || character == Marker$f.EXCLAMATION || character == LESS_THAN || character == Marker$f.SEMICOLON)) {
      isInvalid = true;
      break;
    } else if (!isQuote && i === 0 && RELATION_PATTERN$1.test(character)) {
      isInvalid = true;
      break;
    }

    isEscaped = character == Marker$f.BACK_SLASH;
  }

  return isInvalid;
}

function removeWhitespace(value, format) {
  var stripped = [];
  var character;
  var isNewLineNix;
  var isNewLineWin;
  var isEscaped;
  var wasEscaped;
  var isQuoted;
  var isSingleQuoted;
  var isDoubleQuoted;
  var isAttribute;
  var isRelation;
  var isWhitespace;
  var isSpaceAwarePseudoClass;
  var roundBracketLevel = 0;
  var wasComma = false;
  var wasRelation = false;
  var wasWhitespace = false;
  var withCaseAttribute = CASE_ATTRIBUTE_PATTERN.test(value);
  var spaceAroundRelation = format && format.spaces[Spaces$1.AroundSelectorRelation];
  var i, l;

  for (i = 0, l = value.length; i < l; i++) {
    character = value[i];

    isNewLineNix = character == Marker$f.NEW_LINE_NIX;
    isNewLineWin = character == Marker$f.NEW_LINE_NIX && value[i - 1] == Marker$f.CARRIAGE_RETURN;
    isQuoted = isSingleQuoted || isDoubleQuoted;
    isRelation = !isAttribute && !isEscaped && roundBracketLevel === 0 && RELATION_PATTERN$1.test(character);
    isWhitespace = WHITESPACE_PATTERN$2.test(character);
    isSpaceAwarePseudoClass = roundBracketLevel == 1 && character == Marker$f.CLOSE_ROUND_BRACKET ?
      false :
      isSpaceAwarePseudoClass || (roundBracketLevel === 0 && character == Marker$f.COLON && isPseudoClassWithSelectors(value, i));

    if (wasEscaped && isQuoted && isNewLineWin) {
      // swallow escaped new windows lines in comments
      stripped.pop();
      stripped.pop();
    } else if (isEscaped && isQuoted && isNewLineNix) {
      // swallow escaped new *nix lines in comments
      stripped.pop();
    } else if (isEscaped) {
      stripped.push(character);
    } else if (character == Marker$f.OPEN_SQUARE_BRACKET && !isQuoted) {
      stripped.push(character);
      isAttribute = true;
    } else if (character == Marker$f.CLOSE_SQUARE_BRACKET && !isQuoted) {
      stripped.push(character);
      isAttribute = false;
    } else if (character == Marker$f.OPEN_ROUND_BRACKET && !isQuoted) {
      stripped.push(character);
      roundBracketLevel++;
    } else if (character == Marker$f.CLOSE_ROUND_BRACKET && !isQuoted) {
      stripped.push(character);
      roundBracketLevel--;
    } else if (character == Marker$f.SINGLE_QUOTE && !isQuoted) {
      stripped.push(character);
      isSingleQuoted = true;
    } else if (character == Marker$f.DOUBLE_QUOTE && !isQuoted) {
      stripped.push(character);
      isDoubleQuoted = true;
    } else if (character == Marker$f.SINGLE_QUOTE && isQuoted) {
      stripped.push(character);
      isSingleQuoted = false;
    } else if (character == Marker$f.DOUBLE_QUOTE && isQuoted) {
      stripped.push(character);
      isDoubleQuoted = false;
    } else if (isWhitespace && wasRelation && !spaceAroundRelation) {
      continue;
    } else if (!isWhitespace && wasRelation && spaceAroundRelation) {
      stripped.push(Marker$f.SPACE);
      stripped.push(character);
    } else if (isWhitespace && !wasWhitespace && wasComma && roundBracketLevel > 0 && isSpaceAwarePseudoClass) ; else if (isWhitespace && !wasWhitespace && roundBracketLevel > 0 && isSpaceAwarePseudoClass) {
      stripped.push(character);
    } else if (isWhitespace && (isAttribute || roundBracketLevel > 0) && !isQuoted) ; else if (isWhitespace && wasWhitespace && !isQuoted) ; else if ((isNewLineWin || isNewLineNix) && (isAttribute || roundBracketLevel > 0) && isQuoted) ; else if (isRelation && wasWhitespace && !spaceAroundRelation) {
      stripped.pop();
      stripped.push(character);
    } else if (isRelation && !wasWhitespace && spaceAroundRelation) {
      stripped.push(Marker$f.SPACE);
      stripped.push(character);
    } else if (isWhitespace) {
      stripped.push(Marker$f.SPACE);
    } else {
      stripped.push(character);
    }

    wasEscaped = isEscaped;
    isEscaped = character == Marker$f.BACK_SLASH;
    wasRelation = isRelation;
    wasWhitespace = isWhitespace;
    wasComma = character == Marker$f.COMMA;
  }

  return withCaseAttribute ?
    stripped.join('').replace(CASE_RESTORE_PATTERN, '$1 $2]') :
    stripped.join('');
}

function isPseudoClassWithSelectors(value, colonPosition) {
  var pseudoClass = value.substring(colonPosition, value.indexOf(Marker$f.OPEN_ROUND_BRACKET, colonPosition));

  return PSEUDO_CLASSES_WITH_SELECTORS.indexOf(pseudoClass) > -1;
}

function removeQuotes(value) {
  if (value.indexOf('\'') == -1 && value.indexOf('"') == -1) {
    return value;
  }

  return value
    .replace(SINGLE_QUOTE_CASE_PATTERN, '=$1 $2')
    .replace(SINGLE_QUOTE_PATTERN, '=$1$2')
    .replace(DOUBLE_QUOTE_CASE_PATTERN, '=$1 $2')
    .replace(DOUBLE_QUOTE_PATTERN, '=$1$2');
}

function tidyRules$3(rules, removeUnsupported, adjacentSpace, format, warnings) {
  var list = [];
  var repeated = [];

  function removeHTMLComment(rule, match) {
    warnings.push('HTML comment \'' + match + '\' at ' + formatPosition$3(rule[2][0]) + '. Removing.');
    return '';
  }

  for (var i = 0, l = rules.length; i < l; i++) {
    var rule = rules[i];
    var reduced = rule[1];

    reduced = reduced.replace(HTML_COMMENT_PATTERN, removeHTMLComment.bind(null, rule));

    if (hasInvalidCharacters(reduced)) {
      warnings.push('Invalid selector \'' + rule[1] + '\' at ' + formatPosition$3(rule[2][0]) + '. Ignoring.');
      continue;
    }

    reduced = removeWhitespace(reduced, format);
    reduced = removeQuotes(reduced);

    if (adjacentSpace && reduced.indexOf('nav') > 0) {
      reduced = reduced.replace(/\+nav(\S|$)/, '+ nav$1');
    }

    if (removeUnsupported && reduced.indexOf(ASTERISK_PLUS_HTML_HACK) > -1) {
      continue;
    }

    if (removeUnsupported && reduced.indexOf(ASTERISK_FIRST_CHILD_PLUS_HTML_HACK) > -1) {
      continue;
    }

    if (reduced.indexOf('*') > -1) {
      reduced = reduced
        .replace(/\*([:#\.\[])/g, '$1')
        .replace(/^(\:first\-child)?\+html/, '*$1+html');
    }

    if (repeated.indexOf(reduced) > -1) {
      continue;
    }

    rule[1] = reduced;
    repeated.push(reduced);
    list.push(rule);
  }

  if (list.length == 1 && list[0][1].length === 0) {
    warnings.push('Empty selector \'' + list[0][1] + '\' at ' + formatPosition$3(list[0][2][0]) + '. Ignoring.');
    list = [];
  }

  return list;
}

var tidyRules_1 = tidyRules$3;

var SUPPORTED_COMPACT_BLOCK_MATCHER = /^@media\W/;
var SUPPORTED_QUOTE_REMOVAL_MATCHER = /^@(?:keyframes|-moz-keyframes|-o-keyframes|-webkit-keyframes)\W/;

function tidyBlock$1(values, spaceAfterClosingBrace) {
  var withoutSpaceAfterClosingBrace;
  var withoutQuotes;
  var i;

  for (i = values.length - 1; i >= 0; i--) {
    withoutSpaceAfterClosingBrace = !spaceAfterClosingBrace && SUPPORTED_COMPACT_BLOCK_MATCHER.test(values[i][1]);
    withoutQuotes = SUPPORTED_QUOTE_REMOVAL_MATCHER.test(values[i][1]);

    values[i][1] = values[i][1]
      .replace(/\n|\r\n/g, ' ')
      .replace(/\s+/g, ' ')
      .replace(/(,|:|\() /g, '$1')
      .replace(/ \)/g, ')');

    if (withoutQuotes) {
      values[i][1] = values[i][1]
        .replace(/'([a-zA-Z][a-zA-Z\d\-_]+)'/, '$1')
        .replace(/"([a-zA-Z][a-zA-Z\d\-_]+)"/, '$1');
    }

    if (withoutSpaceAfterClosingBrace) {
      values[i][1] = values[i][1]
        .replace(/\) /g, ')');
    }
  }

  return values;
}

var tidyBlock_1 = tidyBlock$1;

function tidyAtRule$1(value) {
  return value
    .replace(/\s+/g, ' ')
    .replace(/url\(\s+/g, 'url(')
    .replace(/\s+\)/g, ')')
    .trim();
}

var tidyAtRule_1 = tidyAtRule$1;

var Hack$3 = {
  ASTERISK: 'asterisk',
  BANG: 'bang',
  BACKSLASH: 'backslash',
  UNDERSCORE: 'underscore'
};

var hack = Hack$3;

function removeUnused$2(properties) {
  for (var i = properties.length - 1; i >= 0; i--) {
    var property = properties[i];

    if (property.unused) {
      property.all.splice(property.position, 1);
    }
  }
}

var removeUnused_1 = removeUnused$2;

var Hack$2 = hack;

var Marker$e = marker;

var ASTERISK_HACK = '*';
var BACKSLASH_HACK = '\\';
var IMPORTANT_TOKEN = '!important';
var UNDERSCORE_HACK = '_';
var BANG_HACK = '!ie';

function restoreFromOptimizing$5(properties, restoreCallback) {
  var property;
  var restored;
  var current;
  var i;

  for (i = properties.length - 1; i >= 0; i--) {
    property = properties[i];

    if (property.dynamic && property.important) {
      restoreImportant(property);
      continue;
    }

    if (property.dynamic) {
      continue;
    }

    if (property.unused) {
      continue;
    }

    if (!property.dirty && !property.important && !property.hack) {
      continue;
    }

    if (property.optimizable && restoreCallback) {
      restored = restoreCallback(property);
      property.value = restored;
    } else {
      restored = property.value;
    }

    if (property.important) {
      restoreImportant(property);
    }

    if (property.hack) {
      restoreHack(property);
    }

    if ('all' in property) {
      current = property.all[property.position];
      current[1][1] = property.name;

      current.splice(2, current.length - 1);
      Array.prototype.push.apply(current, restored);
    }
  }
}

function restoreImportant(property) {
  property.value[property.value.length - 1][1] += IMPORTANT_TOKEN;
}

function restoreHack(property) {
  if (property.hack[0] == Hack$2.UNDERSCORE) {
    property.name = UNDERSCORE_HACK + property.name;
  } else if (property.hack[0] == Hack$2.ASTERISK) {
    property.name = ASTERISK_HACK + property.name;
  } else if (property.hack[0] == Hack$2.BACKSLASH) {
    property.value[property.value.length - 1][1] += BACKSLASH_HACK + property.hack[1];
  } else if (property.hack[0] == Hack$2.BANG) {
    property.value[property.value.length - 1][1] += Marker$e.SPACE + BANG_HACK;
  }
}

var restoreFromOptimizing_1 = restoreFromOptimizing$5;

var Token$o = {
  AT_RULE: 'at-rule', // e.g. `@import`, `@charset`
  AT_RULE_BLOCK: 'at-rule-block', // e.g. `@font-face{...}`
  AT_RULE_BLOCK_SCOPE: 'at-rule-block-scope', // e.g. `@font-face`
  COMMENT: 'comment', // e.g. `/* comment */`
  NESTED_BLOCK: 'nested-block', // e.g. `@media screen{...}`, `@keyframes animation {...}`
  NESTED_BLOCK_SCOPE: 'nested-block-scope', // e.g. `@media`, `@keyframes`
  PROPERTY: 'property', // e.g. `color:red`
  PROPERTY_BLOCK: 'property-block', // e.g. `--var:{color:red}`
  PROPERTY_NAME: 'property-name', // e.g. `color`
  PROPERTY_VALUE: 'property-value', // e.g. `red`
  RAW: 'raw', // e.g. anything between /* clean-css ignore:start */ and /* clean-css ignore:end */ comments
  RULE: 'rule', // e.g `div > a{...}`
  RULE_SCOPE: 'rule-scope' // e.g `div > a`
};

var token = Token$o;

var Hack$1 = hack;

var Marker$d = marker;
var Token$n = token;

var Match = {
  ASTERISK: '*',
  BACKSLASH: '\\',
  BANG: '!',
  BANG_SUFFIX_PATTERN: /!\w+$/,
  IMPORTANT_TOKEN: '!important',
  IMPORTANT_TOKEN_PATTERN: new RegExp('!important$', 'i'),
  IMPORTANT_WORD: 'important',
  IMPORTANT_WORD_PATTERN: new RegExp('important$', 'i'),
  SUFFIX_BANG_PATTERN: /!$/,
  UNDERSCORE: '_',
  VARIABLE_REFERENCE_PATTERN: /var\(--.+\)$/
};

function wrapAll(properties, skipProperties) {
  var wrapped = [];
  var single;
  var property;
  var i;

  for (i = properties.length - 1; i >= 0; i--) {
    property = properties[i];

    if (property[0] != Token$n.PROPERTY) {
      continue;
    }

    if (skipProperties && skipProperties.indexOf(property[1][1]) > -1) {
      continue;
    }

    single = wrapSingle$3(property);
    single.all = properties;
    single.position = i;
    wrapped.unshift(single);
  }

  return wrapped;
}

function someVariableReferences(property) {
  var i, l;
  var value;

  // skipping `property` and property name tokens
  for (i = 2, l = property.length; i < l; i++) {
    value = property[i];

    if (value[0] != Token$n.PROPERTY_VALUE) {
      continue;
    }

    if (isVariableReference(value[1])) {
      return true;
    }
  }

  return false;
}

function isVariableReference(value) {
  return Match.VARIABLE_REFERENCE_PATTERN.test(value);
}

function isMultiplex(property) {
  var value;
  var i, l;

  for (i = 3, l = property.length; i < l; i++) {
    value = property[i];

    if (value[0] == Token$n.PROPERTY_VALUE && (value[1] == Marker$d.COMMA || value[1] == Marker$d.FORWARD_SLASH)) {
      return true;
    }
  }

  return false;
}

function hackFrom(property) {
  var match = false;
  var name = property[1][1];
  var lastValue = property[property.length - 1];

  if (name[0] == Match.UNDERSCORE) {
    match = [Hack$1.UNDERSCORE];
  } else if (name[0] == Match.ASTERISK) {
    match = [Hack$1.ASTERISK];
  } else if (lastValue[1][0] == Match.BANG && !lastValue[1].match(Match.IMPORTANT_WORD_PATTERN)) {
    match = [Hack$1.BANG];
  } else if (lastValue[1].indexOf(Match.BANG) > 0 && !lastValue[1].match(Match.IMPORTANT_WORD_PATTERN) && Match.BANG_SUFFIX_PATTERN.test(lastValue[1])) {
    match = [Hack$1.BANG];
  } else if (lastValue[1].indexOf(Match.BACKSLASH) > 0 && lastValue[1].indexOf(Match.BACKSLASH) == lastValue[1].length - Match.BACKSLASH.length - 1) {
    match = [Hack$1.BACKSLASH, lastValue[1].substring(lastValue[1].indexOf(Match.BACKSLASH) + 1)];
  } else if (lastValue[1].indexOf(Match.BACKSLASH) === 0 && lastValue[1].length == 2) {
    match = [Hack$1.BACKSLASH, lastValue[1].substring(1)];
  }

  return match;
}

function isImportant(property) {
  if (property.length < 3)
    return false;

  var lastValue = property[property.length - 1];
  if (Match.IMPORTANT_TOKEN_PATTERN.test(lastValue[1])) {
    return true;
  } else if (Match.IMPORTANT_WORD_PATTERN.test(lastValue[1]) && Match.SUFFIX_BANG_PATTERN.test(property[property.length - 2][1])) {
    return true;
  }

  return false;
}

function stripImportant(property) {
  var lastValue = property[property.length - 1];
  var oneButLastValue = property[property.length - 2];

  if (Match.IMPORTANT_TOKEN_PATTERN.test(lastValue[1])) {
    lastValue[1] = lastValue[1].replace(Match.IMPORTANT_TOKEN_PATTERN, '');
  } else {
    lastValue[1] = lastValue[1].replace(Match.IMPORTANT_WORD_PATTERN, '');
    oneButLastValue[1] = oneButLastValue[1].replace(Match.SUFFIX_BANG_PATTERN, '');
  }

  if (lastValue[1].length === 0) {
    property.pop();
  }

  if (oneButLastValue[1].length === 0) {
    property.pop();
  }
}

function stripPrefixHack(property) {
  property[1][1] = property[1][1].substring(1);
}

function stripSuffixHack(property, hackFrom) {
  var lastValue = property[property.length - 1];
  lastValue[1] = lastValue[1]
    .substring(0, lastValue[1].indexOf(hackFrom[0] == Hack$1.BACKSLASH ? Match.BACKSLASH : Match.BANG))
    .trim();

  if (lastValue[1].length === 0) {
    property.pop();
  }
}

function wrapSingle$3(property) {
  var importantProperty = isImportant(property);
  if (importantProperty) {
    stripImportant(property);
  }

  var whichHack = hackFrom(property);
  if (whichHack[0] == Hack$1.ASTERISK || whichHack[0] == Hack$1.UNDERSCORE) {
    stripPrefixHack(property);
  } else if (whichHack[0] == Hack$1.BACKSLASH || whichHack[0] == Hack$1.BANG) {
    stripSuffixHack(property, whichHack);
  }

  return {
    block: property[2] && property[2][0] == Token$n.PROPERTY_BLOCK,
    components: [],
    dirty: false,
    dynamic: someVariableReferences(property),
    hack: whichHack,
    important: importantProperty,
    name: property[1][1],
    multiplex: property.length > 3 ? isMultiplex(property) : false,
    optimizable: true,
    position: 0,
    shorthand: false,
    unused: false,
    value: property.slice(2)
  };
}

var wrapForOptimizing$3 = {
  all: wrapAll,
  single: wrapSingle$3
};

function InvalidPropertyError$2(message) {
  this.name = 'InvalidPropertyError';
  this.message = message;
  this.stack = (new Error()).stack;
}

InvalidPropertyError$2.prototype = Object.create(Error.prototype);
InvalidPropertyError$2.prototype.constructor = InvalidPropertyError$2;

var invalidPropertyError = InvalidPropertyError$2;

var InvalidPropertyError$1 = invalidPropertyError;

var wrapSingle$2 = wrapForOptimizing$3.single;

var Token$m = token;
var Marker$c = marker;

var formatPosition$2 = formatPosition_1;

function _anyIsInherit(values) {
  var i, l;

  for (i = 0, l = values.length; i < l; i++) {
    if (values[i][1] == 'inherit') {
      return true;
    }
  }

  return false;
}

function _colorFilter(validator) {
  return function (value) {
    return value[1] == 'invert' || validator.isColor(value[1]) || validator.isPrefixed(value[1]);
  };
}

function _styleFilter(validator) {
  return function (value) {
    return value[1] != 'inherit' && validator.isStyleKeyword(value[1]) && !validator.isColorFunction(value[1]);
  };
}

function _wrapDefault(name, property, configuration) {
  var descriptor = configuration[name];
  if (descriptor.doubleValues && descriptor.defaultValue.length == 2) {
    return wrapSingle$2([
      Token$m.PROPERTY,
      [Token$m.PROPERTY_NAME, name],
      [Token$m.PROPERTY_VALUE, descriptor.defaultValue[0]],
      [Token$m.PROPERTY_VALUE, descriptor.defaultValue[1]]
    ]);
  } else if (descriptor.doubleValues && descriptor.defaultValue.length == 1) {
    return wrapSingle$2([
      Token$m.PROPERTY,
      [Token$m.PROPERTY_NAME, name],
      [Token$m.PROPERTY_VALUE, descriptor.defaultValue[0]]
    ]);
  } else {
    return wrapSingle$2([
      Token$m.PROPERTY,
      [Token$m.PROPERTY_NAME, name],
      [Token$m.PROPERTY_VALUE, descriptor.defaultValue]
    ]);
  }
}

function _widthFilter(validator) {
  return function (value) {
    return value[1] != 'inherit' &&
      (validator.isWidth(value[1]) || validator.isUnit(value[1]) || validator.isDynamicUnit(value[1])) &&
      !validator.isStyleKeyword(value[1]) &&
      !validator.isColorFunction(value[1]);
  };
}

function animation(property, configuration, validator) {
  var duration = _wrapDefault(property.name + '-duration', property, configuration);
  var timing = _wrapDefault(property.name + '-timing-function', property, configuration);
  var delay = _wrapDefault(property.name + '-delay', property, configuration);
  var iteration = _wrapDefault(property.name + '-iteration-count', property, configuration);
  var direction = _wrapDefault(property.name + '-direction', property, configuration);
  var fill = _wrapDefault(property.name + '-fill-mode', property, configuration);
  var play = _wrapDefault(property.name + '-play-state', property, configuration);
  var name = _wrapDefault(property.name + '-name', property, configuration);
  var components = [duration, timing, delay, iteration, direction, fill, play, name];
  var values = property.value;
  var value;
  var durationSet = false;
  var timingSet = false;
  var delaySet = false;
  var iterationSet = false;
  var directionSet = false;
  var fillSet = false;
  var playSet = false;
  var nameSet = false;
  var i;
  var l;

  if (property.value.length == 1 && property.value[0][1] == 'inherit') {
    duration.value = timing.value = delay.value = iteration.value = direction.value = fill.value = play.value = name.value = property.value;
    return components;
  }

  if (values.length > 1 && _anyIsInherit(values)) {
    throw new InvalidPropertyError$1('Invalid animation values at ' + formatPosition$2(values[0][2][0]) + '. Ignoring.');
  }

  for (i = 0, l = values.length; i < l; i++) {
    value = values[i];

    if (validator.isTime(value[1]) && !durationSet) {
      duration.value = [value];
      durationSet = true;
    } else if (validator.isTime(value[1]) && !delaySet) {
      delay.value = [value];
      delaySet = true;
    } else if ((validator.isGlobal(value[1]) || validator.isTimingFunction(value[1])) && !timingSet) {
      timing.value = [value];
      timingSet = true;
    } else if ((validator.isAnimationIterationCountKeyword(value[1]) || validator.isPositiveNumber(value[1])) && !iterationSet) {
      iteration.value = [value];
      iterationSet = true;
    } else if (validator.isAnimationDirectionKeyword(value[1]) && !directionSet) {
      direction.value = [value];
      directionSet = true;
    } else if (validator.isAnimationFillModeKeyword(value[1]) && !fillSet) {
      fill.value = [value];
      fillSet = true;
    } else if (validator.isAnimationPlayStateKeyword(value[1]) && !playSet) {
      play.value = [value];
      playSet = true;
    } else if ((validator.isAnimationNameKeyword(value[1]) || validator.isIdentifier(value[1])) && !nameSet) {
      name.value = [value];
      nameSet = true;
    } else {
      throw new InvalidPropertyError$1('Invalid animation value at ' + formatPosition$2(value[2][0]) + '. Ignoring.');
    }
  }

  return components;
}

function background$2(property, configuration, validator) {
  var image = _wrapDefault('background-image', property, configuration);
  var position = _wrapDefault('background-position', property, configuration);
  var size = _wrapDefault('background-size', property, configuration);
  var repeat = _wrapDefault('background-repeat', property, configuration);
  var attachment = _wrapDefault('background-attachment', property, configuration);
  var origin = _wrapDefault('background-origin', property, configuration);
  var clip = _wrapDefault('background-clip', property, configuration);
  var color = _wrapDefault('background-color', property, configuration);
  var components = [image, position, size, repeat, attachment, origin, clip, color];
  var values = property.value;

  var positionSet = false;
  var clipSet = false;
  var originSet = false;
  var repeatSet = false;

  var anyValueSet = false;

  if (property.value.length == 1 && property.value[0][1] == 'inherit') {
    // NOTE: 'inherit' is not a valid value for background-attachment
    color.value = image.value =  repeat.value = position.value = size.value = origin.value = clip.value = property.value;
    return components;
  }

  if (property.value.length == 1 && property.value[0][1] == '0 0') {
    return components;
  }

  for (var i = values.length - 1; i >= 0; i--) {
    var value = values[i];

    if (validator.isBackgroundAttachmentKeyword(value[1])) {
      attachment.value = [value];
      anyValueSet = true;
    } else if (validator.isBackgroundClipKeyword(value[1]) || validator.isBackgroundOriginKeyword(value[1])) {
      if (clipSet) {
        origin.value = [value];
        originSet = true;
      } else {
        clip.value = [value];
        clipSet = true;
      }
      anyValueSet = true;
    } else if (validator.isBackgroundRepeatKeyword(value[1])) {
      if (repeatSet) {
        repeat.value.unshift(value);
      } else {
        repeat.value = [value];
        repeatSet = true;
      }
      anyValueSet = true;
    } else if (validator.isBackgroundPositionKeyword(value[1]) || validator.isBackgroundSizeKeyword(value[1]) || validator.isUnit(value[1]) || validator.isDynamicUnit(value[1])) {
      if (i > 0) {
        var previousValue = values[i - 1];

        if (previousValue[1] == Marker$c.FORWARD_SLASH) {
          size.value = [value];
        } else if (i > 1 && values[i - 2][1] == Marker$c.FORWARD_SLASH) {
          size.value = [previousValue, value];
          i -= 2;
        } else {
          if (!positionSet)
            position.value = [];

          position.value.unshift(value);
          positionSet = true;
        }
      } else {
        if (!positionSet)
          position.value = [];

        position.value.unshift(value);
        positionSet = true;
      }
      anyValueSet = true;
    } else if ((color.value[0][1] == configuration[color.name].defaultValue || color.value[0][1] == 'none') && (validator.isColor(value[1]) || validator.isPrefixed(value[1]))) {
      color.value = [value];
      anyValueSet = true;
    } else if (validator.isUrl(value[1]) || validator.isFunction(value[1])) {
      image.value = [value];
      anyValueSet = true;
    }
  }

  if (clipSet && !originSet)
    origin.value = clip.value.slice(0);

  if (!anyValueSet) {
    throw new InvalidPropertyError$1('Invalid background value at ' + formatPosition$2(values[0][2][0]) + '. Ignoring.');
  }

  return components;
}

function borderRadius$2(property, configuration) {
  var values = property.value;
  var splitAt = -1;

  for (var i = 0, l = values.length; i < l; i++) {
    if (values[i][1] == Marker$c.FORWARD_SLASH) {
      splitAt = i;
      break;
    }
  }

  if (splitAt === 0 || splitAt === values.length - 1) {
    throw new InvalidPropertyError$1('Invalid border-radius value at ' + formatPosition$2(values[0][2][0]) + '. Ignoring.');
  }

  var target = _wrapDefault(property.name, property, configuration);
  target.value = splitAt > -1 ?
    values.slice(0, splitAt) :
    values.slice(0);
  target.components = fourValues$1(target, configuration);

  var remainder = _wrapDefault(property.name, property, configuration);
  remainder.value = splitAt > -1 ?
    values.slice(splitAt + 1) :
    values.slice(0);
  remainder.components = fourValues$1(remainder, configuration);

  for (var j = 0; j < 4; j++) {
    target.components[j].multiplex = true;
    target.components[j].value = target.components[j].value.concat(remainder.components[j].value);
  }

  return target.components;
}

function font$1(property, configuration, validator) {
  var style = _wrapDefault('font-style', property, configuration);
  var variant = _wrapDefault('font-variant', property, configuration);
  var weight = _wrapDefault('font-weight', property, configuration);
  var stretch = _wrapDefault('font-stretch', property, configuration);
  var size = _wrapDefault('font-size', property, configuration);
  var height = _wrapDefault('line-height', property, configuration);
  var family = _wrapDefault('font-family', property, configuration);
  var components = [style, variant, weight, stretch, size, height, family];
  var values = property.value;
  var fuzzyMatched = 4; // style, variant, weight, and stretch
  var index = 0;
  var isStretchSet = false;
  var isStretchValid;
  var isStyleSet = false;
  var isStyleValid;
  var isVariantSet = false;
  var isVariantValid;
  var isWeightSet = false;
  var isWeightValid;
  var isSizeSet = false;
  var appendableFamilyName = false;

  if (!values[index]) {
    throw new InvalidPropertyError$1('Missing font values at ' + formatPosition$2(property.all[property.position][1][2][0]) + '. Ignoring.');
  }

  if (values.length == 1 && values[0][1] == 'inherit') {
    style.value = variant.value = weight.value = stretch.value = size.value = height.value = family.value = values;
    return components;
  }

  if (values.length == 1 && (validator.isFontKeyword(values[0][1]) || validator.isGlobal(values[0][1]) || validator.isPrefixed(values[0][1]))) {
    values[0][1] = Marker$c.INTERNAL + values[0][1];
    style.value = variant.value = weight.value = stretch.value = size.value = height.value = family.value = values;
    return components;
  }

  if (values.length < 2 || !_anyIsFontSize(values, validator) || !_anyIsFontFamily(values, validator)) {
    throw new InvalidPropertyError$1('Invalid font values at ' + formatPosition$2(property.all[property.position][1][2][0]) + '. Ignoring.');
  }

  if (values.length > 1 && _anyIsInherit(values)) {
    throw new InvalidPropertyError$1('Invalid font values at ' + formatPosition$2(values[0][2][0]) + '. Ignoring.');
  }

  // fuzzy match style, variant, weight, and stretch on first elements
  while (index < fuzzyMatched) {
    isStretchValid = validator.isFontStretchKeyword(values[index][1]) || validator.isGlobal(values[index][1]);
    isStyleValid = validator.isFontStyleKeyword(values[index][1]) || validator.isGlobal(values[index][1]);
    isVariantValid = validator.isFontVariantKeyword(values[index][1]) || validator.isGlobal(values[index][1]);
    isWeightValid = validator.isFontWeightKeyword(values[index][1]) || validator.isGlobal(values[index][1]);

    if (isStyleValid && !isStyleSet) {
      style.value = [values[index]];
      isStyleSet = true;
    } else if (isVariantValid && !isVariantSet) {
      variant.value = [values[index]];
      isVariantSet = true;
    } else if (isWeightValid && !isWeightSet) {
      weight.value = [values[index]];
      isWeightSet = true;
    } else if (isStretchValid && !isStretchSet) {
      stretch.value = [values[index]];
      isStretchSet = true;
    } else if (isStyleValid && isStyleSet || isVariantValid && isVariantSet || isWeightValid && isWeightSet || isStretchValid && isStretchSet) {
      throw new InvalidPropertyError$1('Invalid font style / variant / weight / stretch value at ' + formatPosition$2(values[0][2][0]) + '. Ignoring.');
    } else {
      break;
    }

    index++;
  }

  // now comes font-size ...
  if (validator.isFontSizeKeyword(values[index][1]) || validator.isUnit(values[index][1]) && !validator.isDynamicUnit(values[index][1])) {
    size.value = [values[index]];
    isSizeSet = true;
    index++;
  } else {
    throw new InvalidPropertyError$1('Missing font size at ' + formatPosition$2(values[0][2][0]) + '. Ignoring.');
  }

  if (!values[index]) {
    throw new InvalidPropertyError$1('Missing font family at ' + formatPosition$2(values[0][2][0]) + '. Ignoring.');
  }

  // ... and perhaps line-height
  if (isSizeSet && values[index] && values[index][1] == Marker$c.FORWARD_SLASH && values[index + 1] && (validator.isLineHeightKeyword(values[index + 1][1]) || validator.isUnit(values[index + 1][1]) || validator.isNumber(values[index + 1][1]))) {
    height.value = [values[index + 1]];
    index++;
    index++;
  }

  // ... and whatever comes next is font-family
  family.value = [];

  while (values[index]) {
    if (values[index][1] == Marker$c.COMMA) {
      appendableFamilyName = false;
    } else {
      if (appendableFamilyName) {
        family.value[family.value.length - 1][1] += Marker$c.SPACE + values[index][1];
      } else {
        family.value.push(values[index]);
      }

      appendableFamilyName = true;
    }

    index++;
  }

  if (family.value.length === 0) {
    throw new InvalidPropertyError$1('Missing font family at ' + formatPosition$2(values[0][2][0]) + '. Ignoring.');
  }

  return components;
}

function _anyIsFontSize(values, validator) {
  var value;
  var i, l;

  for (i = 0, l = values.length; i < l; i++) {
    value = values[i];

    if (validator.isFontSizeKeyword(value[1]) || validator.isUnit(value[1]) && !validator.isDynamicUnit(value[1]) || validator.isFunction(value[1])) {
      return true;
    }
  }

  return false;
}

function _anyIsFontFamily(values, validator) {
  var value;
  var i, l;

  for (i = 0, l = values.length; i < l; i++) {
    value = values[i];

    if (validator.isIdentifier(value[1]) || validator.isQuotedText(value[1])) {
      return true;
    }
  }

  return false;
}

function fourValues$1(property, configuration) {
  var componentNames = configuration[property.name].components;
  var components = [];
  var value = property.value;

  if (value.length < 1)
    return [];

  if (value.length < 2)
    value[1] = value[0].slice(0);
  if (value.length < 3)
    value[2] = value[0].slice(0);
  if (value.length < 4)
    value[3] = value[1].slice(0);

  for (var i = componentNames.length - 1; i >= 0; i--) {
    var component = wrapSingle$2([
      Token$m.PROPERTY,
      [Token$m.PROPERTY_NAME, componentNames[i]]
    ]);
    component.value = [value[i]];
    components.unshift(component);
  }

  return components;
}

function multiplex$1(splitWith) {
  return function (property, configuration, validator) {
    var splitsAt = [];
    var values = property.value;
    var i, j, l, m;

    // find split commas
    for (i = 0, l = values.length; i < l; i++) {
      if (values[i][1] == ',')
        splitsAt.push(i);
    }

    if (splitsAt.length === 0)
      return splitWith(property, configuration, validator);

    var splitComponents = [];

    // split over commas, and into components
    for (i = 0, l = splitsAt.length; i <= l; i++) {
      var from = i === 0 ? 0 : splitsAt[i - 1] + 1;
      var to = i < l ? splitsAt[i] : values.length;

      var _property = _wrapDefault(property.name, property, configuration);
      _property.value = values.slice(from, to);

      if (_property.value.length > 0) {
        splitComponents.push(splitWith(_property, configuration, validator));
      }
    }

    var components = splitComponents[0];

    // group component values from each split
    for (i = 0, l = components.length; i < l; i++) {
      components[i].multiplex = true;

      for (j = 1, m = splitComponents.length; j < m; j++) {
        components[i].value.push([Token$m.PROPERTY_VALUE, Marker$c.COMMA]);
        Array.prototype.push.apply(components[i].value, splitComponents[j][i].value);
      }
    }

    return components;
  };
}

function listStyle(property, configuration, validator) {
  var type = _wrapDefault('list-style-type', property, configuration);
  var position = _wrapDefault('list-style-position', property, configuration);
  var image = _wrapDefault('list-style-image', property, configuration);
  var components = [type, position, image];

  if (property.value.length == 1 && property.value[0][1] == 'inherit') {
    type.value = position.value = image.value = [property.value[0]];
    return components;
  }

  var values = property.value.slice(0);
  var total = values.length;
  var index = 0;

  // `image` first...
  for (index = 0, total = values.length; index < total; index++) {
    if (validator.isUrl(values[index][1]) || values[index][1] == '0') {
      image.value = [values[index]];
      values.splice(index, 1);
      break;
    }
  }

  // ... then `position`
  for (index = 0, total = values.length; index < total; index++) {
    if (validator.isListStylePositionKeyword(values[index][1])) {
      position.value = [values[index]];
      values.splice(index, 1);
      break;
    }
  }

  // ... and what's left is a `type`
  if (values.length > 0 && (validator.isListStyleTypeKeyword(values[0][1]) || validator.isIdentifier(values[0][1]))) {
    type.value = [values[0]];
  }

  return components;
}

function transition(property, configuration, validator) {
  var prop = _wrapDefault(property.name + '-property', property, configuration);
  var duration = _wrapDefault(property.name + '-duration', property, configuration);
  var timing = _wrapDefault(property.name + '-timing-function', property, configuration);
  var delay = _wrapDefault(property.name + '-delay', property, configuration);
  var components = [prop, duration, timing, delay];
  var values = property.value;
  var value;
  var durationSet = false;
  var delaySet = false;
  var propSet = false;
  var timingSet = false;
  var i;
  var l;

  if (property.value.length == 1 && property.value[0][1] == 'inherit') {
    prop.value = duration.value = timing.value = delay.value = property.value;
    return components;
  }

  if (values.length > 1 && _anyIsInherit(values)) {
    throw new InvalidPropertyError$1('Invalid animation values at ' + formatPosition$2(values[0][2][0]) + '. Ignoring.');
  }

  for (i = 0, l = values.length; i < l; i++) {
    value = values[i];

    if (validator.isTime(value[1]) && !durationSet) {
      duration.value = [value];
      durationSet = true;
    } else if (validator.isTime(value[1]) && !delaySet) {
      delay.value = [value];
      delaySet = true;
    } else if ((validator.isGlobal(value[1]) || validator.isTimingFunction(value[1])) && !timingSet) {
      timing.value = [value];
      timingSet = true;
    } else if (validator.isIdentifier(value[1]) && !propSet) {
      prop.value = [value];
      propSet = true;
    } else {
      throw new InvalidPropertyError$1('Invalid animation value at ' + formatPosition$2(value[2][0]) + '. Ignoring.');
    }
  }

  return components;
}

function widthStyleColor(property, configuration, validator) {
  var descriptor = configuration[property.name];
  var components = [
    _wrapDefault(descriptor.components[0], property, configuration),
    _wrapDefault(descriptor.components[1], property, configuration),
    _wrapDefault(descriptor.components[2], property, configuration)
  ];
  var color, style, width;

  for (var i = 0; i < 3; i++) {
    var component = components[i];

    if (component.name.indexOf('color') > 0)
      color = component;
    else if (component.name.indexOf('style') > 0)
      style = component;
    else
      width = component;
  }

  if ((property.value.length == 1 && property.value[0][1] == 'inherit') ||
      (property.value.length == 3 && property.value[0][1] == 'inherit' && property.value[1][1] == 'inherit' && property.value[2][1] == 'inherit')) {
    color.value = style.value = width.value = [property.value[0]];
    return components;
  }

  var values = property.value.slice(0);
  var match, matches;

  // NOTE: usually users don't follow the required order of parts in this shorthand,
  // so we'll try to parse it caring as little about order as possible

  if (values.length > 0) {
    matches = values.filter(_widthFilter(validator));
    match = matches.length > 1 && (matches[0][1] == 'none' || matches[0][1] == 'auto') ? matches[1] : matches[0];
    if (match) {
      width.value = [match];
      values.splice(values.indexOf(match), 1);
    }
  }

  if (values.length > 0) {
    match = values.filter(_styleFilter(validator))[0];
    if (match) {
      style.value = [match];
      values.splice(values.indexOf(match), 1);
    }
  }

  if (values.length > 0) {
    match = values.filter(_colorFilter(validator))[0];
    if (match) {
      color.value = [match];
      values.splice(values.indexOf(match), 1);
    }
  }

  return components;
}

var breakUp$1 = {
  animation: animation,
  background: background$2,
  border: widthStyleColor,
  borderRadius: borderRadius$2,
  font: font$1,
  fourValues: fourValues$1,
  listStyle: listStyle,
  multiplex: multiplex$1,
  outline: widthStyleColor,
  transition: transition
};

var VENDOR_PREFIX_PATTERN = /(?:^|\W)(\-\w+\-)/g;

function unique(value) {
  var prefixes = [];
  var match;

  while ((match = VENDOR_PREFIX_PATTERN.exec(value)) !== null) {
    if (prefixes.indexOf(match[0]) == -1) {
      prefixes.push(match[0]);
    }
  }

  return prefixes;
}

function same(value1, value2) {
  return unique(value1).sort().join(',') == unique(value2).sort().join(',');
}

var vendorPrefixes = {
  unique: unique,
  same: same
};

var sameVendorPrefixes = vendorPrefixes.same;

function understandable$1(validator, value1, value2, _position, isPaired) {
  if (!sameVendorPrefixes(value1, value2)) {
    return false;
  }

  if (isPaired && validator.isVariable(value1) !== validator.isVariable(value2)) {
    return false;
  }

  return true;
}

var understandable_1 = understandable$1;

var understandable = understandable_1;

function animationIterationCount(validator, value1, value2) {
  if (!understandable(validator, value1, value2, 0, true) && !(validator.isAnimationIterationCountKeyword(value2) || validator.isPositiveNumber(value2))) {
    return false;
  } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
    return true;
  }

  return validator.isAnimationIterationCountKeyword(value2) || validator.isPositiveNumber(value2);
}

function animationName(validator, value1, value2) {
  if (!understandable(validator, value1, value2, 0, true) && !(validator.isAnimationNameKeyword(value2) || validator.isIdentifier(value2))) {
    return false;
  } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
    return true;
  }

  return validator.isAnimationNameKeyword(value2) || validator.isIdentifier(value2);
}

function areSameFunction(validator, value1, value2) {
  if (!validator.isFunction(value1) || !validator.isFunction(value2)) {
    return false;
  }

  var function1Name = value1.substring(0, value1.indexOf('('));
  var function2Name = value2.substring(0, value2.indexOf('('));

  var function1Value = value1.substring(function1Name.length + 1, value1.length - 1);
  var function2Value = value2.substring(function2Name.length + 1, value2.length - 1);

  if (validator.isFunction(function1Value) || validator.isFunction(function2Value)) {
    return function1Name === function2Name && areSameFunction(validator, function1Value, function2Value);
  } else {
    return function1Name === function2Name;
  }
}

function backgroundPosition(validator, value1, value2) {
  if (!understandable(validator, value1, value2, 0, true) && !(validator.isBackgroundPositionKeyword(value2) || validator.isGlobal(value2))) {
    return false;
  } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
    return true;
  } else if (validator.isBackgroundPositionKeyword(value2) || validator.isGlobal(value2)) {
    return true;
  }

  return unit$1(validator, value1, value2);
}

function backgroundSize(validator, value1, value2) {
  if (!understandable(validator, value1, value2, 0, true) && !(validator.isBackgroundSizeKeyword(value2) || validator.isGlobal(value2))) {
    return false;
  } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
    return true;
  } else if (validator.isBackgroundSizeKeyword(value2) || validator.isGlobal(value2)) {
    return true;
  }

  return unit$1(validator, value1, value2);
}

function color$1(validator, value1, value2) {
  if (!understandable(validator, value1, value2, 0, true) && !validator.isColor(value2)) {
    return false;
  } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
    return true;
  } else if (!validator.colorOpacity && (validator.isRgbColor(value1) || validator.isHslColor(value1))) {
    return false;
  } else if (!validator.colorOpacity && (validator.isRgbColor(value2) || validator.isHslColor(value2))) {
    return false;
  } else if (!validator.colorHexAlpha && (validator.isHexAlphaColor(value1) || validator.isHexAlphaColor(value2))) {
    return false;
  } else if (validator.isColor(value1) && validator.isColor(value2)) {
    return true;
  }

  return sameFunctionOrValue(validator, value1, value2);
}

function components(overrideCheckers) {
  return function (validator, value1, value2, position) {
    return overrideCheckers[position](validator, value1, value2);
  };
}

function fontFamily(validator, value1, value2) {
  return understandable(validator, value1, value2, 0, true);
}

function image(validator, value1, value2) {
  if (!understandable(validator, value1, value2, 0, true) && !validator.isImage(value2)) {
    return false;
  } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
    return true;
  } else if (validator.isImage(value2)) {
    return true;
  } else if (validator.isImage(value1)) {
    return false;
  }

  return sameFunctionOrValue(validator, value1, value2);
}

function keyword(propertyName) {
  return function(validator, value1, value2) {
    if (!understandable(validator, value1, value2, 0, true) && !validator.isKeyword(propertyName)(value2)) {
      return false;
    } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
      return true;
    }

    return validator.isKeyword(propertyName)(value2);
  };
}

function keywordWithGlobal(propertyName) {
  return function(validator, value1, value2) {
    if (!understandable(validator, value1, value2, 0, true) && !(validator.isKeyword(propertyName)(value2) || validator.isGlobal(value2))) {
      return false;
    } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
      return true;
    }

    return validator.isKeyword(propertyName)(value2) || validator.isGlobal(value2);
  };
}

function propertyName$1(validator, value1, value2) {
  if (!understandable(validator, value1, value2, 0, true) && !validator.isIdentifier(value2)) {
    return false;
  } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
    return true;
  }

  return validator.isIdentifier(value2);
}

function sameFunctionOrValue(validator, value1, value2) {
  return areSameFunction(validator, value1, value2) ?
    true :
    value1 === value2;
}

function textShadow(validator, value1, value2) {
  if (!understandable(validator, value1, value2, 0, true) && !(validator.isUnit(value2) || validator.isColor(value2) || validator.isGlobal(value2))) {
    return false;
  } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
    return true;
  }

  return validator.isUnit(value2) || validator.isColor(value2) || validator.isGlobal(value2);
}

function time$1(validator, value1, value2) {
  if (!understandable(validator, value1, value2, 0, true) && !validator.isTime(value2)) {
    return false;
  } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
    return true;
  } else if (validator.isTime(value1) && !validator.isTime(value2)) {
    return false;
  } else if (validator.isTime(value2)) {
    return true;
  } else if (validator.isTime(value1)) {
    return false;
  } else if (validator.isFunction(value1) && !validator.isPrefixed(value1) && validator.isFunction(value2) && !validator.isPrefixed(value2)) {
    return true;
  }

  return sameFunctionOrValue(validator, value1, value2);
}

function timingFunction(validator, value1, value2) {
  if (!understandable(validator, value1, value2, 0, true) && !(validator.isTimingFunction(value2) || validator.isGlobal(value2))) {
    return false;
  } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
    return true;
  }

  return validator.isTimingFunction(value2) || validator.isGlobal(value2);
}

function unit$1(validator, value1, value2) {
  if (!understandable(validator, value1, value2, 0, true) && !validator.isUnit(value2)) {
    return false;
  } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
    return true;
  } else if (validator.isUnit(value1) && !validator.isUnit(value2)) {
    return false;
  } else if (validator.isUnit(value2)) {
    return true;
  } else if (validator.isUnit(value1)) {
    return false;
  } else if (validator.isFunction(value1) && !validator.isPrefixed(value1) && validator.isFunction(value2) && !validator.isPrefixed(value2)) {
    return true;
  }

  return sameFunctionOrValue(validator, value1, value2);
}

function unitOrKeywordWithGlobal(propertyName) {
  var byKeyword = keywordWithGlobal(propertyName);

  return function(validator, value1, value2) {
    return unit$1(validator, value1, value2) || byKeyword(validator, value1, value2);
  };
}

function unitOrNumber(validator, value1, value2) {
  if (!understandable(validator, value1, value2, 0, true) && !(validator.isUnit(value2) || validator.isNumber(value2))) {
    return false;
  } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
    return true;
  } else if ((validator.isUnit(value1) || validator.isNumber(value1)) && !(validator.isUnit(value2) || validator.isNumber(value2))) {
    return false;
  } else if (validator.isUnit(value2) || validator.isNumber(value2)) {
    return true;
  } else if (validator.isUnit(value1) || validator.isNumber(value1)) {
    return false;
  } else if (validator.isFunction(value1) && !validator.isPrefixed(value1) && validator.isFunction(value2) && !validator.isPrefixed(value2)) {
    return true;
  }

  return sameFunctionOrValue(validator, value1, value2);
}

function zIndex(validator, value1, value2) {
  if (!understandable(validator, value1, value2, 0, true) && !validator.isZIndex(value2)) {
    return false;
  } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
    return true;
  }

  return validator.isZIndex(value2);
}

var canOverride$1 = {
  generic: {
    color: color$1,
    components: components,
    image: image,
    propertyName: propertyName$1,
    time: time$1,
    timingFunction: timingFunction,
    unit: unit$1,
    unitOrNumber: unitOrNumber
  },
  property: {
    animationDirection: keywordWithGlobal('animation-direction'),
    animationFillMode: keyword('animation-fill-mode'),
    animationIterationCount: animationIterationCount,
    animationName: animationName,
    animationPlayState: keywordWithGlobal('animation-play-state'),
    backgroundAttachment: keyword('background-attachment'),
    backgroundClip: keywordWithGlobal('background-clip'),
    backgroundOrigin: keyword('background-origin'),
    backgroundPosition: backgroundPosition,
    backgroundRepeat: keyword('background-repeat'),
    backgroundSize: backgroundSize,
    bottom: unitOrKeywordWithGlobal('bottom'),
    borderCollapse: keyword('border-collapse'),
    borderStyle: keywordWithGlobal('*-style'),
    clear: keywordWithGlobal('clear'),
    cursor: keywordWithGlobal('cursor'),
    display: keywordWithGlobal('display'),
    float: keywordWithGlobal('float'),
    left: unitOrKeywordWithGlobal('left'),
    fontFamily: fontFamily,
    fontStretch: keywordWithGlobal('font-stretch'),
    fontStyle: keywordWithGlobal('font-style'),
    fontVariant: keywordWithGlobal('font-variant'),
    fontWeight: keywordWithGlobal('font-weight'),
    listStyleType: keywordWithGlobal('list-style-type'),
    listStylePosition: keywordWithGlobal('list-style-position'),
    outlineStyle: keywordWithGlobal('*-style'),
    overflow: keywordWithGlobal('overflow'),
    position: keywordWithGlobal('position'),
    right: unitOrKeywordWithGlobal('right'),
    textAlign: keywordWithGlobal('text-align'),
    textDecoration: keywordWithGlobal('text-decoration'),
    textOverflow: keywordWithGlobal('text-overflow'),
    textShadow: textShadow,
    top: unitOrKeywordWithGlobal('top'),
    transform: sameFunctionOrValue,
    verticalAlign: unitOrKeywordWithGlobal('vertical-align'),
    visibility: keywordWithGlobal('visibility'),
    whiteSpace: keywordWithGlobal('white-space'),
    zIndex: zIndex
  }
};

var wrapSingle$1 = wrapForOptimizing$3.single;

var Token$l = token;

function deep(property) {
  var cloned = shallow(property);
  for (var i = property.components.length - 1; i >= 0; i--) {
    var component = shallow(property.components[i]);
    component.value = property.components[i].value.slice(0);
    cloned.components.unshift(component);
  }

  cloned.dirty = true;
  cloned.value = property.value.slice(0);

  return cloned;
}

function shallow(property) {
  var cloned = wrapSingle$1([
    Token$l.PROPERTY,
    [Token$l.PROPERTY_NAME, property.name]
  ]);
  cloned.important = property.important;
  cloned.hack = property.hack;
  cloned.unused = false;
  return cloned;
}

var clone = {
  deep: deep,
  shallow: shallow
};

var shallowClone$1 = clone.shallow;

var Token$k = token;
var Marker$b = marker;

function isInheritOnly(values) {
  for (var i = 0, l = values.length; i < l; i++) {
    var value = values[i][1];

    if (value != 'inherit' && value != Marker$b.COMMA && value != Marker$b.FORWARD_SLASH)
      return false;
  }

  return true;
}

function background$1(property, configuration, lastInMultiplex) {
  var components = property.components;
  var restored = [];
  var needsOne, needsBoth;

  function restoreValue(component) {
    Array.prototype.unshift.apply(restored, component.value);
  }

  function isDefaultValue(component) {
    var descriptor = configuration[component.name];

    if (descriptor.doubleValues && descriptor.defaultValue.length == 1) {
      return component.value[0][1] == descriptor.defaultValue[0] && (component.value[1] ? component.value[1][1] == descriptor.defaultValue[0] : true);
    } else if (descriptor.doubleValues && descriptor.defaultValue.length != 1) {
      return component.value[0][1] == descriptor.defaultValue[0] && (component.value[1] ? component.value[1][1] : component.value[0][1]) == descriptor.defaultValue[1];
    } else {
      return component.value[0][1] == descriptor.defaultValue;
    }
  }

  for (var i = components.length - 1; i >= 0; i--) {
    var component = components[i];
    var isDefault = isDefaultValue(component);

    if (component.name == 'background-clip') {
      var originComponent = components[i - 1];
      var isOriginDefault = isDefaultValue(originComponent);

      needsOne = component.value[0][1] == originComponent.value[0][1];

      needsBoth = !needsOne && (
        (isOriginDefault && !isDefault) ||
        (!isOriginDefault && !isDefault) ||
        (!isOriginDefault && isDefault && component.value[0][1] != originComponent.value[0][1]));

      if (needsOne) {
        restoreValue(originComponent);
      } else if (needsBoth) {
        restoreValue(component);
        restoreValue(originComponent);
      }

      i--;
    } else if (component.name == 'background-size') {
      var positionComponent = components[i - 1];
      var isPositionDefault = isDefaultValue(positionComponent);

      needsOne = !isPositionDefault && isDefault;

      needsBoth = !needsOne &&
        (isPositionDefault && !isDefault || !isPositionDefault && !isDefault);

      if (needsOne) {
        restoreValue(positionComponent);
      } else if (needsBoth) {
        restoreValue(component);
        restored.unshift([Token$k.PROPERTY_VALUE, Marker$b.FORWARD_SLASH]);
        restoreValue(positionComponent);
      } else if (positionComponent.value.length == 1) {
        restoreValue(positionComponent);
      }

      i--;
    } else {
      if (isDefault || configuration[component.name].multiplexLastOnly && !lastInMultiplex)
        continue;

      restoreValue(component);
    }
  }

  if (restored.length === 0 && property.value.length == 1 && property.value[0][1] == '0')
    restored.push(property.value[0]);

  if (restored.length === 0)
    restored.push([Token$k.PROPERTY_VALUE, configuration[property.name].defaultValue]);

  if (isInheritOnly(restored))
    return [restored[0]];

  return restored;
}

function borderRadius$1(property, configuration) {
  if (property.multiplex) {
    var horizontal = shallowClone$1(property);
    var vertical = shallowClone$1(property);

    for (var i = 0; i < 4; i++) {
      var component = property.components[i];

      var horizontalComponent = shallowClone$1(property);
      horizontalComponent.value = [component.value[0]];
      horizontal.components.push(horizontalComponent);

      var verticalComponent = shallowClone$1(property);
      // FIXME: only shorthand compactor (see breakup#borderRadius) knows that border radius
      // longhands have two values, whereas tokenizer does not care about populating 2nd value
      // if it's missing, hence this fallback
      verticalComponent.value = [component.value[1] || component.value[0]];
      vertical.components.push(verticalComponent);
    }

    var horizontalValues = fourValues(horizontal);
    var verticalValues = fourValues(vertical);

    if (horizontalValues.length == verticalValues.length &&
        horizontalValues[0][1] == verticalValues[0][1] &&
        (horizontalValues.length > 1 ? horizontalValues[1][1] == verticalValues[1][1] : true) &&
        (horizontalValues.length > 2 ? horizontalValues[2][1] == verticalValues[2][1] : true) &&
        (horizontalValues.length > 3 ? horizontalValues[3][1] == verticalValues[3][1] : true)) {
      return horizontalValues;
    } else {
      return horizontalValues.concat([[Token$k.PROPERTY_VALUE, Marker$b.FORWARD_SLASH]]).concat(verticalValues);
    }
  } else {
    return fourValues(property);
  }
}

function font(property, configuration) {
  var components = property.components;
  var restored = [];
  var component;
  var componentIndex = 0;
  var fontFamilyIndex = 0;

  if (property.value[0][1].indexOf(Marker$b.INTERNAL) === 0) {
    property.value[0][1] = property.value[0][1].substring(Marker$b.INTERNAL.length);
    return property.value;
  }

  // first four components are optional
  while (componentIndex < 4) {
    component = components[componentIndex];

    if (component.value[0][1] != configuration[component.name].defaultValue) {
      Array.prototype.push.apply(restored, component.value);
    }

    componentIndex++;
  }

  // then comes font-size
  Array.prototype.push.apply(restored, components[componentIndex].value);
  componentIndex++;

  // then may come line-height
  if (components[componentIndex].value[0][1] != configuration[components[componentIndex].name].defaultValue) {
    Array.prototype.push.apply(restored, [[Token$k.PROPERTY_VALUE, Marker$b.FORWARD_SLASH]]);
    Array.prototype.push.apply(restored, components[componentIndex].value);
  }

  componentIndex++;

  // then comes font-family
  while (components[componentIndex].value[fontFamilyIndex]) {
    restored.push(components[componentIndex].value[fontFamilyIndex]);

    if (components[componentIndex].value[fontFamilyIndex + 1]) {
      restored.push([Token$k.PROPERTY_VALUE, Marker$b.COMMA]);
    }

    fontFamilyIndex++;
  }

  if (isInheritOnly(restored)) {
    return [restored[0]];
  }

  return restored;
}

function fourValues(property) {
  var components = property.components;
  var value1 = components[0].value[0];
  var value2 = components[1].value[0];
  var value3 = components[2].value[0];
  var value4 = components[3].value[0];

  if (value1[1] == value2[1] && value1[1] == value3[1] && value1[1] == value4[1]) {
    return [value1];
  } else if (value1[1] == value3[1] && value2[1] == value4[1]) {
    return [value1, value2];
  } else if (value2[1] == value4[1]) {
    return [value1, value2, value3];
  } else {
    return [value1, value2, value3, value4];
  }
}

function multiplex(restoreWith) {
  return function (property, configuration) {
    if (!property.multiplex)
      return restoreWith(property, configuration, true);

    var multiplexSize = 0;
    var restored = [];
    var componentMultiplexSoFar = {};
    var i, l;

    // At this point we don't know what's the multiplex size, e.g. how many background layers are there
    for (i = 0, l = property.components[0].value.length; i < l; i++) {
      if (property.components[0].value[i][1] == Marker$b.COMMA)
        multiplexSize++;
    }

    for (i = 0; i <= multiplexSize; i++) {
      var _property = shallowClone$1(property);

      // We split multiplex into parts and restore them one by one
      for (var j = 0, m = property.components.length; j < m; j++) {
        var componentToClone = property.components[j];
        var _component = shallowClone$1(componentToClone);
        _property.components.push(_component);

        // The trick is some properties has more than one value, so we iterate over values looking for
        // a multiplex separator - a comma
        for (var k = componentMultiplexSoFar[_component.name] || 0, n = componentToClone.value.length; k < n; k++) {
          if (componentToClone.value[k][1] == Marker$b.COMMA) {
            componentMultiplexSoFar[_component.name] = k + 1;
            break;
          }

          _component.value.push(componentToClone.value[k]);
        }
      }

      // No we can restore shorthand value
      var lastInMultiplex = i == multiplexSize;
      var _restored = restoreWith(_property, configuration, lastInMultiplex);
      Array.prototype.push.apply(restored, _restored);

      if (i < multiplexSize)
        restored.push([Token$k.PROPERTY_VALUE, Marker$b.COMMA]);
    }

    return restored;
  };
}

function withoutDefaults(property, configuration) {
  var components = property.components;
  var restored = [];

  for (var i = components.length - 1; i >= 0; i--) {
    var component = components[i];
    var descriptor = configuration[component.name];

    if (component.value[0][1] != descriptor.defaultValue || ('keepUnlessDefault' in descriptor) && !isDefault(components, configuration, descriptor.keepUnlessDefault)) {
      restored.unshift(component.value[0]);
    }
  }

  if (restored.length === 0)
    restored.push([Token$k.PROPERTY_VALUE, configuration[property.name].defaultValue]);

  if (isInheritOnly(restored))
    return [restored[0]];

  return restored;
}

function isDefault(components, configuration, propertyName) {
  var component;
  var i, l;

  for (i = 0, l = components.length; i < l; i++) {
    component = components[i];

    if (component.name == propertyName && component.value[0][1] == configuration[propertyName].defaultValue) {
      return true;
    }
  }

  return false;
}

var restore$1 = {
  background: background$1,
  borderRadius: borderRadius$1,
  font: font,
  fourValues: fourValues,
  multiplex: multiplex,
  withoutDefaults: withoutDefaults
};

var override$5 = override_1;

var INTEGER_PATTERN = /^\d+$/;

var ALL_UNITS = ['*', 'all'];
var DEFAULT_PRECISION = 'off'; // all precision changes are disabled
var DIRECTIVES_SEPARATOR = ','; // e.g. *=5,px=3
var DIRECTIVE_VALUE_SEPARATOR = '='; // e.g. *=5

function roundingPrecisionFrom$1(source) {
  return override$5(defaults$1(DEFAULT_PRECISION), buildPrecisionFrom(source));
}

function defaults$1(value) {
  return {
    'ch': value,
    'cm': value,
    'em': value,
    'ex': value,
    'in': value,
    'mm': value,
    'pc': value,
    'pt': value,
    'px': value,
    'q': value,
    'rem': value,
    'vh': value,
    'vmax': value,
    'vmin': value,
    'vw': value,
    '%': value
  };
}

function buildPrecisionFrom(source) {
  if (source === null || source === undefined) {
    return {};
  }

  if (typeof source == 'boolean') {
    return {};
  }

  if (typeof source == 'number' && source == -1) {
    return defaults$1(DEFAULT_PRECISION);
  }

  if (typeof source == 'number') {
    return defaults$1(source);
  }

  if (typeof source == 'string' && INTEGER_PATTERN.test(source)) {
    return defaults$1(parseInt(source));
  }

  if (typeof source == 'string' && source == DEFAULT_PRECISION) {
    return defaults$1(DEFAULT_PRECISION);
  }

  if (typeof source == 'object') {
    return source;
  }

  return source
    .split(DIRECTIVES_SEPARATOR)
    .reduce(function (accumulator, directive) {
      var directiveParts = directive.split(DIRECTIVE_VALUE_SEPARATOR);
      var name = directiveParts[0];
      var value = parseInt(directiveParts[1]);

      if (isNaN(value) || value == -1) {
        value = DEFAULT_PRECISION;
      }

      if (ALL_UNITS.indexOf(name) > -1) {
        accumulator = override$5(accumulator, defaults$1(value));
      } else {
        accumulator[name] = value;
      }

      return accumulator;
    }, {});
}

var roundingPrecision = {
  DEFAULT: DEFAULT_PRECISION,
  roundingPrecisionFrom: roundingPrecisionFrom$1
};

var roundingPrecisionFrom = roundingPrecision.roundingPrecisionFrom;

var override$4 = override_1;

var OptimizationLevel$j = {
  Zero: '0',
  One: '1',
  Two: '2'
};

var DEFAULTS$1 = {};

DEFAULTS$1[OptimizationLevel$j.Zero] = {};
DEFAULTS$1[OptimizationLevel$j.One] = {
  cleanupCharsets: true,
  normalizeUrls: true,
  optimizeBackground: true,
  optimizeBorderRadius: true,
  optimizeFilter: true,
  optimizeFontWeight: true,
  optimizeOutline: true,
  removeEmpty: true,
  removeNegativePaddings: true,
  removeQuotes: true,
  removeWhitespace: true,
  replaceMultipleZeros: true,
  replaceTimeUnits: true,
  replaceZeroUnits: true,
  roundingPrecision: roundingPrecisionFrom(undefined),
  selectorsSortingMethod: 'standard',
  specialComments: 'all',
  tidyAtRules: true,
  tidyBlockScopes: true,
  tidySelectors: true
};
DEFAULTS$1[OptimizationLevel$j.Two] = {
  mergeAdjacentRules: true,
  mergeIntoShorthands: true,
  mergeMedia: true,
  mergeNonAdjacentRules: true,
  mergeSemantically: false,
  overrideProperties: true,
  removeEmpty: true,
  reduceNonAdjacentRules: true,
  removeDuplicateFontRules: true,
  removeDuplicateMediaBlocks: true,
  removeDuplicateRules: true,
  removeUnusedAtRules: false,
  restructureRules: false,
  skipProperties: []
};

var ALL_KEYWORD_1 = '*';
var ALL_KEYWORD_2 = 'all';
var FALSE_KEYWORD_1 = 'false';
var FALSE_KEYWORD_2 = 'off';
var TRUE_KEYWORD_1 = 'true';
var TRUE_KEYWORD_2 = 'on';

var LIST_VALUE_SEPARATOR = ',';
var OPTION_SEPARATOR = ';';
var OPTION_VALUE_SEPARATOR = ':';

function optimizationLevelFrom$1(source) {
  var level = override$4(DEFAULTS$1, {});
  var Zero = OptimizationLevel$j.Zero;
  var One = OptimizationLevel$j.One;
  var Two = OptimizationLevel$j.Two;

  if (undefined === source) {
    delete level[Two];
    return level;
  }

  if (typeof source == 'string') {
    source = parseInt(source);
  }

  if (typeof source == 'number' && source === parseInt(Two)) {
    return level;
  }

  if (typeof source == 'number' && source === parseInt(One)) {
    delete level[Two];
    return level;
  }

  if (typeof source == 'number' && source === parseInt(Zero)) {
    delete level[Two];
    delete level[One];
    return level;
  }

  if (typeof source == 'object') {
    source = covertValuesToHashes(source);
  }

  if (One in source && 'roundingPrecision' in source[One]) {
    source[One].roundingPrecision = roundingPrecisionFrom(source[One].roundingPrecision);
  }

  if (Two in source && 'skipProperties' in source[Two] && typeof(source[Two].skipProperties) == 'string') {
    source[Two].skipProperties = source[Two].skipProperties.split(LIST_VALUE_SEPARATOR);
  }

  if (Zero in source || One in source || Two in source) {
    level[Zero] = override$4(level[Zero], source[Zero]);
  }

  if (One in source && ALL_KEYWORD_1 in source[One]) {
    level[One] = override$4(level[One], defaults(One, normalizeValue(source[One][ALL_KEYWORD_1])));
    delete source[One][ALL_KEYWORD_1];
  }

  if (One in source && ALL_KEYWORD_2 in source[One]) {
    level[One] = override$4(level[One], defaults(One, normalizeValue(source[One][ALL_KEYWORD_2])));
    delete source[One][ALL_KEYWORD_2];
  }

  if (One in source || Two in source) {
    level[One] = override$4(level[One], source[One]);
  } else {
    delete level[One];
  }

  if (Two in source && ALL_KEYWORD_1 in source[Two]) {
    level[Two] = override$4(level[Two], defaults(Two, normalizeValue(source[Two][ALL_KEYWORD_1])));
    delete source[Two][ALL_KEYWORD_1];
  }

  if (Two in source && ALL_KEYWORD_2 in source[Two]) {
    level[Two] = override$4(level[Two], defaults(Two, normalizeValue(source[Two][ALL_KEYWORD_2])));
    delete source[Two][ALL_KEYWORD_2];
  }

  if (Two in source) {
    level[Two] = override$4(level[Two], source[Two]);
  } else {
    delete level[Two];
  }

  return level;
}

function defaults(level, value) {
  var options = override$4(DEFAULTS$1[level], {});
  var key;

  for (key in options) {
    if (typeof options[key] == 'boolean') {
      options[key] = value;
    }
  }

  return options;
}

function normalizeValue(value) {
  switch (value) {
    case FALSE_KEYWORD_1:
    case FALSE_KEYWORD_2:
      return false;
    case TRUE_KEYWORD_1:
    case TRUE_KEYWORD_2:
      return true;
    default:
      return value;
  }
}

function covertValuesToHashes(source) {
  var clonedSource = override$4(source, {});
  var level;
  var i;

  for (i = 0; i <= 2; i++) {
    level = '' + i;

    if (level in clonedSource && (clonedSource[level] === undefined || clonedSource[level] === false)) {
      delete clonedSource[level];
    }

    if (level in clonedSource && clonedSource[level] === true) {
      clonedSource[level] = {};
    }

    if (level in clonedSource && typeof clonedSource[level] == 'string') {
      clonedSource[level] = covertToHash(clonedSource[level], level);
    }
  }

  return clonedSource;
}

function covertToHash(asString, level) {
  return asString
    .split(OPTION_SEPARATOR)
    .reduce(function (accumulator, directive) {
      var parts = directive.split(OPTION_VALUE_SEPARATOR);
      var name = parts[0];
      var value = parts[1];
      var normalizedValue = normalizeValue(value);

      if (ALL_KEYWORD_1 == name || ALL_KEYWORD_2 == name) {
        accumulator = override$4(accumulator, defaults(level, normalizedValue));
      } else {
        accumulator[name] = normalizedValue;
      }

      return accumulator;
    }, {});
}

var optimizationLevel = {
  OptimizationLevel: OptimizationLevel$j,
  optimizationLevelFrom: optimizationLevelFrom$1,
};

var OptimizationLevel$i = optimizationLevel.OptimizationLevel;

var plugin$j = {
  level1: {
    property: function background(_rule, property, options) {
      var values = property.value;

      if (!options.level[OptimizationLevel$i.One].optimizeBackground) {
        return;
      }

      if (values.length == 1 && values[0][1] == 'none') {
        values[0][1] = '0 0';
      }

      if (values.length == 1 && values[0][1] == 'transparent') {
        values[0][1] = '0 0';
      }
    }
  }
};

var background = plugin$j;

var plugin$i = {
  level1: {
    property: function boxShadow(_rule, property) {
      var values = property.value;

      // remove multiple zeros
      if (values.length == 4 && values[0][1] === '0' && values[1][1] === '0' && values[2][1] === '0' && values[3][1] === '0') {
        property.value.splice(2);
        property.dirty = true;
      }
    }
  }
};

var boxShadow = plugin$i;

var OptimizationLevel$h = optimizationLevel.OptimizationLevel;

var plugin$h = {
  level1: {
    property: function borderRadius(_rule, property, options) {
      var values = property.value;

      if (!options.level[OptimizationLevel$h.One].optimizeBorderRadius) {
        return;
      }

      if (values.length == 3 && values[1][1] == '/' && values[0][1] == values[2][1]) {
        property.value.splice(1);
        property.dirty = true;
      } else if (values.length == 5 && values[2][1] == '/' && values[0][1] == values[3][1] && values[1][1] == values[4][1]) {
        property.value.splice(2);
        property.dirty = true;
      } else if (values.length == 7 && values[3][1] == '/' && values[0][1] == values[4][1] && values[1][1] == values[5][1] && values[2][1] == values[6][1]) {
        property.value.splice(3);
        property.dirty = true;
      } else if (values.length == 9 && values[4][1] == '/' && values[0][1] == values[5][1] && values[1][1] == values[6][1] && values[2][1] == values[7][1] && values[3][1] == values[8][1]) {
        property.value.splice(4);
        property.dirty = true;
      }
    }
  }
};

var borderRadius = plugin$h;

var OptimizationLevel$g = optimizationLevel.OptimizationLevel;

var ALPHA_OR_CHROMA_FILTER_PATTERN = /progid:DXImageTransform\.Microsoft\.(Alpha|Chroma)(\W)/;
var NO_SPACE_AFTER_COMMA_PATTERN = /,(\S)/g;
var WHITESPACE_AROUND_EQUALS_PATTERN = / ?= ?/g;

var plugin$g = {
  level1: {
    property: function filter(_rule, property, options) {
      if (!options.compatibility.properties.ieFilters) {
        return;
      }

      if (!options.level[OptimizationLevel$g.One].optimizeFilter) {
        return;
      }

      if (property.value.length == 1) {
        property.value[0][1] = property.value[0][1].replace(ALPHA_OR_CHROMA_FILTER_PATTERN, function (match, filter, suffix) {
          return filter.toLowerCase() + suffix;
        });
      }

      property.value[0][1] = property.value[0][1]
        .replace(NO_SPACE_AFTER_COMMA_PATTERN, ', $1')
        .replace(WHITESPACE_AROUND_EQUALS_PATTERN, '=');
    }
  }
};

var filter = plugin$g;

var OptimizationLevel$f = optimizationLevel.OptimizationLevel;

var plugin$f = {
  level1: {
    property: function fontWeight(_rule, property, options) {
      var value = property.value[0][1];

      if (!options.level[OptimizationLevel$f.One].optimizeFontWeight) {
        return;
      }

      if (value == 'normal') {
        value = '400';
      } else if (value == 'bold') {
        value = '700';
      }

      property.value[0][1] = value;
    }
  }
};

var fontWeight = plugin$f;

var OptimizationLevel$e = optimizationLevel.OptimizationLevel;

var plugin$e = {
  level1: {
    property: function margin(_rule, property, options) {
      var values = property.value;

      if (!options.level[OptimizationLevel$e.One].replaceMultipleZeros) {
        return;
      }

      // remove multiple zeros
      if (values.length == 4 && values[0][1] === '0' && values[1][1] === '0' && values[2][1] === '0' && values[3][1] === '0') {
        property.value.splice(1);
        property.dirty = true;
      }
    }
  }
};

var margin = plugin$e;

var OptimizationLevel$d = optimizationLevel.OptimizationLevel;

var plugin$d = {
  level1: {
    property: function outline(_rule, property, options) {
      var values = property.value;

      if (!options.level[OptimizationLevel$d.One].optimizeOutline) {
        return;
      }

      if (values.length == 1 && values[0][1] == 'none') {
        values[0][1] = '0';
      }
    }
  }
};

var outline = plugin$d;

var OptimizationLevel$c = optimizationLevel.OptimizationLevel;

function isNegative(value) {
  return value && value[1][0] == '-' && parseFloat(value[1]) < 0;
}

var plugin$c = {
  level1: {
    property: function padding(_rule, property, options) {
      var values = property.value;

      // remove multiple zeros
      if (values.length == 4 && values[0][1] === '0' && values[1][1] === '0' && values[2][1] === '0' && values[3][1] === '0') {
        property.value.splice(1);
        property.dirty = true;
      }

      // remove negative paddings
      if (options.level[OptimizationLevel$c.One].removeNegativePaddings && (isNegative(property.value[0]) || isNegative(property.value[1]) || isNegative(property.value[2]) || isNegative(property.value[3]))) {
        property.unused = true;
      }
    }
  }
};

var padding = plugin$c;

var propertyOptimizers$1 = {
  background: background.level1.property,
  boxShadow: boxShadow.level1.property,
  borderRadius: borderRadius.level1.property,
  filter: filter.level1.property,
  fontWeight: fontWeight.level1.property,
  margin: margin.level1.property,
  outline: outline.level1.property,
  padding: padding.level1.property
};

var COLORS = {
  aliceblue: '#f0f8ff',
  antiquewhite: '#faebd7',
  aqua: '#0ff',
  aquamarine: '#7fffd4',
  azure: '#f0ffff',
  beige: '#f5f5dc',
  bisque: '#ffe4c4',
  black: '#000',
  blanchedalmond: '#ffebcd',
  blue: '#00f',
  blueviolet: '#8a2be2',
  brown: '#a52a2a',
  burlywood: '#deb887',
  cadetblue: '#5f9ea0',
  chartreuse: '#7fff00',
  chocolate: '#d2691e',
  coral: '#ff7f50',
  cornflowerblue: '#6495ed',
  cornsilk: '#fff8dc',
  crimson: '#dc143c',
  cyan: '#0ff',
  darkblue: '#00008b',
  darkcyan: '#008b8b',
  darkgoldenrod: '#b8860b',
  darkgray: '#a9a9a9',
  darkgreen: '#006400',
  darkgrey: '#a9a9a9',
  darkkhaki: '#bdb76b',
  darkmagenta: '#8b008b',
  darkolivegreen: '#556b2f',
  darkorange: '#ff8c00',
  darkorchid: '#9932cc',
  darkred: '#8b0000',
  darksalmon: '#e9967a',
  darkseagreen: '#8fbc8f',
  darkslateblue: '#483d8b',
  darkslategray: '#2f4f4f',
  darkslategrey: '#2f4f4f',
  darkturquoise: '#00ced1',
  darkviolet: '#9400d3',
  deeppink: '#ff1493',
  deepskyblue: '#00bfff',
  dimgray: '#696969',
  dimgrey: '#696969',
  dodgerblue: '#1e90ff',
  firebrick: '#b22222',
  floralwhite: '#fffaf0',
  forestgreen: '#228b22',
  fuchsia: '#f0f',
  gainsboro: '#dcdcdc',
  ghostwhite: '#f8f8ff',
  gold: '#ffd700',
  goldenrod: '#daa520',
  gray: '#808080',
  green: '#008000',
  greenyellow: '#adff2f',
  grey: '#808080',
  honeydew: '#f0fff0',
  hotpink: '#ff69b4',
  indianred: '#cd5c5c',
  indigo: '#4b0082',
  ivory: '#fffff0',
  khaki: '#f0e68c',
  lavender: '#e6e6fa',
  lavenderblush: '#fff0f5',
  lawngreen: '#7cfc00',
  lemonchiffon: '#fffacd',
  lightblue: '#add8e6',
  lightcoral: '#f08080',
  lightcyan: '#e0ffff',
  lightgoldenrodyellow: '#fafad2',
  lightgray: '#d3d3d3',
  lightgreen: '#90ee90',
  lightgrey: '#d3d3d3',
  lightpink: '#ffb6c1',
  lightsalmon: '#ffa07a',
  lightseagreen: '#20b2aa',
  lightskyblue: '#87cefa',
  lightslategray: '#778899',
  lightslategrey: '#778899',
  lightsteelblue: '#b0c4de',
  lightyellow: '#ffffe0',
  lime: '#0f0',
  limegreen: '#32cd32',
  linen: '#faf0e6',
  magenta: '#ff00ff',
  maroon: '#800000',
  mediumaquamarine: '#66cdaa',
  mediumblue: '#0000cd',
  mediumorchid: '#ba55d3',
  mediumpurple: '#9370db',
  mediumseagreen: '#3cb371',
  mediumslateblue: '#7b68ee',
  mediumspringgreen: '#00fa9a',
  mediumturquoise: '#48d1cc',
  mediumvioletred: '#c71585',
  midnightblue: '#191970',
  mintcream: '#f5fffa',
  mistyrose: '#ffe4e1',
  moccasin: '#ffe4b5',
  navajowhite: '#ffdead',
  navy: '#000080',
  oldlace: '#fdf5e6',
  olive: '#808000',
  olivedrab: '#6b8e23',
  orange: '#ffa500',
  orangered: '#ff4500',
  orchid: '#da70d6',
  palegoldenrod: '#eee8aa',
  palegreen: '#98fb98',
  paleturquoise: '#afeeee',
  palevioletred: '#db7093',
  papayawhip: '#ffefd5',
  peachpuff: '#ffdab9',
  peru: '#cd853f',
  pink: '#ffc0cb',
  plum: '#dda0dd',
  powderblue: '#b0e0e6',
  purple: '#800080',
  rebeccapurple: '#663399',
  red: '#f00',
  rosybrown: '#bc8f8f',
  royalblue: '#4169e1',
  saddlebrown: '#8b4513',
  salmon: '#fa8072',
  sandybrown: '#f4a460',
  seagreen: '#2e8b57',
  seashell: '#fff5ee',
  sienna: '#a0522d',
  silver: '#c0c0c0',
  skyblue: '#87ceeb',
  slateblue: '#6a5acd',
  slategray: '#708090',
  slategrey: '#708090',
  snow: '#fffafa',
  springgreen: '#00ff7f',
  steelblue: '#4682b4',
  tan: '#d2b48c',
  teal: '#008080',
  thistle: '#d8bfd8',
  tomato: '#ff6347',
  turquoise: '#40e0d0',
  violet: '#ee82ee',
  wheat: '#f5deb3',
  white: '#fff',
  whitesmoke: '#f5f5f5',
  yellow: '#ff0',
  yellowgreen: '#9acd32'
};

var toHex = {};
var toName = {};

for (var name in COLORS) {
  var hex = COLORS[name];

  if (name.length < hex.length) {
    toName[hex] = name;
  } else {
    toHex[name] = hex;
  }
}

var toHexPattern = new RegExp('(^| |,|\\))(' + Object.keys(toHex).join('|') + ')( |,|\\)|$)', 'ig');
var toNamePattern = new RegExp('(' + Object.keys(toName).join('|') + ')([^a-f0-9]|$)', 'ig');

function hexConverter(match, prefix, colorValue, suffix) {
  return prefix + toHex[colorValue.toLowerCase()] + suffix;
}

function nameConverter(match, colorValue, suffix) {
  return toName[colorValue.toLowerCase()] + suffix;
}

function shortenHex$1(value) {
  var hasHex = value.indexOf('#') > -1;
  var shortened = value.replace(toHexPattern, hexConverter);

  if (shortened != value) {
    shortened = shortened.replace(toHexPattern, hexConverter);
  }

  return hasHex ?
    shortened.replace(toNamePattern, nameConverter) :
    shortened;
}

var shortenHex_1 = shortenHex$1;

// HSL to RGB converter. Both methods adapted from:
// http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript

function hslToRgb(h, s, l) {
  var r, g, b;

  // normalize hue orientation b/w 0 and 360 degrees
  h = h % 360;
  if (h < 0)
    h += 360;
  h = ~~h / 360;

  if (s < 0)
    s = 0;
  else if (s > 100)
    s = 100;
  s = ~~s / 100;

  if (l < 0)
    l = 0;
  else if (l > 100)
    l = 100;
  l = ~~l / 100;

  if (s === 0) {
    r = g = b = l; // achromatic
  } else {
    var q = l < 0.5 ?
      l * (1 + s) :
      l + s - l * s;
    var p = 2 * l - q;
    r = hueToRgb(p, q, h + 1/3);
    g = hueToRgb(p, q, h);
    b = hueToRgb(p, q, h - 1/3);
  }

  return [~~(r * 255), ~~(g * 255), ~~(b * 255)];
}

function hueToRgb(p, q, t) {
  if (t < 0) t += 1;
  if (t > 1) t -= 1;
  if (t < 1/6) return p + (q - p) * 6 * t;
  if (t < 1/2) return q;
  if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
  return p;
}

function shortenHsl$1(hue, saturation, lightness) {
  var asRgb = hslToRgb(hue, saturation, lightness);
  var redAsHex = asRgb[0].toString(16);
  var greenAsHex = asRgb[1].toString(16);
  var blueAsHex = asRgb[2].toString(16);

  return '#' +
    ((redAsHex.length == 1 ? '0' : '') + redAsHex) +
    ((greenAsHex.length == 1 ? '0' : '') + greenAsHex) +
    ((blueAsHex.length == 1 ? '0' : '') + blueAsHex);
}

var shortenHsl_1 = shortenHsl$1;

function shortenRgb$1(red, green, blue) {
  var normalizedRed = Math.max(0, Math.min(parseInt(red), 255));
  var normalizedGreen = Math.max(0, Math.min(parseInt(green), 255));
  var normalizedBlue = Math.max(0, Math.min(parseInt(blue), 255));

  // Credit: Asen  http://jsbin.com/UPUmaGOc/2/edit?js,console
  return '#' + ('00000' + (normalizedRed << 16 | normalizedGreen << 8 | normalizedBlue).toString(16)).slice(-6);
}

var shortenRgb_1 = shortenRgb$1;

var Marker$a = marker;

function is(value, separator, isSeparatorRegex) {
  return isSeparatorRegex ?
    separator.test(value) :
    value === separator;
}

function split$4(value, separator) {
  var openLevel = Marker$a.OPEN_ROUND_BRACKET;
  var closeLevel = Marker$a.CLOSE_ROUND_BRACKET;
  var level = 0;
  var cursor = 0;
  var lastStart = 0;
  var lastValue;
  var lastCharacter;
  var len = value.length;
  var parts = [];
  var isSeparatorRegex = typeof(separator) == 'object' && 'exec' in separator;

  if (!isSeparatorRegex && value.indexOf(separator) == -1) {
    return [value];
  }

  if (value.indexOf(openLevel) == -1) {
    return value.split(separator);
  }

  while (cursor < len) {
    if (value[cursor] == openLevel) {
      level++;
    } else if (value[cursor] == closeLevel) {
      level--;
    }

    if (level === 0 && cursor > 0 && cursor + 1 < len && is(value[cursor], separator, isSeparatorRegex)) {
      parts.push(value.substring(lastStart, cursor));

      if (isSeparatorRegex && separator.exec(value[cursor]).length > 1) {
        parts.push(value[cursor]);
      }

      lastStart = cursor + 1;
    }

    cursor++;
  }

  if (lastStart < cursor + 1) {
    lastValue = value.substring(lastStart);
    lastCharacter = lastValue[lastValue.length - 1];
    if (is(lastCharacter, separator, isSeparatorRegex)) {
      lastValue = lastValue.substring(0, lastValue.length - 1);
    }

    parts.push(lastValue);
  }

  return parts;
}

var split_1 = split$4;

var shortenHex = shortenHex_1;
var shortenHsl = shortenHsl_1;
var shortenRgb = shortenRgb_1;

var split$3 = split_1;

var ANY_COLOR_FUNCTION_PATTERN = /(rgb|rgba|hsl|hsla)\(([^\(\)]+)\)/gi;
var COLOR_PREFIX_PATTERN = /#|rgb|hsl/gi;
var HEX_LONG_PATTERN = /(^|[^='"])#([0-9a-f]{6})/gi;
var HEX_SHORT_PATTERN = /(^|[^='"])#([0-9a-f]{3})/gi;
var HEX_VALUE_PATTERN = /[0-9a-f]/i;
var HSL_PATTERN = /hsl\((-?\d+),(-?\d+)%?,(-?\d+)%?\)/gi;
var RGBA_HSLA_PATTERN = /(rgb|hsl)a?\((\-?\d+),(\-?\d+\%?),(\-?\d+\%?),(0*[1-9]+[0-9]*(\.?\d*)?)\)/gi;
var RGB_PATTERN = /rgb\((\-?\d+),(\-?\d+),(\-?\d+)\)/gi;
var TRANSPARENT_FUNCTION_PATTERN = /(?:rgba|hsla)\(0,0%?,0%?,0\)/g;

var plugin$b = {
  level1: {
    value: function color(name, value, options) {
      if (!options.compatibility.properties.colors) {
        return value;
      }

      if (!value.match(COLOR_PREFIX_PATTERN)) {
        return shortenHex(value);
      }

      value = value
        .replace(RGBA_HSLA_PATTERN, function (match, colorFn, p1, p2, p3, alpha) {
          return (parseInt(alpha, 10) >= 1 ? colorFn + '(' + [p1,p2,p3].join(',') + ')' : match);
        })
        .replace(RGB_PATTERN, function (match, red, green, blue) {
          return shortenRgb(red, green, blue);
        })
        .replace(HSL_PATTERN, function (match, hue, saturation, lightness) {
          return shortenHsl(hue, saturation, lightness);
        })
        .replace(HEX_LONG_PATTERN, function (match, prefix, color, at, inputValue) {
          var suffix = inputValue[at + match.length];

          if (suffix && HEX_VALUE_PATTERN.test(suffix)) {
            return match;
          } else if (color[0] == color[1] && color[2] == color[3] && color[4] == color[5]) {
            return (prefix + '#' + color[0] + color[2] + color[4]).toLowerCase();
          } else {
            return (prefix + '#' + color).toLowerCase();
          }
        })
        .replace(HEX_SHORT_PATTERN, function (match, prefix, color) {
          return prefix + '#' + color.toLowerCase();
        })
        .replace(ANY_COLOR_FUNCTION_PATTERN, function (match, colorFunction, colorDef) {
          var tokens = colorDef.split(',');
          var colorFnLowercase = colorFunction && colorFunction.toLowerCase();
          var applies = (colorFnLowercase == 'hsl' && tokens.length == 3) ||
            (colorFnLowercase == 'hsla' && tokens.length == 4) ||
            (colorFnLowercase == 'rgb' && tokens.length === 3 && colorDef.indexOf('%') > 0) ||
            (colorFnLowercase == 'rgba' && tokens.length == 4 && colorDef.indexOf('%') > 0);

          if (!applies) {
            return match;
          }

          if (tokens[1].indexOf('%') == -1) {
            tokens[1] += '%';
          }

          if (tokens[2].indexOf('%') == -1) {
            tokens[2] += '%';
          }

          return colorFunction + '(' + tokens.join(',') + ')';
        });

      if (options.compatibility.colors.opacity && name.indexOf('background') == -1) {
        value = value.replace(TRANSPARENT_FUNCTION_PATTERN, function (match) {
          if (split$3(value, ',').pop().indexOf('gradient(') > -1) {
            return match;
          }

          return 'transparent';
        });
      }

      return shortenHex(value);
    }
  }
};

var color = plugin$b;

var ZERO_DEG_PATTERN = /\(0deg\)/g;

var plugin$a = {
  level1: {
    value: function degrees(_name, value, options) {
      if (!options.compatibility.properties.zeroUnits) {
        return value;
      }

      if (value.indexOf('0deg') == -1) {
        return value;
      }

      return value.replace(ZERO_DEG_PATTERN, '(0)');
    }
  }
};

var degrees = plugin$a;

var URL_PREFIX_PATTERN$4 = /^url\(/i;

function startsAsUrl$4(value) {
  return URL_PREFIX_PATTERN$4.test(value);
}

var startsAsUrl_1 = startsAsUrl$4;

var startsAsUrl$3 = startsAsUrl_1;

var OptimizationLevel$b = optimizationLevel.OptimizationLevel;

var DOT_ZERO_PATTERN = /(^|\D)\.0+(\D|$)/g;
var FRACTION_PATTERN = /\.([1-9]*)0+(\D|$)/g;
var LEADING_ZERO_FRACTION_PATTERN = /(^|\D)0\.(\d)/g;
var MINUS_ZERO_FRACTION_PATTERN = /([^\w\d\-]|^)\-0([^\.]|$)/g;
var ZERO_PREFIXED_UNIT_PATTERN = /(^|\s)0+([1-9])/g;

var plugin$9 = {
  level1: {
    value: function fraction(name, value, options) {
      if (!options.level[OptimizationLevel$b.One].replaceZeroUnits) {
        return value;
      }

      if (startsAsUrl$3(value)) {
        return value;
      }

      if (value.indexOf('0') == -1) {
        return value;
      }

      if (value.indexOf('-') > -1) {
        value = value
          .replace(MINUS_ZERO_FRACTION_PATTERN, '$10$2')
          .replace(MINUS_ZERO_FRACTION_PATTERN, '$10$2');
      }

      return value
        .replace(ZERO_PREFIXED_UNIT_PATTERN, '$1$2')
        .replace(DOT_ZERO_PATTERN, '$10$2')
        .replace(FRACTION_PATTERN, function (match, nonZeroPart, suffix) {
          return (nonZeroPart.length > 0 ? '.' : '') + nonZeroPart + suffix;
        })
        .replace(LEADING_ZERO_FRACTION_PATTERN, '$1.$2');
    }
  }
};

var fraction = plugin$9;

var plugin$8 = {
  level1: {
    value: function precision(_name, value, options) {
      if (!options.precision.enabled || value.indexOf('.') === -1) {
        return value;
      }

      return value
        .replace(options.precision.decimalPointMatcher, '$1$2$3')
        .replace(options.precision.zeroMatcher, function (match, integerPart, fractionPart, unit) {
          var multiplier = options.precision.units[unit].multiplier;
          var parsedInteger = parseInt(integerPart);
          var integer = isNaN(parsedInteger) ? 0 : parsedInteger;
          var fraction = parseFloat(fractionPart);

          return Math.round((integer + fraction) * multiplier) / multiplier + unit;
        });
    }
  }
};

var precision = plugin$8;

var OptimizationLevel$a = optimizationLevel.OptimizationLevel;

var LOCAL_PREFIX_PATTERN = /^local\(/i;
var QUOTED_PATTERN = /^('.*'|".*")$/;
var QUOTED_BUT_SAFE_PATTERN = /^['"][a-zA-Z][a-zA-Z\d\-_]+['"]$/;

var plugin$7 = {
  level1: {
    value: function textQuotes(_name, value, options) {
      if (!options.level[OptimizationLevel$a.One].removeQuotes) {
        return value;
      }

      if (!QUOTED_PATTERN.test(value) && !LOCAL_PREFIX_PATTERN.test(value)) {
        return value;
      }

      return QUOTED_BUT_SAFE_PATTERN.test(value) ?
        value.substring(1, value.length - 1) :
        value;
    }
  }
};

var textQuotes = plugin$7;

var OptimizationLevel$9 = optimizationLevel.OptimizationLevel;

var TIME_VALUE = /^(\-?[\d\.]+)(m?s)$/;

var plugin$6 = {
  level1: {
    value: function time(name, value, options) {
      if (!options.level[OptimizationLevel$9.One].replaceTimeUnits) {
        return value;
      }

      if (!TIME_VALUE.test(value)) {
        return value;
      }

      return value.replace(TIME_VALUE, function (match, val, unit) {
        var newValue;

        if (unit == 'ms') {
          newValue = parseInt(val) / 1000 + 's';
        } else if (unit == 's') {
          newValue = parseFloat(val) * 1000 + 'ms';
        }

        return newValue.length < match.length ? newValue : match;
      });
    }
  }
};

var time = plugin$6;

var WHOLE_PIXEL_VALUE = /(?:^|\s|\()(-?\d+)px/;

var plugin$5 = {
  level1: {
    value: function unit(_name, value, options) {
      if (!WHOLE_PIXEL_VALUE.test(value)) {
        return value;
      }

      return value.replace(WHOLE_PIXEL_VALUE, function (match, val) {
        var newValue;
        var intVal = parseInt(val);

        if (intVal === 0) {
          return match;
        }

        if (options.compatibility.properties.shorterLengthUnits && options.compatibility.units.pt && intVal * 3 % 4 === 0) {
          newValue = intVal * 3 / 4 + 'pt';
        }

        if (options.compatibility.properties.shorterLengthUnits && options.compatibility.units.pc && intVal % 16 === 0) {
          newValue = intVal / 16 + 'pc';
        }

        if (options.compatibility.properties.shorterLengthUnits && options.compatibility.units.in && intVal % 96 === 0) {
          newValue = intVal / 96 + 'in';
        }

        if (newValue) {
          newValue = match.substring(0, match.indexOf(val)) + newValue;
        }

        return newValue && newValue.length < match.length ? newValue : match;
      });
    }
  }
};

var unit = plugin$5;

var startsAsUrl$2 = startsAsUrl_1;

var OptimizationLevel$8 = optimizationLevel.OptimizationLevel;

var URL_PREFIX_PATTERN$3 = /^url\(/i;

var plugin$4 = {
  level1: {
    value: function urlPrefix(_name, value, options) {
      if (!options.level[OptimizationLevel$8.One].normalizeUrls) {
        return value;
      }

      if (!startsAsUrl$2(value)) {
        return value;
      }

      return value.replace(URL_PREFIX_PATTERN$3, 'url(');
    }
  }
};

var urlPrefix = plugin$4;

var QUOTED_URL_PATTERN = /^url\(['"].+['"]\)$/;
var QUOTED_URL_WITH_WHITESPACE_PATTERN = /^url\(['"].*[\*\s\(\)'"].*['"]\)$/;
var QUOTES_PATTERN = /["']/g;
var URL_DATA_PATTERN = /^url\(['"]data:[^;]+;charset/;

var plugin$3 = {
  level1: {
    value: function urlQuotes(_name, value, options) {
      if (options.compatibility.properties.urlQuotes) {
        return value;
      }

      return QUOTED_URL_PATTERN.test(value) && !QUOTED_URL_WITH_WHITESPACE_PATTERN.test(value) && !URL_DATA_PATTERN.test(value) ?
        value.replace(QUOTES_PATTERN, '') :
        value;
    }
  }
};

var urlQuotes = plugin$3;

var startsAsUrl$1 = startsAsUrl_1;

var WHITESPACE_PATTERN$1 = /\\?\n|\\?\r\n/g;
var WHITESPACE_PREFIX_PATTERN = /(\()\s+/g;
var WHITESPACE_SUFFIX_PATTERN = /\s+(\))/g;

var plugin$2 = {
  level1: {
    value: function urlWhitespace(_name, value) {
      if (!startsAsUrl$1(value)) {
        return value;
      }

      return value
        .replace(WHITESPACE_PATTERN$1, '')
        .replace(WHITESPACE_PREFIX_PATTERN, '$1')
        .replace(WHITESPACE_SUFFIX_PATTERN, '$1');
    }
  }
};

var urlWhitespace = plugin$2;

var OptimizationLevel$7 = optimizationLevel.OptimizationLevel;

var Marker$9 = marker;

var CALC_DIVISION_WHITESPACE_PATTERN = /\) ?\/ ?/g;
var COMMA_AND_SPACE_PATTERN = /, /g;
var MULTI_WHITESPACE_PATTERN = /\s+/g;
var FUNCTION_CLOSING_BRACE_WHITESPACE_PATTERN = /\s+(;?\))/g;
var FUNCTION_OPENING_BRACE_WHITESPACE_PATTERN = /(\(;?)\s+/g;

var plugin$1 = {
  level1: {
    value: function whitespace(name, value, options) {
      if (!options.level[OptimizationLevel$7.One].removeWhitespace) {
        return value;
      }

      if (value.indexOf(' ') == -1 || value.indexOf('expression') === 0) {
        return value;
      }

      if (value.indexOf(Marker$9.SINGLE_QUOTE) > -1 || value.indexOf(Marker$9.DOUBLE_QUOTE) > -1) {
        return value;
      }

      value = value.replace(MULTI_WHITESPACE_PATTERN, ' ');

      if (value.indexOf('calc') > -1) {
        value = value.replace(CALC_DIVISION_WHITESPACE_PATTERN, ')/ ');
      }

      return value
        .replace(FUNCTION_OPENING_BRACE_WHITESPACE_PATTERN, '$1')
        .replace(FUNCTION_CLOSING_BRACE_WHITESPACE_PATTERN, '$1')
        .replace(COMMA_AND_SPACE_PATTERN, ',');
    }
  }
};

var whitespace = plugin$1;

var split$2 = split_1;

var ANY_FUNCTION_PATTERN = /^(\-(?:moz|ms|o|webkit)\-[a-z\-]+|[a-z\-]+)\((.+)\)$/;
var SKIP_FUNCTION_PATTERN = /^(?:\-moz\-calc|\-webkit\-calc|calc|rgb|hsl|rgba|hsla|min|max|clamp|expression)\(/;
var TOKEN_SEPARATOR_PATTERN = /([\s,\/])/;

function removeRecursively(value, options) {
  var functionTokens;
  var tokens;

  if (SKIP_FUNCTION_PATTERN.test(value)) {
    return value;
  }

  functionTokens = ANY_FUNCTION_PATTERN.exec(value);

  if (!functionTokens) {
    return removeZeros(value, options);
  }

  tokens = split$2(functionTokens[2], TOKEN_SEPARATOR_PATTERN)
    .map(function (token) { return removeRecursively(token, options); });

  return functionTokens[1] + '(' + tokens.join('') + ')';
}

function removeZeros(value, options) {
  return value
    .replace(options.unitsRegexp, '$1' + '0' + '$2')
    .replace(options.unitsRegexp, '$1' + '0' + '$2');
}

var plugin = {
  level1: {
    value: function zero(name, value, options) {
      if (!options.compatibility.properties.zeroUnits) {
        return value;
      }

      if (value.indexOf('%') > 0 && (name == 'height' || name == 'max-height' || name == 'width' || name == 'max-width')) {
        return value;
      }

      return removeRecursively(value, options);
    }
  }
};

var zero = plugin;

var valueOptimizers$1 = {
  color: color.level1.value,
  degrees: degrees.level1.value,
  fraction: fraction.level1.value,
  precision: precision.level1.value,
  textQuotes: textQuotes.level1.value,
  time: time.level1.value,
  unit: unit.level1.value,
  urlPrefix: urlPrefix.level1.value,
  urlQuotes: urlQuotes.level1.value,
  urlWhiteSpace: urlWhitespace.level1.value,
  whiteSpace: whitespace.level1.value,
  zero: zero.level1.value
};

// Contains the interpretation of CSS properties, as used by the property optimizer

var breakUp = breakUp$1;
var canOverride = canOverride$1;
var restore = restore$1;

var propertyOptimizers = propertyOptimizers$1;
var valueOptimizers = valueOptimizers$1;

var override$3 = override_1;

// Properties to process
// Extend this object in order to add support for more properties in the optimizer.
//
// Each key in this object represents a CSS property and should be an object.
// Such an object contains properties that describe how the represented CSS property should be handled.
// Possible options:
//
// * components: array (Only specify for shorthand properties.)
//   Contains the names of the granular properties this shorthand compacts.
//
// * canOverride: function
//   Returns whether two tokens of this property can be merged with each other.
//   This property has no meaning for shorthands.
//
// * defaultValue: string
//   Specifies the default value of the property according to the CSS standard.
//   For shorthand, this is used when every component is set to its default value, therefore it should be the shortest possible default value of all the components.
//
// * shortestValue: string
//   Specifies the shortest possible value the property can possibly have.
//   (Falls back to defaultValue if unspecified.)
//
// * breakUp: function (Only specify for shorthand properties.)
//   Breaks the shorthand up to its components.
//
// * restore: function (Only specify for shorthand properties.)
//   Puts the shorthand together from its components.
//
var configuration$8 = {
  'animation': {
    canOverride: canOverride.generic.components([
      canOverride.generic.time,
      canOverride.generic.timingFunction,
      canOverride.generic.time,
      canOverride.property.animationIterationCount,
      canOverride.property.animationDirection,
      canOverride.property.animationFillMode,
      canOverride.property.animationPlayState,
      canOverride.property.animationName
    ]),
    components: [
      'animation-duration',
      'animation-timing-function',
      'animation-delay',
      'animation-iteration-count',
      'animation-direction',
      'animation-fill-mode',
      'animation-play-state',
      'animation-name'
    ],
    breakUp: breakUp.multiplex(breakUp.animation),
    defaultValue: 'none',
    restore: restore.multiplex(restore.withoutDefaults),
    shorthand: true,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.textQuotes,
      valueOptimizers.time,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ],
    vendorPrefixes: [
      '-moz-',
      '-o-',
      '-webkit-'
    ]
  },
  'animation-delay': {
    canOverride: canOverride.generic.time,
    componentOf: [
      'animation'
    ],
    defaultValue: '0s',
    intoMultiplexMode: 'real',
    valueOptimizers: [
      valueOptimizers.time,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ],
    vendorPrefixes: [
      '-moz-',
      '-o-',
      '-webkit-'
    ]
  },
  'animation-direction': {
    canOverride: canOverride.property.animationDirection,
    componentOf: [
      'animation'
    ],
    defaultValue: 'normal',
    intoMultiplexMode: 'real',
    vendorPrefixes: [
      '-moz-',
      '-o-',
      '-webkit-'
    ]
  },
  'animation-duration': {
    canOverride: canOverride.generic.time,
    componentOf: [
      'animation'
    ],
    defaultValue: '0s',
    intoMultiplexMode: 'real',
    keepUnlessDefault: 'animation-delay',
    valueOptimizers: [
      valueOptimizers.time,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ],
    vendorPrefixes: [
      '-moz-',
      '-o-',
      '-webkit-'
    ]
  },
  'animation-fill-mode': {
    canOverride: canOverride.property.animationFillMode,
    componentOf: [
      'animation'
    ],
    defaultValue: 'none',
    intoMultiplexMode: 'real',
    vendorPrefixes: [
      '-moz-',
      '-o-',
      '-webkit-'
    ]
  },
  'animation-iteration-count': {
    canOverride: canOverride.property.animationIterationCount,
    componentOf: [
      'animation'
    ],
    defaultValue: '1',
    intoMultiplexMode: 'real',
    vendorPrefixes: [
      '-moz-',
      '-o-',
      '-webkit-'
    ]
  },
  'animation-name': {
    canOverride: canOverride.property.animationName,
    componentOf: [
      'animation'
    ],
    defaultValue: 'none',
    intoMultiplexMode: 'real',
    valueOptimizers: [
      valueOptimizers.textQuotes
    ],
    vendorPrefixes: [
      '-moz-',
      '-o-',
      '-webkit-'
    ]
  },
  'animation-play-state': {
    canOverride: canOverride.property.animationPlayState,
    componentOf: [
      'animation'
    ],
    defaultValue: 'running',
    intoMultiplexMode: 'real',
    vendorPrefixes: [
      '-moz-',
      '-o-',
      '-webkit-'
    ]
  },
  'animation-timing-function': {
    canOverride: canOverride.generic.timingFunction,
    componentOf: [
      'animation'
    ],
    defaultValue: 'ease',
    intoMultiplexMode: 'real',
    vendorPrefixes: [
      '-moz-',
      '-o-',
      '-webkit-'
    ]
  },
  'background': {
    canOverride: canOverride.generic.components([
      canOverride.generic.image,
      canOverride.property.backgroundPosition,
      canOverride.property.backgroundSize,
      canOverride.property.backgroundRepeat,
      canOverride.property.backgroundAttachment,
      canOverride.property.backgroundOrigin,
      canOverride.property.backgroundClip,
      canOverride.generic.color
    ]),
    components: [
      'background-image',
      'background-position',
      'background-size',
      'background-repeat',
      'background-attachment',
      'background-origin',
      'background-clip',
      'background-color'
    ],
    breakUp: breakUp.multiplex(breakUp.background),
    defaultValue: '0 0',
    propertyOptimizer: propertyOptimizers.background,
    restore: restore.multiplex(restore.background),
    shortestValue: '0',
    shorthand: true,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.urlWhiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.zero,
      valueOptimizers.color,
      valueOptimizers.urlPrefix,
      valueOptimizers.urlQuotes
    ]
  },
  'background-attachment': {
    canOverride: canOverride.property.backgroundAttachment,
    componentOf: [
      'background'
    ],
    defaultValue: 'scroll',
    intoMultiplexMode: 'real'
  },
  'background-clip': {
    canOverride: canOverride.property.backgroundClip,
    componentOf: [
      'background'
    ],
    defaultValue: 'border-box',
    intoMultiplexMode: 'real',
    shortestValue: 'border-box'
  },
  'background-color': {
    canOverride: canOverride.generic.color,
    componentOf: [
      'background'
    ],
    defaultValue: 'transparent',
    intoMultiplexMode: 'real', // otherwise real color will turn into default since color appears in last multiplex only
    multiplexLastOnly: true,
    nonMergeableValue: 'none',
    shortestValue: 'red',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.color
    ]
  },
  'background-image': {
    canOverride: canOverride.generic.image,
    componentOf: [
      'background'
    ],
    defaultValue: 'none',
    intoMultiplexMode: 'default',
    valueOptimizers: [
      valueOptimizers.urlWhiteSpace,
      valueOptimizers.urlPrefix,
      valueOptimizers.urlQuotes,
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero,
      valueOptimizers.color
    ]
  },
  'background-origin': {
    canOverride: canOverride.property.backgroundOrigin,
    componentOf: [
      'background'
    ],
    defaultValue: 'padding-box',
    intoMultiplexMode: 'real',
    shortestValue: 'border-box'
  },
  'background-position': {
    canOverride: canOverride.property.backgroundPosition,
    componentOf: [
      'background'
    ],
    defaultValue: ['0', '0'],
    doubleValues: true,
    intoMultiplexMode: 'real',
    shortestValue: '0',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'background-repeat': {
    canOverride: canOverride.property.backgroundRepeat,
    componentOf: [
      'background'
    ],
    defaultValue: ['repeat'],
    doubleValues: true,
    intoMultiplexMode: 'real'
  },
  'background-size': {
    canOverride: canOverride.property.backgroundSize,
    componentOf: [
      'background'
    ],
    defaultValue: ['auto'],
    doubleValues: true,
    intoMultiplexMode: 'real',
    shortestValue: '0 0',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'bottom': {
    canOverride: canOverride.property.bottom,
    defaultValue: 'auto',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'border': {
    breakUp: breakUp.border,
    canOverride: canOverride.generic.components([
      canOverride.generic.unit,
      canOverride.property.borderStyle,
      canOverride.generic.color
    ]),
    components: [
      'border-width',
      'border-style',
      'border-color'
    ],
    defaultValue: 'none',
    overridesShorthands: [
      'border-bottom',
      'border-left',
      'border-right',
      'border-top'
    ],
    restore: restore.withoutDefaults,
    shorthand: true,
    shorthandComponents: true,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.zero,
      valueOptimizers.color
    ]
  },
  'border-bottom': {
    breakUp: breakUp.border,
    canOverride: canOverride.generic.components([
      canOverride.generic.unit,
      canOverride.property.borderStyle,
      canOverride.generic.color
    ]),
    components: [
      'border-bottom-width',
      'border-bottom-style',
      'border-bottom-color'
    ],
    defaultValue: 'none',
    restore: restore.withoutDefaults,
    shorthand: true,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.zero,
      valueOptimizers.color
    ]
  },
  'border-bottom-color': {
    canOverride: canOverride.generic.color,
    componentOf: [
      'border-bottom',
      'border-color'
    ],
    defaultValue: 'none',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.color
    ]
  },
  'border-bottom-left-radius': {
    canOverride: canOverride.generic.unit,
    componentOf: [
      'border-radius'
    ],
    defaultValue: '0',
    propertyOptimizer: propertyOptimizers.borderRadius,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ],
    vendorPrefixes: [
      '-moz-',
      '-o-'
    ]
  },
  'border-bottom-right-radius': {
    canOverride: canOverride.generic.unit,
    componentOf: [
      'border-radius'
    ],
    defaultValue: '0',
    propertyOptimizer: propertyOptimizers.borderRadius,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ],
    vendorPrefixes: [
      '-moz-',
      '-o-'
    ]
  },
  'border-bottom-style': {
    canOverride: canOverride.property.borderStyle,
    componentOf: [
      'border-bottom',
      'border-style'
    ],
    defaultValue: 'none'
  },
  'border-bottom-width': {
    canOverride: canOverride.generic.unit,
    componentOf: [
      'border-bottom',
      'border-width'
    ],
    defaultValue: 'medium',
    oppositeTo: 'border-top-width',
    shortestValue: '0',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'border-collapse': {
    canOverride: canOverride.property.borderCollapse,
    defaultValue: 'separate'
  },
  'border-color': {
    breakUp: breakUp.fourValues,
    canOverride: canOverride.generic.components([
      canOverride.generic.color,
      canOverride.generic.color,
      canOverride.generic.color,
      canOverride.generic.color
    ]),
    componentOf: [
      'border'
    ],
    components: [
      'border-top-color',
      'border-right-color',
      'border-bottom-color',
      'border-left-color'
    ],
    defaultValue: 'none',
    restore: restore.fourValues,
    shortestValue: 'red',
    shorthand: true,
    singleTypeComponents: true,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.color
    ]
  },
  'border-left': {
    breakUp: breakUp.border,
    canOverride: canOverride.generic.components([
      canOverride.generic.unit,
      canOverride.property.borderStyle,
      canOverride.generic.color
    ]),
    components: [
      'border-left-width',
      'border-left-style',
      'border-left-color'
    ],
    defaultValue: 'none',
    restore: restore.withoutDefaults,
    shorthand: true,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.zero,
      valueOptimizers.color
    ]
  },
  'border-left-color': {
    canOverride: canOverride.generic.color,
    componentOf: [
      'border-color',
      'border-left'
    ],
    defaultValue: 'none',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.color
    ]
  },
  'border-left-style': {
    canOverride: canOverride.property.borderStyle,
    componentOf: [
      'border-left',
      'border-style'
    ],
    defaultValue: 'none'
  },
  'border-left-width': {
    canOverride: canOverride.generic.unit,
    componentOf: [
      'border-left',
      'border-width'
    ],
    defaultValue: 'medium',
    oppositeTo: 'border-right-width',
    shortestValue: '0',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'border-radius': {
    breakUp: breakUp.borderRadius,
    canOverride: canOverride.generic.components([
      canOverride.generic.unit,
      canOverride.generic.unit,
      canOverride.generic.unit,
      canOverride.generic.unit
    ]),
    components: [
      'border-top-left-radius',
      'border-top-right-radius',
      'border-bottom-right-radius',
      'border-bottom-left-radius'
    ],
    defaultValue: '0',
    propertyOptimizer: propertyOptimizers.borderRadius,
    restore: restore.borderRadius,
    shorthand: true,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ],
    vendorPrefixes: [
      '-moz-',
      '-o-'
    ]
  },
  'border-right': {
    breakUp: breakUp.border,
    canOverride: canOverride.generic.components([
      canOverride.generic.unit,
      canOverride.property.borderStyle,
      canOverride.generic.color
    ]),
    components: [
      'border-right-width',
      'border-right-style',
      'border-right-color'
    ],
    defaultValue: 'none',
    restore: restore.withoutDefaults,
    shorthand: true,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.color
    ]
  },
  'border-right-color': {
    canOverride: canOverride.generic.color,
    componentOf: [
      'border-color',
      'border-right'
    ],
    defaultValue: 'none',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.color
    ]
  },
  'border-right-style': {
    canOverride: canOverride.property.borderStyle,
    componentOf: [
      'border-right',
      'border-style'
    ],
    defaultValue: 'none'
  },
  'border-right-width': {
    canOverride: canOverride.generic.unit,
    componentOf: [
      'border-right',
      'border-width'
    ],
    defaultValue: 'medium',
    oppositeTo: 'border-left-width',
    shortestValue: '0',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'border-style': {
    breakUp: breakUp.fourValues,
    canOverride: canOverride.generic.components([
      canOverride.property.borderStyle,
      canOverride.property.borderStyle,
      canOverride.property.borderStyle,
      canOverride.property.borderStyle
    ]),
    componentOf: [
      'border'
    ],
    components: [
      'border-top-style',
      'border-right-style',
      'border-bottom-style',
      'border-left-style'
    ],
    defaultValue: 'none',
    restore: restore.fourValues,
    shorthand: true,
    singleTypeComponents: true
  },
  'border-top': {
    breakUp: breakUp.border,
    canOverride: canOverride.generic.components([
      canOverride.generic.unit,
      canOverride.property.borderStyle,
      canOverride.generic.color
    ]),
    components: [
      'border-top-width',
      'border-top-style',
      'border-top-color'
    ],
    defaultValue: 'none',
    restore: restore.withoutDefaults,
    shorthand: true,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.zero,
      valueOptimizers.color,
      valueOptimizers.unit
    ]
  },
  'border-top-color': {
    canOverride: canOverride.generic.color,
    componentOf: [
      'border-color',
      'border-top'
    ],
    defaultValue: 'none',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.color
    ]
  },
  'border-top-left-radius': {
    canOverride: canOverride.generic.unit,
    componentOf: [
      'border-radius'
    ],
    defaultValue: '0',
    propertyOptimizer: propertyOptimizers.borderRadius,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ],
    vendorPrefixes: [
      '-moz-',
      '-o-'
    ]
  },
  'border-top-right-radius': {
    canOverride: canOverride.generic.unit,
    componentOf: [
      'border-radius'
    ],
    defaultValue: '0',
    propertyOptimizer: propertyOptimizers.borderRadius,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ],
    vendorPrefixes: [
      '-moz-',
      '-o-'
    ]
  },
  'border-top-style': {
    canOverride: canOverride.property.borderStyle,
    componentOf: [
      'border-style',
      'border-top'
    ],
    defaultValue: 'none'
  },
  'border-top-width': {
    canOverride: canOverride.generic.unit,
    componentOf: [
      'border-top',
      'border-width'
    ],
    defaultValue: 'medium',
    oppositeTo: 'border-bottom-width',
    shortestValue: '0',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'border-width': {
    breakUp: breakUp.fourValues,
    canOverride: canOverride.generic.components([
      canOverride.generic.unit,
      canOverride.generic.unit,
      canOverride.generic.unit,
      canOverride.generic.unit
    ]),
    componentOf: [
      'border'
    ],
    components: [
      'border-top-width',
      'border-right-width',
      'border-bottom-width',
      'border-left-width'
    ],
    defaultValue: 'medium',
    restore: restore.fourValues,
    shortestValue: '0',
    shorthand: true,
    singleTypeComponents: true,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'box-shadow': {
    propertyOptimizer: propertyOptimizers.boxShadow,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero,
      valueOptimizers.color
    ],
    vendorPrefixes: [
      '-moz-',
      '-ms-',
      '-o-',
      '-webkit-'
    ]
  },
  'clear': {
    canOverride: canOverride.property.clear,
    defaultValue: 'none'
  },
  'clip': {
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'color': {
    canOverride: canOverride.generic.color,
    defaultValue: 'transparent',
    shortestValue: 'red',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.color
    ]
  },
  'column-gap': {
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'cursor': {
    canOverride: canOverride.property.cursor,
    defaultValue: 'auto'
  },
  'display': {
    canOverride: canOverride.property.display,
  },
  'filter': {
    propertyOptimizer: propertyOptimizers.filter,
    valueOptimizers: [
      valueOptimizers.fraction
    ]
  },
  'float': {
    canOverride: canOverride.property.float,
    defaultValue: 'none'
  },
  'font': {
    breakUp: breakUp.font,
    canOverride: canOverride.generic.components([
      canOverride.property.fontStyle,
      canOverride.property.fontVariant,
      canOverride.property.fontWeight,
      canOverride.property.fontStretch,
      canOverride.generic.unit,
      canOverride.generic.unit,
      canOverride.property.fontFamily
    ]),
    components: [
      'font-style',
      'font-variant',
      'font-weight',
      'font-stretch',
      'font-size',
      'line-height',
      'font-family'
    ],
    restore: restore.font,
    shorthand: true,
    valueOptimizers: [
      valueOptimizers.textQuotes
    ]
  },
  'font-family': {
    canOverride: canOverride.property.fontFamily,
    defaultValue: 'user|agent|specific',
    valueOptimizers: [
      valueOptimizers.textQuotes
    ]
  },
  'font-size': {
    canOverride: canOverride.generic.unit,
    defaultValue: 'medium',
    shortestValue: '0',
    valueOptimizers: [
      valueOptimizers.fraction
    ]
  },
  'font-stretch': {
    canOverride: canOverride.property.fontStretch,
    defaultValue: 'normal'
  },
  'font-style': {
    canOverride: canOverride.property.fontStyle,
    defaultValue: 'normal'
  },
  'font-variant': {
    canOverride: canOverride.property.fontVariant,
    defaultValue: 'normal'
  },
  'font-weight': {
    canOverride: canOverride.property.fontWeight,
    defaultValue: 'normal',
    propertyOptimizer: propertyOptimizers.fontWeight,
    shortestValue: '400'
  },
  'gap': {
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'height': {
    canOverride: canOverride.generic.unit,
    defaultValue: 'auto',
    shortestValue: '0',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'left': {
    canOverride: canOverride.property.left,
    defaultValue: 'auto',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'letter-spacing': {
    valueOptimizers: [
      valueOptimizers.fraction,
      valueOptimizers.zero
    ]
  },
  'line-height': {
    canOverride: canOverride.generic.unitOrNumber,
    defaultValue: 'normal',
    shortestValue: '0',
    valueOptimizers: [
      valueOptimizers.fraction,
      valueOptimizers.zero
    ]
  },
  'list-style': {
    canOverride: canOverride.generic.components([
      canOverride.property.listStyleType,
      canOverride.property.listStylePosition,
      canOverride.property.listStyleImage
    ]),
    components: [
      'list-style-type',
      'list-style-position',
      'list-style-image'
    ],
    breakUp: breakUp.listStyle,
    restore: restore.withoutDefaults,
    defaultValue: 'outside', // can't use 'disc' because that'd override default 'decimal' for <ol>
    shortestValue: 'none',
    shorthand: true
  },
  'list-style-image' : {
    canOverride: canOverride.generic.image,
    componentOf: [
      'list-style'
    ],
    defaultValue: 'none'
  },
  'list-style-position' : {
    canOverride: canOverride.property.listStylePosition,
    componentOf: [
      'list-style'
    ],
    defaultValue: 'outside',
    shortestValue: 'inside'
  },
  'list-style-type' : {
    canOverride: canOverride.property.listStyleType,
    componentOf: [
      'list-style'
    ],
    // NOTE: we can't tell the real default value here, it's 'disc' for <ul> and 'decimal' for <ol>
    // this is a hack, but it doesn't matter because this value will be either overridden or
    // it will disappear at the final step anyway
    defaultValue: 'decimal|disc',
    shortestValue: 'none'
  },
  'margin': {
    breakUp: breakUp.fourValues,
    canOverride: canOverride.generic.components([
      canOverride.generic.unit,
      canOverride.generic.unit,
      canOverride.generic.unit,
      canOverride.generic.unit
    ]),
    components: [
      'margin-top',
      'margin-right',
      'margin-bottom',
      'margin-left'
    ],
    defaultValue: '0',
    propertyOptimizer: propertyOptimizers.margin,
    restore: restore.fourValues,
    shorthand: true,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'margin-bottom': {
    canOverride: canOverride.generic.unit,
    componentOf: [
      'margin'
    ],
    defaultValue: '0',
    oppositeTo: 'margin-top',
    propertyOptimizer: propertyOptimizers.margin,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'margin-inline-end': {
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'margin-inline-start': {
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'margin-left': {
    canOverride: canOverride.generic.unit,
    componentOf: [
      'margin'
    ],
    defaultValue: '0',
    oppositeTo: 'margin-right',
    propertyOptimizer: propertyOptimizers.margin,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'margin-right': {
    canOverride: canOverride.generic.unit,
    componentOf: [
      'margin'
    ],
    defaultValue: '0',
    oppositeTo: 'margin-left',
    propertyOptimizer: propertyOptimizers.margin,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'margin-top': {
    canOverride: canOverride.generic.unit,
    componentOf: [
      'margin'
    ],
    defaultValue: '0',
    oppositeTo: 'margin-bottom',
    propertyOptimizer: propertyOptimizers.margin,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'max-height': {
    canOverride: canOverride.generic.unit,
    defaultValue: 'none',
    shortestValue: '0',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'max-width': {
    canOverride: canOverride.generic.unit,
    defaultValue: 'none',
    shortestValue: '0',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'min-height': {
    canOverride: canOverride.generic.unit,
    defaultValue: '0',
    shortestValue: '0',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'min-width': {
    canOverride: canOverride.generic.unit,
    defaultValue: '0',
    shortestValue: '0',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'opacity': {
    valueOptimizers: [
      valueOptimizers.fraction,
      valueOptimizers.precision
    ]
  },
  'outline': {
    canOverride: canOverride.generic.components([
      canOverride.generic.color,
      canOverride.property.outlineStyle,
      canOverride.generic.unit
    ]),
    components: [
      'outline-color',
      'outline-style',
      'outline-width'
    ],
    breakUp: breakUp.outline,
    restore: restore.withoutDefaults,
    defaultValue: '0',
    propertyOptimizer: propertyOptimizers.outline,
    shorthand: true,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'outline-color': {
    canOverride: canOverride.generic.color,
    componentOf: [
      'outline'
    ],
    defaultValue: 'invert',
    shortestValue: 'red',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.color
    ]
  },
  'outline-style': {
    canOverride: canOverride.property.outlineStyle,
    componentOf: [
      'outline'
    ],
    defaultValue: 'none'
  },
  'outline-width': {
    canOverride: canOverride.generic.unit,
    componentOf: [
      'outline'
    ],
    defaultValue: 'medium',
    shortestValue: '0',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'overflow': {
    canOverride: canOverride.property.overflow,
    defaultValue: 'visible'
  },
  'overflow-x': {
    canOverride: canOverride.property.overflow,
    defaultValue: 'visible'
  },
  'overflow-y': {
    canOverride: canOverride.property.overflow,
    defaultValue: 'visible'
  },
  'padding': {
    breakUp: breakUp.fourValues,
    canOverride: canOverride.generic.components([
      canOverride.generic.unit,
      canOverride.generic.unit,
      canOverride.generic.unit,
      canOverride.generic.unit
    ]),
    components: [
      'padding-top',
      'padding-right',
      'padding-bottom',
      'padding-left'
    ],
    defaultValue: '0',
    propertyOptimizer: propertyOptimizers.padding,
    restore: restore.fourValues,
    shorthand: true,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'padding-bottom': {
    canOverride: canOverride.generic.unit,
    componentOf: [
      'padding'
    ],
    defaultValue: '0',
    oppositeTo: 'padding-top',
    propertyOptimizer: propertyOptimizers.padding,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'padding-left': {
    canOverride: canOverride.generic.unit,
    componentOf: [
      'padding'
    ],
    defaultValue: '0',
    oppositeTo: 'padding-right',
    propertyOptimizer: propertyOptimizers.padding,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'padding-right': {
    canOverride: canOverride.generic.unit,
    componentOf: [
      'padding'
    ],
    defaultValue: '0',
    oppositeTo: 'padding-left',
    propertyOptimizer: propertyOptimizers.padding,
        valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'padding-top': {
    canOverride: canOverride.generic.unit,
    componentOf: [
      'padding'
    ],
    defaultValue: '0',
    oppositeTo: 'padding-bottom',
    propertyOptimizer: propertyOptimizers.padding,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'position': {
    canOverride: canOverride.property.position,
    defaultValue: 'static'
  },
  'right': {
    canOverride: canOverride.property.right,
    defaultValue: 'auto',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'row-gap': {
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'src': {
    valueOptimizers: [
      valueOptimizers.urlWhiteSpace,
      valueOptimizers.urlPrefix,
      valueOptimizers.urlQuotes
    ]
  },
  'stroke-width': {
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'text-align': {
    canOverride: canOverride.property.textAlign,
    // NOTE: we can't tell the real default value here, as it depends on default text direction
    // this is a hack, but it doesn't matter because this value will be either overridden or
    // it will disappear anyway
    defaultValue: 'left|right'
  },
  'text-decoration': {
    canOverride: canOverride.property.textDecoration,
    defaultValue: 'none'
  },
  'text-indent': {
    canOverride: canOverride.property.textOverflow,
    defaultValue: 'none',
    valueOptimizers: [
      valueOptimizers.fraction,
      valueOptimizers.zero
    ]
  },
  'text-overflow': {
    canOverride: canOverride.property.textOverflow,
    defaultValue: 'none'
  },
  'text-shadow': {
    canOverride: canOverride.property.textShadow,
    defaultValue: 'none',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.zero,
      valueOptimizers.color
    ]
  },
  'top': {
    canOverride: canOverride.property.top,
    defaultValue: 'auto',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'transform': {
    canOverride: canOverride.property.transform,
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.degrees,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ],
    vendorPrefixes: [
      '-moz-',
      '-ms-',
      '-o-',
      '-webkit-'
    ]
  },
  'transition': {
    breakUp: breakUp.multiplex(breakUp.transition),
    canOverride: canOverride.generic.components([
      canOverride.property.transitionProperty,
      canOverride.generic.time,
      canOverride.generic.timingFunction,
      canOverride.generic.time
    ]),
    components: [
      'transition-property',
      'transition-duration',
      'transition-timing-function',
      'transition-delay'
    ],
    defaultValue: 'none',
    restore: restore.multiplex(restore.withoutDefaults),
    shorthand: true,
    valueOptimizers: [
      valueOptimizers.time,
      valueOptimizers.fraction
    ],
    vendorPrefixes: [
      '-moz-',
      '-ms-',
      '-o-',
      '-webkit-'
    ]
  },
  'transition-delay': {
    canOverride: canOverride.generic.time,
    componentOf: [
      'transition'
    ],
    defaultValue: '0s',
    intoMultiplexMode: 'real',
    valueOptimizers: [
      valueOptimizers.time
    ],
    vendorPrefixes: [
      '-moz-',
      '-ms-',
      '-o-',
      '-webkit-'
    ]
  },
  'transition-duration': {
    canOverride: canOverride.generic.time,
    componentOf: [
      'transition'
    ],
    defaultValue: '0s',
    intoMultiplexMode: 'real',
    keepUnlessDefault: 'transition-delay',
    valueOptimizers: [
      valueOptimizers.time,
      valueOptimizers.fraction
    ],
    vendorPrefixes: [
      '-moz-',
      '-ms-',
      '-o-',
      '-webkit-'
    ]
  },
  'transition-property': {
    canOverride: canOverride.generic.propertyName,
    componentOf: [
      'transition'
    ],
    defaultValue: 'all',
    intoMultiplexMode: 'placeholder',
    placeholderValue: '_', // it's a short value that won't match any property and still be a valid `transition-property`
    vendorPrefixes: [
      '-moz-',
      '-ms-',
      '-o-',
      '-webkit-'
    ]
  },
  'transition-timing-function': {
    canOverride: canOverride.generic.timingFunction,
    componentOf: [
      'transition'
    ],
    defaultValue: 'ease',
    intoMultiplexMode: 'real',
    vendorPrefixes: [
      '-moz-',
      '-ms-',
      '-o-',
      '-webkit-'
    ]
  },
  'vertical-align': {
    canOverride: canOverride.property.verticalAlign,
    defaultValue: 'baseline',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'visibility': {
    canOverride: canOverride.property.visibility,
    defaultValue: 'visible'
  },
  '-webkit-tap-highlight-color': {
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.color
    ]
  },
  '-webkit-margin-end': {
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'white-space': {
    canOverride: canOverride.property.whiteSpace,
    defaultValue: 'normal'
  },
  'width': {
    canOverride: canOverride.generic.unit,
    defaultValue: 'auto',
    shortestValue: '0',
    valueOptimizers: [
      valueOptimizers.whiteSpace,
      valueOptimizers.fraction,
      valueOptimizers.precision,
      valueOptimizers.unit,
      valueOptimizers.zero
    ]
  },
  'z-index': {
    canOverride: canOverride.property.zIndex,
    defaultValue: 'auto'
  }
};

// generate vendor-prefixed configuration
var vendorPrefixedConfiguration = {};

function cloneDescriptor(propertyName, prefix) {
  var clonedDescriptor = override$3(configuration$8[propertyName], {});

  if ('componentOf' in clonedDescriptor) {
    clonedDescriptor.componentOf = clonedDescriptor.componentOf.map(function (shorthandName) {
      return prefix + shorthandName;
    });
  }

  if ('components' in clonedDescriptor) {
    clonedDescriptor.components = clonedDescriptor.components.map(function (longhandName) {
      return prefix + longhandName;
    });
  }

  if ('keepUnlessDefault' in clonedDescriptor) {
    clonedDescriptor.keepUnlessDefault = prefix + clonedDescriptor.keepUnlessDefault;
  }

  return clonedDescriptor;
}

var vendorPrefixedConfiguration = {};

for (var propertyName in configuration$8) {
  var descriptor = configuration$8[propertyName];

  if (!('vendorPrefixes' in descriptor)) {
    continue;
  }

  for (var i = 0; i < descriptor.vendorPrefixes.length; i++) {
    var prefix = descriptor.vendorPrefixes[i];
    var clonedDescriptor = cloneDescriptor(propertyName, prefix);
    delete clonedDescriptor.vendorPrefixes;

    vendorPrefixedConfiguration[prefix + propertyName] = clonedDescriptor;
  }

  delete descriptor.vendorPrefixes;
}

var configuration_1 = override$3(configuration$8, vendorPrefixedConfiguration);

var emptyCharacter = '';

var Breaks = format.Breaks;
var Spaces = format.Spaces;

var Marker$8 = marker;
var Token$j = token;

function supportsAfterClosingBrace(token) {
  return token[1][1] == 'background' || token[1][1] == 'transform' || token[1][1] == 'src';
}

function afterClosingBrace(token, valueIndex) {
  return token[valueIndex][1][token[valueIndex][1].length - 1] == Marker$8.CLOSE_ROUND_BRACKET;
}

function afterComma(token, valueIndex) {
  return token[valueIndex][1] == Marker$8.COMMA;
}

function afterSlash(token, valueIndex) {
  return token[valueIndex][1] == Marker$8.FORWARD_SLASH;
}

function beforeComma(token, valueIndex) {
  return token[valueIndex + 1] && token[valueIndex + 1][1] == Marker$8.COMMA;
}

function beforeSlash(token, valueIndex) {
  return token[valueIndex + 1] && token[valueIndex + 1][1] == Marker$8.FORWARD_SLASH;
}

function inFilter(token) {
  return token[1][1] == 'filter' || token[1][1] == '-ms-filter';
}

function disallowsSpace(context, token, valueIndex) {
  return !context.spaceAfterClosingBrace && supportsAfterClosingBrace(token) && afterClosingBrace(token, valueIndex) ||
    beforeSlash(token, valueIndex) ||
    afterSlash(token, valueIndex) ||
    beforeComma(token, valueIndex) ||
    afterComma(token, valueIndex);
}

function rules$1(context, tokens) {
  var store = context.store;

  for (var i = 0, l = tokens.length; i < l; i++) {
    store(context, tokens[i]);

    if (i < l - 1) {
      store(context, comma(context));
    }
  }
}

function body$1(context, tokens) {
  var lastPropertyAt = lastPropertyIndex(tokens);

  for (var i = 0, l = tokens.length; i < l; i++) {
    property$1(context, tokens, i, lastPropertyAt);
  }
}

function lastPropertyIndex(tokens) {
  var index = tokens.length - 1;

  for (; index >= 0; index--) {
    if (tokens[index][0] != Token$j.COMMENT) {
      break;
    }
  }

  return index;
}

function property$1(context, tokens, position, lastPropertyAt) {
  var store = context.store;
  var token = tokens[position];

  var propertyValue = token[2];
  var isPropertyBlock = propertyValue && propertyValue[0] === Token$j.PROPERTY_BLOCK;

  var needsSemicolon;
  if ( context.format ) {
    if ( context.format.semicolonAfterLastProperty || isPropertyBlock ) {
      needsSemicolon = true;
    } else if ( position < lastPropertyAt ) {
      needsSemicolon = true;
    } else {
      needsSemicolon = false;
    }
  } else {
    needsSemicolon = position < lastPropertyAt || isPropertyBlock;
  }

  var isLast = position === lastPropertyAt;

  switch (token[0]) {
    case Token$j.AT_RULE:
      store(context, token);
      store(context, semicolon(context, Breaks.AfterProperty, false));
      break;
    case Token$j.AT_RULE_BLOCK:
      rules$1(context, token[1]);
      store(context, openBrace(context, Breaks.AfterRuleBegins, true));
      body$1(context, token[2]);
      store(context, closeBrace(context, Breaks.AfterRuleEnds, false, isLast));
      break;
    case Token$j.COMMENT:
      store(context, token);
      store(context, breakFor(context, Breaks.AfterComment) + context.indentWith);
      break;
    case Token$j.PROPERTY:
      store(context, token[1]);
      store(context, colon(context));
      if (propertyValue) {
        value$1(context, token);
      }
      store(context, needsSemicolon ? semicolon(context, Breaks.AfterProperty, isLast) : emptyCharacter);
      break;
    case Token$j.RAW:
      store(context, token);
  }
}

function value$1(context, token) {
  var store = context.store;
  var j, m;

  if (token[2][0] == Token$j.PROPERTY_BLOCK) {
    store(context, openBrace(context, Breaks.AfterBlockBegins, false));
    body$1(context, token[2][1]);
    store(context, closeBrace(context, Breaks.AfterBlockEnds, false, true));
  } else {
    for (j = 2, m = token.length; j < m; j++) {
      store(context, token[j]);

      if (j < m - 1 && (inFilter(token) || !disallowsSpace(context, token, j))) {
        store(context, Marker$8.SPACE);
      }
    }
  }
}

function breakFor(context, where) {
  return context.format ? context.format.breaks[where] : emptyCharacter;
}

function allowsSpace(context, where) {
  return context.format && context.format.spaces[where];
}

function openBrace(context, where, needsPrefixSpace) {
  if (context.format) {
    context.indentBy += context.format.indentBy;
    context.indentWith = context.format.indentWith.repeat(context.indentBy);
    return (needsPrefixSpace && allowsSpace(context, Spaces.BeforeBlockBegins) ? Marker$8.SPACE : emptyCharacter) +
      Marker$8.OPEN_CURLY_BRACKET +
      breakFor(context, where) +
      context.indentWith;
  } else {
    return Marker$8.OPEN_CURLY_BRACKET;
  }
}

function closeBrace(context, where, beforeBlockEnd, isLast) {
  if (context.format) {
    context.indentBy -= context.format.indentBy;
    context.indentWith = context.format.indentWith.repeat(context.indentBy);
    return (beforeBlockEnd ? breakFor(context, Breaks.BeforeBlockEnds) : breakFor(context, Breaks.AfterProperty)) +
      context.indentWith +
      Marker$8.CLOSE_CURLY_BRACKET +
      (isLast ? emptyCharacter : breakFor(context, where) + context.indentWith);
  } else {
    return Marker$8.CLOSE_CURLY_BRACKET;
  }
}

function colon(context) {
  return context.format ?
    Marker$8.COLON + (allowsSpace(context, Spaces.BeforeValue) ? Marker$8.SPACE : emptyCharacter) :
    Marker$8.COLON;
}

function semicolon(context, where, isLast) {
  return context.format ?
    Marker$8.SEMICOLON + (isLast ? emptyCharacter : (breakFor(context, where) + context.indentWith)) :
    Marker$8.SEMICOLON;
}

function comma(context) {
  return context.format ?
    Marker$8.COMMA + breakFor(context, Breaks.BetweenSelectors) + context.indentWith :
    Marker$8.COMMA;
}

function all$4(context, tokens) {
  var store = context.store;
  var token;
  var isLast;
  var i, l;

  for (i = 0, l = tokens.length; i < l; i++) {
    token = tokens[i];
    isLast = i == l - 1;

    switch (token[0]) {
      case Token$j.AT_RULE:
        store(context, token);
        store(context, semicolon(context, Breaks.AfterAtRule, isLast));
        break;
      case Token$j.AT_RULE_BLOCK:
        rules$1(context, token[1]);
        store(context, openBrace(context, Breaks.AfterRuleBegins, true));
        body$1(context, token[2]);
        store(context, closeBrace(context, Breaks.AfterRuleEnds, false, isLast));
        break;
      case Token$j.NESTED_BLOCK:
        rules$1(context, token[1]);
        store(context, openBrace(context, Breaks.AfterBlockBegins, true));
        all$4(context, token[2]);
        store(context, closeBrace(context, Breaks.AfterBlockEnds, true, isLast));
        break;
      case Token$j.COMMENT:
        store(context, token);
        store(context, breakFor(context, Breaks.AfterComment) + context.indentWith);
        break;
      case Token$j.RAW:
        store(context, token);
        break;
      case Token$j.RULE:
        rules$1(context, token[1]);
        store(context, openBrace(context, Breaks.AfterRuleBegins, true));
        body$1(context, token[2]);
        store(context, closeBrace(context, Breaks.AfterRuleEnds, false, isLast));
        break;
    }
  }
}

var helpers$1 = {
  all: all$4,
  body: body$1,
  property: property$1,
  rules: rules$1,
  value: value$1
};

var helpers = helpers$1;

function store$2(serializeContext, token) {
  serializeContext.output.push(typeof token == 'string' ? token : token[1]);
}

function context() {
  var newContext = {
    output: [],
    store: store$2
  };

  return newContext;
}

function all$3(tokens) {
  var oneTimeContext = context();
  helpers.all(oneTimeContext, tokens);
  return oneTimeContext.output.join('');
}

function body(tokens) {
  var oneTimeContext = context();
  helpers.body(oneTimeContext, tokens);
  return oneTimeContext.output.join('');
}

function property(tokens, position) {
  var oneTimeContext = context();
  helpers.property(oneTimeContext, tokens, position, true);
  return oneTimeContext.output.join('');
}

function rules(tokens) {
  var oneTimeContext = context();
  helpers.rules(oneTimeContext, tokens);
  return oneTimeContext.output.join('');
}

function value(tokens) {
  var oneTimeContext = context();
  helpers.value(oneTimeContext, tokens);
  return oneTimeContext.output.join('');
}

var oneTime = {
  all: all$3,
  body: body,
  property: property,
  rules: rules,
  value: value
};

var sortSelectors$2 = sortSelectors_1;
var tidyRules$2 = tidyRules_1;
var tidyBlock = tidyBlock_1;
var tidyAtRule = tidyAtRule_1;

var Hack = hack;
var removeUnused$1 = removeUnused_1;
var restoreFromOptimizing$4 = restoreFromOptimizing_1;
var wrapForOptimizing$2 = wrapForOptimizing$3.all;

var configuration$7 = configuration_1;
var optimizers = valueOptimizers$1;

var OptimizationLevel$6 = optimizationLevel.OptimizationLevel;

var Token$i = token;
var Marker$7 = marker;

var formatPosition$1 = formatPosition_1;

var serializeRules$9 = oneTime.rules;

var CHARSET_TOKEN = '@charset';
var CHARSET_REGEXP = new RegExp('^' + CHARSET_TOKEN, 'i');

var DEFAULT_ROUNDING_PRECISION = roundingPrecision.DEFAULT;

var PROPERTY_NAME_PATTERN = /^(?:\-chrome\-|\-[\w\-]+\w|\w[\w\-]+\w|\w{1,}|\-\-\S+)$/;
var IMPORT_PREFIX_PATTERN$2 = /^@import/i;
var URL_PREFIX_PATTERN$2 = /^url\(/i;
var VARIABLE_NAME_PATTERN = /^--\S+$/;

function startsAsUrl(value) {
  return URL_PREFIX_PATTERN$2.test(value);
}

function isImport$3(token) {
  return IMPORT_PREFIX_PATTERN$2.test(token[1]);
}

function isLegacyFilter(property) {
  var value;

  if (property.name == 'filter' || property.name == '-ms-filter') {
    value = property.value[0][1];

    return value.indexOf('progid') > -1 ||
      value.indexOf('alpha') === 0 ||
      value.indexOf('chroma') === 0;
  } else {
    return false;
  }
}

function noop() {}

function optimizeBody(rule, properties, context) {
  var options = context.options;
  var valueOptimizers;
  var property, name, type, value;
  var propertyToken;
  var propertyOptimizer;
  var serializedRule = serializeRules$9(rule);
  var _properties = wrapForOptimizing$2(properties);
  var pluginValueOptimizers = context.options.plugins.level1Value;
  var pluginPropertyOptimizers = context.options.plugins.level1Property;
  var i, l;

  for (i = 0, l = _properties.length; i < l; i++) {
    var j, k, m, n;

    property = _properties[i];
    name = property.name;
    propertyOptimizer = configuration$7[name] && configuration$7[name].propertyOptimizer || noop;
    valueOptimizers = configuration$7[name] && configuration$7[name].valueOptimizers || [optimizers.whiteSpace];

    if (!PROPERTY_NAME_PATTERN.test(name)) {
      propertyToken = property.all[property.position];
      context.warnings.push('Invalid property name \'' + name + '\' at ' + formatPosition$1(propertyToken[1][2][0]) + '. Ignoring.');
      property.unused = true;
      continue;
    }

    if (property.value.length === 0) {
      propertyToken = property.all[property.position];
      context.warnings.push('Empty property \'' + name + '\' at ' + formatPosition$1(propertyToken[1][2][0]) + '. Ignoring.');
      property.unused = true;
      continue;
    }

    if (property.hack && (
        (property.hack[0] == Hack.ASTERISK || property.hack[0] == Hack.UNDERSCORE) && !options.compatibility.properties.iePrefixHack ||
        property.hack[0] == Hack.BACKSLASH && !options.compatibility.properties.ieSuffixHack ||
        property.hack[0] == Hack.BANG && !options.compatibility.properties.ieBangHack)) {
      property.unused = true;
      continue;
    }

    if (!options.compatibility.properties.ieFilters && isLegacyFilter(property)) {
      property.unused = true;
      continue;
    }

    if (property.block) {
      optimizeBody(rule, property.value[0][1], context);
      continue;
    }

    if (VARIABLE_NAME_PATTERN.test(name)) {
      continue;
    }

    for (j = 0, m = property.value.length; j < m; j++) {
      type = property.value[j][0];
      value = property.value[j][1];

      if (type == Token$i.PROPERTY_BLOCK) {
        property.unused = true;
        context.warnings.push('Invalid value token at ' + formatPosition$1(value[0][1][2][0]) + '. Ignoring.');
        break;
      }

      if (startsAsUrl(value) && !context.validator.isUrl(value)) {
        property.unused = true;
        context.warnings.push('Broken URL \'' + value + '\' at ' + formatPosition$1(property.value[j][2][0]) + '. Ignoring.');
        break;
      }

      for (k = 0, n = valueOptimizers.length; k < n; k++) {
        value = valueOptimizers[k](name, value, options);
      }

      for (k = 0, n = pluginValueOptimizers.length; k < n; k++) {
        value = pluginValueOptimizers[k](name, value, options);
      }

      property.value[j][1] = value;
    }

    propertyOptimizer(serializedRule, property, options);

    for (j = 0, m = pluginPropertyOptimizers.length; j < m; j++) {
      pluginPropertyOptimizers[j](serializedRule, property, options);
    }
  }

  restoreFromOptimizing$4(_properties);
  removeUnused$1(_properties);
  removeComments(properties, options);
}

function removeComments(tokens, options) {
  var token;
  var i;

  for (i = 0; i < tokens.length; i++) {
    token = tokens[i];

    if (token[0] != Token$i.COMMENT) {
      continue;
    }

    optimizeComment(token, options);

    if (token[1].length === 0) {
      tokens.splice(i, 1);
      i--;
    }
  }
}

function optimizeComment(token, options) {
  if (token[1][2] == Marker$7.EXCLAMATION && (options.level[OptimizationLevel$6.One].specialComments == 'all' || options.commentsKept < options.level[OptimizationLevel$6.One].specialComments)) {
    options.commentsKept++;
    return;
  }

  token[1] = [];
}

function cleanupCharsets(tokens) {
  var hasCharset = false;

  for (var i = 0, l = tokens.length; i < l; i++) {
    var token = tokens[i];

    if (token[0] != Token$i.AT_RULE)
      continue;

    if (!CHARSET_REGEXP.test(token[1]))
      continue;

    if (hasCharset || token[1].indexOf(CHARSET_TOKEN) == -1) {
      tokens.splice(i, 1);
      i--;
      l--;
    } else {
      hasCharset = true;
      tokens.splice(i, 1);
      tokens.unshift([Token$i.AT_RULE, token[1].replace(CHARSET_REGEXP, CHARSET_TOKEN)]);
    }
  }
}

function buildUnitRegexp(options) {
  var units = ['px', 'em', 'ex', 'cm', 'mm', 'in', 'pt', 'pc', '%'];
  var otherUnits = ['ch', 'rem', 'vh', 'vm', 'vmax', 'vmin', 'vw'];

  otherUnits.forEach(function (unit) {
    if (options.compatibility.units[unit]) {
      units.push(unit);
    }
  });

  return new RegExp('(^|\\s|\\(|,)0(?:' + units.join('|') + ')(\\W|$)', 'g');
}

function buildPrecisionOptions(roundingPrecision) {
  var precisionOptions = {
    matcher: null,
    units: {},
  };
  var optimizable = [];
  var unit;
  var value;

  for (unit in roundingPrecision) {
    value = roundingPrecision[unit];

    if (value != DEFAULT_ROUNDING_PRECISION) {
      precisionOptions.units[unit] = {};
      precisionOptions.units[unit].value = value;
      precisionOptions.units[unit].multiplier = Math.pow(10, value);

      optimizable.push(unit);
    }
  }

  if (optimizable.length > 0) {
    precisionOptions.enabled = true;
    precisionOptions.decimalPointMatcher = new RegExp('(\\d)\\.($|' + optimizable.join('|') + ')($|\W)', 'g');
    precisionOptions.zeroMatcher = new RegExp('(\\d*)(\\.\\d+)(' + optimizable.join('|') + ')', 'g');
  }

  return precisionOptions;
}

function level1Optimize$1(tokens, context) {
  var options = context.options;
  var levelOptions = options.level[OptimizationLevel$6.One];
  var ie7Hack = options.compatibility.selectors.ie7Hack;
  var adjacentSpace = options.compatibility.selectors.adjacentSpace;
  var spaceAfterClosingBrace = options.compatibility.properties.spaceAfterClosingBrace;
  var format = options.format;
  var mayHaveCharset = false;
  var afterRules = false;

  options.unitsRegexp = options.unitsRegexp || buildUnitRegexp(options);
  options.precision = options.precision || buildPrecisionOptions(levelOptions.roundingPrecision);
  options.commentsKept = options.commentsKept || 0;

  for (var i = 0, l = tokens.length; i < l; i++) {
    var token = tokens[i];

    switch (token[0]) {
      case Token$i.AT_RULE:
        token[1] = isImport$3(token) && afterRules ? '' : token[1];
        token[1] = levelOptions.tidyAtRules ? tidyAtRule(token[1]) : token[1];
        mayHaveCharset = true;
        break;
      case Token$i.AT_RULE_BLOCK:
        optimizeBody(token[1], token[2], context);
        afterRules = true;
        break;
      case Token$i.NESTED_BLOCK:
        token[1] = levelOptions.tidyBlockScopes ? tidyBlock(token[1], spaceAfterClosingBrace) : token[1];
        level1Optimize$1(token[2], context);
        afterRules = true;
        break;
      case Token$i.COMMENT:
        optimizeComment(token, options);
        break;
      case Token$i.RULE:
        token[1] = levelOptions.tidySelectors ? tidyRules$2(token[1], !ie7Hack, adjacentSpace, format, context.warnings) : token[1];
        token[1] = token[1].length > 1 ? sortSelectors$2(token[1], levelOptions.selectorsSortingMethod) : token[1];
        optimizeBody(token[1], token[2], context);
        afterRules = true;
        break;
    }

    if (token[0] == Token$i.COMMENT && token[1].length === 0 || levelOptions.removeEmpty && (token[1].length === 0 || (token[2] && token[2].length === 0))) {
      tokens.splice(i, 1);
      i--;
      l--;
    }
  }

  if (levelOptions.cleanupCharsets && mayHaveCharset) {
    cleanupCharsets(tokens);
  }

  return tokens;
}

var optimize$3 = level1Optimize$1;

var Marker$6 = marker;
var split$1 = split_1;

var DEEP_SELECTOR_PATTERN = /\/deep\//;
var DOUBLE_COLON_PATTERN = /^::/;
var VENDOR_PREFIXED_PATTERN = /:(-moz-|-ms-|-o-|-webkit-)/;

var NOT_PSEUDO = ':not';
var PSEUDO_CLASSES_WITH_ARGUMENTS = [
  ':dir',
  ':lang',
  ':not',
  ':nth-child',
  ':nth-last-child',
  ':nth-last-of-type',
  ':nth-of-type'
];
var RELATION_PATTERN = /[>\+~]/;
var UNMIXABLE_PSEUDO_CLASSES = [
  ':after',
  ':before',
  ':first-letter',
  ':first-line',
  ':lang'
];
var UNMIXABLE_PSEUDO_ELEMENTS = [
  '::after',
  '::before',
  '::first-letter',
  '::first-line'
];

var Level$1 = {
  DOUBLE_QUOTE: 'double-quote',
  SINGLE_QUOTE: 'single-quote',
  ROOT: 'root'
};

function isMergeable$4(selector, mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging) {
  var singleSelectors = split$1(selector, Marker$6.COMMA);
  var singleSelector;
  var i, l;

  for (i = 0, l = singleSelectors.length; i < l; i++) {
    singleSelector = singleSelectors[i];

    if (singleSelector.length === 0 ||
        isDeepSelector(singleSelector) ||
        isVendorPrefixed(singleSelector) ||
        (singleSelector.indexOf(Marker$6.COLON) > -1 && !areMergeable(singleSelector, extractPseudoFrom(singleSelector), mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging))) {
      return false;
    }
  }

  return true;
}

function isDeepSelector(selector) {
  return DEEP_SELECTOR_PATTERN.test(selector);
}

function isVendorPrefixed(selector) {
  return VENDOR_PREFIXED_PATTERN.test(selector);
}

function extractPseudoFrom(selector) {
  var list = [];
  var character;
  var buffer = [];
  var level = Level$1.ROOT;
  var roundBracketLevel = 0;
  var isQuoted;
  var isEscaped;
  var isPseudo = false;
  var isRelation;
  var wasColon = false;
  var index;
  var len;

  for (index = 0, len = selector.length; index < len; index++) {
    character = selector[index];

    isRelation = !isEscaped && RELATION_PATTERN.test(character);
    isQuoted = level == Level$1.DOUBLE_QUOTE || level == Level$1.SINGLE_QUOTE;

    if (isEscaped) {
      buffer.push(character);
    } else if (character == Marker$6.DOUBLE_QUOTE && level == Level$1.ROOT) {
      buffer.push(character);
      level = Level$1.DOUBLE_QUOTE;
    } else if (character == Marker$6.DOUBLE_QUOTE && level == Level$1.DOUBLE_QUOTE) {
      buffer.push(character);
      level = Level$1.ROOT;
    } else if (character == Marker$6.SINGLE_QUOTE && level == Level$1.ROOT) {
      buffer.push(character);
      level = Level$1.SINGLE_QUOTE;
    } else if (character == Marker$6.SINGLE_QUOTE && level == Level$1.SINGLE_QUOTE) {
      buffer.push(character);
      level = Level$1.ROOT;
    } else if (isQuoted) {
      buffer.push(character);
    } else if (character == Marker$6.OPEN_ROUND_BRACKET) {
      buffer.push(character);
      roundBracketLevel++;
    } else if (character == Marker$6.CLOSE_ROUND_BRACKET && roundBracketLevel == 1 && isPseudo) {
      buffer.push(character);
      list.push(buffer.join(''));
      roundBracketLevel--;
      buffer = [];
      isPseudo = false;
    } else if (character == Marker$6.CLOSE_ROUND_BRACKET) {
      buffer.push(character);
      roundBracketLevel--;
    } else if (character == Marker$6.COLON && roundBracketLevel === 0 && isPseudo && !wasColon) {
      list.push(buffer.join(''));
      buffer = [];
      buffer.push(character);
    } else if (character == Marker$6.COLON && roundBracketLevel === 0 && !wasColon) {
      buffer = [];
      buffer.push(character);
      isPseudo = true;
    } else if (character == Marker$6.SPACE && roundBracketLevel === 0 && isPseudo) {
      list.push(buffer.join(''));
      buffer = [];
      isPseudo = false;
    } else if (isRelation && roundBracketLevel === 0 && isPseudo) {
      list.push(buffer.join(''));
      buffer = [];
      isPseudo = false;
    } else {
      buffer.push(character);
    }

    isEscaped = character == Marker$6.BACK_SLASH;
    wasColon = character == Marker$6.COLON;
  }

  if (buffer.length > 0 && isPseudo) {
    list.push(buffer.join(''));
  }

  return list;
}

function areMergeable(selector, matches, mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging) {
  return areAllowed(matches, mergeablePseudoClasses, mergeablePseudoElements) &&
    needArguments(matches) &&
    (matches.length < 2 || !someIncorrectlyChained(selector, matches)) &&
    (matches.length < 2 || multiplePseudoMerging && allMixable(matches));
}

function areAllowed(matches, mergeablePseudoClasses, mergeablePseudoElements) {
  var match;
  var name;
  var i, l;

  for (i = 0, l = matches.length; i < l; i++) {
    match = matches[i];
    name = match.indexOf(Marker$6.OPEN_ROUND_BRACKET) > -1 ?
      match.substring(0, match.indexOf(Marker$6.OPEN_ROUND_BRACKET)) :
      match;

    if (mergeablePseudoClasses.indexOf(name) === -1 && mergeablePseudoElements.indexOf(name) === -1) {
      return false;
    }
  }

  return true;
}

function needArguments(matches) {
  var match;
  var name;
  var bracketOpensAt;
  var hasArguments;
  var i, l;

  for (i = 0, l = matches.length; i < l; i++) {
    match = matches[i];

    bracketOpensAt = match.indexOf(Marker$6.OPEN_ROUND_BRACKET);
    hasArguments = bracketOpensAt > -1;
    name = hasArguments ?
      match.substring(0, bracketOpensAt) :
      match;

    if (hasArguments && PSEUDO_CLASSES_WITH_ARGUMENTS.indexOf(name) == -1) {
      return false;
    }

    if (!hasArguments && PSEUDO_CLASSES_WITH_ARGUMENTS.indexOf(name) > -1) {
      return false;
    }
  }

  return true;
}

function someIncorrectlyChained(selector, matches) {
  var positionInSelector = 0;
  var match;
  var matchAt;
  var nextMatch;
  var nextMatchAt;
  var name;
  var nextName;
  var areChained;
  var i, l;

  for (i = 0, l = matches.length; i < l; i++) {
    match = matches[i];
    nextMatch = matches[i + 1];

    if (!nextMatch) {
      break;
    }

    matchAt = selector.indexOf(match, positionInSelector);
    nextMatchAt = selector.indexOf(match, matchAt + 1);
    positionInSelector = nextMatchAt;
    areChained = matchAt + match.length == nextMatchAt;

    if (areChained) {
      name = match.indexOf(Marker$6.OPEN_ROUND_BRACKET) > -1 ?
        match.substring(0, match.indexOf(Marker$6.OPEN_ROUND_BRACKET)) :
        match;
      nextName = nextMatch.indexOf(Marker$6.OPEN_ROUND_BRACKET) > -1 ?
        nextMatch.substring(0, nextMatch.indexOf(Marker$6.OPEN_ROUND_BRACKET)) :
        nextMatch;

      if (name != NOT_PSEUDO || nextName != NOT_PSEUDO) {
        return true;
      }
    }
  }

  return false;
}

function allMixable(matches) {
  var unmixableMatches = 0;
  var match;
  var i, l;

  for (i = 0, l = matches.length; i < l; i++) {
    match = matches[i];

    if (isPseudoElement(match)) {
      unmixableMatches += UNMIXABLE_PSEUDO_ELEMENTS.indexOf(match) > -1 ? 1 : 0;
    } else {
      unmixableMatches += UNMIXABLE_PSEUDO_CLASSES.indexOf(match) > -1 ? 1 : 0;
    }

    if (unmixableMatches > 1) {
      return false;
    }
  }

  return true;
}

function isPseudoElement(pseudo) {
  return DOUBLE_COLON_PATTERN.test(pseudo);
}

var isMergeable_1 = isMergeable$4;

var Marker$5 = marker;

function everyValuesPair$2(fn, left, right) {
  var leftSize = left.value.length;
  var rightSize = right.value.length;
  var total = Math.max(leftSize, rightSize);
  var lowerBound = Math.min(leftSize, rightSize) - 1;
  var leftValue;
  var rightValue;
  var position;

  for (position = 0; position < total; position++) {
    leftValue = left.value[position] && left.value[position][1] || leftValue;
    rightValue = right.value[position] && right.value[position][1] || rightValue;

    if (leftValue == Marker$5.COMMA || rightValue == Marker$5.COMMA) {
      continue;
    }

    if (!fn(leftValue, rightValue, position, position <= lowerBound)) {
      return false;
    }
  }

  return true;
}

var everyValuesPair_1 = everyValuesPair$2;

function hasInherit$2(property) {
  for (var i = property.value.length - 1; i >= 0; i--) {
    if (property.value[i][1] == 'inherit')
      return true;
  }

  return false;
}

var hasInherit_1 = hasInherit$2;

function hasSameValues$1(property) {
  var firstValue = property.value[0][1];
  var i, l;

  for (i = 1, l = property.value.length; i < l; i++) {
    if (property.value[i][1] != firstValue) {
      return false;
    }
  }

  return true;
}

var hasSameValues_1 = hasSameValues$1;

var configuration$6 = configuration_1;
var InvalidPropertyError = invalidPropertyError;

function populateComponents$3(properties, validator, warnings) {
  var component;
  var j, m;

  for (var i = properties.length - 1; i >= 0; i--) {
    var property = properties[i];
    var descriptor = configuration$6[property.name];

    if (!property.dynamic && descriptor && descriptor.shorthand) {
      if (onlyValueIsVariable(property, validator) || moreThanOneValueIsVariable(property, validator)) {
        property.optimizable = false;
        continue;
      }

      property.shorthand = true;
      property.dirty = true;

      try {
        property.components = descriptor.breakUp(property, configuration$6, validator);

        if (descriptor.shorthandComponents) {
          for (j = 0, m = property.components.length; j < m; j++) {
            component = property.components[j];
            component.components = configuration$6[component.name].breakUp(component, configuration$6, validator);
          }
        }
      } catch (e) {
        if (e instanceof InvalidPropertyError) {
          property.components = []; // this will set property.unused to true below
          warnings.push(e.message);
        } else {
          throw e;
        }
      }

      if (property.components.length > 0)
        property.multiplex = property.components[0].multiplex;
      else
        property.unused = true;
    }
  }
}

function onlyValueIsVariable(property, validator) {
  return property.value.length == 1 && validator.isVariable(property.value[0][1]);
}

function moreThanOneValueIsVariable(property, validator) {
  return property.value.length > 1 && property.value.filter(function (value) { return validator.isVariable(value[1]); }).length > 1;
}

var populateComponents_1 = populateComponents$3;

var configuration$5 = configuration_1;

function restoreWithComponents$3(property) {
  var descriptor = configuration$5[property.name];

  if (descriptor && descriptor.shorthand) {
    return descriptor.restore(property, configuration$5);
  } else {
    return property.value;
  }
}

var restoreWithComponents_1 = restoreWithComponents$3;

var everyValuesPair$1 = everyValuesPair_1;
var hasInherit$1 = hasInherit_1;
var hasSameValues = hasSameValues_1;
var populateComponents$2 = populateComponents_1;

var configuration$4 = configuration_1;
var deepClone$1 = clone.deep;
var restoreWithComponents$2 = restoreWithComponents_1;

var restoreFromOptimizing$3 = restoreFromOptimizing_1;
var wrapSingle = wrapForOptimizing$3.single;

var serializeBody$5 = oneTime.body;
var Token$h = token;

function mergeIntoShorthands$1(properties, validator) {
  var candidates = {};
  var descriptor;
  var componentOf;
  var property;
  var i, l;
  var j, m;

  // there is no shorthand property made up of less than 3 longhands
  if (properties.length < 3) {
    return;
  }

  for (i = 0, l = properties.length; i < l; i++) {
    property = properties[i];
    descriptor = configuration$4[property.name];

    if (property.dynamic) {
      continue;
    }

    if (property.unused) {
      continue;
    }

    if (property.hack) {
      continue;
    }

    if (property.block) {
      continue;
    }

    if (descriptor && descriptor.singleTypeComponents && !hasSameValues(property)) {
      continue;
    }

    invalidateOrCompact(properties, i, candidates, validator);

    if (descriptor && descriptor.componentOf) {
      for (j = 0, m = descriptor.componentOf.length; j < m; j++) {
        componentOf = descriptor.componentOf[j];

        candidates[componentOf] = candidates[componentOf] || {};
        candidates[componentOf][property.name] = property;
      }
    }
  }

  invalidateOrCompact(properties, i, candidates, validator);
}

function invalidateOrCompact(properties, position, candidates, validator) {
  var invalidatedBy = properties[position];
  var shorthandName;
  var shorthandDescriptor;
  var candidateComponents;
  var replacedCandidates = [];
  var i;

  for (shorthandName in candidates) {
    if (undefined !== invalidatedBy && shorthandName == invalidatedBy.name) {
      continue;
    }

    shorthandDescriptor = configuration$4[shorthandName];
    candidateComponents = candidates[shorthandName];
    if (invalidatedBy && invalidates(candidates, shorthandName, invalidatedBy)) {
      delete candidates[shorthandName];
      continue;
    }

    if (shorthandDescriptor.components.length > Object.keys(candidateComponents).length) {
      continue;
    }

    if (mixedImportance(candidateComponents)) {
      continue;
    }

    if (!overridable(candidateComponents, shorthandName, validator)) {
      continue;
    }

    if (!mergeable(candidateComponents)) {
      continue;
    }

    if (mixedInherit(candidateComponents)) {
      replaceWithInheritBestFit(properties, candidateComponents, shorthandName, validator);
    } else {
      replaceWithShorthand(properties, candidateComponents, shorthandName, validator);
    }

    replacedCandidates.push(shorthandName);
  }

  for (i = replacedCandidates.length - 1; i >= 0; i--) {
    delete candidates[replacedCandidates[i]];
  }
}

function invalidates(candidates, shorthandName, invalidatedBy) {
  var shorthandDescriptor = configuration$4[shorthandName];
  var invalidatedByDescriptor = configuration$4[invalidatedBy.name];
  var componentName;

  if ('overridesShorthands' in shorthandDescriptor && shorthandDescriptor.overridesShorthands.indexOf(invalidatedBy.name) > -1) {
    return true;
  }

  if (invalidatedByDescriptor && 'componentOf' in invalidatedByDescriptor) {
    for (componentName in candidates[shorthandName]) {
      if (invalidatedByDescriptor.componentOf.indexOf(componentName) > -1) {
        return true;
      }
    }
  }

  return false;
}

function mixedImportance(components) {
  var important;
  var componentName;

  for (componentName in components) {
    if (undefined !== important && components[componentName].important != important) {
      return true;
    }

    important = components[componentName].important;
  }

  return false;
}

function overridable(components, shorthandName, validator) {
  var descriptor = configuration$4[shorthandName];
  var newValuePlaceholder = [
    Token$h.PROPERTY,
    [Token$h.PROPERTY_NAME, shorthandName],
    [Token$h.PROPERTY_VALUE, descriptor.defaultValue]
  ];
  var newProperty = wrapSingle(newValuePlaceholder);
  var component;
  var mayOverride;
  var i, l;

  populateComponents$2([newProperty], validator, []);

  for (i = 0, l = descriptor.components.length; i < l; i++) {
    component = components[descriptor.components[i]];
    mayOverride = configuration$4[component.name].canOverride || sameValue$1;

    if (!everyValuesPair$1(mayOverride.bind(null, validator), newProperty.components[i], component)) {
      return false;
    }
  }

  return true;
}

function sameValue$1(_validator, value1, value2) {
  return value1 === value2;
}

function mergeable(components) {
  var lastCount = null;
  var currentCount;
  var componentName;
  var component;
  var descriptor;
  var values;

  for (componentName in components) {
    component = components[componentName];
    descriptor = configuration$4[componentName];

    if (!('restore' in descriptor)) {
      continue;
    }

    restoreFromOptimizing$3([component.all[component.position]], restoreWithComponents$2);
    values = descriptor.restore(component, configuration$4);

    currentCount = values.length;

    if (lastCount !== null && currentCount !== lastCount) {
      return false;
    }

    lastCount = currentCount;
  }

  return true;
}

function mixedInherit(components) {
  var componentName;
  var lastValue = null;
  var currentValue;

  for (componentName in components) {
    currentValue = hasInherit$1(components[componentName]);

    if (lastValue !== null && lastValue !== currentValue) {
      return true;
    }

    lastValue = currentValue;
  }

  return false;
}

function replaceWithInheritBestFit(properties, candidateComponents, shorthandName, validator) {
  var viaLonghands = buildSequenceWithInheritLonghands(candidateComponents, shorthandName, validator);
  var viaShorthand = buildSequenceWithInheritShorthand(candidateComponents, shorthandName, validator);
  var longhandTokensSequence = viaLonghands[0];
  var shorthandTokensSequence = viaShorthand[0];
  var isLonghandsShorter = serializeBody$5(longhandTokensSequence).length < serializeBody$5(shorthandTokensSequence).length;
  var newTokensSequence = isLonghandsShorter ? longhandTokensSequence : shorthandTokensSequence;
  var newProperty = isLonghandsShorter ? viaLonghands[1] : viaShorthand[1];
  var newComponents = isLonghandsShorter ? viaLonghands[2] : viaShorthand[2];
  var lastComponent = candidateComponents[Object.keys(candidateComponents).pop()];
  var all = lastComponent.all;
  var insertAt = lastComponent.position;
  var componentName;
  var oldComponent;
  var newComponent;
  var newToken;

  newProperty.position = insertAt;
  newProperty.shorthand = true;
  newProperty.important = lastComponent.important;
  newProperty.multiplex = false;
  newProperty.dirty = true;
  newProperty.all = all;
  newProperty.all[insertAt] = newTokensSequence[0];

  properties.splice(insertAt, 1, newProperty);

  for (componentName in candidateComponents) {
    oldComponent = candidateComponents[componentName];
    oldComponent.unused = true;

    newProperty.multiplex = newProperty.multiplex || oldComponent.multiplex;

    if (oldComponent.name in newComponents) {
      newComponent = newComponents[oldComponent.name];
      newToken = findTokenIn(newTokensSequence, componentName);

      newComponent.position = all.length;
      newComponent.all = all;
      newComponent.all.push(newToken);

      properties.push(newComponent);
    }
  }
}

function buildSequenceWithInheritLonghands(components, shorthandName, validator) {
  var tokensSequence = [];
  var inheritComponents = {};
  var nonInheritComponents = {};
  var descriptor = configuration$4[shorthandName];
  var shorthandToken = [
    Token$h.PROPERTY,
    [Token$h.PROPERTY_NAME, shorthandName],
    [Token$h.PROPERTY_VALUE, descriptor.defaultValue]
  ];
  var newProperty = wrapSingle(shorthandToken);
  var component;
  var longhandToken;
  var newComponent;
  var nameMetadata;
  var i, l;

  populateComponents$2([newProperty], validator, []);

  for (i = 0, l = descriptor.components.length; i < l; i++) {
    component = components[descriptor.components[i]];

    if (hasInherit$1(component)) {
      longhandToken = component.all[component.position].slice(0, 2);
      Array.prototype.push.apply(longhandToken, component.value);
      tokensSequence.push(longhandToken);

      newComponent = deepClone$1(component);
      newComponent.value = inferComponentValue(components, newComponent.name);

      newProperty.components[i] = newComponent;
      inheritComponents[component.name] = deepClone$1(component);
    } else {
      newComponent = deepClone$1(component);
      newComponent.all = component.all;
      newProperty.components[i] = newComponent;

      nonInheritComponents[component.name] = component;
    }
  }

  newProperty.important = components[Object.keys(components).pop()].important;

  nameMetadata = joinMetadata(nonInheritComponents, 1);
  shorthandToken[1].push(nameMetadata);

  restoreFromOptimizing$3([newProperty], restoreWithComponents$2);

  shorthandToken = shorthandToken.slice(0, 2);
  Array.prototype.push.apply(shorthandToken, newProperty.value);

  tokensSequence.unshift(shorthandToken);

  return [tokensSequence, newProperty, inheritComponents];
}

function inferComponentValue(components, propertyName) {
  var descriptor = configuration$4[propertyName];

  if ('oppositeTo' in descriptor) {
    return components[descriptor.oppositeTo].value;
  } else {
    return [[Token$h.PROPERTY_VALUE, descriptor.defaultValue]];
  }
}

function joinMetadata(components, at) {
  var metadata = [];
  var component;
  var originalValue;
  var componentMetadata;
  var componentName;

  for (componentName in components) {
    component = components[componentName];
    originalValue = component.all[component.position];
    componentMetadata = originalValue[at][originalValue[at].length - 1];

    Array.prototype.push.apply(metadata, componentMetadata);
  }

  return metadata.sort(metadataSorter);
}

function metadataSorter(metadata1, metadata2) {
  var line1 = metadata1[0];
  var line2 = metadata2[0];
  var column1 = metadata1[1];
  var column2 = metadata2[1];

  if (line1 < line2) {
    return -1;
  } else if (line1 === line2) {
    return column1 < column2 ? -1 : 1;
  } else {
    return 1;
  }
}

function buildSequenceWithInheritShorthand(components, shorthandName, validator) {
  var tokensSequence = [];
  var inheritComponents = {};
  var nonInheritComponents = {};
  var descriptor = configuration$4[shorthandName];
  var shorthandToken = [
    Token$h.PROPERTY,
    [Token$h.PROPERTY_NAME, shorthandName],
    [Token$h.PROPERTY_VALUE, 'inherit']
  ];
  var newProperty = wrapSingle(shorthandToken);
  var component;
  var longhandToken;
  var nameMetadata;
  var valueMetadata;
  var i, l;

  populateComponents$2([newProperty], validator, []);

  for (i = 0, l = descriptor.components.length; i < l; i++) {
    component = components[descriptor.components[i]];

    if (hasInherit$1(component)) {
      inheritComponents[component.name] = component;
    } else {
      longhandToken = component.all[component.position].slice(0, 2);
      Array.prototype.push.apply(longhandToken, component.value);
      tokensSequence.push(longhandToken);

      nonInheritComponents[component.name] = deepClone$1(component);
    }
  }

  nameMetadata = joinMetadata(inheritComponents, 1);
  shorthandToken[1].push(nameMetadata);

  valueMetadata = joinMetadata(inheritComponents, 2);
  shorthandToken[2].push(valueMetadata);

  tokensSequence.unshift(shorthandToken);

  return [tokensSequence, newProperty, nonInheritComponents];
}

function findTokenIn(tokens, componentName) {
  var i, l;

  for (i = 0, l = tokens.length; i < l; i++) {
    if (tokens[i][1][1] == componentName) {
      return tokens[i];
    }
  }
}

function replaceWithShorthand(properties, candidateComponents, shorthandName, validator) {
  var descriptor = configuration$4[shorthandName];
  var nameMetadata;
  var valueMetadata;
  var newValuePlaceholder = [
    Token$h.PROPERTY,
    [Token$h.PROPERTY_NAME, shorthandName],
    [Token$h.PROPERTY_VALUE, descriptor.defaultValue]
  ];
  var all;
  var insertAt = inferInsertAtFrom(properties, candidateComponents, shorthandName);

  var newProperty = wrapSingle(newValuePlaceholder);
  newProperty.shorthand = true;
  newProperty.dirty = true;
  newProperty.multiplex = false;

  populateComponents$2([newProperty], validator, []);

  for (var i = 0, l = descriptor.components.length; i < l; i++) {
    var component = candidateComponents[descriptor.components[i]];

    newProperty.components[i] = deepClone$1(component);
    newProperty.important = component.important;
    newProperty.multiplex = newProperty.multiplex || component.multiplex;

    all = component.all;
  }

  for (var componentName in candidateComponents) {
    candidateComponents[componentName].unused = true;
  }

  nameMetadata = joinMetadata(candidateComponents, 1);
  newValuePlaceholder[1].push(nameMetadata);

  valueMetadata = joinMetadata(candidateComponents, 2);
  newValuePlaceholder[2].push(valueMetadata);

  newProperty.position = insertAt;
  newProperty.all = all;
  newProperty.all[insertAt] = newValuePlaceholder;

  properties.splice(insertAt, 1, newProperty);
}

function inferInsertAtFrom(properties, candidateComponents, shorthandName) {
  var candidateComponentNames = Object.keys(candidateComponents);
  var firstCandidatePosition = candidateComponents[candidateComponentNames[0]].position;
  var lastCandidatePosition = candidateComponents[candidateComponentNames[candidateComponentNames.length - 1]].position;

  if (shorthandName == 'border' && traversesVia(properties.slice(firstCandidatePosition, lastCandidatePosition), 'border-image')) {
    return firstCandidatePosition;
  } else {
    return lastCandidatePosition;
  }
}

function traversesVia(properties, propertyName) {
  for (var i = properties.length - 1; i >= 0; i--) {
    if (properties[i].name == propertyName) {
      return true;
    }
  }

  return false;
}

var mergeIntoShorthands_1 = mergeIntoShorthands$1;

function hasUnset$1(property) {
  for (var i = property.value.length - 1; i >= 0; i--) {
    if (property.value[i][1] == 'unset')
      return true;
  }

  return false;
}

var hasUnset_1 = hasUnset$1;

var configuration$3 = configuration_1;

function findComponentIn$1(shorthand, longhand) {
  var comparator = nameComparator(longhand);

  return findInDirectComponents(shorthand, comparator) || findInSubComponents(shorthand, comparator);
}

function nameComparator(to) {
  return function (property) {
    return to.name === property.name;
  };
}

function findInDirectComponents(shorthand, comparator) {
  return shorthand.components.filter(comparator)[0];
}

function findInSubComponents(shorthand, comparator) {
  var shorthandComponent;
  var longhandMatch;
  var i, l;

  if (!configuration$3[shorthand.name].shorthandComponents) {
    return;
  }

  for (i = 0, l = shorthand.components.length; i < l; i++) {
    shorthandComponent = shorthand.components[i];
    longhandMatch = findInDirectComponents(shorthandComponent, comparator);

    if (longhandMatch) {
      return longhandMatch;
    }
  }

  return;
}

var findComponentIn_1 = findComponentIn$1;

var configuration$2 = configuration_1;

function isComponentOf$1(property1, property2, shallow) {
  return isDirectComponentOf(property1, property2) ||
    !shallow && !!configuration$2[property1.name].shorthandComponents && isSubComponentOf(property1, property2);
}

function isDirectComponentOf(property1, property2) {
  var descriptor = configuration$2[property1.name];

  return 'components' in descriptor && descriptor.components.indexOf(property2.name) > -1;
}

function isSubComponentOf(property1, property2) {
  return property1
    .components
    .some(function (component) {
      return isDirectComponentOf(component, property2);
    });
}

var isComponentOf_1 = isComponentOf$1;

var Marker$4 = marker;

function isMergeableShorthand$1(shorthand) {
  if (shorthand.name != 'font') {
    return true;
  }

  return shorthand.value[0][1].indexOf(Marker$4.INTERNAL) == -1;
}

var isMergeableShorthand_1 = isMergeableShorthand$1;

var configuration$1 = configuration_1;

function overridesNonComponentShorthand$1(property1, property2) {
  return property1.name in configuration$1 &&
    'overridesShorthands' in configuration$1[property1.name] &&
    configuration$1[property1.name].overridesShorthands.indexOf(property2.name) > -1;
}

var overridesNonComponentShorthand_1 = overridesNonComponentShorthand$1;

var hasInherit = hasInherit_1;
var hasUnset = hasUnset_1;
var everyValuesPair = everyValuesPair_1;
var findComponentIn = findComponentIn_1;
var isComponentOf = isComponentOf_1;
var isMergeableShorthand = isMergeableShorthand_1;
var overridesNonComponentShorthand = overridesNonComponentShorthand_1;
var sameVendorPrefixesIn = vendorPrefixes.same;

var configuration = configuration_1;
var deepClone = clone.deep;
var restoreWithComponents$1 = restoreWithComponents_1;
var shallowClone = clone.shallow;

var restoreFromOptimizing$2 = restoreFromOptimizing_1;

var Token$g = token;
var Marker$3 = marker;

var serializeProperty = oneTime.property;

function sameValue(_validator, value1, value2) {
  return value1 === value2;
}

function wouldBreakCompatibility(property, validator) {
  for (var i = 0; i < property.components.length; i++) {
    var component = property.components[i];
    var descriptor = configuration[component.name];
    var canOverride = descriptor && descriptor.canOverride || sameValue;

    var _component = shallowClone(component);
    _component.value = [[Token$g.PROPERTY_VALUE, descriptor.defaultValue]];

    if (!everyValuesPair(canOverride.bind(null, validator), _component, component)) {
      return true;
    }
  }

  return false;
}

function overrideIntoMultiplex(property, by) {
  by.unused = true;

  turnIntoMultiplex(by, multiplexSize(property));
  property.value = by.value;
}

function overrideByMultiplex(property, by) {
  by.unused = true;
  property.multiplex = true;
  property.value = by.value;
}

function overrideSimple(property, by) {
  by.unused = true;
  property.value = by.value;
}

function override$2(property, by) {
  if (by.multiplex)
    overrideByMultiplex(property, by);
  else if (property.multiplex)
    overrideIntoMultiplex(property, by);
  else
    overrideSimple(property, by);
}

function overrideShorthand(property, by) {
  by.unused = true;

  for (var i = 0, l = property.components.length; i < l; i++) {
    override$2(property.components[i], by.components[i]);
  }
}

function turnIntoMultiplex(property, size) {
  property.multiplex = true;

  if (configuration[property.name].shorthand) {
    turnShorthandValueIntoMultiplex(property, size);
  } else {
    turnLonghandValueIntoMultiplex(property, size);
  }
}

function turnShorthandValueIntoMultiplex(property, size) {
  var component;
  var i, l;

  for (i = 0, l = property.components.length; i < l; i++) {
    component = property.components[i];

    if (!component.multiplex) {
      turnLonghandValueIntoMultiplex(component, size);
    }
  }
}

function turnLonghandValueIntoMultiplex(property, size) {
  var descriptor = configuration[property.name];
  var withRealValue = descriptor.intoMultiplexMode == 'real';
  var withValue = descriptor.intoMultiplexMode == 'real' ?
    property.value.slice(0) :
    (descriptor.intoMultiplexMode == 'placeholder' ? descriptor.placeholderValue : descriptor.defaultValue);
  var i = multiplexSize(property);
  var j;
  var m = withValue.length;

  for (; i < size; i++) {
    property.value.push([Token$g.PROPERTY_VALUE, Marker$3.COMMA]);

    if (Array.isArray(withValue)) {
      for (j = 0; j < m; j++) {
        property.value.push(withRealValue ? withValue[j] : [Token$g.PROPERTY_VALUE, withValue[j]]);
      }
    } else {
      property.value.push(withRealValue ? withValue : [Token$g.PROPERTY_VALUE, withValue]);
    }
  }
}

function multiplexSize(component) {
  var size = 0;

  for (var i = 0, l = component.value.length; i < l; i++) {
    if (component.value[i][1] == Marker$3.COMMA)
      size++;
  }

  return size + 1;
}

function lengthOf(property) {
  var fakeAsArray = [
    Token$g.PROPERTY,
    [Token$g.PROPERTY_NAME, property.name]
  ].concat(property.value);
  return serializeProperty([fakeAsArray], 0).length;
}

function moreSameShorthands(properties, startAt, name) {
  // Since we run the main loop in `compactOverrides` backwards, at this point some
  // properties may not be marked as unused.
  // We should consider reverting the order if possible
  var count = 0;

  for (var i = startAt; i >= 0; i--) {
    if (properties[i].name == name && !properties[i].unused)
      count++;
    if (count > 1)
      break;
  }

  return count > 1;
}

function overridingFunction(shorthand, validator) {
  for (var i = 0, l = shorthand.components.length; i < l; i++) {
    if (!anyValue(validator.isUrl, shorthand.components[i]) && anyValue(validator.isFunction, shorthand.components[i])) {
      return true;
    }
  }

  return false;
}

function anyValue(fn, property) {
  for (var i = 0, l = property.value.length; i < l; i++) {
    if (property.value[i][1] == Marker$3.COMMA)
      continue;

    if (fn(property.value[i][1]))
      return true;
  }

  return false;
}

function wouldResultInLongerValue(left, right) {
  if (!left.multiplex && !right.multiplex || left.multiplex && right.multiplex)
    return false;

  var multiplex = left.multiplex ? left : right;
  var simple = left.multiplex ? right : left;
  var component;

  var multiplexClone = deepClone(multiplex);
  restoreFromOptimizing$2([multiplexClone], restoreWithComponents$1);

  var simpleClone = deepClone(simple);
  restoreFromOptimizing$2([simpleClone], restoreWithComponents$1);

  var lengthBefore = lengthOf(multiplexClone) + 1 + lengthOf(simpleClone);

  if (left.multiplex) {
    component = findComponentIn(multiplexClone, simpleClone);
    overrideIntoMultiplex(component, simpleClone);
  } else {
    component = findComponentIn(simpleClone, multiplexClone);
    turnIntoMultiplex(simpleClone, multiplexSize(multiplexClone));
    overrideByMultiplex(component, multiplexClone);
  }

  restoreFromOptimizing$2([simpleClone], restoreWithComponents$1);

  var lengthAfter = lengthOf(simpleClone);

  return lengthBefore <= lengthAfter;
}

function isCompactable(property) {
  return property.name in configuration;
}

function noneOverrideHack(left, right) {
  return !left.multiplex &&
    (left.name == 'background' || left.name == 'background-image') &&
    right.multiplex &&
    (right.name == 'background' || right.name == 'background-image') &&
    anyLayerIsNone(right.value);
}

function anyLayerIsNone(values) {
  var layers = intoLayers(values);

  for (var i = 0, l = layers.length; i < l; i++) {
    if (layers[i].length == 1 && layers[i][0][1] == 'none')
      return true;
  }

  return false;
}

function intoLayers(values) {
  var layers = [];

  for (var i = 0, layer = [], l = values.length; i < l; i++) {
    var value = values[i];
    if (value[1] == Marker$3.COMMA) {
      layers.push(layer);
      layer = [];
    } else {
      layer.push(value);
    }
  }

  layers.push(layer);
  return layers;
}

function overrideProperties$1(properties, withMerging, compatibility, validator) {
  var mayOverride, right, left, component;
  var overriddenComponents;
  var overriddenComponent;
  var overridingComponent;
  var overridable;
  var i, j, k;

  propertyLoop:
  for (i = properties.length - 1; i >= 0; i--) {
    right = properties[i];

    if (!isCompactable(right))
      continue;

    if (right.block)
      continue;

    mayOverride = configuration[right.name].canOverride || sameValue;

    traverseLoop:
    for (j = i - 1; j >= 0; j--) {
      left = properties[j];

      if (!isCompactable(left))
        continue;

      if (left.block)
        continue;

      if (left.dynamic || right.dynamic)
        continue;

      if (left.unused || right.unused)
        continue;

      if (left.hack && !right.hack && !right.important || !left.hack && !left.important && right.hack)
        continue;

      if (left.important == right.important && left.hack[0] != right.hack[0])
        continue;

      if (left.important == right.important && (left.hack[0] != right.hack[0] || (left.hack[1] && left.hack[1] != right.hack[1])))
        continue;

      if (hasInherit(right))
        continue;

      if (noneOverrideHack(left, right))
        continue;

      if (right.shorthand && isComponentOf(right, left)) {
        // maybe `left` can be overridden by `right` which is a shorthand?
        if (!right.important && left.important)
          continue;

        if (!sameVendorPrefixesIn([left], right.components))
          continue;

        if (!anyValue(validator.isFunction, left) && overridingFunction(right, validator))
          continue;

        if (!isMergeableShorthand(right)) {
          left.unused = true;
          continue;
        }

        component = findComponentIn(right, left);
        mayOverride = configuration[left.name].canOverride || sameValue;
        if (everyValuesPair(mayOverride.bind(null, validator), left, component)) {
          left.unused = true;
        }
      } else if (right.shorthand && overridesNonComponentShorthand(right, left)) {
        // `right` is a shorthand while `left` can be overriden by it, think `border` and `border-top`
        if (!right.important && left.important) {
          continue;
        }

        if (!sameVendorPrefixesIn([left], right.components)) {
          continue;
        }

        if (!anyValue(validator.isFunction, left) && overridingFunction(right, validator)) {
          continue;
        }

        overriddenComponents = left.shorthand ?
          left.components:
          [left];

        for (k = overriddenComponents.length - 1; k >= 0; k--) {
          overriddenComponent = overriddenComponents[k];
          overridingComponent = findComponentIn(right, overriddenComponent);
          mayOverride = configuration[overriddenComponent.name].canOverride || sameValue;

          if (!everyValuesPair(mayOverride.bind(null, validator), left, overridingComponent)) {
            continue traverseLoop;
          }
        }

        left.unused = true;
      } else if (withMerging && left.shorthand && !right.shorthand && isComponentOf(left, right, true)) {
        // maybe `right` can be pulled into `left` which is a shorthand?
        if (right.important && !left.important)
          continue;

        if (!right.important && left.important) {
          right.unused = true;
          continue;
        }

        // Pending more clever algorithm in #527
        if (moreSameShorthands(properties, i - 1, left.name))
          continue;

        if (overridingFunction(left, validator))
          continue;

        if (!isMergeableShorthand(left))
          continue;

        if (hasUnset(left) || hasUnset(right))
          continue;

        component = findComponentIn(left, right);
        if (everyValuesPair(mayOverride.bind(null, validator), component, right)) {
          var disabledBackgroundMerging =
            !compatibility.properties.backgroundClipMerging && component.name.indexOf('background-clip') > -1 ||
            !compatibility.properties.backgroundOriginMerging && component.name.indexOf('background-origin') > -1 ||
            !compatibility.properties.backgroundSizeMerging && component.name.indexOf('background-size') > -1;
          var nonMergeableValue = configuration[right.name].nonMergeableValue === right.value[0][1];

          if (disabledBackgroundMerging || nonMergeableValue)
            continue;

          if (!compatibility.properties.merging && wouldBreakCompatibility(left, validator))
            continue;

          if (component.value[0][1] != right.value[0][1] && (hasInherit(left) || hasInherit(right)))
            continue;

          if (wouldResultInLongerValue(left, right))
            continue;

          if (!left.multiplex && right.multiplex)
            turnIntoMultiplex(left, multiplexSize(right));

          override$2(component, right);
          left.dirty = true;
        }
      } else if (withMerging && left.shorthand && right.shorthand && left.name == right.name) {
        // merge if all components can be merged

        if (!left.multiplex && right.multiplex)
          continue;

        if (!right.important && left.important) {
          right.unused = true;
          continue propertyLoop;
        }

        if (right.important && !left.important) {
          left.unused = true;
          continue;
        }

        if (!isMergeableShorthand(right)) {
          left.unused = true;
          continue;
        }

        for (k = left.components.length - 1; k >= 0; k--) {
          var leftComponent = left.components[k];
          var rightComponent = right.components[k];

          mayOverride = configuration[leftComponent.name].canOverride || sameValue;
          if (!everyValuesPair(mayOverride.bind(null, validator), leftComponent, rightComponent))
            continue propertyLoop;
        }

        overrideShorthand(left, right);
        left.dirty = true;
      } else if (withMerging && left.shorthand && right.shorthand && isComponentOf(left, right)) {
        // border is a shorthand but any of its components is a shorthand too

        if (!left.important && right.important)
          continue;

        component = findComponentIn(left, right);
        mayOverride = configuration[right.name].canOverride || sameValue;
        if (!everyValuesPair(mayOverride.bind(null, validator), component, right))
          continue;

        if (left.important && !right.important) {
          right.unused = true;
          continue;
        }

        var rightRestored = configuration[right.name].restore(right, configuration);
        if (rightRestored.length > 1)
          continue;

        component = findComponentIn(left, right);
        override$2(component, right);
        right.dirty = true;
      } else if (left.name == right.name) {
        // two non-shorthands should be merged based on understandability
        overridable = true;

        if (right.shorthand) {
          for (k = right.components.length - 1; k >= 0 && overridable; k--) {
            overriddenComponent = left.components[k];
            overridingComponent = right.components[k];
            mayOverride = configuration[overridingComponent.name].canOverride || sameValue;

            overridable = overridable && everyValuesPair(mayOverride.bind(null, validator), overriddenComponent, overridingComponent);
          }
        } else {
          mayOverride = configuration[right.name].canOverride || sameValue;
          overridable = everyValuesPair(mayOverride.bind(null, validator), left, right);
        }

        if (left.important && !right.important && overridable) {
          right.unused = true;
          continue;
        }

        if (!left.important && right.important && overridable) {
          left.unused = true;
          continue;
        }

        if (!overridable) {
          continue;
        }

        left.unused = true;
      }
    }
  }
}

var overrideProperties_1 = overrideProperties$1;

var mergeIntoShorthands = mergeIntoShorthands_1;
var overrideProperties = overrideProperties_1;
var populateComponents$1 = populateComponents_1;

var restoreWithComponents = restoreWithComponents_1;

var wrapForOptimizing$1 = wrapForOptimizing$3.all;
var removeUnused = removeUnused_1;
var restoreFromOptimizing$1 = restoreFromOptimizing_1;

var OptimizationLevel$5 = optimizationLevel.OptimizationLevel;

function optimizeProperties$4(properties, withOverriding, withMerging, context) {
  var levelOptions = context.options.level[OptimizationLevel$5.Two];
  var _properties = wrapForOptimizing$1(properties, levelOptions.skipProperties);
  var _property;
  var i, l;

  populateComponents$1(_properties, context.validator, context.warnings);

  for (i = 0, l = _properties.length; i < l; i++) {
    _property = _properties[i];
    if (_property.block) {
      optimizeProperties$4(_property.value[0][1], withOverriding, withMerging, context);
    }
  }

  if (withMerging && levelOptions.mergeIntoShorthands) {
    mergeIntoShorthands(_properties, context.validator);
  }

  if (withOverriding && levelOptions.overrideProperties) {
    overrideProperties(_properties, withMerging, context.options.compatibility, context.validator);
  }

  restoreFromOptimizing$1(_properties, restoreWithComponents);
  removeUnused(_properties);
}

var optimize$2 = optimizeProperties$4;

var isMergeable$3 = isMergeable_1;

var optimizeProperties$3 = optimize$2;

var sortSelectors$1 = sortSelectors_1;
var tidyRules$1 = tidyRules_1;

var OptimizationLevel$4 = optimizationLevel.OptimizationLevel;

var serializeBody$4 = oneTime.body;
var serializeRules$8 = oneTime.rules;

var Token$f = token;

function mergeAdjacent$1(tokens, context) {
  var lastToken = [null, [], []];
  var options = context.options;
  var adjacentSpace = options.compatibility.selectors.adjacentSpace;
  var selectorsSortingMethod = options.level[OptimizationLevel$4.One].selectorsSortingMethod;
  var mergeablePseudoClasses = options.compatibility.selectors.mergeablePseudoClasses;
  var mergeablePseudoElements = options.compatibility.selectors.mergeablePseudoElements;
  var mergeLimit = options.compatibility.selectors.mergeLimit;
  var multiplePseudoMerging = options.compatibility.selectors.multiplePseudoMerging;

  for (var i = 0, l = tokens.length; i < l; i++) {
    var token = tokens[i];

    if (token[0] != Token$f.RULE) {
      lastToken = [null, [], []];
      continue;
    }

    if (lastToken[0] == Token$f.RULE && serializeRules$8(token[1]) == serializeRules$8(lastToken[1])) {
      Array.prototype.push.apply(lastToken[2], token[2]);
      optimizeProperties$3(lastToken[2], true, true, context);
      token[2] = [];
    } else if (lastToken[0] == Token$f.RULE && serializeBody$4(token[2]) == serializeBody$4(lastToken[2]) &&
        isMergeable$3(serializeRules$8(token[1]), mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging) &&
        isMergeable$3(serializeRules$8(lastToken[1]), mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging) &&
        lastToken[1].length < mergeLimit) {
      lastToken[1] = tidyRules$1(lastToken[1].concat(token[1]), false, adjacentSpace, false, context.warnings);
      lastToken[1] = lastToken.length > 1 ? sortSelectors$1(lastToken[1], selectorsSortingMethod) : lastToken[1];
      token[2] = [];
    } else {
      lastToken = token;
    }
  }
}

var mergeAdjacent_1 = mergeAdjacent$1;

var MODIFIER_PATTERN = /\-\-.+$/;

function rulesOverlap$2(rule1, rule2, bemMode) {
  var scope1;
  var scope2;
  var i, l;
  var j, m;

  for (i = 0, l = rule1.length; i < l; i++) {
    scope1 = rule1[i][1];

    for (j = 0, m = rule2.length; j < m; j++) {
      scope2 = rule2[j][1];

      if (scope1 == scope2) {
        return true;
      }

      if (bemMode && withoutModifiers(scope1) == withoutModifiers(scope2)) {
        return true;
      }
    }
  }

  return false;
}

function withoutModifiers(scope) {
  return scope.replace(MODIFIER_PATTERN, '');
}

var rulesOverlap_1 = rulesOverlap$2;

var Marker$2 = marker;

var Selector = {
  ADJACENT_SIBLING: '+',
  DESCENDANT: '>',
  DOT: '.',
  HASH: '#',
  NON_ADJACENT_SIBLING: '~',
  PSEUDO: ':'
};

var LETTER_PATTERN = /[a-zA-Z]/;
var NOT_PREFIX = ':not(';
var SEPARATOR_PATTERN = /[\s,\(>~\+]/;

function specificity$1(selector) {
  var result = [0, 0, 0];
  var character;
  var isEscaped;
  var isSingleQuoted;
  var isDoubleQuoted;
  var roundBracketLevel = 0;
  var couldIntroduceNewTypeSelector;
  var withinNotPseudoClass = false;
  var wasPseudoClass = false;
  var i, l;

  for (i = 0, l = selector.length; i < l; i++) {
    character = selector[i];

    if (isEscaped) ; else if (character == Marker$2.SINGLE_QUOTE && !isDoubleQuoted && !isSingleQuoted) {
      isSingleQuoted = true;
    } else if (character == Marker$2.SINGLE_QUOTE && !isDoubleQuoted && isSingleQuoted) {
      isSingleQuoted = false;
    } else if (character == Marker$2.DOUBLE_QUOTE && !isDoubleQuoted && !isSingleQuoted) {
      isDoubleQuoted = true;
    } else if (character == Marker$2.DOUBLE_QUOTE && isDoubleQuoted && !isSingleQuoted) {
      isDoubleQuoted = false;
    } else if (isSingleQuoted || isDoubleQuoted) {
      continue;
    } else if (roundBracketLevel > 0 && !withinNotPseudoClass) ; else if (character == Marker$2.OPEN_ROUND_BRACKET) {
      roundBracketLevel++;
    } else if (character == Marker$2.CLOSE_ROUND_BRACKET && roundBracketLevel == 1) {
      roundBracketLevel--;
      withinNotPseudoClass = false;
    } else if (character == Marker$2.CLOSE_ROUND_BRACKET) {
      roundBracketLevel--;
    } else if (character == Selector.HASH) {
      result[0]++;
    } else if (character == Selector.DOT || character == Marker$2.OPEN_SQUARE_BRACKET) {
      result[1]++;
    } else if (character == Selector.PSEUDO && !wasPseudoClass && !isNotPseudoClass(selector, i)) {
      result[1]++;
      withinNotPseudoClass = false;
    } else if (character == Selector.PSEUDO) {
      withinNotPseudoClass = true;
    } else if ((i === 0 || couldIntroduceNewTypeSelector) && LETTER_PATTERN.test(character)) {
      result[2]++;
    }

    isEscaped = character == Marker$2.BACK_SLASH;
    wasPseudoClass = character == Selector.PSEUDO;
    couldIntroduceNewTypeSelector = !isEscaped && SEPARATOR_PATTERN.test(character);
  }

  return result;
}

function isNotPseudoClass(selector, index) {
  return selector.indexOf(NOT_PREFIX, index) === index;
}

var specificity_1 = specificity$1;

var specificity = specificity_1;

function specificitiesOverlap$1(selector1, selector2, cache) {
  var specificity1;
  var specificity2;
  var i, l;
  var j, m;

  for (i = 0, l = selector1.length; i < l; i++) {
    specificity1 = findSpecificity(selector1[i][1], cache);

    for (j = 0, m = selector2.length; j < m; j++) {
      specificity2 = findSpecificity(selector2[j][1], cache);

      if (specificity1[0] === specificity2[0] && specificity1[1] === specificity2[1] && specificity1[2] === specificity2[2]) {
        return true;
      }
    }
  }

  return false;
}

function findSpecificity(selector, cache) {
  var value;

  if (!(selector in cache)) {
    cache[selector] = value = specificity(selector);
  }

  return value || cache[selector];
}

var specificitiesOverlap_1 = specificitiesOverlap$1;

// TODO: it'd be great to merge it with the other canReorder functionality

var rulesOverlap$1 = rulesOverlap_1;
var specificitiesOverlap = specificitiesOverlap_1;

var FLEX_PROPERTIES = /align\-items|box\-align|box\-pack|flex|justify/;
var BORDER_PROPERTIES = /^border\-(top|right|bottom|left|color|style|width|radius)/;

function canReorder$2(left, right, cache) {
  for (var i = right.length - 1; i >= 0; i--) {
    for (var j = left.length - 1; j >= 0; j--) {
      if (!canReorderSingle$2(left[j], right[i], cache))
        return false;
    }
  }

  return true;
}

function canReorderSingle$2(left, right, cache) {
  var leftName = left[0];
  var leftValue = left[1];
  var leftNameRoot = left[2];
  var leftSelector = left[5];
  var leftInSpecificSelector = left[6];
  var rightName = right[0];
  var rightValue = right[1];
  var rightNameRoot = right[2];
  var rightSelector = right[5];
  var rightInSpecificSelector = right[6];

  if (leftName == 'font' && rightName == 'line-height' || rightName == 'font' && leftName == 'line-height')
    return false;
  if (FLEX_PROPERTIES.test(leftName) && FLEX_PROPERTIES.test(rightName))
    return false;
  if (leftNameRoot == rightNameRoot && unprefixed(leftName) == unprefixed(rightName) && (vendorPrefixed(leftName) ^ vendorPrefixed(rightName)))
    return false;
  if (leftNameRoot == 'border' && BORDER_PROPERTIES.test(rightNameRoot) && (leftName == 'border' || leftName == rightNameRoot || (leftValue != rightValue && sameBorderComponent(leftName, rightName))))
    return false;
  if (rightNameRoot == 'border' && BORDER_PROPERTIES.test(leftNameRoot) && (rightName == 'border' || rightName == leftNameRoot || (leftValue != rightValue && sameBorderComponent(leftName, rightName))))
    return false;
  if (leftNameRoot == 'border' && rightNameRoot == 'border' && leftName != rightName && (isSideBorder(leftName) && isStyleBorder(rightName) || isStyleBorder(leftName) && isSideBorder(rightName)))
    return false;
  if (leftNameRoot != rightNameRoot)
    return true;
  if (leftName == rightName && leftNameRoot == rightNameRoot && (leftValue == rightValue || withDifferentVendorPrefix(leftValue, rightValue)))
    return true;
  if (leftName != rightName && leftNameRoot == rightNameRoot && leftName != leftNameRoot && rightName != rightNameRoot)
    return true;
  if (leftName != rightName && leftNameRoot == rightNameRoot && leftValue == rightValue)
    return true;
  if (rightInSpecificSelector && leftInSpecificSelector && !inheritable(leftNameRoot) && !inheritable(rightNameRoot) && !rulesOverlap$1(rightSelector, leftSelector, false))
    return true;
  if (!specificitiesOverlap(leftSelector, rightSelector, cache))
    return true;

  return false;
}

function vendorPrefixed(name) {
  return /^\-(?:moz|webkit|ms|o)\-/.test(name);
}

function unprefixed(name) {
  return name.replace(/^\-(?:moz|webkit|ms|o)\-/, '');
}

function sameBorderComponent(name1, name2) {
  return name1.split('-').pop() == name2.split('-').pop();
}

function isSideBorder(name) {
  return name == 'border-top' || name == 'border-right' || name == 'border-bottom' || name == 'border-left';
}

function isStyleBorder(name) {
  return name == 'border-color' || name == 'border-style' || name == 'border-width';
}

function withDifferentVendorPrefix(value1, value2) {
  return vendorPrefixed(value1) && vendorPrefixed(value2) && value1.split('-')[1] != value2.split('-')[2];
}

function inheritable(name) {
  // According to http://www.w3.org/TR/CSS21/propidx.html
  // Others will be catched by other, preceeding rules
  return name == 'font' || name == 'line-height' || name == 'list-style';
}

var reorderable = {
  canReorder: canReorder$2,
  canReorderSingle: canReorderSingle$2
};

// This extractor is used in level 2 optimizations
// IMPORTANT: Mind Token class and this code is not related!
// Properties will be tokenized in one step, see #429

var Token$e = token;
var serializeRules$7 = oneTime.rules;
var serializeValue = oneTime.value;

function extractProperties$3(token) {
  var properties = [];
  var inSpecificSelector;
  var property;
  var name;
  var value;
  var i, l;

  if (token[0] == Token$e.RULE) {
    inSpecificSelector = !/[\.\+>~]/.test(serializeRules$7(token[1]));

    for (i = 0, l = token[2].length; i < l; i++) {
      property = token[2][i];

      if (property[0] != Token$e.PROPERTY)
        continue;

      name = property[1][1];
      if (name.length === 0)
        continue;

      value = serializeValue(property, i);

      properties.push([
        name,
        value,
        findNameRoot(name),
        token[2][i],
        name + ':' + value,
        token[1],
        inSpecificSelector
      ]);
    }
  } else if (token[0] == Token$e.NESTED_BLOCK) {
    for (i = 0, l = token[2].length; i < l; i++) {
      properties = properties.concat(extractProperties$3(token[2][i]));
    }
  }

  return properties;
}

function findNameRoot(name) {
  if (name == 'list-style')
    return name;
  if (name.indexOf('-radius') > 0)
    return 'border-radius';
  if (name == 'border-collapse' || name == 'border-spacing' || name == 'border-image')
    return name;
  if (name.indexOf('border-') === 0 && /^border\-\w+\-\w+$/.test(name))
    return name.match(/border\-\w+/)[0];
  if (name.indexOf('border-') === 0 && /^border\-\w+$/.test(name))
    return 'border';
  if (name.indexOf('text-') === 0)
    return name;
  if (name == '-chrome-')
    return name;

  return name.replace(/^\-\w+\-/, '').match(/([a-zA-Z]+)/)[0].toLowerCase();
}

var extractProperties_1 = extractProperties$3;

var canReorder$1 = reorderable.canReorder;
var canReorderSingle$1 = reorderable.canReorderSingle;
var extractProperties$2 = extractProperties_1;
var rulesOverlap = rulesOverlap_1;

var serializeRules$6 = oneTime.rules;
var OptimizationLevel$3 = optimizationLevel.OptimizationLevel;
var Token$d = token;

function mergeMediaQueries$1(tokens, context) {
  var mergeSemantically = context.options.level[OptimizationLevel$3.Two].mergeSemantically;
  var specificityCache = context.cache.specificity;
  var candidates = {};
  var reduced = [];

  for (var i = tokens.length - 1; i >= 0; i--) {
    var token = tokens[i];
    if (token[0] != Token$d.NESTED_BLOCK) {
      continue;
    }

    var key = serializeRules$6(token[1]);
    var candidate = candidates[key];
    if (!candidate) {
      candidate = [];
      candidates[key] = candidate;
    }

    candidate.push(i);
  }

  for (var name in candidates) {
    var positions = candidates[name];

    positionLoop:
    for (var j = positions.length - 1; j > 0; j--) {
      var positionOne = positions[j];
      var tokenOne = tokens[positionOne];
      var positionTwo = positions[j - 1];
      var tokenTwo = tokens[positionTwo];

      directionLoop:
      for (var direction = 1; direction >= -1; direction -= 2) {
        var topToBottom = direction == 1;
        var from = topToBottom ? positionOne + 1 : positionTwo - 1;
        var to = topToBottom ? positionTwo : positionOne;
        var delta = topToBottom ? 1 : -1;
        var source = topToBottom ? tokenOne : tokenTwo;
        var target = topToBottom ? tokenTwo : tokenOne;
        var movedProperties = extractProperties$2(source);

        while (from != to) {
          var traversedProperties = extractProperties$2(tokens[from]);
          from += delta;

          if (mergeSemantically && allSameRulePropertiesCanBeReordered(movedProperties, traversedProperties, specificityCache)) {
            continue;
          }

          if (!canReorder$1(movedProperties, traversedProperties, specificityCache))
            continue directionLoop;
        }

        target[2] = topToBottom ?
          source[2].concat(target[2]) :
          target[2].concat(source[2]);
        source[2] = [];

        reduced.push(target);
        continue positionLoop;
      }
    }
  }

  return reduced;
}

function allSameRulePropertiesCanBeReordered(movedProperties, traversedProperties, specificityCache) {
  var movedProperty;
  var movedRule;
  var traversedProperty;
  var traversedRule;
  var i, l;
  var j, m;

  for (i = 0, l = movedProperties.length; i < l; i++) {
    movedProperty = movedProperties[i];
    movedRule = movedProperty[5];

    for (j = 0, m = traversedProperties.length; j < m; j++) {
      traversedProperty = traversedProperties[j];
      traversedRule = traversedProperty[5];

      if (rulesOverlap(movedRule, traversedRule, true) && !canReorderSingle$1(movedProperty, traversedProperty, specificityCache)) {
        return false;
      }
    }
  }

  return true;
}

var mergeMediaQueries_1 = mergeMediaQueries$1;

var isMergeable$2 = isMergeable_1;

var sortSelectors = sortSelectors_1;
var tidyRules = tidyRules_1;

var OptimizationLevel$2 = optimizationLevel.OptimizationLevel;

var serializeBody$3 = oneTime.body;
var serializeRules$5 = oneTime.rules;

var Token$c = token;

function unsafeSelector(value) {
  return /\.|\*| :/.test(value);
}

function isBemElement(token) {
  var asString = serializeRules$5(token[1]);
  return asString.indexOf('__') > -1 || asString.indexOf('--') > -1;
}

function withoutModifier(selector) {
  return selector.replace(/--[^ ,>\+~:]+/g, '');
}

function removeAnyUnsafeElements(left, candidates) {
  var leftSelector = withoutModifier(serializeRules$5(left[1]));

  for (var body in candidates) {
    var right = candidates[body];
    var rightSelector = withoutModifier(serializeRules$5(right[1]));

    if (rightSelector.indexOf(leftSelector) > -1 || leftSelector.indexOf(rightSelector) > -1)
      delete candidates[body];
  }
}

function mergeNonAdjacentByBody$1(tokens, context) {
  var options = context.options;
  var mergeSemantically = options.level[OptimizationLevel$2.Two].mergeSemantically;
  var adjacentSpace = options.compatibility.selectors.adjacentSpace;
  var selectorsSortingMethod = options.level[OptimizationLevel$2.One].selectorsSortingMethod;
  var mergeablePseudoClasses = options.compatibility.selectors.mergeablePseudoClasses;
  var mergeablePseudoElements = options.compatibility.selectors.mergeablePseudoElements;
  var multiplePseudoMerging = options.compatibility.selectors.multiplePseudoMerging;
  var candidates = {};

  for (var i = tokens.length - 1; i >= 0; i--) {
    var token = tokens[i];
    if (token[0] != Token$c.RULE)
      continue;

    if (token[2].length > 0 && (!mergeSemantically && unsafeSelector(serializeRules$5(token[1]))))
      candidates = {};

    if (token[2].length > 0 && mergeSemantically && isBemElement(token))
      removeAnyUnsafeElements(token, candidates);

    var candidateBody = serializeBody$3(token[2]);
    var oldToken = candidates[candidateBody];
    if (oldToken &&
        isMergeable$2(serializeRules$5(token[1]), mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging) &&
        isMergeable$2(serializeRules$5(oldToken[1]), mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging)) {

      if (token[2].length > 0) {
        token[1] = tidyRules(oldToken[1].concat(token[1]), false, adjacentSpace, false, context.warnings);
        token[1] = token[1].length > 1 ? sortSelectors(token[1], selectorsSortingMethod) : token[1];
      } else {
        token[1] = oldToken[1].concat(token[1]);
      }

      oldToken[2] = [];
      candidates[candidateBody] = null;
    }

    candidates[serializeBody$3(token[2])] = token;
  }
}

var mergeNonAdjacentByBody_1 = mergeNonAdjacentByBody$1;

var canReorder = reorderable.canReorder;
var extractProperties$1 = extractProperties_1;

var optimizeProperties$2 = optimize$2;

var serializeRules$4 = oneTime.rules;

var Token$b = token;

function mergeNonAdjacentBySelector$1(tokens, context) {
  var specificityCache = context.cache.specificity;
  var allSelectors = {};
  var repeatedSelectors = [];
  var i;

  for (i = tokens.length - 1; i >= 0; i--) {
    if (tokens[i][0] != Token$b.RULE)
      continue;
    if (tokens[i][2].length === 0)
      continue;

    var selector = serializeRules$4(tokens[i][1]);
    allSelectors[selector] = [i].concat(allSelectors[selector] || []);

    if (allSelectors[selector].length == 2)
      repeatedSelectors.push(selector);
  }

  for (i = repeatedSelectors.length - 1; i >= 0; i--) {
    var positions = allSelectors[repeatedSelectors[i]];

    selectorIterator:
    for (var j = positions.length - 1; j > 0; j--) {
      var positionOne = positions[j - 1];
      var tokenOne = tokens[positionOne];
      var positionTwo = positions[j];
      var tokenTwo = tokens[positionTwo];

      directionIterator:
      for (var direction = 1; direction >= -1; direction -= 2) {
        var topToBottom = direction == 1;
        var from = topToBottom ? positionOne + 1 : positionTwo - 1;
        var to = topToBottom ? positionTwo : positionOne;
        var delta = topToBottom ? 1 : -1;
        var moved = topToBottom ? tokenOne : tokenTwo;
        var target = topToBottom ? tokenTwo : tokenOne;
        var movedProperties = extractProperties$1(moved);

        while (from != to) {
          var traversedProperties = extractProperties$1(tokens[from]);
          from += delta;

          // traversed then moved as we move selectors towards the start
          var reorderable = topToBottom ?
            canReorder(movedProperties, traversedProperties, specificityCache) :
            canReorder(traversedProperties, movedProperties, specificityCache);

          if (!reorderable && !topToBottom)
            continue selectorIterator;
          if (!reorderable && topToBottom)
            continue directionIterator;
        }

        if (topToBottom) {
          Array.prototype.push.apply(moved[2], target[2]);
          target[2] = moved[2];
        } else {
          Array.prototype.push.apply(target[2], moved[2]);
        }

        optimizeProperties$2(target[2], true, true, context);
        moved[2] = [];
      }
    }
  }
}

var mergeNonAdjacentBySelector_1 = mergeNonAdjacentBySelector$1;

function cloneArray$2(array) {
  var cloned = array.slice(0);

  for (var i = 0, l = cloned.length; i < l; i++) {
    if (Array.isArray(cloned[i]))
      cloned[i] = cloneArray$2(cloned[i]);
  }

  return cloned;
}

var cloneArray_1 = cloneArray$2;

var isMergeable$1 = isMergeable_1;

var optimizeProperties$1 = optimize$2;

var cloneArray$1 = cloneArray_1;

var Token$a = token;

var serializeBody$2 = oneTime.body;
var serializeRules$3 = oneTime.rules;

function reduceNonAdjacent$1(tokens, context) {
  var options = context.options;
  var mergeablePseudoClasses = options.compatibility.selectors.mergeablePseudoClasses;
  var mergeablePseudoElements = options.compatibility.selectors.mergeablePseudoElements;
  var multiplePseudoMerging = options.compatibility.selectors.multiplePseudoMerging;
  var candidates = {};
  var repeated = [];

  for (var i = tokens.length - 1; i >= 0; i--) {
    var token = tokens[i];

    if (token[0] != Token$a.RULE) {
      continue;
    } else if (token[2].length === 0) {
      continue;
    }

    var selectorAsString = serializeRules$3(token[1]);
    var isComplexAndNotSpecial = token[1].length > 1 &&
      isMergeable$1(selectorAsString, mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging);
    var wrappedSelectors = wrappedSelectorsFrom(token[1]);
    var selectors = isComplexAndNotSpecial ?
      [selectorAsString].concat(wrappedSelectors) :
      [selectorAsString];

    for (var j = 0, m = selectors.length; j < m; j++) {
      var selector = selectors[j];

      if (!candidates[selector])
        candidates[selector] = [];
      else
        repeated.push(selector);

      candidates[selector].push({
        where: i,
        list: wrappedSelectors,
        isPartial: isComplexAndNotSpecial && j > 0,
        isComplex: isComplexAndNotSpecial && j === 0
      });
    }
  }

  reduceSimpleNonAdjacentCases(tokens, repeated, candidates, options, context);
  reduceComplexNonAdjacentCases(tokens, candidates, options, context);
}

function wrappedSelectorsFrom(list) {
  var wrapped = [];

  for (var i = 0; i < list.length; i++) {
    wrapped.push([list[i][1]]);
  }

  return wrapped;
}

function reduceSimpleNonAdjacentCases(tokens, repeated, candidates, options, context) {
  function filterOut(idx, bodies) {
    return data[idx].isPartial && bodies.length === 0;
  }

  function reduceBody(token, newBody, processedCount, tokenIdx) {
    if (!data[processedCount - tokenIdx - 1].isPartial)
      token[2] = newBody;
  }

  for (var i = 0, l = repeated.length; i < l; i++) {
    var selector = repeated[i];
    var data = candidates[selector];

    reduceSelector(tokens, data, {
      filterOut: filterOut,
      callback: reduceBody
    }, options, context);
  }
}

function reduceComplexNonAdjacentCases(tokens, candidates, options, context) {
  var mergeablePseudoClasses = options.compatibility.selectors.mergeablePseudoClasses;
  var mergeablePseudoElements = options.compatibility.selectors.mergeablePseudoElements;
  var multiplePseudoMerging = options.compatibility.selectors.multiplePseudoMerging;
  var localContext = {};

  function filterOut(idx) {
    return localContext.data[idx].where < localContext.intoPosition;
  }

  function collectReducedBodies(token, newBody, processedCount, tokenIdx) {
    if (tokenIdx === 0)
      localContext.reducedBodies.push(newBody);
  }

  allSelectors:
  for (var complexSelector in candidates) {
    var into = candidates[complexSelector];
    if (!into[0].isComplex)
      continue;

    var intoPosition = into[into.length - 1].where;
    var intoToken = tokens[intoPosition];
    var reducedBodies = [];

    var selectors = isMergeable$1(complexSelector, mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging) ?
      into[0].list :
      [complexSelector];

    localContext.intoPosition = intoPosition;
    localContext.reducedBodies = reducedBodies;

    for (var j = 0, m = selectors.length; j < m; j++) {
      var selector = selectors[j];
      var data = candidates[selector];

      if (data.length < 2)
        continue allSelectors;

      localContext.data = data;

      reduceSelector(tokens, data, {
        filterOut: filterOut,
        callback: collectReducedBodies
      }, options, context);

      if (serializeBody$2(reducedBodies[reducedBodies.length - 1]) != serializeBody$2(reducedBodies[0]))
        continue allSelectors;
    }

    intoToken[2] = reducedBodies[0];
  }
}

function reduceSelector(tokens, data, context, options, outerContext) {
  var bodies = [];
  var bodiesAsList = [];
  var processedTokens = [];

  for (var j = data.length - 1; j >= 0; j--) {
    if (context.filterOut(j, bodies))
      continue;

    var where = data[j].where;
    var token = tokens[where];
    var clonedBody = cloneArray$1(token[2]);

    bodies = bodies.concat(clonedBody);
    bodiesAsList.push(clonedBody);
    processedTokens.push(where);
  }

  optimizeProperties$1(bodies, true, false, outerContext);

  var processedCount = processedTokens.length;
  var propertyIdx = bodies.length - 1;
  var tokenIdx = processedCount - 1;

  while (tokenIdx >= 0) {
     if ((tokenIdx === 0 || (bodies[propertyIdx] && bodiesAsList[tokenIdx].indexOf(bodies[propertyIdx]) > -1)) && propertyIdx > -1) {
      propertyIdx--;
      continue;
    }

    var newBody = bodies.splice(propertyIdx + 1);
    context.callback(tokens[processedTokens[tokenIdx]], newBody, processedCount, tokenIdx);

    tokenIdx--;
  }
}

var reduceNonAdjacent_1 = reduceNonAdjacent$1;

var Token$9 = token;

var serializeAll$1 = oneTime.all;

var FONT_FACE_SCOPE = '@font-face';

function removeDuplicateFontAtRules$1(tokens) {
  var fontAtRules = [];
  var token;
  var key;
  var i, l;

  for (i = 0, l = tokens.length; i < l; i++) {
    token = tokens[i];

    if (token[0] != Token$9.AT_RULE_BLOCK && token[1][0][1] != FONT_FACE_SCOPE) {
      continue;
    }

    key = serializeAll$1([token]);

    if (fontAtRules.indexOf(key) > -1) {
      token[2] = [];
    } else {
      fontAtRules.push(key);
    }
  }
}

var removeDuplicateFontAtRules_1 = removeDuplicateFontAtRules$1;

var Token$8 = token;

var serializeAll = oneTime.all;
var serializeRules$2 = oneTime.rules;

function removeDuplicateMediaQueries$1(tokens) {
  var candidates = {};
  var candidate;
  var token;
  var key;
  var i, l;

  for (i = 0, l = tokens.length; i < l; i++) {
    token = tokens[i];
    if (token[0] != Token$8.NESTED_BLOCK) {
      continue;
    }

    key = serializeRules$2(token[1]) + '%' + serializeAll(token[2]);
    candidate = candidates[key];

    if (candidate) {
      candidate[2] = [];
    }

    candidates[key] = token;
  }
}

var removeDuplicateMediaQueries_1 = removeDuplicateMediaQueries$1;

var Token$7 = token;

var serializeBody$1 = oneTime.body;
var serializeRules$1 = oneTime.rules;

function removeDuplicates$1(tokens) {
  var matched = {};
  var moreThanOnce = [];
  var id, token;
  var body, bodies;

  for (var i = 0, l = tokens.length; i < l; i++) {
    token = tokens[i];
    if (token[0] != Token$7.RULE)
      continue;

    id = serializeRules$1(token[1]);

    if (matched[id] && matched[id].length == 1)
      moreThanOnce.push(id);
    else
      matched[id] = matched[id] || [];

    matched[id].push(i);
  }

  for (i = 0, l = moreThanOnce.length; i < l; i++) {
    id = moreThanOnce[i];
    bodies = [];

    for (var j = matched[id].length - 1; j >= 0; j--) {
      token = tokens[matched[id][j]];
      body = serializeBody$1(token[2]);

      if (bodies.indexOf(body) > -1)
        token[2] = [];
      else
        bodies.push(body);
    }
  }
}

var removeDuplicates_1 = removeDuplicates$1;

var populateComponents = populateComponents_1;

var wrapForOptimizing = wrapForOptimizing$3.single;
var restoreFromOptimizing = restoreFromOptimizing_1;

var Token$6 = token;

var animationNameRegex = /^(\-moz\-|\-o\-|\-webkit\-)?animation-name$/;
var animationRegex = /^(\-moz\-|\-o\-|\-webkit\-)?animation$/;
var keyframeRegex = /^@(\-moz\-|\-o\-|\-webkit\-)?keyframes /;
var importantRegex = /\s{0,31}!important$/;
var optionalMatchingQuotesRegex = /^(['"]?)(.*)\1$/;

function normalize$1(value) {
  return value
    .replace(optionalMatchingQuotesRegex, '$2')
    .replace(importantRegex, '');
}

function removeUnusedAtRules$1(tokens, context) {
  removeUnusedAtRule(tokens, matchCounterStyle, markCounterStylesAsUsed, context);
  removeUnusedAtRule(tokens, matchFontFace, markFontFacesAsUsed, context);
  removeUnusedAtRule(tokens, matchKeyframe, markKeyframesAsUsed, context);
  removeUnusedAtRule(tokens, matchNamespace, markNamespacesAsUsed, context);
}

function removeUnusedAtRule(tokens, matchCallback, markCallback, context) {
  var atRules = {};
  var atRule;
  var atRuleTokens;
  var atRuleToken;
  var zeroAt;
  var i, l;

  for (i = 0, l = tokens.length; i < l; i++) {
    matchCallback(tokens[i], atRules);
  }

  if (Object.keys(atRules).length === 0) {
    return;
  }

  markUsedAtRules(tokens, markCallback, atRules, context);

  for (atRule in atRules) {
    atRuleTokens = atRules[atRule];

    for (i = 0, l = atRuleTokens.length; i < l; i++) {
      atRuleToken = atRuleTokens[i];
      zeroAt = atRuleToken[0] == Token$6.AT_RULE ? 1 : 2;
      atRuleToken[zeroAt] = [];
    }
  }
}

function markUsedAtRules(tokens, markCallback, atRules, context) {
  var boundMarkCallback = markCallback(atRules);
  var i, l;

  for (i = 0, l = tokens.length; i < l; i++) {
    switch (tokens[i][0]) {
      case Token$6.RULE:
        boundMarkCallback(tokens[i], context);
        break;
      case Token$6.NESTED_BLOCK:
        markUsedAtRules(tokens[i][2], markCallback, atRules, context);
    }
  }
}

function matchCounterStyle(token, atRules) {
  var match;

  if (token[0] == Token$6.AT_RULE_BLOCK && token[1][0][1].indexOf('@counter-style') === 0) {
    match = token[1][0][1].split(' ')[1];
    atRules[match] = atRules[match] || [];
    atRules[match].push(token);
  }
}

function markCounterStylesAsUsed(atRules) {
  return function (token, context) {
    var property;
    var wrappedProperty;
    var i, l;

    for (i = 0, l = token[2].length; i < l; i++) {
      property = token[2][i];

      if (property[1][1] == 'list-style') {
        wrappedProperty = wrapForOptimizing(property);
        populateComponents([wrappedProperty], context.validator, context.warnings);

        if (wrappedProperty.components[0].value[0][1] in atRules) {
          delete atRules[property[2][1]];
        }

        restoreFromOptimizing([wrappedProperty]);
      }

      if (property[1][1] == 'list-style-type' && property[2][1] in atRules) {
        delete atRules[property[2][1]];
      }
    }
  };
}

function matchFontFace(token, atRules) {
  var property;
  var match;
  var i, l;

  if (token[0] == Token$6.AT_RULE_BLOCK && token[1][0][1] == '@font-face') {
    for (i = 0, l = token[2].length; i < l; i++) {
      property = token[2][i];

      if (property[1][1] == 'font-family') {
        match = normalize$1(property[2][1].toLowerCase());
        atRules[match] = atRules[match] || [];
        atRules[match].push(token);
        break;
      }
    }
  }
}

function markFontFacesAsUsed(atRules) {
  return function (token, context) {
    var property;
    var wrappedProperty;
    var component;
    var normalizedMatch;
    var i, l;
    var j, m;

    for (i = 0, l = token[2].length; i < l; i++) {
      property = token[2][i];

      if (property[1][1] == 'font') {
        wrappedProperty = wrapForOptimizing(property);
        populateComponents([wrappedProperty], context.validator, context.warnings);
        component = wrappedProperty.components[6];

        for (j = 0, m = component.value.length; j < m; j++) {
          normalizedMatch = normalize$1(component.value[j][1].toLowerCase());

          if (normalizedMatch in atRules) {
            delete atRules[normalizedMatch];
          }
        }

        restoreFromOptimizing([wrappedProperty]);
      }

      if (property[1][1] == 'font-family') {
        for (j = 2, m = property.length; j < m; j++) {
          normalizedMatch = normalize$1(property[j][1].toLowerCase());

          if (normalizedMatch in atRules) {
            delete atRules[normalizedMatch];
          }
        }
      }
    }
  };
}

function matchKeyframe(token, atRules) {
  var match;

  if (token[0] == Token$6.NESTED_BLOCK && keyframeRegex.test(token[1][0][1])) {
    match = token[1][0][1].split(' ')[1];
    atRules[match] = atRules[match] || [];
    atRules[match].push(token);
  }
}

function markKeyframesAsUsed(atRules) {
  return function (token, context) {
    var property;
    var wrappedProperty;
    var component;
    var i, l;
    var j, m;

    for (i = 0, l = token[2].length; i < l; i++) {
      property = token[2][i];

      if (animationRegex.test(property[1][1])) {
        wrappedProperty = wrapForOptimizing(property);
        populateComponents([wrappedProperty], context.validator, context.warnings);
        component = wrappedProperty.components[7];

        for (j = 0, m = component.value.length; j < m; j++) {
          if (component.value[j][1] in atRules) {
            delete atRules[component.value[j][1]];
          }
        }

        restoreFromOptimizing([wrappedProperty]);
      }

      if (animationNameRegex.test(property[1][1])) {
        for (j = 2, m = property.length; j < m; j++) {
          if (property[j][1] in atRules) {
            delete atRules[property[j][1]];
          }
        }
      }
    }
  };
}

function matchNamespace(token, atRules) {
  var match;

  if (token[0] == Token$6.AT_RULE && token[1].indexOf('@namespace') === 0) {
    match = token[1].split(' ')[1];
    atRules[match] = atRules[match] || [];
    atRules[match].push(token);
  }
}

function markNamespacesAsUsed(atRules) {
  var namespaceRegex = new RegExp(Object.keys(atRules).join('\\\||') + '\\\|', 'g');

  return function (token) {
    var match;
    var scope;
    var normalizedMatch;
    var i, l;
    var j, m;

    for (i = 0, l = token[1].length; i < l; i++) {
      scope = token[1][i];
      match = scope[1].match(namespaceRegex);

      for (j = 0, m = match.length; j < m; j++) {
        normalizedMatch = match[j].substring(0, match[j].length - 1);

        if (normalizedMatch in atRules) {
          delete atRules[normalizedMatch];
        }
      }
    }
  };
}

var removeUnusedAtRules_1 = removeUnusedAtRules$1;

function ruleSorter(s1, s2) {
  return s1[1] > s2[1] ? 1 : -1;
}

function tidyRuleDuplicates$1(rules) {
  var list = [];
  var repeated = [];

  for (var i = 0, l = rules.length; i < l; i++) {
    var rule = rules[i];

    if (repeated.indexOf(rule[1]) == -1) {
      repeated.push(rule[1]);
      list.push(rule);
    }
  }

  return list.sort(ruleSorter);
}

var tidyRuleDuplicates_1 = tidyRuleDuplicates$1;

var canReorderSingle = reorderable.canReorderSingle;
var extractProperties = extractProperties_1;
var isMergeable = isMergeable_1;
var tidyRuleDuplicates = tidyRuleDuplicates_1;

var Token$5 = token;

var cloneArray = cloneArray_1;

var serializeBody = oneTime.body;
var serializeRules = oneTime.rules;

function naturalSorter(a, b) {
  return a > b ? 1 : -1;
}

function cloneAndMergeSelectors(propertyA, propertyB) {
  var cloned = cloneArray(propertyA);
  cloned[5] = cloned[5].concat(propertyB[5]);

  return cloned;
}

function restructure$1(tokens, context) {
  var options = context.options;
  var mergeablePseudoClasses = options.compatibility.selectors.mergeablePseudoClasses;
  var mergeablePseudoElements = options.compatibility.selectors.mergeablePseudoElements;
  var mergeLimit = options.compatibility.selectors.mergeLimit;
  var multiplePseudoMerging = options.compatibility.selectors.multiplePseudoMerging;
  var specificityCache = context.cache.specificity;
  var movableTokens = {};
  var movedProperties = [];
  var multiPropertyMoveCache = {};
  var movedToBeDropped = [];
  var maxCombinationsLevel = 2;
  var ID_JOIN_CHARACTER = '%';

  function sendToMultiPropertyMoveCache(position, movedProperty, allFits) {
    for (var i = allFits.length - 1; i >= 0; i--) {
      var fit = allFits[i][0];
      var id = addToCache(movedProperty, fit);

      if (multiPropertyMoveCache[id].length > 1 && processMultiPropertyMove(position, multiPropertyMoveCache[id])) {
        removeAllMatchingFromCache(id);
        break;
      }
    }
  }

  function addToCache(movedProperty, fit) {
    var id = cacheId(fit);
    multiPropertyMoveCache[id] = multiPropertyMoveCache[id] || [];
    multiPropertyMoveCache[id].push([movedProperty, fit]);
    return id;
  }

  function removeAllMatchingFromCache(matchId) {
    var matchSelectors = matchId.split(ID_JOIN_CHARACTER);
    var forRemoval = [];
    var i;

    for (var id in multiPropertyMoveCache) {
      var selectors = id.split(ID_JOIN_CHARACTER);
      for (i = selectors.length - 1; i >= 0; i--) {
        if (matchSelectors.indexOf(selectors[i]) > -1) {
          forRemoval.push(id);
          break;
        }
      }
    }

    for (i = forRemoval.length - 1; i >= 0; i--) {
      delete multiPropertyMoveCache[forRemoval[i]];
    }
  }

  function cacheId(cachedTokens) {
    var id = [];
    for (var i = 0, l = cachedTokens.length; i < l; i++) {
      id.push(serializeRules(cachedTokens[i][1]));
    }
    return id.join(ID_JOIN_CHARACTER);
  }

  function tokensToMerge(sourceTokens) {
    var uniqueTokensWithBody = [];
    var mergeableTokens = [];

    for (var i = sourceTokens.length - 1; i >= 0; i--) {
      if (!isMergeable(serializeRules(sourceTokens[i][1]), mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging)) {
        continue;
      }

      mergeableTokens.unshift(sourceTokens[i]);
      if (sourceTokens[i][2].length > 0 && uniqueTokensWithBody.indexOf(sourceTokens[i]) == -1)
        uniqueTokensWithBody.push(sourceTokens[i]);
    }

    return uniqueTokensWithBody.length > 1 ?
      mergeableTokens :
      [];
  }

  function shortenIfPossible(position, movedProperty) {
    var name = movedProperty[0];
    var value = movedProperty[1];
    var key = movedProperty[4];
    var valueSize = name.length + value.length + 1;
    var allSelectors = [];
    var qualifiedTokens = [];

    var mergeableTokens = tokensToMerge(movableTokens[key]);
    if (mergeableTokens.length < 2)
      return;

    var allFits = findAllFits(mergeableTokens, valueSize, 1);
    var bestFit = allFits[0];
    if (bestFit[1] > 0)
      return sendToMultiPropertyMoveCache(position, movedProperty, allFits);

    for (var i = bestFit[0].length - 1; i >=0; i--) {
      allSelectors = bestFit[0][i][1].concat(allSelectors);
      qualifiedTokens.unshift(bestFit[0][i]);
    }

    allSelectors = tidyRuleDuplicates(allSelectors);
    dropAsNewTokenAt(position, [movedProperty], allSelectors, qualifiedTokens);
  }

  function fitSorter(fit1, fit2) {
    return fit1[1] > fit2[1] ? 1 : (fit1[1] == fit2[1] ? 0 : -1);
  }

  function findAllFits(mergeableTokens, propertySize, propertiesCount) {
    var combinations = allCombinations(mergeableTokens, propertySize, propertiesCount, maxCombinationsLevel - 1);
    return combinations.sort(fitSorter);
  }

  function allCombinations(tokensVariant, propertySize, propertiesCount, level) {
    var differenceVariants = [[tokensVariant, sizeDifference(tokensVariant, propertySize, propertiesCount)]];
    if (tokensVariant.length > 2 && level > 0) {
      for (var i = tokensVariant.length - 1; i >= 0; i--) {
        var subVariant = Array.prototype.slice.call(tokensVariant, 0);
        subVariant.splice(i, 1);
        differenceVariants = differenceVariants.concat(allCombinations(subVariant, propertySize, propertiesCount, level - 1));
      }
    }

    return differenceVariants;
  }

  function sizeDifference(tokensVariant, propertySize, propertiesCount) {
    var allSelectorsSize = 0;
    for (var i = tokensVariant.length - 1; i >= 0; i--) {
      allSelectorsSize += tokensVariant[i][2].length > propertiesCount ? serializeRules(tokensVariant[i][1]).length : -1;
    }
    return allSelectorsSize - (tokensVariant.length - 1) * propertySize + 1;
  }

  function dropAsNewTokenAt(position, properties, allSelectors, mergeableTokens) {
    var i, j, k, m;
    var allProperties = [];

    for (i = mergeableTokens.length - 1; i >= 0; i--) {
      var mergeableToken = mergeableTokens[i];

      for (j = mergeableToken[2].length - 1; j >= 0; j--) {
        var mergeableProperty = mergeableToken[2][j];

        for (k = 0, m = properties.length; k < m; k++) {
          var property = properties[k];

          var mergeablePropertyName = mergeableProperty[1][1];
          var propertyName = property[0];
          var propertyBody = property[4];
          if (mergeablePropertyName == propertyName && serializeBody([mergeableProperty]) == propertyBody) {
            mergeableToken[2].splice(j, 1);
            break;
          }
        }
      }
    }

    for (i = properties.length - 1; i >= 0; i--) {
      allProperties.unshift(properties[i][3]);
    }

    var newToken = [Token$5.RULE, allSelectors, allProperties];
    tokens.splice(position, 0, newToken);
  }

  function dropPropertiesAt(position, movedProperty) {
    var key = movedProperty[4];
    var toMove = movableTokens[key];

    if (toMove && toMove.length > 1) {
      if (!shortenMultiMovesIfPossible(position, movedProperty))
        shortenIfPossible(position, movedProperty);
    }
  }

  function shortenMultiMovesIfPossible(position, movedProperty) {
    var candidates = [];
    var propertiesAndMergableTokens = [];
    var key = movedProperty[4];
    var j, k;

    var mergeableTokens = tokensToMerge(movableTokens[key]);
    if (mergeableTokens.length < 2)
      return;

    movableLoop:
    for (var value in movableTokens) {
      var tokensList = movableTokens[value];

      for (j = mergeableTokens.length - 1; j >= 0; j--) {
        if (tokensList.indexOf(mergeableTokens[j]) == -1)
          continue movableLoop;
      }

      candidates.push(value);
    }

    if (candidates.length < 2)
      return false;

    for (j = candidates.length - 1; j >= 0; j--) {
      for (k = movedProperties.length - 1; k >= 0; k--) {
        if (movedProperties[k][4] == candidates[j]) {
          propertiesAndMergableTokens.unshift([movedProperties[k], mergeableTokens]);
          break;
        }
      }
    }

    return processMultiPropertyMove(position, propertiesAndMergableTokens);
  }

  function processMultiPropertyMove(position, propertiesAndMergableTokens) {
    var valueSize = 0;
    var properties = [];
    var property;

    for (var i = propertiesAndMergableTokens.length - 1; i >= 0; i--) {
      property = propertiesAndMergableTokens[i][0];
      var fullValue = property[4];
      valueSize += fullValue.length + (i > 0 ? 1 : 0);

      properties.push(property);
    }

    var mergeableTokens = propertiesAndMergableTokens[0][1];
    var bestFit = findAllFits(mergeableTokens, valueSize, properties.length)[0];
    if (bestFit[1] > 0)
      return false;

    var allSelectors = [];
    var qualifiedTokens = [];
    for (i = bestFit[0].length - 1; i >= 0; i--) {
      allSelectors = bestFit[0][i][1].concat(allSelectors);
      qualifiedTokens.unshift(bestFit[0][i]);
    }

    allSelectors = tidyRuleDuplicates(allSelectors);
    dropAsNewTokenAt(position, properties, allSelectors, qualifiedTokens);

    for (i = properties.length - 1; i >= 0; i--) {
      property = properties[i];
      var index = movedProperties.indexOf(property);

      delete movableTokens[property[4]];

      if (index > -1 && movedToBeDropped.indexOf(index) == -1)
        movedToBeDropped.push(index);
    }

    return true;
  }

  function boundToAnotherPropertyInCurrrentToken(property, movedProperty, token) {
    var propertyName = property[0];
    var movedPropertyName = movedProperty[0];
    if (propertyName != movedPropertyName)
      return false;

    var key = movedProperty[4];
    var toMove = movableTokens[key];
    return toMove && toMove.indexOf(token) > -1;
  }

  for (var i = tokens.length - 1; i >= 0; i--) {
    var token = tokens[i];
    var isRule;
    var j, k, m;
    var samePropertyAt;

    if (token[0] == Token$5.RULE) {
      isRule = true;
    } else if (token[0] == Token$5.NESTED_BLOCK) {
      isRule = false;
    } else {
      continue;
    }

    // We cache movedProperties.length as it may change in the loop
    var movedCount = movedProperties.length;

    var properties = extractProperties(token);
    movedToBeDropped = [];

    var unmovableInCurrentToken = [];
    for (j = properties.length - 1; j >= 0; j--) {
      for (k = j - 1; k >= 0; k--) {
        if (!canReorderSingle(properties[j], properties[k], specificityCache)) {
          unmovableInCurrentToken.push(j);
          break;
        }
      }
    }

    for (j = properties.length - 1; j >= 0; j--) {
      var property = properties[j];
      var movedSameProperty = false;

      for (k = 0; k < movedCount; k++) {
        var movedProperty = movedProperties[k];

        if (movedToBeDropped.indexOf(k) == -1 && (!canReorderSingle(property, movedProperty, specificityCache) && !boundToAnotherPropertyInCurrrentToken(property, movedProperty, token) ||
            movableTokens[movedProperty[4]] && movableTokens[movedProperty[4]].length === mergeLimit)) {
          dropPropertiesAt(i + 1, movedProperty);

          if (movedToBeDropped.indexOf(k) == -1) {
            movedToBeDropped.push(k);
            delete movableTokens[movedProperty[4]];
          }
        }

        if (!movedSameProperty) {
          movedSameProperty = property[0] == movedProperty[0] && property[1] == movedProperty[1];

          if (movedSameProperty) {
            samePropertyAt = k;
          }
        }
      }

      if (!isRule || unmovableInCurrentToken.indexOf(j) > -1)
        continue;

      var key = property[4];

      if (movedSameProperty && movedProperties[samePropertyAt][5].length + property[5].length > mergeLimit) {
        dropPropertiesAt(i + 1, movedProperties[samePropertyAt]);
        movedProperties.splice(samePropertyAt, 1);
        movableTokens[key] = [token];
        movedSameProperty = false;
      } else {
        movableTokens[key] = movableTokens[key] || [];
        movableTokens[key].push(token);
      }

      if (movedSameProperty) {
        movedProperties[samePropertyAt] = cloneAndMergeSelectors(movedProperties[samePropertyAt], property);
      } else {
        movedProperties.push(property);
      }
    }

    movedToBeDropped = movedToBeDropped.sort(naturalSorter);
    for (j = 0, m = movedToBeDropped.length; j < m; j++) {
      var dropAt = movedToBeDropped[j] - j;
      movedProperties.splice(dropAt, 1);
    }
  }

  var position = tokens[0] && tokens[0][0] == Token$5.AT_RULE && tokens[0][1].indexOf('@charset') === 0 ? 1 : 0;
  for (; position < tokens.length - 1; position++) {
    var isImportRule = tokens[position][0] === Token$5.AT_RULE && tokens[position][1].indexOf('@import') === 0;
    var isComment = tokens[position][0] === Token$5.COMMENT;
    if (!(isImportRule || isComment))
      break;
  }

  for (i = 0; i < movedProperties.length; i++) {
    dropPropertiesAt(position, movedProperties[i]);
  }
}

var restructure_1 = restructure$1;

var mergeAdjacent = mergeAdjacent_1;
var mergeMediaQueries = mergeMediaQueries_1;
var mergeNonAdjacentByBody = mergeNonAdjacentByBody_1;
var mergeNonAdjacentBySelector = mergeNonAdjacentBySelector_1;
var reduceNonAdjacent = reduceNonAdjacent_1;
var removeDuplicateFontAtRules = removeDuplicateFontAtRules_1;
var removeDuplicateMediaQueries = removeDuplicateMediaQueries_1;
var removeDuplicates = removeDuplicates_1;
var removeUnusedAtRules = removeUnusedAtRules_1;
var restructure = restructure_1;

var optimizeProperties = optimize$2;

var OptimizationLevel$1 = optimizationLevel.OptimizationLevel;

var Token$4 = token;

function removeEmpty(tokens) {
  for (var i = 0, l = tokens.length; i < l; i++) {
    var token = tokens[i];
    var isEmpty = false;

    switch (token[0]) {
      case Token$4.RULE:
        isEmpty = token[1].length === 0 || token[2].length === 0;
        break;
      case Token$4.NESTED_BLOCK:
        removeEmpty(token[2]);
        isEmpty = token[2].length === 0;
        break;
      case Token$4.AT_RULE:
        isEmpty = token[1].length === 0;
        break;
      case Token$4.AT_RULE_BLOCK:
        isEmpty = token[2].length === 0;
    }

    if (isEmpty) {
      tokens.splice(i, 1);
      i--;
      l--;
    }
  }
}

function recursivelyOptimizeBlocks(tokens, context) {
  for (var i = 0, l = tokens.length; i < l; i++) {
    var token = tokens[i];

    if (token[0] == Token$4.NESTED_BLOCK) {
      var isKeyframes = /@(-moz-|-o-|-webkit-)?keyframes/.test(token[1][0][1]);
      level2Optimize$1(token[2], context, !isKeyframes);
    }
  }
}

function recursivelyOptimizeProperties(tokens, context) {
  for (var i = 0, l = tokens.length; i < l; i++) {
    var token = tokens[i];

    switch (token[0]) {
      case Token$4.RULE:
        optimizeProperties(token[2], true, true, context);
        break;
      case Token$4.NESTED_BLOCK:
        recursivelyOptimizeProperties(token[2], context);
    }
  }
}

function level2Optimize$1(tokens, context, withRestructuring) {
  var levelOptions = context.options.level[OptimizationLevel$1.Two];
  var level2Plugins = context.options.plugins.level2Block;
  var reduced;
  var i;

  recursivelyOptimizeBlocks(tokens, context);
  recursivelyOptimizeProperties(tokens, context);

  if (levelOptions.removeDuplicateRules) {
    removeDuplicates(tokens);
  }

  if (levelOptions.mergeAdjacentRules) {
    mergeAdjacent(tokens, context);
  }

  if (levelOptions.reduceNonAdjacentRules) {
    reduceNonAdjacent(tokens, context);
  }

  if (levelOptions.mergeNonAdjacentRules && levelOptions.mergeNonAdjacentRules != 'body') {
    mergeNonAdjacentBySelector(tokens, context);
  }

  if (levelOptions.mergeNonAdjacentRules && levelOptions.mergeNonAdjacentRules != 'selector') {
    mergeNonAdjacentByBody(tokens, context);
  }

  if (levelOptions.restructureRules && levelOptions.mergeAdjacentRules && withRestructuring) {
    restructure(tokens, context);
    mergeAdjacent(tokens, context);
  }

  if (levelOptions.restructureRules && !levelOptions.mergeAdjacentRules && withRestructuring) {
    restructure(tokens, context);
  }

  if (levelOptions.removeDuplicateFontRules) {
    removeDuplicateFontAtRules(tokens);
  }

  if (levelOptions.removeDuplicateMediaBlocks) {
    removeDuplicateMediaQueries(tokens);
  }

  if (levelOptions.removeUnusedAtRules) {
    removeUnusedAtRules(tokens, context);
  }

  if (levelOptions.mergeMedia) {
    reduced = mergeMediaQueries(tokens, context);
    for (i = reduced.length - 1; i >= 0; i--) {
      level2Optimize$1(reduced[i][2], context, false);
    }
  }

  for (i = 0; i < level2Plugins.length; i++) {
    level2Plugins[i](tokens);
  }

  if (levelOptions.removeEmpty) {
    removeEmpty(tokens);
  }

  return tokens;
}

var optimize$1 = level2Optimize$1;

var functionNoVendorRegexStr = '[A-Z]+(\\-|[A-Z]|[0-9])+\\(.*?\\)';
var functionVendorRegexStr = '\\-(\\-|[A-Z]|[0-9])+\\(.*?\\)';
var variableRegexStr = 'var\\(\\-\\-[^\\)]+\\)';
var functionAnyRegexStr = '(' + variableRegexStr + '|' + functionNoVendorRegexStr + '|' + functionVendorRegexStr + ')';

var calcRegex = new RegExp('^(\\-moz\\-|\\-webkit\\-)?calc\\([^\\)]+\\)$', 'i');
var decimalRegex = /[0-9]/;
var functionAnyRegex = new RegExp('^' + functionAnyRegexStr + '$', 'i');
var hexAlphaColorRegex = /^#(?:[0-9a-f]{4}|[0-9a-f]{8})$/i;
var hslColorRegex = /^hsl\(\s{0,31}[\-\.]?\d+\s{0,31},\s{0,31}\d*\.?\d+%\s{0,31},\s{0,31}\d*\.?\d+%\s{0,31}\)|hsla\(\s{0,31}[\-\.]?\d+\s{0,31},\s{0,31}\d*\.?\d+%\s{0,31},\s{0,31}\d*\.?\d+%\s{0,31},\s{0,31}\.?\d+\s{0,31}\)$/;
var identifierRegex = /^(\-[a-z0-9_][a-z0-9\-_]*|[a-z_][a-z0-9\-_]*)$/i;
var namedEntityRegex = /^[a-z]+$/i;
var prefixRegex = /^-([a-z0-9]|-)*$/i;
var quotedTextRegex = /^("[^"]*"|'[^']*')$/i;
var rgbColorRegex = /^rgb\(\s{0,31}[\d]{1,3}\s{0,31},\s{0,31}[\d]{1,3}\s{0,31},\s{0,31}[\d]{1,3}\s{0,31}\)|rgba\(\s{0,31}[\d]{1,3}\s{0,31},\s{0,31}[\d]{1,3}\s{0,31},\s{0,31}[\d]{1,3}\s{0,31},\s{0,31}[\.\d]+\s{0,31}\)$/i;
var timeUnitPattern = /\d+(s|ms)/;
var timingFunctionRegex = /^(cubic\-bezier|steps)\([^\)]+\)$/;
var validTimeUnits = ['ms', 's'];
var urlRegex = /^url\([\s\S]+\)$/i;
var variableRegex = new RegExp('^' + variableRegexStr + '$', 'i');

var eightValueColorRegex = /^#[0-9a-f]{8}$/i;
var fourValueColorRegex = /^#[0-9a-f]{4}$/i;
var sixValueColorRegex = /^#[0-9a-f]{6}$/i;
var threeValueColorRegex = /^#[0-9a-f]{3}$/i;

var DECIMAL_DOT = '.';
var MINUS_SIGN = '-';
var PLUS_SIGN = '+';

var Keywords = {
  '^': [
    'inherit',
    'initial',
    'unset'
  ],
  '*-style': [
    'auto',
    'dashed',
    'dotted',
    'double',
    'groove',
    'hidden',
    'inset',
    'none',
    'outset',
    'ridge',
    'solid'
  ],
  '*-timing-function': [
    'ease',
    'ease-in',
    'ease-in-out',
    'ease-out',
    'linear',
    'step-end',
    'step-start'
  ],
  'animation-direction': [
    'alternate',
    'alternate-reverse',
    'normal',
    'reverse'
  ],
  'animation-fill-mode': [
    'backwards',
    'both',
    'forwards',
    'none'
  ],
  'animation-iteration-count': [
    'infinite'
  ],
  'animation-name': [
    'none'
  ],
  'animation-play-state': [
    'paused',
    'running'
  ],
  'background-attachment': [
    'fixed',
    'inherit',
    'local',
    'scroll'
  ],
  'background-clip': [
    'border-box',
    'content-box',
    'inherit',
    'padding-box',
    'text'
  ],
  'background-origin': [
    'border-box',
    'content-box',
    'inherit',
    'padding-box'
  ],
  'background-position': [
    'bottom',
    'center',
    'left',
    'right',
    'top'
  ],
  'background-repeat': [
    'no-repeat',
    'inherit',
    'repeat',
    'repeat-x',
    'repeat-y',
    'round',
    'space'
  ],
  'background-size': [
    'auto',
    'cover',
    'contain'
  ],
  'border-collapse': [
    'collapse',
    'inherit',
    'separate'
  ],
  'bottom': [
    'auto'
  ],
  'clear': [
    'both',
    'left',
    'none',
    'right'
  ],
  'color': [
    'transparent'
  ],
  'cursor': [
    'all-scroll',
    'auto',
    'col-resize',
    'crosshair',
    'default',
    'e-resize',
    'help',
    'move',
    'n-resize',
    'ne-resize',
    'no-drop',
    'not-allowed',
    'nw-resize',
    'pointer',
    'progress',
    'row-resize',
    's-resize',
    'se-resize',
    'sw-resize',
    'text',
    'vertical-text',
    'w-resize',
    'wait'
  ],
  'display': [
    'block',
    'inline',
    'inline-block',
    'inline-table',
    'list-item',
    'none',
    'table',
    'table-caption',
    'table-cell',
    'table-column',
    'table-column-group',
    'table-footer-group',
    'table-header-group',
    'table-row',
    'table-row-group'
  ],
  'float': [
    'left',
    'none',
    'right'
  ],
  'left': [
    'auto'
  ],
  'font': [
    'caption',
    'icon',
    'menu',
    'message-box',
    'small-caption',
    'status-bar',
    'unset'
  ],
  'font-size': [
    'large',
    'larger',
    'medium',
    'small',
    'smaller',
    'x-large',
    'x-small',
    'xx-large',
    'xx-small'
  ],
  'font-stretch': [
    'condensed',
    'expanded',
    'extra-condensed',
    'extra-expanded',
    'normal',
    'semi-condensed',
    'semi-expanded',
    'ultra-condensed',
    'ultra-expanded'
  ],
  'font-style': [
    'italic',
    'normal',
    'oblique'
  ],
  'font-variant': [
    'normal',
    'small-caps'
  ],
  'font-weight': [
    '100',
    '200',
    '300',
    '400',
    '500',
    '600',
    '700',
    '800',
    '900',
    'bold',
    'bolder',
    'lighter',
    'normal'
  ],
  'line-height': [
    'normal'
  ],
  'list-style-position': [
    'inside',
    'outside'
  ],
  'list-style-type': [
    'armenian',
    'circle',
    'decimal',
    'decimal-leading-zero',
    'disc',
    'decimal|disc', // this is the default value of list-style-type, see comment in configuration.js
    'georgian',
    'lower-alpha',
    'lower-greek',
    'lower-latin',
    'lower-roman',
    'none',
    'square',
    'upper-alpha',
    'upper-latin',
    'upper-roman'
  ],
  'overflow': [
    'auto',
    'hidden',
    'scroll',
    'visible'
  ],
  'position': [
    'absolute',
    'fixed',
    'relative',
    'static'
  ],
  'right': [
    'auto'
  ],
  'text-align': [
    'center',
    'justify',
    'left',
    'left|right', // this is the default value of list-style-type, see comment in configuration.js
    'right'
  ],
  'text-decoration': [
    'line-through',
    'none',
    'overline',
    'underline'
  ],
  'text-overflow': [
    'clip',
    'ellipsis'
  ],
  'top': [
    'auto'
  ],
  'vertical-align': [
    'baseline',
    'bottom',
    'middle',
    'sub',
    'super',
    'text-bottom',
    'text-top',
    'top'
  ],
  'visibility': [
    'collapse',
    'hidden',
    'visible'
  ],
  'white-space': [
    'normal',
    'nowrap',
    'pre'
  ],
  'width': [
    'inherit',
    'initial',
    'medium',
    'thick',
    'thin'
  ]
};

var Units = [
  '%',
  'ch',
  'cm',
  'em',
  'ex',
  'in',
  'mm',
  'pc',
  'pt',
  'px',
  'rem',
  'vh',
  'vm',
  'vmax',
  'vmin',
  'vw'
];

function isColor(value) {
  return value != 'auto' &&
    (
      isKeyword('color')(value) ||
      isHexColor(value) ||
      isColorFunction(value) ||
      isNamedEntity(value)
    );
}

function isColorFunction(value) {
  return isRgbColor(value) || isHslColor(value);
}

function isDynamicUnit(value) {
  return calcRegex.test(value);
}

function isFunction(value) {
  return functionAnyRegex.test(value);
}

function isHexColor(value) {
  return threeValueColorRegex.test(value) || fourValueColorRegex.test(value) || sixValueColorRegex.test(value) || eightValueColorRegex.test(value);
}

function isHslColor(value) {
  return hslColorRegex.test(value);
}

function isHexAlphaColor(value) {
  return hexAlphaColorRegex.test(value);
}

function isIdentifier(value) {
  return identifierRegex.test(value);
}

function isQuotedText(value) {
  return quotedTextRegex.test(value);
}

function isImage(value) {
  return value == 'none' || value == 'inherit' || isUrl(value);
}

function isKeyword(propertyName) {
  return function(value) {
    return Keywords[propertyName].indexOf(value) > -1;
  };
}

function isNamedEntity(value) {
  return namedEntityRegex.test(value);
}

function isNumber(value) {
  return scanForNumber(value) == value.length;
}

function isRgbColor(value) {
  return rgbColorRegex.test(value);
}

function isPrefixed(value) {
  return prefixRegex.test(value);
}

function isPositiveNumber(value) {
  return isNumber(value) &&
    parseFloat(value) >= 0;
}

function isVariable(value) {
  return variableRegex.test(value);
}

function isTime(value) {
  var numberUpTo = scanForNumber(value);

  return numberUpTo == value.length && parseInt(value) === 0 ||
    numberUpTo > -1 && validTimeUnits.indexOf(value.slice(numberUpTo + 1)) > -1 ||
    isCalculatedTime(value);
}

function isCalculatedTime(value) {
  return isFunction(value) && timeUnitPattern.test(value);
}

function isTimingFunction() {
  var isTimingFunctionKeyword = isKeyword('*-timing-function');

  return function (value) {
    return isTimingFunctionKeyword(value) || timingFunctionRegex.test(value);
  };
}

function isUnit(validUnits, value) {
  var numberUpTo = scanForNumber(value);

  return numberUpTo == value.length && parseInt(value) === 0 ||
    numberUpTo > -1 && validUnits.indexOf(value.slice(numberUpTo + 1).toLowerCase()) > -1 ||
    value == 'auto' ||
    value == 'inherit';
}

function isUrl(value) {
  return urlRegex.test(value);
}

function isZIndex(value) {
  return value == 'auto' ||
    isNumber(value) ||
    isKeyword('^')(value);
}

function scanForNumber(value) {
  var hasDot = false;
  var hasSign = false;
  var character;
  var i, l;

  for (i = 0, l = value.length; i < l; i++) {
    character = value[i];

    if (i === 0 && (character == PLUS_SIGN || character == MINUS_SIGN)) {
      hasSign = true;
    } else if (i > 0 && hasSign && (character == PLUS_SIGN || character == MINUS_SIGN)) {
      return i - 1;
    } else if (character == DECIMAL_DOT && !hasDot) {
      hasDot = true;
    } else if (character == DECIMAL_DOT && hasDot) {
      return i - 1;
    } else if (decimalRegex.test(character)) {
      continue;
    } else {
      return i - 1;
    }
  }

  return i;
}

function validator$1(compatibility) {
  var validUnits = Units.slice(0).filter(function (value) {
    return !(value in compatibility.units) || compatibility.units[value] === true;
  });

  if (compatibility.customUnits.rpx) {
    validUnits.push('rpx');
  }

  return {
    colorOpacity: compatibility.colors.opacity,
    colorHexAlpha: compatibility.colors.hexAlpha,
    isAnimationDirectionKeyword: isKeyword('animation-direction'),
    isAnimationFillModeKeyword: isKeyword('animation-fill-mode'),
    isAnimationIterationCountKeyword: isKeyword('animation-iteration-count'),
    isAnimationNameKeyword: isKeyword('animation-name'),
    isAnimationPlayStateKeyword: isKeyword('animation-play-state'),
    isTimingFunction: isTimingFunction(),
    isBackgroundAttachmentKeyword: isKeyword('background-attachment'),
    isBackgroundClipKeyword: isKeyword('background-clip'),
    isBackgroundOriginKeyword: isKeyword('background-origin'),
    isBackgroundPositionKeyword: isKeyword('background-position'),
    isBackgroundRepeatKeyword: isKeyword('background-repeat'),
    isBackgroundSizeKeyword: isKeyword('background-size'),
    isColor: isColor,
    isColorFunction: isColorFunction,
    isDynamicUnit: isDynamicUnit,
    isFontKeyword: isKeyword('font'),
    isFontSizeKeyword: isKeyword('font-size'),
    isFontStretchKeyword: isKeyword('font-stretch'),
    isFontStyleKeyword: isKeyword('font-style'),
    isFontVariantKeyword: isKeyword('font-variant'),
    isFontWeightKeyword: isKeyword('font-weight'),
    isFunction: isFunction,
    isGlobal: isKeyword('^'),
    isHexAlphaColor: isHexAlphaColor,
    isHslColor: isHslColor,
    isIdentifier: isIdentifier,
    isImage: isImage,
    isKeyword: isKeyword,
    isLineHeightKeyword: isKeyword('line-height'),
    isListStylePositionKeyword: isKeyword('list-style-position'),
    isListStyleTypeKeyword: isKeyword('list-style-type'),
    isNumber: isNumber,
    isPrefixed: isPrefixed,
    isPositiveNumber: isPositiveNumber,
    isQuotedText: isQuotedText,
    isRgbColor: isRgbColor,
    isStyleKeyword: isKeyword('*-style'),
    isTime: isTime,
    isUnit: isUnit.bind(null, validUnits),
    isUrl: isUrl,
    isVariable: isVariable,
    isWidth: isKeyword('width'),
    isZIndex: isZIndex
  };
}

var validator_1 = validator$1;

var DEFAULTS = {
  '*': {
    colors: {
      hexAlpha: false, // 4- and 8-character hex notation
      opacity: true // rgba / hsla
    },
    customUnits: {
      rpx: false
    },
    properties: {
      backgroundClipMerging: true, // background-clip to shorthand
      backgroundOriginMerging: true, // background-origin to shorthand
      backgroundSizeMerging: true, // background-size to shorthand
      colors: true, // any kind of color transformations, like `#ff00ff` to `#f0f` or `#fff` into `red`
      ieBangHack: false, // !ie suffix hacks on IE<8
      ieFilters: false, // whether to preserve `filter` and `-ms-filter` properties
      iePrefixHack: false, // underscore / asterisk prefix hacks on IE
      ieSuffixHack: false, // \9 suffix hacks on IE6-9, \0 suffix hack on IE6-11
      merging: true, // merging properties into one
      shorterLengthUnits: false, // optimize pixel units into `pt`, `pc` or `in` units
      spaceAfterClosingBrace: true, // 'url() no-repeat' to 'url()no-repeat'
      urlQuotes: true, // whether to wrap content of `url()` into quotes or not
      zeroUnits: true // 0[unit] -> 0
    },
    selectors: {
      adjacentSpace: false, // div+ nav Android stock browser hack
      ie7Hack: false, // *+html hack
      mergeablePseudoClasses: [
        ':active',
        ':after',
        ':before',
        ':empty',
        ':checked',
        ':disabled',
        ':empty',
        ':enabled',
        ':first-child',
        ':first-letter',
        ':first-line',
        ':first-of-type',
        ':focus',
        ':hover',
        ':lang',
        ':last-child',
        ':last-of-type',
        ':link',
        ':not',
        ':nth-child',
        ':nth-last-child',
        ':nth-last-of-type',
        ':nth-of-type',
        ':only-child',
        ':only-of-type',
        ':root',
        ':target',
        ':visited'
      ], // selectors with these pseudo-classes can be merged as these are universally supported
      mergeablePseudoElements: [
        '::after',
        '::before',
        '::first-letter',
        '::first-line'
      ], // selectors with these pseudo-elements can be merged as these are universally supported
      mergeLimit: 8191, // number of rules that can be safely merged together
      multiplePseudoMerging: true
    },
    units: {
      ch: true,
      in: true,
      pc: true,
      pt: true,
      rem: true,
      vh: true,
      vm: true, // vm is vmin on IE9+ see https://developer.mozilla.org/en-US/docs/Web/CSS/length
      vmax: true,
      vmin: true,
      vw: true
    }
  }
};

DEFAULTS.ie11 = merge(DEFAULTS['*'], {
  properties: {
    ieSuffixHack: true
  }
});

DEFAULTS.ie10 = merge(DEFAULTS['*'], {
  properties: {
    ieSuffixHack: true
  }
});

DEFAULTS.ie9 = merge(DEFAULTS['*'], {
  properties: {
    ieFilters: true,
    ieSuffixHack: true
  }
});

DEFAULTS.ie8 = merge(DEFAULTS.ie9, {
  colors: {
    opacity: false
  },
  properties: {
    backgroundClipMerging: false,
    backgroundOriginMerging: false,
    backgroundSizeMerging: false,
    iePrefixHack: true,
    merging: false
  },
  selectors: {
    mergeablePseudoClasses: [
      ':after',
      ':before',
      ':first-child',
      ':first-letter',
      ':focus',
      ':hover',
      ':visited'
    ],
    mergeablePseudoElements: []
  },
  units: {
    ch: false,
    rem: false,
    vh: false,
    vm: false,
    vmax: false,
    vmin: false,
    vw: false
  }
});

DEFAULTS.ie7 = merge(DEFAULTS.ie8, {
  properties: {
    ieBangHack: true
  },
  selectors: {
    ie7Hack: true,
    mergeablePseudoClasses: [
      ':first-child',
      ':first-letter',
      ':hover',
      ':visited'
    ]
  },
});

function compatibilityFrom$1(source) {
  return merge(DEFAULTS['*'], calculateSource(source));
}

function merge(source, target) {
  for (var key in source) {
    var value = source[key];

    if (typeof value === 'object' && !Array.isArray(value)) {
      target[key] = merge(value, target[key] || {});
    } else {
      target[key] = key in target ? target[key] : value;
    }
  }

  return target;
}

function calculateSource(source) {
  if (typeof source == 'object')
    return source;

  if (!/[,\+\-]/.test(source))
    return DEFAULTS[source] || DEFAULTS['*'];

  var parts = source.split(',');
  var template = parts[0] in DEFAULTS ?
    DEFAULTS[parts.shift()] :
    DEFAULTS['*'];

  source = {};

  parts.forEach(function (part) {
    var isAdd = part[0] == '+';
    var key = part.substring(1).split('.');
    var group = key[0];
    var option = key[1];

    source[group] = source[group] || {};
    source[group][option] = isAdd;
  });

  return merge(template, source);
}

var compatibility = compatibilityFrom$1;

var HTTP_RESOURCE_PATTERN = /^http:\/\//;

function isHttpResource$1(uri) {
  return HTTP_RESOURCE_PATTERN.test(uri);
}

var isHttpResource_1 = isHttpResource$1;

var HTTPS_RESOURCE_PATTERN = /^https:\/\//;

function isHttpsResource$1(uri) {
  return HTTPS_RESOURCE_PATTERN.test(uri);
}

var isHttpsResource_1 = isHttpsResource$1;

var http = require$$0__default$1;
var https = require$$1__default;
var url$4 = require$$0__default$2;

var isHttpResource = isHttpResource_1;
var isHttpsResource = isHttpsResource_1;
var override$1 = override_1;

var HTTP_PROTOCOL$1 = 'http:';

function loadRemoteResource$1(uri, inlineRequest, inlineTimeout, callback) {
  var proxyProtocol = inlineRequest.protocol || inlineRequest.hostname;
  var errorHandled = false;
  var requestOptions;
  var fetch;

  requestOptions = override$1(
    url$4.parse(uri),
    inlineRequest || {}
  );

  if (inlineRequest.hostname !== undefined) {
    // overwrite as we always expect a http proxy currently
    requestOptions.protocol = inlineRequest.protocol || HTTP_PROTOCOL$1;
    requestOptions.path = requestOptions.href;
  }

  fetch = (proxyProtocol && !isHttpsResource(proxyProtocol)) || isHttpResource(uri) ?
    http.get :
    https.get;

  fetch(requestOptions, function (res) {
    var chunks = [];
    var movedUri;

    if (errorHandled) {
      return;
    }

    if (res.statusCode < 200 || res.statusCode > 399) {
      return callback(res.statusCode, null);
    } else if (res.statusCode > 299) {
      movedUri = url$4.resolve(uri, res.headers.location);
      return loadRemoteResource$1(movedUri, inlineRequest, inlineTimeout, callback);
    }

    res.on('data', function (chunk) {
      chunks.push(chunk.toString());
    });
    res.on('end', function () {
      var body = chunks.join('');
      callback(null, body);
    });
  })
  .on('error', function (res) {
    if (errorHandled) {
      return;
    }

    errorHandled = true;
    callback(res.message, null);
  })
  .on('timeout', function () {
    if (errorHandled) {
      return;
    }

    errorHandled = true;
    callback('timeout', null);
  })
  .setTimeout(inlineTimeout);
}

var loadRemoteResource_1 = loadRemoteResource$1;

var loadRemoteResource = loadRemoteResource_1;

function fetchFrom$1(callback) {
  return callback || loadRemoteResource;
}

var fetch = fetchFrom$1;

function inlineOptionsFrom(rules) {
  if (Array.isArray(rules)) {
    return rules;
  }

  if (rules === false) {
    return ['none'];
  }

  return undefined === rules ?
    ['local'] :
    rules.split(',');
}

var inline$1 = inlineOptionsFrom;

var url$3 = require$$0__default$2;

var override = override_1;

function inlineRequestFrom$1(option) {
  return override(
    /* jshint camelcase: false */
    proxyOptionsFrom(process.env.HTTP_PROXY || process.env.http_proxy),
    option || {}
  );
}

function proxyOptionsFrom(httpProxy) {
  return httpProxy ?
    {
      hostname: url$3.parse(httpProxy).hostname,
      port: parseInt(url$3.parse(httpProxy).port)
    } :
    {};
}

var inlineRequest = inlineRequestFrom$1;

var DEFAULT_TIMEOUT = 5000;

function inlineTimeoutFrom$1(option) {
  return option || DEFAULT_TIMEOUT;
}

var inlineTimeout = inlineTimeoutFrom$1;

function pluginsFrom$1(plugins) {
  var flatPlugins = {
    level1Value: [],
    level1Property: [],
    level2Block: []
  };

  plugins = plugins || [];

  flatPlugins.level1Value = plugins
    .map(function (plugin) { return plugin.level1 && plugin.level1.value; })
    .filter(function (plugin) { return plugin != null; });

  flatPlugins.level1Property = plugins
    .map(function (plugin) { return plugin.level1 && plugin.level1.property; })
    .filter(function (plugin) { return plugin != null; });

  flatPlugins.level2Block = plugins
    .map(function (plugin) { return plugin.level2 && plugin.level2.block; })
    .filter(function (plugin) { return plugin != null; });

  return flatPlugins;
}

var plugins = pluginsFrom$1;

function rebaseFrom$1(rebaseOption, rebaseToOption) {
  if (undefined !== rebaseToOption) {
    return true;
  } else if (undefined === rebaseOption) {
    return false;
  } else {
    return !!rebaseOption;
  }
}

var rebase$3 = rebaseFrom$1;

var path$7 = path__default;

function rebaseToFrom$1(option) {
  return option ? path$7.resolve(option) : process.cwd();
}

var rebaseTo = rebaseToFrom$1;

var SourceMapConsumer = build.sourceMap.SourceMapConsumer;

function inputSourceMapTracker$1() {
  var maps = {};

  return {
    all: all$2.bind(null, maps),
    isTracking: isTracking.bind(null, maps),
    originalPositionFor: originalPositionFor.bind(null, maps),
    track: track$2.bind(null, maps)
  };
}

function all$2(maps) {
  return maps;
}

function isTracking(maps, source) {
  return source in maps;
}

function originalPositionFor(maps, metadata, range, selectorFallbacks) {
  var line = metadata[0];
  var column = metadata[1];
  var source = metadata[2];
  var position = {
    line: line,
    column: column + range
  };
  var originalPosition;

  while (!originalPosition && position.column > column) {
    position.column--;
    originalPosition = maps[source].originalPositionFor(position);
  }

  if (!originalPosition || originalPosition.column < 0) {
    return metadata;
  }

  if (originalPosition.line === null && line > 1 && selectorFallbacks > 0) {
    return originalPositionFor(maps, [line - 1, column, source], range, selectorFallbacks - 1);
  }

  return originalPosition.line !== null ?
    toMetadata(originalPosition) :
    metadata;
}

function toMetadata(asHash) {
  return [asHash.line, asHash.column, asHash.source];
}

function track$2(maps, source, data) {
  maps[source] = new SourceMapConsumer(data);
}

var inputSourceMapTracker_1 = inputSourceMapTracker$1;

var REMOTE_RESOURCE_PATTERN = /^(\w+:\/\/|\/\/)/;

function isRemoteResource$5(uri) {
  return REMOTE_RESOURCE_PATTERN.test(uri);
}

var isRemoteResource_1 = isRemoteResource$5;

var NO_PROTOCOL_RESOURCE_PATTERN = /^\/\//;

function hasProtocol$4(uri) {
  return !NO_PROTOCOL_RESOURCE_PATTERN.test(uri);
}

var hasProtocol_1 = hasProtocol$4;

var path$6 = path__default;
var url$2 = require$$0__default$2;

var isRemoteResource$4 = isRemoteResource_1;
var hasProtocol$3 = hasProtocol_1;

var HTTP_PROTOCOL = 'http:';

function isAllowedResource$3(uri, isRemote, rules) {
  var match;
  var absoluteUri;
  var allowed = isRemote ? false : true;
  var rule;
  var isNegated;
  var normalizedRule;
  var i;

  if (rules.length === 0) {
    return false;
  }

  if (isRemote && !hasProtocol$3(uri)) {
    uri = HTTP_PROTOCOL + uri;
  }

  match = isRemote ?
    url$2.parse(uri).host :
    uri;

  absoluteUri = isRemote ?
    uri :
    path$6.resolve(uri);

  for (i = 0; i < rules.length; i++) {
    rule = rules[i];
    isNegated = rule[0] == '!';
    normalizedRule = rule.substring(1);

    if (isNegated && isRemote && isRemoteRule(normalizedRule)) {
      allowed = allowed && !isAllowedResource$3(uri, true, [normalizedRule]);
    } else if (isNegated && !isRemote && !isRemoteRule(normalizedRule)) {
      allowed = allowed && !isAllowedResource$3(uri, false, [normalizedRule]);
    } else if (isNegated) {
      allowed = allowed && true;
    } else if (rule == 'all') {
      allowed = true;
    } else if (isRemote && rule == 'local') {
      allowed = allowed || false;
    } else if (isRemote && rule == 'remote') {
      allowed = true;
    } else if (!isRemote && rule == 'remote') {
      allowed = false;
    } else if (!isRemote && rule == 'local') {
      allowed = true;
    } else if (rule === match) {
      allowed = true;
    } else if (rule === uri) {
      allowed = true;
    } else if (isRemote && absoluteUri.indexOf(rule) === 0) {
      allowed = true;
    } else if (!isRemote && absoluteUri.indexOf(path$6.resolve(rule)) === 0) {
      allowed = true;
    } else if (isRemote != isRemoteRule(normalizedRule)) {
      allowed = allowed && true;
    } else {
      allowed = false;
    }
  }

  return allowed;
}

function isRemoteRule(rule) {
  return isRemoteResource$4(rule) || url$2.parse(HTTP_PROTOCOL + '//' + rule).host == rule;
}

var isAllowedResource_1 = isAllowedResource$3;

var DATA_URI_PATTERN$1 = /^data:(\S*?)?(;charset=[^;]+)?(;[^,]+?)?,(.+)/;

function matchDataUri$1(uri) {
  return DATA_URI_PATTERN$1.exec(uri);
}

var matchDataUri_1 = matchDataUri$1;

var path$5 = path__default;

function rebaseLocalMap$2(sourceMap, sourceUri, rebaseTo) {
  var currentPath = path$5.resolve('');
  var absoluteUri = path$5.resolve(currentPath, sourceUri);
  var absoluteUriDirectory = path$5.dirname(absoluteUri);

  sourceMap.sources = sourceMap.sources.map(function(source) {
    return path$5.relative(rebaseTo, path$5.resolve(absoluteUriDirectory, source));
  });

  return sourceMap;
}

var rebaseLocalMap_1 = rebaseLocalMap$2;

var path$4 = path__default;
var url$1 = require$$0__default$2;

function rebaseRemoteMap$2(sourceMap, sourceUri) {
  var sourceDirectory = path$4.dirname(sourceUri);

  sourceMap.sources = sourceMap.sources.map(function(source) {
    return url$1.resolve(sourceDirectory, source);
  });

  return sourceMap;
}

var rebaseRemoteMap_1 = rebaseRemoteMap$2;

var DATA_URI_PATTERN = /^data:(\S*?)?(;charset=[^;]+)?(;[^,]+?)?,(.+)/;

function isDataUriResource$2(uri) {
  return DATA_URI_PATTERN.test(uri);
}

var isDataUriResource_1 = isDataUriResource$2;

var fs$2 = fs__default;
var path$3 = path__default;

var isAllowedResource$2 = isAllowedResource_1;
var matchDataUri = matchDataUri_1;
var rebaseLocalMap$1 = rebaseLocalMap_1;
var rebaseRemoteMap$1 = rebaseRemoteMap_1;

var Token$3 = token;
var hasProtocol$2 = hasProtocol_1;
var isDataUriResource$1 = isDataUriResource_1;
var isRemoteResource$3 = isRemoteResource_1;

var MAP_MARKER_PATTERN = /^\/\*# sourceMappingURL=(\S+) \*\/$/;

function applySourceMaps$1(tokens, context, callback) {
  var applyContext = {
    callback: callback,
    fetch: context.options.fetch,
    index: 0,
    inline: context.options.inline,
    inlineRequest: context.options.inlineRequest,
    inlineTimeout: context.options.inlineTimeout,
    inputSourceMapTracker: context.inputSourceMapTracker,
    localOnly: context.localOnly,
    processedTokens: [],
    rebaseTo: context.options.rebaseTo,
    sourceTokens: tokens,
    warnings: context.warnings
  };

  return context.options.sourceMap && tokens.length > 0 ?
    doApplySourceMaps(applyContext) :
    callback(tokens);
}

function doApplySourceMaps(applyContext) {
  var singleSourceTokens = [];
  var lastSource = findTokenSource(applyContext.sourceTokens[0]);
  var source;
  var token;
  var l;

  for (l = applyContext.sourceTokens.length; applyContext.index < l; applyContext.index++) {
    token = applyContext.sourceTokens[applyContext.index];
    source = findTokenSource(token);

    if (source != lastSource) {
      singleSourceTokens = [];
      lastSource = source;
    }

    singleSourceTokens.push(token);
    applyContext.processedTokens.push(token);

    if (token[0] == Token$3.COMMENT && MAP_MARKER_PATTERN.test(token[1])) {
      return fetchAndApplySourceMap(token[1], source, singleSourceTokens, applyContext);
    }
  }

  return applyContext.callback(applyContext.processedTokens);
}

function findTokenSource(token) {
  var scope;
  var metadata;

  if (token[0] == Token$3.AT_RULE || token[0] == Token$3.COMMENT || token[0] == Token$3.RAW) {
    metadata = token[2][0];
  } else {
    scope = token[1][0];
    metadata = scope[2][0];
  }

  return metadata[2];
}

function fetchAndApplySourceMap(sourceMapComment, source, singleSourceTokens, applyContext) {
  return extractInputSourceMapFrom(sourceMapComment, applyContext, function (inputSourceMap) {
    if (inputSourceMap) {
      applyContext.inputSourceMapTracker.track(source, inputSourceMap);
      applySourceMapRecursively(singleSourceTokens, applyContext.inputSourceMapTracker);
    }

    applyContext.index++;
    return doApplySourceMaps(applyContext);
  });
}

function extractInputSourceMapFrom(sourceMapComment, applyContext, whenSourceMapReady) {
  var uri = MAP_MARKER_PATTERN.exec(sourceMapComment)[1];
  var absoluteUri;
  var sourceMap;
  var rebasedMap;

  if (isDataUriResource$1(uri)) {
    sourceMap = extractInputSourceMapFromDataUri(uri);
    return whenSourceMapReady(sourceMap);
  } else if (isRemoteResource$3(uri)) {
    return loadInputSourceMapFromRemoteUri(uri, applyContext, function (sourceMap) {
      var parsedMap;

      if (sourceMap) {
        parsedMap = JSON.parse(sourceMap);
        rebasedMap = rebaseRemoteMap$1(parsedMap, uri);
        whenSourceMapReady(rebasedMap);
      } else {
        whenSourceMapReady(null);
      }
    });
  } else {
    // at this point `uri` is already rebased, see lib/reader/rebase.js#rebaseSourceMapComment
    // it is rebased to be consistent with rebasing other URIs
    // however here we need to resolve it back to read it from disk
    absoluteUri = path$3.resolve(applyContext.rebaseTo, uri);
    sourceMap = loadInputSourceMapFromLocalUri(absoluteUri, applyContext);

    if (sourceMap) {
      rebasedMap = rebaseLocalMap$1(sourceMap, absoluteUri, applyContext.rebaseTo);
      return whenSourceMapReady(rebasedMap);
    } else {
      return whenSourceMapReady(null);
    }
  }
}

function extractInputSourceMapFromDataUri(uri) {
  var dataUriMatch = matchDataUri(uri);
  var charset = dataUriMatch[2] ? dataUriMatch[2].split(/[=;]/)[2] : 'us-ascii';
  var encoding = dataUriMatch[3] ? dataUriMatch[3].split(';')[1] : 'utf8';
  var data = encoding == 'utf8' ? build.commonjsGlobal.unescape(dataUriMatch[4]) : dataUriMatch[4];

  var buffer = Buffer.from(data, encoding);
  buffer.charset = charset;

  return JSON.parse(buffer.toString());
}

function loadInputSourceMapFromRemoteUri(uri, applyContext, whenLoaded) {
  var isAllowed = isAllowedResource$2(uri, true, applyContext.inline);
  var isRuntimeResource = !hasProtocol$2(uri);

  if (applyContext.localOnly) {
    applyContext.warnings.push('Cannot fetch remote resource from "' + uri + '" as no callback given.');
    return whenLoaded(null);
  } else if (isRuntimeResource) {
    applyContext.warnings.push('Cannot fetch "' + uri + '" as no protocol given.');
    return whenLoaded(null);
  } else if (!isAllowed) {
    applyContext.warnings.push('Cannot fetch "' + uri + '" as resource is not allowed.');
    return whenLoaded(null);
  }

  applyContext.fetch(uri, applyContext.inlineRequest, applyContext.inlineTimeout, function (error, body) {
    if (error) {
      applyContext.warnings.push('Missing source map at "' + uri + '" - ' + error);
      return whenLoaded(null);
    }

    whenLoaded(body);
  });
}

function loadInputSourceMapFromLocalUri(uri, applyContext) {
  var isAllowed = isAllowedResource$2(uri, false, applyContext.inline);
  var sourceMap;

  if (!fs$2.existsSync(uri) || !fs$2.statSync(uri).isFile()) {
    applyContext.warnings.push('Ignoring local source map at "' + uri + '" as resource is missing.');
    return null;
  } else if (!isAllowed) {
    applyContext.warnings.push('Cannot fetch "' + uri + '" as resource is not allowed.');
    return null;
  }

  sourceMap = fs$2.readFileSync(uri, 'utf-8');
  return JSON.parse(sourceMap);
}

function applySourceMapRecursively(tokens, inputSourceMapTracker) {
  var token;
  var i, l;

  for (i = 0, l = tokens.length; i < l; i++) {
    token = tokens[i];

    switch (token[0]) {
      case Token$3.AT_RULE:
        applySourceMapTo(token, inputSourceMapTracker);
        break;
      case Token$3.AT_RULE_BLOCK:
        applySourceMapRecursively(token[1], inputSourceMapTracker);
        applySourceMapRecursively(token[2], inputSourceMapTracker);
        break;
      case Token$3.AT_RULE_BLOCK_SCOPE:
        applySourceMapTo(token, inputSourceMapTracker);
        break;
      case Token$3.NESTED_BLOCK:
        applySourceMapRecursively(token[1], inputSourceMapTracker);
        applySourceMapRecursively(token[2], inputSourceMapTracker);
        break;
      case Token$3.NESTED_BLOCK_SCOPE:
        applySourceMapTo(token, inputSourceMapTracker);
        break;
      case Token$3.COMMENT:
        applySourceMapTo(token, inputSourceMapTracker);
        break;
      case Token$3.PROPERTY:
        applySourceMapRecursively(token, inputSourceMapTracker);
        break;
      case Token$3.PROPERTY_BLOCK:
        applySourceMapRecursively(token[1], inputSourceMapTracker);
        break;
      case Token$3.PROPERTY_NAME:
        applySourceMapTo(token, inputSourceMapTracker);
        break;
      case Token$3.PROPERTY_VALUE:
        applySourceMapTo(token, inputSourceMapTracker);
        break;
      case Token$3.RULE:
        applySourceMapRecursively(token[1], inputSourceMapTracker);
        applySourceMapRecursively(token[2], inputSourceMapTracker);
        break;
      case Token$3.RULE_SCOPE:
        applySourceMapTo(token, inputSourceMapTracker);
    }
  }

  return tokens;
}

function applySourceMapTo(token, inputSourceMapTracker) {
  var value = token[1];
  var metadata = token[2];
  var newMetadata = [];
  var i, l;

  for (i = 0, l = metadata.length; i < l; i++) {
    newMetadata.push(inputSourceMapTracker.originalPositionFor(metadata[i], value.length));
  }

  token[2] = newMetadata;
}

var applySourceMaps_1 = applySourceMaps$1;

var split = split_1;

var BRACE_PREFIX = /^\(/;
var BRACE_SUFFIX = /\)$/;
var IMPORT_PREFIX_PATTERN$1 = /^@import/i;
var QUOTE_PREFIX_PATTERN$1 = /['"]\s*/;
var QUOTE_SUFFIX_PATTERN$1 = /\s*['"]/;
var URL_PREFIX_PATTERN$1 = /^url\(\s*/i;
var URL_SUFFIX_PATTERN$1 = /\s*\)/i;

function extractImportUrlAndMedia$2(atRuleValue) {
  var uri;
  var mediaQuery;
  var stripped;
  var parts;

  stripped = atRuleValue
    .replace(IMPORT_PREFIX_PATTERN$1, '')
    .trim()
    .replace(URL_PREFIX_PATTERN$1, '(')
    .replace(URL_SUFFIX_PATTERN$1, ')')
    .replace(QUOTE_PREFIX_PATTERN$1, '')
    .replace(QUOTE_SUFFIX_PATTERN$1, '');

  parts = split(stripped, ' ');

  uri = parts[0]
    .replace(BRACE_PREFIX, '')
    .replace(BRACE_SUFFIX, '');
  mediaQuery = parts.slice(1).join(' ');

  return [uri, mediaQuery];
}

var extractImportUrlAndMedia_1 = extractImportUrlAndMedia$2;

var fs$1 = fs__default;
var path$2 = path__default;

var isAllowedResource$1 = isAllowedResource_1;

var hasProtocol$1 = hasProtocol_1;
var isRemoteResource$2 = isRemoteResource_1;

function loadOriginalSources$1(context, callback) {
  var loadContext = {
    callback: callback,
    fetch: context.options.fetch,
    index: 0,
    inline: context.options.inline,
    inlineRequest: context.options.inlineRequest,
    inlineTimeout: context.options.inlineTimeout,
    localOnly: context.localOnly,
    rebaseTo: context.options.rebaseTo,
    sourcesContent: context.sourcesContent,
    uriToSource: uriToSourceMapping(context.inputSourceMapTracker.all()),
    warnings: context.warnings
  };

  return context.options.sourceMap && context.options.sourceMapInlineSources ?
    doLoadOriginalSources(loadContext) :
    callback();
}

function uriToSourceMapping(allSourceMapConsumers) {
  var mapping = {};
  var consumer;
  var uri;
  var source;
  var i, l;

  for (source in allSourceMapConsumers) {
    consumer = allSourceMapConsumers[source];

    for (i = 0, l = consumer.sources.length; i < l; i++) {
      uri = consumer.sources[i];
      source = consumer.sourceContentFor(uri, true);

      mapping[uri] = source;
    }
  }

  return mapping;
}

function doLoadOriginalSources(loadContext) {
  var uris = Object.keys(loadContext.uriToSource);
  var uri;
  var source;
  var total;

  for (total = uris.length; loadContext.index < total; loadContext.index++) {
    uri = uris[loadContext.index];
    source = loadContext.uriToSource[uri];

    if (source) {
      loadContext.sourcesContent[uri] = source;
    } else {
      return loadOriginalSource(uri, loadContext);
    }
  }

  return loadContext.callback();
}

function loadOriginalSource(uri, loadContext) {
  var content;

  if (isRemoteResource$2(uri)) {
    return loadOriginalSourceFromRemoteUri(uri, loadContext, function (content) {
      loadContext.index++;
      loadContext.sourcesContent[uri] = content;
      return doLoadOriginalSources(loadContext);
    });
  } else {
    content = loadOriginalSourceFromLocalUri(uri, loadContext);
    loadContext.index++;
    loadContext.sourcesContent[uri] = content;
    return doLoadOriginalSources(loadContext);
  }
}

function loadOriginalSourceFromRemoteUri(uri, loadContext, whenLoaded) {
  var isAllowed = isAllowedResource$1(uri, true, loadContext.inline);
  var isRuntimeResource = !hasProtocol$1(uri);

  if (loadContext.localOnly) {
    loadContext.warnings.push('Cannot fetch remote resource from "' + uri + '" as no callback given.');
    return whenLoaded(null);
  } else if (isRuntimeResource) {
    loadContext.warnings.push('Cannot fetch "' + uri + '" as no protocol given.');
    return whenLoaded(null);
  } else if (!isAllowed) {
    loadContext.warnings.push('Cannot fetch "' + uri + '" as resource is not allowed.');
    return whenLoaded(null);
  }

  loadContext.fetch(uri, loadContext.inlineRequest, loadContext.inlineTimeout, function (error, content) {
    if (error) {
      loadContext.warnings.push('Missing original source at "' + uri + '" - ' + error);
    }

    whenLoaded(content);
  });
}

function loadOriginalSourceFromLocalUri(relativeUri, loadContext) {
  var isAllowed = isAllowedResource$1(relativeUri, false, loadContext.inline);
  var absoluteUri = path$2.resolve(loadContext.rebaseTo, relativeUri);

  if (!fs$1.existsSync(absoluteUri) || !fs$1.statSync(absoluteUri).isFile()) {
    loadContext.warnings.push('Ignoring local source map at "' + absoluteUri + '" as resource is missing.');
    return null;
  } else if (!isAllowed) {
    loadContext.warnings.push('Cannot fetch "' + absoluteUri + '" as resource is not allowed.');
    return null;
  }

  return fs$1.readFileSync(absoluteUri, 'utf8');
}

var loadOriginalSources_1 = loadOriginalSources$1;

var UNIX_SEPARATOR = '/';
var WINDOWS_SEPARATOR_PATTERN = /\\/g;

function normalizePath$1(path) {
  return path.replace(WINDOWS_SEPARATOR_PATTERN, UNIX_SEPARATOR);
}

var normalizePath_1 = normalizePath$1;

function restoreImport$2(uri, mediaQuery) {
  return ('@import ' + uri + ' ' + mediaQuery).trim();
}

var restoreImport_1 = restoreImport$2;

var path$1 = path__default;
var url = require$$0__default$2;

var isDataUriResource = isDataUriResource_1;

var DOUBLE_QUOTE = '"';
var SINGLE_QUOTE = '\'';
var URL_PREFIX = 'url(';
var URL_SUFFIX = ')';

var PROTOCOL_LESS_PREFIX_PATTERN = /^[^\w\d]*\/\//;
var QUOTE_PREFIX_PATTERN = /^["']/;
var QUOTE_SUFFIX_PATTERN = /["']$/;
var ROUND_BRACKETS_PATTERN = /[\(\)]/;
var URL_PREFIX_PATTERN = /^url\(/i;
var URL_SUFFIX_PATTERN = /\)$/;
var WHITESPACE_PATTERN = /\s/;

var isWindows$1 = process.platform == 'win32';

function rebase$2(uri, rebaseConfig) {
  if (!rebaseConfig) {
    return uri;
  }

  if (isAbsolute(uri) && !isRemote(rebaseConfig.toBase)) {
    return uri;
  }

  if (isRemote(uri) || isSVGMarker(uri) || isInternal(uri) || isDataUriResource(uri)) {
    return uri;
  }

  if (isRemote(rebaseConfig.toBase)) {
    return url.resolve(rebaseConfig.toBase, uri);
  }

  return rebaseConfig.absolute ?
    normalize(absolute(uri, rebaseConfig)) :
    normalize(relative(uri, rebaseConfig));
}

function isAbsolute(uri) {
  return path$1.isAbsolute(uri);
}

function isSVGMarker(uri) {
  return uri[0] == '#';
}

function isInternal(uri) {
  return /^\w+:\w+/.test(uri);
}

function isRemote(uri) {
  return /^[^:]+?:\/\//.test(uri) || PROTOCOL_LESS_PREFIX_PATTERN.test(uri);
}

function absolute(uri, rebaseConfig) {
  return path$1
    .resolve(path$1.join(rebaseConfig.fromBase || '', uri))
    .replace(rebaseConfig.toBase, '');
}

function relative(uri, rebaseConfig) {
  return path$1.relative(rebaseConfig.toBase, path$1.join(rebaseConfig.fromBase || '', uri));
}

function normalize(uri) {
  return isWindows$1 ? uri.replace(/\\/g, '/') : uri;
}

function quoteFor(unquotedUrl) {
  if (unquotedUrl.indexOf(SINGLE_QUOTE) > -1) {
    return DOUBLE_QUOTE;
  } else if (unquotedUrl.indexOf(DOUBLE_QUOTE) > -1) {
    return SINGLE_QUOTE;
  } else if (hasWhitespace(unquotedUrl) || hasRoundBrackets(unquotedUrl)) {
    return SINGLE_QUOTE;
  } else {
    return '';
  }
}

function hasWhitespace(url) {
  return WHITESPACE_PATTERN.test(url);
}

function hasRoundBrackets(url) {
  return ROUND_BRACKETS_PATTERN.test(url);
}

function rewriteUrl$1(originalUrl, rebaseConfig, pathOnly) {
  var strippedUrl = originalUrl
    .replace(URL_PREFIX_PATTERN, '')
    .replace(URL_SUFFIX_PATTERN, '')
    .trim();

  var unquotedUrl = strippedUrl
    .replace(QUOTE_PREFIX_PATTERN, '')
    .replace(QUOTE_SUFFIX_PATTERN, '')
    .trim();

  var quote = strippedUrl[0] == SINGLE_QUOTE || strippedUrl[0] == DOUBLE_QUOTE ?
    strippedUrl[0] :
    quoteFor(unquotedUrl);

  return pathOnly ?
    rebase$2(unquotedUrl, rebaseConfig) :
    URL_PREFIX + quote + rebase$2(unquotedUrl, rebaseConfig) + quote + URL_SUFFIX;
}

var rewriteUrl_1 = rewriteUrl$1;

var IMPORT_PREFIX_PATTERN = /^@import/i;

function isImport$2(value) {
  return IMPORT_PREFIX_PATTERN.test(value);
}

var isImport_1 = isImport$2;

var extractImportUrlAndMedia$1 = extractImportUrlAndMedia_1;
var restoreImport$1 = restoreImport_1;
var rewriteUrl = rewriteUrl_1;

var Token$2 = token;
var isImport$1 = isImport_1;

var SOURCE_MAP_COMMENT_PATTERN = /^\/\*# sourceMappingURL=(\S+) \*\/$/;

function rebase$1(tokens, rebaseAll, validator, rebaseConfig) {
  return rebaseAll ?
    rebaseEverything(tokens, validator, rebaseConfig) :
    rebaseAtRules(tokens, validator, rebaseConfig);
}

function rebaseEverything(tokens, validator, rebaseConfig) {
  var token;
  var i, l;

  for (i = 0, l = tokens.length; i < l; i++) {
    token = tokens[i];

    switch (token[0]) {
      case Token$2.AT_RULE:
        rebaseAtRule(token, validator, rebaseConfig);
        break;
      case Token$2.AT_RULE_BLOCK:
        rebaseProperties(token[2], validator, rebaseConfig);
        break;
      case Token$2.COMMENT:
        rebaseSourceMapComment(token, rebaseConfig);
        break;
      case Token$2.NESTED_BLOCK:
        rebaseEverything(token[2], validator, rebaseConfig);
        break;
      case Token$2.RULE:
        rebaseProperties(token[2], validator, rebaseConfig);
        break;
    }
  }

  return tokens;
}

function rebaseAtRules(tokens, validator, rebaseConfig) {
  var token;
  var i, l;

  for (i = 0, l = tokens.length; i < l; i++) {
    token = tokens[i];

    switch (token[0]) {
      case Token$2.AT_RULE:
        rebaseAtRule(token, validator, rebaseConfig);
        break;
    }
  }

  return tokens;
}

function rebaseAtRule(token, validator, rebaseConfig) {
  if (!isImport$1(token[1])) {
    return;
  }

  var uriAndMediaQuery = extractImportUrlAndMedia$1(token[1]);
  var newUrl = rewriteUrl(uriAndMediaQuery[0], rebaseConfig);
  var mediaQuery = uriAndMediaQuery[1];

  token[1] = restoreImport$1(newUrl, mediaQuery);
}

function rebaseSourceMapComment(token, rebaseConfig) {
  var matches = SOURCE_MAP_COMMENT_PATTERN.exec(token[1]);

  if (matches && matches[1].indexOf('data:') === -1) {
    token[1] = token[1].replace(matches[1], rewriteUrl(matches[1], rebaseConfig, true));
  }
}

function rebaseProperties(properties, validator, rebaseConfig) {
  var property;
  var value;
  var i, l;
  var j, m;

  for (i = 0, l = properties.length; i < l; i++) {
    property = properties[i];

    for (j = 2 /* 0 is Token.PROPERTY, 1 is name */, m = property.length; j < m; j++) {
      value = property[j][1];

      if (validator.isUrl(value)) {
        property[j][1] = rewriteUrl(value, rebaseConfig);
      }
    }
  }
}

var rebase_1 = rebase$1;

var Marker$1 = marker;
var Token$1 = token;

var formatPosition = formatPosition_1;

var Level = {
  BLOCK: 'block',
  COMMENT: 'comment',
  DOUBLE_QUOTE: 'double-quote',
  RULE: 'rule',
  SINGLE_QUOTE: 'single-quote'
};

var AT_RULES = [
  '@charset',
  '@import'
];

var BLOCK_RULES = [
  '@-moz-document',
  '@document',
  '@-moz-keyframes',
  '@-ms-keyframes',
  '@-o-keyframes',
  '@-webkit-keyframes',
  '@keyframes',
  '@media',
  '@supports'
];

var IGNORE_END_COMMENT_PATTERN = /\/\* clean\-css ignore:end \*\/$/;
var IGNORE_START_COMMENT_PATTERN = /^\/\* clean\-css ignore:start \*\//;

var PAGE_MARGIN_BOXES = [
  '@bottom-center',
  '@bottom-left',
  '@bottom-left-corner',
  '@bottom-right',
  '@bottom-right-corner',
  '@left-bottom',
  '@left-middle',
  '@left-top',
  '@right-bottom',
  '@right-middle',
  '@right-top',
  '@top-center',
  '@top-left',
  '@top-left-corner',
  '@top-right',
  '@top-right-corner'
];

var EXTRA_PAGE_BOXES = [
  '@footnote',
  '@footnotes',
  '@left',
  '@page-float-bottom',
  '@page-float-top',
  '@right'
];

var REPEAT_PATTERN = /^\[\s{0,31}\d+\s{0,31}\]$/;
var RULE_WORD_SEPARATOR_PATTERN = /[\s\(]/;
var TAIL_BROKEN_VALUE_PATTERN = /[\s|\}]*$/;

function tokenize$1(source, externalContext) {
  var internalContext = {
    level: Level.BLOCK,
    position: {
      source: externalContext.source || undefined,
      line: 1,
      column: 0,
      index: 0
    }
  };

  return intoTokens(source, externalContext, internalContext, false);
}

function intoTokens(source, externalContext, internalContext, isNested) {
  var allTokens = [];
  var newTokens = allTokens;
  var lastToken;
  var ruleToken;
  var ruleTokens = [];
  var propertyToken;
  var metadata;
  var metadatas = [];
  var level = internalContext.level;
  var levels = [];
  var buffer = [];
  var buffers = [];
  var isBufferEmpty = true;
  var serializedBuffer;
  var serializedBufferPart;
  var roundBracketLevel = 0;
  var isQuoted;
  var isSpace;
  var isNewLineNix;
  var isNewLineWin;
  var isCarriageReturn;
  var isCommentStart;
  var wasCommentStart = false;
  var isCommentEnd;
  var wasCommentEnd = false;
  var isCommentEndMarker;
  var isEscaped;
  var wasEscaped = false;
  var characterWithNoSpecialMeaning;
  var isRaw = false;
  var seekingValue = false;
  var seekingPropertyBlockClosing = false;
  var position = internalContext.position;
  var lastCommentStartAt;

  for (; position.index < source.length; position.index++) {
    var character = source[position.index];

    isQuoted = level == Level.SINGLE_QUOTE || level == Level.DOUBLE_QUOTE;
    isSpace = character == Marker$1.SPACE || character == Marker$1.TAB;
    isNewLineNix = character == Marker$1.NEW_LINE_NIX;
    isNewLineWin = character == Marker$1.NEW_LINE_NIX && source[position.index - 1] == Marker$1.CARRIAGE_RETURN;
    isCarriageReturn = character == Marker$1.CARRIAGE_RETURN && source[position.index + 1] && source[position.index + 1] != Marker$1.NEW_LINE_NIX;
    isCommentStart = !wasCommentEnd && level != Level.COMMENT && !isQuoted && character == Marker$1.ASTERISK && source[position.index - 1] == Marker$1.FORWARD_SLASH;
    isCommentEndMarker = !wasCommentStart && !isQuoted && character == Marker$1.FORWARD_SLASH && source[position.index - 1] == Marker$1.ASTERISK;
    isCommentEnd = level == Level.COMMENT && isCommentEndMarker;
    characterWithNoSpecialMeaning = !isSpace && !isCarriageReturn && (character >= 'A' && character <= 'Z' || character >= 'a' && character <= 'z' || character >= '0' && character <= '9' || character == '-');
    roundBracketLevel = Math.max(roundBracketLevel, 0);

    metadata = isBufferEmpty ?
      [position.line, position.column, position.source] :
      metadata;

    if (isEscaped) {
      // previous character was a backslash
      buffer.push(character);
      isBufferEmpty = false;
    } else if (characterWithNoSpecialMeaning) {
      // it's just an alphanumeric character or a hyphen (part of any rule or property name) so let's end it quickly
      buffer.push(character);
      isBufferEmpty = false;
    } else if ((isSpace || isNewLineNix && !isNewLineWin) && (isQuoted || level == Level.COMMENT)) {
      buffer.push(character);
      isBufferEmpty = false;
    } else if ((isSpace || isNewLineNix && !isNewLineWin) && isBufferEmpty) ; else if (!isCommentEnd && level == Level.COMMENT) {
      buffer.push(character);
      isBufferEmpty = false;
    } else if (!isCommentStart && !isCommentEnd && isRaw) {
      buffer.push(character);
      isBufferEmpty = false;
    } else if (isCommentStart && (level == Level.BLOCK || level == Level.RULE) && buffer.length > 1) {
      // comment start within block preceded by some content, e.g. div/*<--
      metadatas.push(metadata);
      buffer.push(character);
      buffers.push(buffer.slice(0, -2));
      isBufferEmpty = false;

      buffer = buffer.slice(-2);
      metadata = [position.line, position.column - 1, position.source];

      levels.push(level);
      level = Level.COMMENT;
    } else if (isCommentStart) {
      // comment start, e.g. /*<--
      levels.push(level);
      level = Level.COMMENT;
      buffer.push(character);
      isBufferEmpty = false;
    } else if (isCommentEnd && isIgnoreStartComment(buffer)) {
      // ignore:start comment end, e.g. /* clean-css ignore:start */<--
      serializedBuffer = buffer.join('').trim() + character;
      lastToken = [Token$1.COMMENT, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]];
      newTokens.push(lastToken);

      isRaw = true;
      metadata = metadatas.pop() || null;
      buffer = buffers.pop() || [];
      isBufferEmpty = buffer.length === 0;
    } else if (isCommentEnd && isIgnoreEndComment(buffer)) {
      // ignore:start comment end, e.g. /* clean-css ignore:end */<--
      serializedBuffer = buffer.join('') + character;
      lastCommentStartAt = serializedBuffer.lastIndexOf(Marker$1.FORWARD_SLASH + Marker$1.ASTERISK);

      serializedBufferPart = serializedBuffer.substring(0, lastCommentStartAt);
      lastToken = [Token$1.RAW, serializedBufferPart, [originalMetadata(metadata, serializedBufferPart, externalContext)]];
      newTokens.push(lastToken);

      serializedBufferPart = serializedBuffer.substring(lastCommentStartAt);
      metadata = [position.line, position.column - serializedBufferPart.length + 1, position.source];
      lastToken = [Token$1.COMMENT, serializedBufferPart, [originalMetadata(metadata, serializedBufferPart, externalContext)]];
      newTokens.push(lastToken);

      isRaw = false;
      level = levels.pop();
      metadata = metadatas.pop() || null;
      buffer = buffers.pop() || [];
      isBufferEmpty = buffer.length === 0;
    } else if (isCommentEnd) {
      // comment end, e.g. /* comment */<--
      serializedBuffer = buffer.join('').trim() + character;
      lastToken = [Token$1.COMMENT, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]];
      newTokens.push(lastToken);

      level = levels.pop();
      metadata = metadatas.pop() || null;
      buffer = buffers.pop() || [];
      isBufferEmpty = buffer.length === 0;
    } else if (isCommentEndMarker && source[position.index + 1] != Marker$1.ASTERISK) {
      externalContext.warnings.push('Unexpected \'*/\' at ' + formatPosition([position.line, position.column, position.source]) + '.');
      buffer = [];
      isBufferEmpty = true;
    } else if (character == Marker$1.SINGLE_QUOTE && !isQuoted) {
      // single quotation start, e.g. a[href^='https<--
      levels.push(level);
      level = Level.SINGLE_QUOTE;
      buffer.push(character);
      isBufferEmpty = false;
    } else if (character == Marker$1.SINGLE_QUOTE && level == Level.SINGLE_QUOTE) {
      // single quotation end, e.g. a[href^='https'<--
      level = levels.pop();
      buffer.push(character);
      isBufferEmpty = false;
    } else if (character == Marker$1.DOUBLE_QUOTE && !isQuoted) {
      // double quotation start, e.g. a[href^="<--
      levels.push(level);
      level = Level.DOUBLE_QUOTE;
      buffer.push(character);
      isBufferEmpty = false;
    } else if (character == Marker$1.DOUBLE_QUOTE && level == Level.DOUBLE_QUOTE) {
      // double quotation end, e.g. a[href^="https"<--
      level = levels.pop();
      buffer.push(character);
      isBufferEmpty = false;
    } else if (!isCommentStart && !isCommentEnd && character != Marker$1.CLOSE_ROUND_BRACKET && character != Marker$1.OPEN_ROUND_BRACKET && level != Level.COMMENT && !isQuoted && roundBracketLevel > 0) {
      // character inside any function, e.g. hsla(.<--
      buffer.push(character);
      isBufferEmpty = false;
    } else if (character == Marker$1.OPEN_ROUND_BRACKET && !isQuoted && level != Level.COMMENT && !seekingValue) {
      // round open bracket, e.g. @import url(<--
      buffer.push(character);
      isBufferEmpty = false;

      roundBracketLevel++;
    } else if (character == Marker$1.CLOSE_ROUND_BRACKET && !isQuoted && level != Level.COMMENT && !seekingValue) {
      // round open bracket, e.g. @import url(test.css)<--
      buffer.push(character);
      isBufferEmpty = false;

      roundBracketLevel--;
    } else if (character == Marker$1.SEMICOLON && level == Level.BLOCK && buffer[0] == Marker$1.AT) {
      // semicolon ending rule at block level, e.g. @import '...';<--
      serializedBuffer = buffer.join('').trim();
      allTokens.push([Token$1.AT_RULE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);

      buffer = [];
      isBufferEmpty = true;
    } else if (character == Marker$1.COMMA && level == Level.BLOCK && ruleToken) {
      // comma separator at block level, e.g. a,div,<--
      serializedBuffer = buffer.join('').trim();
      ruleToken[1].push([tokenScopeFrom(ruleToken[0]), serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext, ruleToken[1].length)]]);

      buffer = [];
      isBufferEmpty = true;
    } else if (character == Marker$1.COMMA && level == Level.BLOCK && tokenTypeFrom(buffer) == Token$1.AT_RULE) {
      // comma separator at block level, e.g. @import url(...) screen,<--
      // keep iterating as end semicolon will create the token
      buffer.push(character);
      isBufferEmpty = false;
    } else if (character == Marker$1.COMMA && level == Level.BLOCK) {
      // comma separator at block level, e.g. a,<--
      ruleToken = [tokenTypeFrom(buffer), [], []];
      serializedBuffer = buffer.join('').trim();
      ruleToken[1].push([tokenScopeFrom(ruleToken[0]), serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext, 0)]]);

      buffer = [];
      isBufferEmpty = true;
    } else if (character == Marker$1.OPEN_CURLY_BRACKET && level == Level.BLOCK && ruleToken && ruleToken[0] == Token$1.NESTED_BLOCK) {
      // open brace opening at-rule at block level, e.g. @media{<--
      serializedBuffer = buffer.join('').trim();
      ruleToken[1].push([Token$1.NESTED_BLOCK_SCOPE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);
      allTokens.push(ruleToken);

      levels.push(level);
      position.column++;
      position.index++;
      buffer = [];
      isBufferEmpty = true;

      ruleToken[2] = intoTokens(source, externalContext, internalContext, true);
      ruleToken = null;
    } else if (character == Marker$1.OPEN_CURLY_BRACKET && level == Level.BLOCK && tokenTypeFrom(buffer) == Token$1.NESTED_BLOCK) {
      // open brace opening at-rule at block level, e.g. @media{<--
      serializedBuffer = buffer.join('').trim();
      ruleToken = ruleToken || [Token$1.NESTED_BLOCK, [], []];
      ruleToken[1].push([Token$1.NESTED_BLOCK_SCOPE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);
      allTokens.push(ruleToken);

      levels.push(level);
      position.column++;
      position.index++;
      buffer = [];
      isBufferEmpty = true;

      ruleToken[2] = intoTokens(source, externalContext, internalContext, true);
      ruleToken = null;
    } else if (character == Marker$1.OPEN_CURLY_BRACKET && level == Level.BLOCK) {
      // open brace opening rule at block level, e.g. div{<--
      serializedBuffer = buffer.join('').trim();
      ruleToken = ruleToken || [tokenTypeFrom(buffer), [], []];
      ruleToken[1].push([tokenScopeFrom(ruleToken[0]), serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext, ruleToken[1].length)]]);
      newTokens = ruleToken[2];
      allTokens.push(ruleToken);

      levels.push(level);
      level = Level.RULE;
      buffer = [];
      isBufferEmpty = true;
    } else if (character == Marker$1.OPEN_CURLY_BRACKET && level == Level.RULE && seekingValue) {
      // open brace opening rule at rule level, e.g. div{--variable:{<--
      ruleTokens.push(ruleToken);
      ruleToken = [Token$1.PROPERTY_BLOCK, []];
      propertyToken.push(ruleToken);
      newTokens = ruleToken[1];

      levels.push(level);
      level = Level.RULE;
      seekingValue = false;
    } else if (character == Marker$1.OPEN_CURLY_BRACKET && level == Level.RULE && isPageMarginBox(buffer)) {
      // open brace opening page-margin box at rule level, e.g. @page{@top-center{<--
      serializedBuffer = buffer.join('').trim();
      ruleTokens.push(ruleToken);
      ruleToken = [Token$1.AT_RULE_BLOCK, [], []];
      ruleToken[1].push([Token$1.AT_RULE_BLOCK_SCOPE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);
      newTokens.push(ruleToken);
      newTokens = ruleToken[2];

      levels.push(level);
      level = Level.RULE;
      buffer = [];
      isBufferEmpty = true;
    } else if (character == Marker$1.COLON && level == Level.RULE && !seekingValue) {
      // colon at rule level, e.g. a{color:<--
      serializedBuffer = buffer.join('').trim();
      propertyToken = [Token$1.PROPERTY, [Token$1.PROPERTY_NAME, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]];
      newTokens.push(propertyToken);

      seekingValue = true;
      buffer = [];
      isBufferEmpty = true;
    } else if (character == Marker$1.SEMICOLON && level == Level.RULE && propertyToken && ruleTokens.length > 0 && !isBufferEmpty && buffer[0] == Marker$1.AT) {
      // semicolon at rule level for at-rule, e.g. a{--color:{@apply(--other-color);<--
      serializedBuffer = buffer.join('').trim();
      ruleToken[1].push([Token$1.AT_RULE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);

      buffer = [];
      isBufferEmpty = true;
    } else if (character == Marker$1.SEMICOLON && level == Level.RULE && propertyToken && !isBufferEmpty) {
      // semicolon at rule level, e.g. a{color:red;<--
      serializedBuffer = buffer.join('').trim();
      propertyToken.push([Token$1.PROPERTY_VALUE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);

      propertyToken = null;
      seekingValue = false;
      buffer = [];
      isBufferEmpty = true;
    } else if (character == Marker$1.SEMICOLON && level == Level.RULE && propertyToken && isBufferEmpty) {
      // semicolon after bracketed value at rule level, e.g. a{color:rgb(...);<--
      propertyToken = null;
      seekingValue = false;
    } else if (character == Marker$1.SEMICOLON && level == Level.RULE && !isBufferEmpty && buffer[0] == Marker$1.AT) {
      // semicolon for at-rule at rule level, e.g. a{@apply(--variable);<--
      serializedBuffer = buffer.join('');
      newTokens.push([Token$1.AT_RULE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);

      seekingValue = false;
      buffer = [];
      isBufferEmpty = true;
    } else if (character == Marker$1.SEMICOLON && level == Level.RULE && seekingPropertyBlockClosing) {
      // close brace after a property block at rule level, e.g. a{--custom:{color:red;};<--
      seekingPropertyBlockClosing = false;
      buffer = [];
      isBufferEmpty = true;
    } else if (character == Marker$1.SEMICOLON && level == Level.RULE && isBufferEmpty) ; else if (character == Marker$1.CLOSE_CURLY_BRACKET && level == Level.RULE && propertyToken && seekingValue && !isBufferEmpty && ruleTokens.length > 0) {
      // close brace at rule level, e.g. a{--color:{color:red}<--
      serializedBuffer = buffer.join('');
      propertyToken.push([Token$1.PROPERTY_VALUE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);
      propertyToken = null;
      ruleToken = ruleTokens.pop();
      newTokens = ruleToken[2];

      level = levels.pop();
      seekingValue = false;
      buffer = [];
      isBufferEmpty = true;
    } else if (character == Marker$1.CLOSE_CURLY_BRACKET && level == Level.RULE && propertyToken && !isBufferEmpty && buffer[0] == Marker$1.AT && ruleTokens.length > 0) {
      // close brace at rule level for at-rule, e.g. a{--color:{@apply(--other-color)}<--
      serializedBuffer = buffer.join('');
      ruleToken[1].push([Token$1.AT_RULE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);
      propertyToken = null;
      ruleToken = ruleTokens.pop();
      newTokens = ruleToken[2];

      level = levels.pop();
      seekingValue = false;
      buffer = [];
      isBufferEmpty = true;
    } else if (character == Marker$1.CLOSE_CURLY_BRACKET && level == Level.RULE && propertyToken && ruleTokens.length > 0) {
      // close brace at rule level after space, e.g. a{--color:{color:red }<--
      propertyToken = null;
      ruleToken = ruleTokens.pop();
      newTokens = ruleToken[2];

      level = levels.pop();
      seekingValue = false;
    } else if (character == Marker$1.CLOSE_CURLY_BRACKET && level == Level.RULE && propertyToken && !isBufferEmpty) {
      // close brace at rule level, e.g. a{color:red}<--
      serializedBuffer = buffer.join('');
      propertyToken.push([Token$1.PROPERTY_VALUE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);
      propertyToken = null;
      ruleToken = ruleTokens.pop();
      newTokens = allTokens;

      level = levels.pop();
      seekingValue = false;
      buffer = [];
      isBufferEmpty = true;
    } else if (character == Marker$1.CLOSE_CURLY_BRACKET && level == Level.RULE && !isBufferEmpty && buffer[0] == Marker$1.AT) {
      // close brace after at-rule at rule level, e.g. a{@apply(--variable)}<--
      propertyToken = null;
      ruleToken = null;
      serializedBuffer = buffer.join('').trim();
      newTokens.push([Token$1.AT_RULE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);
      newTokens = allTokens;

      level = levels.pop();
      seekingValue = false;
      buffer = [];
      isBufferEmpty = true;
    } else if (character == Marker$1.CLOSE_CURLY_BRACKET && level == Level.RULE && levels[levels.length - 1] == Level.RULE) {
      // close brace after a property block at rule level, e.g. a{--custom:{color:red;}<--
      propertyToken = null;
      ruleToken = ruleTokens.pop();
      newTokens = ruleToken[2];

      level = levels.pop();
      seekingValue = false;
      seekingPropertyBlockClosing = true;
      buffer = [];
      isBufferEmpty = true;
    } else if (character == Marker$1.CLOSE_CURLY_BRACKET && level == Level.RULE) {
      // close brace after a rule, e.g. a{color:red;}<--
      propertyToken = null;
      ruleToken = null;
      newTokens = allTokens;

      level = levels.pop();
      seekingValue = false;
    } else if (character == Marker$1.CLOSE_CURLY_BRACKET && level == Level.BLOCK && !isNested && position.index <= source.length - 1) {
      // stray close brace at block level, e.g. a{color:red}color:blue}<--
      externalContext.warnings.push('Unexpected \'}\' at ' + formatPosition([position.line, position.column, position.source]) + '.');
      buffer.push(character);
      isBufferEmpty = false;
    } else if (character == Marker$1.CLOSE_CURLY_BRACKET && level == Level.BLOCK) {
      // close brace at block level, e.g. @media screen {...}<--
      break;
    } else if (character == Marker$1.OPEN_ROUND_BRACKET && level == Level.RULE && seekingValue) {
      // round open bracket, e.g. a{color:hsla(<--
      buffer.push(character);
      isBufferEmpty = false;
      roundBracketLevel++;
    } else if (character == Marker$1.CLOSE_ROUND_BRACKET && level == Level.RULE && seekingValue && roundBracketLevel == 1) {
      // round close bracket, e.g. a{color:hsla(0,0%,0%)<--
      buffer.push(character);
      isBufferEmpty = false;
      serializedBuffer = buffer.join('').trim();
      propertyToken.push([Token$1.PROPERTY_VALUE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);

      roundBracketLevel--;
      buffer = [];
      isBufferEmpty = true;
    } else if (character == Marker$1.CLOSE_ROUND_BRACKET && level == Level.RULE && seekingValue) {
      // round close bracket within other brackets, e.g. a{width:calc((10rem / 2)<--
      buffer.push(character);
      isBufferEmpty = false;
      roundBracketLevel--;
    } else if (character == Marker$1.FORWARD_SLASH && source[position.index + 1] != Marker$1.ASTERISK && level == Level.RULE && seekingValue && !isBufferEmpty) {
      // forward slash within a property, e.g. a{background:url(image.png) 0 0/<--
      serializedBuffer = buffer.join('').trim();
      propertyToken.push([Token$1.PROPERTY_VALUE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);
      propertyToken.push([Token$1.PROPERTY_VALUE, character, [[position.line, position.column, position.source]]]);

      buffer = [];
      isBufferEmpty = true;
    } else if (character == Marker$1.FORWARD_SLASH && source[position.index + 1] != Marker$1.ASTERISK && level == Level.RULE && seekingValue) {
      // forward slash within a property after space, e.g. a{background:url(image.png) 0 0 /<--
      propertyToken.push([Token$1.PROPERTY_VALUE, character, [[position.line, position.column, position.source]]]);

      buffer = [];
      isBufferEmpty = true;
    } else if (character == Marker$1.COMMA && level == Level.RULE && seekingValue && !isBufferEmpty) {
      // comma within a property, e.g. a{background:url(image.png),<--
      serializedBuffer = buffer.join('').trim();
      propertyToken.push([Token$1.PROPERTY_VALUE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);
      propertyToken.push([Token$1.PROPERTY_VALUE, character, [[position.line, position.column, position.source]]]);

      buffer = [];
      isBufferEmpty = true;
    } else if (character == Marker$1.COMMA && level == Level.RULE && seekingValue) {
      // comma within a property after space, e.g. a{background:url(image.png) ,<--
      propertyToken.push([Token$1.PROPERTY_VALUE, character, [[position.line, position.column, position.source]]]);

      buffer = [];
      isBufferEmpty = true;
    } else if (character == Marker$1.CLOSE_SQUARE_BRACKET && propertyToken && propertyToken.length > 1 && !isBufferEmpty && isRepeatToken(buffer)) {
      buffer.push(character);
      serializedBuffer = buffer.join('').trim();
      propertyToken[propertyToken.length - 1][1] += serializedBuffer;

      buffer = [];
      isBufferEmpty = true;
    } else if ((isSpace || (isNewLineNix && !isNewLineWin)) && level == Level.RULE && seekingValue && propertyToken && !isBufferEmpty) {
      // space or *nix newline within property, e.g. a{margin:0 <--
      serializedBuffer = buffer.join('').trim();
      propertyToken.push([Token$1.PROPERTY_VALUE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);

      buffer = [];
      isBufferEmpty = true;
    } else if (isNewLineWin && level == Level.RULE && seekingValue && propertyToken && buffer.length > 1) {
      // win newline within property, e.g. a{margin:0\r\n<--
      serializedBuffer = buffer.join('').trim();
      propertyToken.push([Token$1.PROPERTY_VALUE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);

      buffer = [];
      isBufferEmpty = true;
    } else if (isNewLineWin && level == Level.RULE && seekingValue) {
      // win newline
      buffer = [];
      isBufferEmpty = true;
    } else if (isNewLineWin && buffer.length == 1) {
      // ignore windows newline which is composed of two characters
      buffer.pop();
      isBufferEmpty = buffer.length === 0;
    } else if (!isBufferEmpty || !isSpace && !isNewLineNix && !isNewLineWin && !isCarriageReturn) {
      // any character
      buffer.push(character);
      isBufferEmpty = false;
    }

    wasEscaped = isEscaped;
    isEscaped = !wasEscaped && character == Marker$1.BACK_SLASH;
    wasCommentStart = isCommentStart;
    wasCommentEnd = isCommentEnd;

    position.line = (isNewLineWin || isNewLineNix || isCarriageReturn) ? position.line + 1 : position.line;
    position.column = (isNewLineWin || isNewLineNix || isCarriageReturn) ? 0 : position.column + 1;
  }

  if (seekingValue) {
    externalContext.warnings.push('Missing \'}\' at ' + formatPosition([position.line, position.column, position.source]) + '.');
  }

  if (seekingValue && buffer.length > 0) {
    serializedBuffer = buffer.join('').replace(TAIL_BROKEN_VALUE_PATTERN, '');
    propertyToken.push([Token$1.PROPERTY_VALUE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);

    buffer = [];
  }

  if (buffer.length > 0) {
    externalContext.warnings.push('Invalid character(s) \'' + buffer.join('') + '\' at ' + formatPosition(metadata) + '. Ignoring.');
  }

  return allTokens;
}

function isIgnoreStartComment(buffer) {
  return IGNORE_START_COMMENT_PATTERN.test(buffer.join('') + Marker$1.FORWARD_SLASH);
}

function isIgnoreEndComment(buffer) {
  return IGNORE_END_COMMENT_PATTERN.test(buffer.join('') + Marker$1.FORWARD_SLASH);
}

function originalMetadata(metadata, value, externalContext, selectorFallbacks) {
  var source = metadata[2];

  return externalContext.inputSourceMapTracker.isTracking(source) ?
    externalContext.inputSourceMapTracker.originalPositionFor(metadata, value.length, selectorFallbacks) :
    metadata;
}

function tokenTypeFrom(buffer) {
  var isAtRule = buffer[0] == Marker$1.AT || buffer[0] == Marker$1.UNDERSCORE;
  var ruleWord = buffer.join('').split(RULE_WORD_SEPARATOR_PATTERN)[0];

  if (isAtRule && BLOCK_RULES.indexOf(ruleWord) > -1) {
    return Token$1.NESTED_BLOCK;
  } else if (isAtRule && AT_RULES.indexOf(ruleWord) > -1) {
    return Token$1.AT_RULE;
  } else if (isAtRule) {
    return Token$1.AT_RULE_BLOCK;
  } else {
    return Token$1.RULE;
  }
}

function tokenScopeFrom(tokenType) {
  if (tokenType == Token$1.RULE) {
    return Token$1.RULE_SCOPE;
  } else if (tokenType == Token$1.NESTED_BLOCK) {
    return Token$1.NESTED_BLOCK_SCOPE;
  } else if (tokenType == Token$1.AT_RULE_BLOCK) {
    return Token$1.AT_RULE_BLOCK_SCOPE;
  }
}

function isPageMarginBox(buffer) {
  var serializedBuffer = buffer.join('').trim();

  return PAGE_MARGIN_BOXES.indexOf(serializedBuffer) > -1 || EXTRA_PAGE_BOXES.indexOf(serializedBuffer) > -1;
}

function isRepeatToken(buffer) {
  return REPEAT_PATTERN.test(buffer.join('') + Marker$1.CLOSE_SQUARE_BRACKET);
}

var tokenize_1 = tokenize$1;

var fs = fs__default;
var path = path__default;

var applySourceMaps = applySourceMaps_1;
var extractImportUrlAndMedia = extractImportUrlAndMedia_1;
var isAllowedResource = isAllowedResource_1;
var loadOriginalSources = loadOriginalSources_1;
var normalizePath = normalizePath_1;
var rebase = rebase_1;
var rebaseLocalMap = rebaseLocalMap_1;
var rebaseRemoteMap = rebaseRemoteMap_1;
var restoreImport = restoreImport_1;

var tokenize = tokenize_1;
var Token = token;
var Marker = marker;
var hasProtocol = hasProtocol_1;
var isImport = isImport_1;
var isRemoteResource$1 = isRemoteResource_1;

var UNKNOWN_URI = 'uri:unknown';

function readSources$1(input, context, callback) {
  return doReadSources(input, context, function (tokens) {
    return applySourceMaps(tokens, context, function () {
      return loadOriginalSources(context, function () { return callback(tokens); });
    });
  });
}

function doReadSources(input, context, callback) {
  if (typeof input == 'string') {
    return fromString(input, context, callback);
  } else if (Buffer.isBuffer(input)) {
    return fromString(input.toString(), context, callback);
  } else if (Array.isArray(input)) {
    return fromArray(input, context, callback);
  } else if (typeof input == 'object') {
    return fromHash(input, context, callback);
  }
}

function fromString(input, context, callback) {
  context.source = undefined;
  context.sourcesContent[undefined] = input;
  context.stats.originalSize += input.length;

  return fromStyles(input, context, { inline: context.options.inline }, callback);
}

function fromArray(input, context, callback) {
  var inputAsImports = input.reduce(function (accumulator, uriOrHash) {
    if (typeof uriOrHash === 'string') {
      return addStringSource(uriOrHash, accumulator);
    } else {
      return addHashSource(uriOrHash, context, accumulator);
    }

  }, []);

  return fromStyles(inputAsImports.join(''), context, { inline: ['all'] }, callback);
}

function fromHash(input, context, callback) {
  var inputAsImports = addHashSource(input, context, []);
  return fromStyles(inputAsImports.join(''), context, { inline: ['all'] }, callback);
}

function addStringSource(input, imports) {
  imports.push(restoreAsImport(normalizeUri(input)));
  return imports;
}

function addHashSource(input, context, imports) {
  var uri;
  var normalizedUri;
  var source;

  for (uri in input) {
    source = input[uri];
    normalizedUri = normalizeUri(uri);

    imports.push(restoreAsImport(normalizedUri));

    context.sourcesContent[normalizedUri] = source.styles;

    if (source.sourceMap) {
      trackSourceMap(source.sourceMap, normalizedUri, context);
    }
  }

  return imports;
}

function normalizeUri(uri) {
  var currentPath = path.resolve('');
  var absoluteUri;
  var relativeToCurrentPath;
  var normalizedUri;

  if (isRemoteResource$1(uri)) {
    return uri;
  }

  absoluteUri = path.isAbsolute(uri) ?
    uri :
    path.resolve(uri);
  relativeToCurrentPath = path.relative(currentPath, absoluteUri);
  normalizedUri = normalizePath(relativeToCurrentPath);

  return normalizedUri;
}

function trackSourceMap(sourceMap, uri, context) {
  var parsedMap = typeof sourceMap == 'string' ?
      JSON.parse(sourceMap) :
      sourceMap;
  var rebasedMap = isRemoteResource$1(uri) ?
    rebaseRemoteMap(parsedMap, uri) :
    rebaseLocalMap(parsedMap, uri || UNKNOWN_URI, context.options.rebaseTo);

  context.inputSourceMapTracker.track(uri, rebasedMap);
}

function restoreAsImport(uri) {
  return restoreImport('url(' + uri + ')', '') + Marker.SEMICOLON;
}

function fromStyles(styles, context, parentInlinerContext, callback) {
  var tokens;
  var rebaseConfig = {};

  if (!context.source) {
    rebaseConfig.fromBase = path.resolve('');
    rebaseConfig.toBase = context.options.rebaseTo;
  } else if (isRemoteResource$1(context.source)) {
    rebaseConfig.fromBase = context.source;
    rebaseConfig.toBase = context.source;
  } else if (path.isAbsolute(context.source)) {
    rebaseConfig.fromBase = path.dirname(context.source);
    rebaseConfig.toBase = context.options.rebaseTo;
  } else {
    rebaseConfig.fromBase = path.dirname(path.resolve(context.source));
    rebaseConfig.toBase = context.options.rebaseTo;
  }

  tokens = tokenize(styles, context);
  tokens = rebase(tokens, context.options.rebase, context.validator, rebaseConfig);

  return allowsAnyImports(parentInlinerContext.inline) ?
    inline(tokens, context, parentInlinerContext, callback) :
    callback(tokens);
}

function allowsAnyImports(inline) {
  return !(inline.length == 1 && inline[0] == 'none');
}

function inline(tokens, externalContext, parentInlinerContext, callback) {
  var inlinerContext = {
    afterContent: false,
    callback: callback,
    errors: externalContext.errors,
    externalContext: externalContext,
    fetch: externalContext.options.fetch,
    inlinedStylesheets: parentInlinerContext.inlinedStylesheets || externalContext.inlinedStylesheets,
    inline: parentInlinerContext.inline,
    inlineRequest: externalContext.options.inlineRequest,
    inlineTimeout: externalContext.options.inlineTimeout,
    isRemote: parentInlinerContext.isRemote || false,
    localOnly: externalContext.localOnly,
    outputTokens: [],
    rebaseTo: externalContext.options.rebaseTo,
    sourceTokens: tokens,
    warnings: externalContext.warnings
  };

  return doInlineImports(inlinerContext);
}

function doInlineImports(inlinerContext) {
  var token;
  var i, l;

  for (i = 0, l = inlinerContext.sourceTokens.length; i < l; i++) {
    token = inlinerContext.sourceTokens[i];

    if (token[0] == Token.AT_RULE && isImport(token[1])) {
      inlinerContext.sourceTokens.splice(0, i);
      return inlineStylesheet(token, inlinerContext);
    } else if (token[0] == Token.AT_RULE || token[0] == Token.COMMENT) {
      inlinerContext.outputTokens.push(token);
    } else {
      inlinerContext.outputTokens.push(token);
      inlinerContext.afterContent = true;
    }
  }

  inlinerContext.sourceTokens = [];
  return inlinerContext.callback(inlinerContext.outputTokens);
}

function inlineStylesheet(token, inlinerContext) {
  var uriAndMediaQuery = extractImportUrlAndMedia(token[1]);
  var uri = uriAndMediaQuery[0];
  var mediaQuery = uriAndMediaQuery[1];
  var metadata = token[2];

  return isRemoteResource$1(uri) ?
    inlineRemoteStylesheet(uri, mediaQuery, metadata, inlinerContext) :
    inlineLocalStylesheet(uri, mediaQuery, metadata, inlinerContext);
}

function inlineRemoteStylesheet(uri, mediaQuery, metadata, inlinerContext) {
  var isAllowed = isAllowedResource(uri, true, inlinerContext.inline);
  var originalUri = uri;
  var isLoaded = uri in inlinerContext.externalContext.sourcesContent;
  var isRuntimeResource = !hasProtocol(uri);

  if (inlinerContext.inlinedStylesheets.indexOf(uri) > -1) {
    inlinerContext.warnings.push('Ignoring remote @import of "' + uri + '" as it has already been imported.');
    inlinerContext.sourceTokens = inlinerContext.sourceTokens.slice(1);
    return doInlineImports(inlinerContext);
  } else if (inlinerContext.localOnly && inlinerContext.afterContent) {
    inlinerContext.warnings.push('Ignoring remote @import of "' + uri + '" as no callback given and after other content.');
    inlinerContext.sourceTokens = inlinerContext.sourceTokens.slice(1);
    return doInlineImports(inlinerContext);
  } else if (isRuntimeResource) {
    inlinerContext.warnings.push('Skipping remote @import of "' + uri + '" as no protocol given.');
    inlinerContext.outputTokens = inlinerContext.outputTokens.concat(inlinerContext.sourceTokens.slice(0, 1));
    inlinerContext.sourceTokens = inlinerContext.sourceTokens.slice(1);
    return doInlineImports(inlinerContext);
  } else if (inlinerContext.localOnly && !isLoaded) {
    inlinerContext.warnings.push('Skipping remote @import of "' + uri + '" as no callback given.');
    inlinerContext.outputTokens = inlinerContext.outputTokens.concat(inlinerContext.sourceTokens.slice(0, 1));
    inlinerContext.sourceTokens = inlinerContext.sourceTokens.slice(1);
    return doInlineImports(inlinerContext);
  } else if (!isAllowed && inlinerContext.afterContent) {
    inlinerContext.warnings.push('Ignoring remote @import of "' + uri + '" as resource is not allowed and after other content.');
    inlinerContext.sourceTokens = inlinerContext.sourceTokens.slice(1);
    return doInlineImports(inlinerContext);
  } else if (!isAllowed) {
    inlinerContext.warnings.push('Skipping remote @import of "' + uri + '" as resource is not allowed.');
    inlinerContext.outputTokens = inlinerContext.outputTokens.concat(inlinerContext.sourceTokens.slice(0, 1));
    inlinerContext.sourceTokens = inlinerContext.sourceTokens.slice(1);
    return doInlineImports(inlinerContext);
  }

  inlinerContext.inlinedStylesheets.push(uri);

  function whenLoaded(error, importedStyles) {
    if (error) {
      inlinerContext.errors.push('Broken @import declaration of "' + uri + '" - ' + error);

      return process.nextTick(function () {
        inlinerContext.outputTokens = inlinerContext.outputTokens.concat(inlinerContext.sourceTokens.slice(0, 1));
        inlinerContext.sourceTokens = inlinerContext.sourceTokens.slice(1);
        doInlineImports(inlinerContext);
      });
    }

    inlinerContext.inline = inlinerContext.externalContext.options.inline;
    inlinerContext.isRemote = true;

    inlinerContext.externalContext.source = originalUri;
    inlinerContext.externalContext.sourcesContent[uri] = importedStyles;
    inlinerContext.externalContext.stats.originalSize += importedStyles.length;

    return fromStyles(importedStyles, inlinerContext.externalContext, inlinerContext, function (importedTokens) {
      importedTokens = wrapInMedia(importedTokens, mediaQuery, metadata);

      inlinerContext.outputTokens = inlinerContext.outputTokens.concat(importedTokens);
      inlinerContext.sourceTokens = inlinerContext.sourceTokens.slice(1);

      return doInlineImports(inlinerContext);
    });
  }

  return isLoaded ?
    whenLoaded(null, inlinerContext.externalContext.sourcesContent[uri]) :
    inlinerContext.fetch(uri, inlinerContext.inlineRequest, inlinerContext.inlineTimeout, whenLoaded);
}

function inlineLocalStylesheet(uri, mediaQuery, metadata, inlinerContext) {
  var currentPath = path.resolve('');
  var absoluteUri = path.isAbsolute(uri) ?
    path.resolve(currentPath, uri[0] == '/' ? uri.substring(1) : uri) :
    path.resolve(inlinerContext.rebaseTo, uri);
  var relativeToCurrentPath = path.relative(currentPath, absoluteUri);
  var importedStyles;
  var isAllowed = isAllowedResource(uri, false, inlinerContext.inline);
  var normalizedPath = normalizePath(relativeToCurrentPath);
  var isLoaded = normalizedPath in inlinerContext.externalContext.sourcesContent;

  if (inlinerContext.inlinedStylesheets.indexOf(absoluteUri) > -1) {
    inlinerContext.warnings.push('Ignoring local @import of "' + uri + '" as it has already been imported.');
  } else if (!isLoaded && (!fs.existsSync(absoluteUri) || !fs.statSync(absoluteUri).isFile())) {
    inlinerContext.errors.push('Ignoring local @import of "' + uri + '" as resource is missing.');
  } else if (!isAllowed && inlinerContext.afterContent) {
    inlinerContext.warnings.push('Ignoring local @import of "' + uri + '" as resource is not allowed and after other content.');
  } else if (inlinerContext.afterContent) {
    inlinerContext.warnings.push('Ignoring local @import of "' + uri + '" as after other content.');
  } else if (!isAllowed) {
    inlinerContext.warnings.push('Skipping local @import of "' + uri + '" as resource is not allowed.');
    inlinerContext.outputTokens = inlinerContext.outputTokens.concat(inlinerContext.sourceTokens.slice(0, 1));
  } else {
    importedStyles = isLoaded ?
      inlinerContext.externalContext.sourcesContent[normalizedPath] :
      fs.readFileSync(absoluteUri, 'utf-8');

    inlinerContext.inlinedStylesheets.push(absoluteUri);
    inlinerContext.inline = inlinerContext.externalContext.options.inline;

    inlinerContext.externalContext.source = normalizedPath;
    inlinerContext.externalContext.sourcesContent[normalizedPath] = importedStyles;
    inlinerContext.externalContext.stats.originalSize += importedStyles.length;

    return fromStyles(importedStyles, inlinerContext.externalContext, inlinerContext, function (importedTokens) {
      importedTokens = wrapInMedia(importedTokens, mediaQuery, metadata);

      inlinerContext.outputTokens = inlinerContext.outputTokens.concat(importedTokens);
      inlinerContext.sourceTokens = inlinerContext.sourceTokens.slice(1);

      return doInlineImports(inlinerContext);
    });
  }

  inlinerContext.sourceTokens = inlinerContext.sourceTokens.slice(1);

  return doInlineImports(inlinerContext);
}

function wrapInMedia(tokens, mediaQuery, metadata) {
  if (mediaQuery) {
    return [[Token.NESTED_BLOCK, [[Token.NESTED_BLOCK_SCOPE, '@media ' + mediaQuery, metadata]], tokens]];
  } else {
    return tokens;
  }
}

var readSources_1 = readSources$1;

var all$1 = helpers$1.all;

function store$1(serializeContext, token) {
  var value = typeof token == 'string' ?
    token :
    token[1];
  var wrap = serializeContext.wrap;

  wrap(serializeContext, value);
  track$1(serializeContext, value);
  serializeContext.output.push(value);
}

function wrap$1(serializeContext, value) {
  if (serializeContext.column + value.length > serializeContext.format.wrapAt) {
    track$1(serializeContext, serializeContext.format.breakWith);
    serializeContext.output.push(serializeContext.format.breakWith);
  }
}

function track$1(serializeContext, value) {
  var parts = value.split('\n');

  serializeContext.line += parts.length - 1;
  serializeContext.column = parts.length > 1 ? 0 : (serializeContext.column + parts.pop().length);
}

function serializeStyles$1(tokens, context) {
  var serializeContext = {
    column: 0,
    format: context.options.format,
    indentBy: 0,
    indentWith: '',
    line: 1,
    output: [],
    spaceAfterClosingBrace: context.options.compatibility.properties.spaceAfterClosingBrace,
    store: store$1,
    wrap: context.options.format.wrapAt ?
      wrap$1 :
      function () { /* noop */  }
  };

  all$1(serializeContext, tokens);

  return {
    styles: serializeContext.output.join('')
  };
}

var simple = serializeStyles$1;

var SourceMapGenerator = build.sourceMap.SourceMapGenerator;
var all = helpers$1.all;

var isRemoteResource = isRemoteResource_1;

var isWindows = process.platform == 'win32';

var NIX_SEPARATOR_PATTERN = /\//g;
var UNKNOWN_SOURCE = '$stdin';
var WINDOWS_SEPARATOR = '\\';

function store(serializeContext, element) {
  var fromString = typeof element == 'string';
  var value = fromString ? element : element[1];
  var mappings = fromString ? null : element[2];
  var wrap = serializeContext.wrap;

  wrap(serializeContext, value);
  track(serializeContext, value, mappings);
  serializeContext.output.push(value);
}

function wrap(serializeContext, value) {
  if (serializeContext.column + value.length > serializeContext.format.wrapAt) {
    track(serializeContext, serializeContext.format.breakWith, false);
    serializeContext.output.push(serializeContext.format.breakWith);
  }
}

function track(serializeContext, value, mappings) {
  var parts = value.split('\n');

  if (mappings) {
    trackAllMappings(serializeContext, mappings);
  }

  serializeContext.line += parts.length - 1;
  serializeContext.column = parts.length > 1 ? 0 : (serializeContext.column + parts.pop().length);
}

function trackAllMappings(serializeContext, mappings) {
  for (var i = 0, l = mappings.length; i < l; i++) {
    trackMapping(serializeContext, mappings[i]);
  }
}

function trackMapping(serializeContext, mapping) {
  var line = mapping[0];
  var column = mapping[1];
  var originalSource = mapping[2];
  var source = originalSource;
  var storedSource = source || UNKNOWN_SOURCE;

  if (isWindows && source && !isRemoteResource(source)) {
    storedSource = source.replace(NIX_SEPARATOR_PATTERN, WINDOWS_SEPARATOR);
  }

  serializeContext.outputMap.addMapping({
    generated: {
      line: serializeContext.line,
      column: serializeContext.column
    },
    source: storedSource,
    original: {
      line: line,
      column: column
    }
  });

  if (serializeContext.inlineSources && (originalSource in serializeContext.sourcesContent)) {
    serializeContext.outputMap.setSourceContent(storedSource, serializeContext.sourcesContent[originalSource]);
  }
}

function serializeStylesAndSourceMap$1(tokens, context) {
  var serializeContext = {
    column: 0,
    format: context.options.format,
    indentBy: 0,
    indentWith: '',
    inlineSources: context.options.sourceMapInlineSources,
    line: 1,
    output: [],
    outputMap: new SourceMapGenerator(),
    sourcesContent: context.sourcesContent,
    spaceAfterClosingBrace: context.options.compatibility.properties.spaceAfterClosingBrace,
    store: store,
    wrap: context.options.format.wrapAt ?
      wrap :
      function () { /* noop */  }
  };

  all(serializeContext, tokens);

  return {
    sourceMap: serializeContext.outputMap,
    styles: serializeContext.output.join('')
  };
}

var sourceMaps = serializeStylesAndSourceMap$1;

/**
 * Clean-css - https://github.com/jakubpawlowicz/clean-css
 * Released under the terms of MIT license
 *
 * Copyright (C) 2017 JakubPawlowicz.com
 */

var level0Optimize = optimize$4;
var level1Optimize = optimize$3;
var level2Optimize = optimize$1;
var validator = validator_1;

var compatibilityFrom = compatibility;
var fetchFrom = fetch;
var formatFrom = format.formatFrom;
var inlineFrom = inline$1;
var inlineRequestFrom = inlineRequest;
var inlineTimeoutFrom = inlineTimeout;
var OptimizationLevel = optimizationLevel.OptimizationLevel;
var optimizationLevelFrom = optimizationLevel.optimizationLevelFrom;
var pluginsFrom = plugins;
var rebaseFrom = rebase$3;
var rebaseToFrom = rebaseTo;

var inputSourceMapTracker = inputSourceMapTracker_1;
var readSources = readSources_1;

var serializeStyles = simple;
var serializeStylesAndSourceMap = sourceMaps;

var CleanCSS = clean.exports = function CleanCSS(options) {
  options = options || {};

  this.options = {
    batch: !!options.batch,
    compatibility: compatibilityFrom(options.compatibility),
    explicitRebaseTo: 'rebaseTo' in options,
    fetch: fetchFrom(options.fetch),
    format: formatFrom(options.format),
    inline: inlineFrom(options.inline),
    inlineRequest: inlineRequestFrom(options.inlineRequest),
    inlineTimeout: inlineTimeoutFrom(options.inlineTimeout),
    level: optimizationLevelFrom(options.level),
    plugins: pluginsFrom(options.plugins),
    rebase: rebaseFrom(options.rebase, options.rebaseTo),
    rebaseTo: rebaseToFrom(options.rebaseTo),
    returnPromise: !!options.returnPromise,
    sourceMap: !!options.sourceMap,
    sourceMapInlineSources: !!options.sourceMapInlineSources
  };
};


// for compatibility with optimize-css-assets-webpack-plugin
CleanCSS.process = function (input, opts) {
  var cleanCss;
  var optsTo = opts.to;

  delete opts.to;
  cleanCss = new CleanCSS(Object.assign({ returnPromise: true, rebaseTo: optsTo }, opts));

  return cleanCss.minify(input)
    .then(function(output) {
      return { css: output.styles };
    });
};


CleanCSS.prototype.minify = function (input, maybeSourceMap, maybeCallback) {
  var options = this.options;

  if (options.returnPromise) {
    return new Promise(function (resolve, reject) {
      minifyAll(input, options, maybeSourceMap, function (errors, output) {
        return errors ?
          reject(errors) :
          resolve(output);
      });
    });
  } else {
    return minifyAll(input, options, maybeSourceMap, maybeCallback);
  }
};

function minifyAll(input, options, maybeSourceMap, maybeCallback) {
  if (options.batch && Array.isArray(input)) {
    return minifyInBatchesFromArray(input, options, maybeSourceMap, maybeCallback);
  } else if (options.batch && (typeof input == 'object')) {
    return minifyInBatchesFromHash(input, options, maybeSourceMap, maybeCallback);
  } else {
    return minify(input, options, maybeSourceMap, maybeCallback);
  }
}

function minifyInBatchesFromArray(input, options, maybeSourceMap, maybeCallback) {
  var callback = typeof maybeCallback == 'function' ?
    maybeCallback :
    (typeof maybeSourceMap == 'function' ? maybeSourceMap : null);
  var errors = [];
  var outputAsHash = {};
  var inputValue;
  var i, l;

  function whenHashBatchDone(innerErrors, output) {
    outputAsHash = Object.assign(outputAsHash, output);
    errors.concat(innerErrors);
  }

  for (i = 0, l = input.length; i < l; i++) {
    if (typeof input[i] == 'object') {
      minifyInBatchesFromHash(input[i], options, whenHashBatchDone);
    } else {
      inputValue = input[i];

      outputAsHash[inputValue] = minify([inputValue], options);
      errors.concat(outputAsHash[inputValue].errors);
    }
  }

  return callback ?
    callback(errors.length > 0 ? errors : null, outputAsHash) :
    outputAsHash;
}

function minifyInBatchesFromHash(input, options, maybeSourceMap, maybeCallback) {
  var callback = typeof maybeCallback == 'function' ?
    maybeCallback :
    (typeof maybeSourceMap == 'function' ? maybeSourceMap : null);
  var errors = [];
  var outputAsHash = {};
  var inputKey;
  var inputValue;

  for (inputKey in input) {
    inputValue = input[inputKey];

    outputAsHash[inputKey] = minify(inputValue.styles, options, inputValue.sourceMap);
    errors.concat(outputAsHash[inputKey].errors);
  }

  return callback ?
    callback(errors.length > 0 ? errors : null, outputAsHash) :
    outputAsHash;
}

function minify(input, options, maybeSourceMap, maybeCallback) {
  var sourceMap = typeof maybeSourceMap != 'function' ?
    maybeSourceMap :
    null;
  var callback = typeof maybeCallback == 'function' ?
    maybeCallback :
    (typeof maybeSourceMap == 'function' ? maybeSourceMap : null);
  var context = {
    stats: {
      efficiency: 0,
      minifiedSize: 0,
      originalSize: 0,
      startedAt: Date.now(),
      timeSpent: 0
    },
    cache: {
      specificity: {}
    },
    errors: [],
    inlinedStylesheets: [],
    inputSourceMapTracker: inputSourceMapTracker(),
    localOnly: !callback,
    options: options,
    source: null,
    sourcesContent: {},
    validator: validator(options.compatibility),
    warnings: []
  };
  var implicitRebaseToWarning;

  if (sourceMap) {
    context.inputSourceMapTracker.track(undefined, sourceMap);
  }

  if (options.rebase && !options.explicitRebaseTo) {
    implicitRebaseToWarning =
      'You have set `rebase: true` without giving `rebaseTo` option, which, in this case, defaults to the current working directory. ' +
      'You are then warned this can lead to unexpected URL rebasing (aka here be dragons)! ' +
      'If you are OK with the clean-css output, then you can get rid of this warning by giving clean-css a `rebaseTo: process.cwd()` option.';
    context.warnings.push(implicitRebaseToWarning);
  }

  return runner(context.localOnly)(function () {
    return readSources(input, context, function (tokens) {
      var serialize = context.options.sourceMap ?
        serializeStylesAndSourceMap :
        serializeStyles;

      var optimizedTokens = optimize(tokens, context);
      var optimizedStyles = serialize(optimizedTokens, context);
      var output = withMetadata(optimizedStyles, context);

      return callback ?
        callback(context.errors.length > 0 ? context.errors : null, output) :
        output;
    });
  });
}

function runner(localOnly) {
  // to always execute code asynchronously when a callback is given
  // more at blog.izs.me/post/59142742143/designing-apis-for-asynchrony
  return localOnly ?
    function (callback) { return callback(); } :
    process.nextTick;
}

function optimize(tokens, context) {
  var optimized;

  optimized = level0Optimize(tokens);
  optimized = OptimizationLevel.One in context.options.level ?
    level1Optimize(tokens, context) :
    tokens;
  optimized = OptimizationLevel.Two in context.options.level ?
    level2Optimize(tokens, context, true) :
    optimized;

  return optimized;
}

function withMetadata(output, context) {
  output.stats = calculateStatsFrom(output.styles, context);
  output.errors = context.errors;
  output.inlinedStylesheets = context.inlinedStylesheets;
  output.warnings = context.warnings;

  return output;
}

function calculateStatsFrom(styles, context) {
  var finishedAt = Date.now();
  var timeSpent = finishedAt - context.stats.startedAt;

  delete context.stats.startedAt;
  context.stats.timeSpent = timeSpent;
  context.stats.efficiency = 1 - styles.length / context.stats.originalSize;
  context.stats.minifiedSize = styles.length;

  return context.stats;
}

var cleanCss = clean.exports;

var index = /*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), cleanCss, {
  'default': cleanCss
});

exports.index = index;
//# sourceMappingURL=dep-cb9bf5e2.js.map