text: (function (global, factory) {
  	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  	typeof define === 'function' && define.amd ? define(['exports'], factory) :
  	(factory((global.d3 = {})));
  }(this, function (exports) { 'use strict';
  
  	var version = "4.0.0-alpha.14";
  
  	function ascending(a, b) {
  	  return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
  	}
  
  	function bisector(compare) {
  	  if (compare.length === 1) compare = ascendingComparator(compare);
  	  return {
  	    left: function(a, x, lo, hi) {
  	      if (lo == null) lo = 0;
  	      if (hi == null) hi = a.length;
  	      while (lo < hi) {
  	        var mid = lo + hi >>> 1;
  	        if (compare(a[mid], x) < 0) lo = mid + 1;
  	        else hi = mid;
  	      }
  	      return lo;
  	    },
  	    right: function(a, x, lo, hi) {
  	      if (lo == null) lo = 0;
  	      if (hi == null) hi = a.length;
  	      while (lo < hi) {
  	        var mid = lo + hi >>> 1;
  	        if (compare(a[mid], x) > 0) hi = mid;
  	        else lo = mid + 1;
  	      }
  	      return lo;
  	    }
  	  };
  	}
  
  	function ascendingComparator(f) {
  	  return function(d, x) {
  	    return ascending(f(d), x);
  	  };
  	}
  
  	var ascendingBisect = bisector(ascending);
  	var bisectRight = ascendingBisect.right;
  	var bisectLeft = ascendingBisect.left;
  
  	function descending(a, b) {
  	  return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
  	}
  
  	function number$1(x) {
  	  return x === null ? NaN : +x;
  	}
  
  	function variance(array, f) {
  	  var n = array.length,
  	      m = 0,
  	      a,
  	      d,
  	      s = 0,
  	      i = -1,
  	      j = 0;
  
  	  if (f == null) {
  	    while (++i < n) {
  	      if (!isNaN(a = number$1(array[i]))) {
  	        d = a - m;
  	        m += d / ++j;
  	        s += d * (a - m);
  	      }
  	    }
  	  }
  
  	  else {
  	    while (++i < n) {
  	      if (!isNaN(a = number$1(f(array[i], i, array)))) {
  	        d = a - m;
  	        m += d / ++j;
  	        s += d * (a - m);
  	      }
  	    }
  	  }
  
  	  if (j > 1) return s / (j - 1);
  	}
  
  	function deviation(array, f) {
  	  var v = variance(array, f);
  	  return v ? Math.sqrt(v) : v;
  	}
  
  	function extent(array, f) {
  	  var i = -1,
  	      n = array.length,
  	      a,
  	      b,
  	      c;
  
  	  if (f == null) {
  	    while (++i < n) if ((b = array[i]) != null && b >= b) { a = c = b; break; }
  	    while (++i < n) if ((b = array[i]) != null) {
  	      if (a > b) a = b;
  	      if (c < b) c = b;
  	    }
  	  }
  
  	  else {
  	    while (++i < n) if ((b = f(array[i], i, array)) != null && b >= b) { a = c = b; break; }
  	    while (++i < n) if ((b = f(array[i], i, array)) != null) {
  	      if (a > b) a = b;
  	      if (c < b) c = b;
  	    }
  	  }
  
  	  return [a, c];
  	}
  
  	function constant(x) {
  	  return function() {
  	    return x;
  	  };
  	}
  
  	function identity$3(x) {
  	  return x;
  	}
  
  	function sequence(start, stop, step) {
  	  start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step;
  
  	  var i = -1,
  	      n = Math.max(0, Math.ceil((stop - start) / step)) | 0,
  	      range = new Array(n);
  
  	  while (++i < n) {
  	    range[i] = start + i * step;
  	  }
  
  	  return range;
  	}
  
  	var e10 = Math.sqrt(50);
  	var e5 = Math.sqrt(10);
  	var e2 = Math.sqrt(2);
  	function ticks(start, stop, count) {
  	  var step = tickStep(start, stop, count);
  	  return sequence(
  	    Math.ceil(start / step) * step,
  	    Math.floor(stop / step) * step + step / 2, // inclusive
  	    step
  	  );
  	}
  
  	function tickStep(start, stop, count) {
  	  var step0 = Math.abs(stop - start) / Math.max(0, count),
  	      step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)),
  	      error = step0 / step1;
  	  if (error >= e10) step1 *= 10;
  	  else if (error >= e5) step1 *= 5;
  	  else if (error >= e2) step1 *= 2;
  	  return stop < start ? -step1 : step1;
  	}
  
  	function sturges(values) {
  	  return Math.ceil(Math.log(values.length) / Math.LN2) + 1;
  	}
  
  	function number(x) {
  	  return +x;
  	}
  
  	function histogram() {
  	  var value = identity$3,
  	      domain = extent,
  	      threshold = sturges;
  
  	  function histogram(data) {
  	    var i,
  	        n = data.length,
  	        x,
  	        values = new Array(n);
  
  	    // Coerce values to numbers.
  	    for (i = 0; i < n; ++i) {
  	      values[i] = +value(data[i], i, data);
  	    }
  
  	    var xz = domain(values),
  	        x0 = +xz[0],
  	        x1 = +xz[1],
  	        tz = threshold(values, x0, x1);
  
  	    // Convert number of thresholds into uniform thresholds.
  	    if (!Array.isArray(tz)) tz = ticks(x0, x1, +tz);
  
  	    // Coerce thresholds to numbers, ignoring any outside the domain.
  	    var m = tz.length;
  	    for (i = 0; i < m; ++i) tz[i] = +tz[i];
  	    while (tz[0] <= x0) tz.shift(), --m;
  	    while (tz[m - 1] >= x1) tz.pop(), --m;
  
  	    var bins = new Array(m + 1),
  	        bin;
  
  	    // Initialize bins.
  	    for (i = 0; i <= m; ++i) {
  	      bin = bins[i] = [];
  	      bin.x0 = i > 0 ? tz[i - 1] : x0;
  	      bin.x1 = i < m ? tz[i] : x1;
  	    }
  
  	    // Assign data to bins by value, ignoring any outside the domain.
  	    for (i = 0; i < n; ++i) {
  	      x = values[i];
  	      if (x0 <= x && x <= x1) {
  	        bins[bisectRight(tz, x, 0, m)].push(data[i]);
  	      }
  	    }
  
  	    return bins;
  	  }
  
  	  histogram.value = function(_) {
  	    return arguments.length ? (value = typeof _ === "function" ? _ : constant(+_), histogram) : value;
  	  };
  
  	  histogram.domain = function(_) {
  	    return arguments.length ? (domain = typeof _ === "function" ? _ : constant([+_[0], +_[1]]), histogram) : domain;
  	  };
  
  	  histogram.thresholds = function(_) {
  	    if (!arguments.length) return threshold;
  	    threshold = typeof _ === "function" ? _
  	        : Array.isArray(_) ? constant(Array.prototype.map.call(_, number))
  	        : constant(+_);
  	    return histogram;
  	  };
  
  	  return histogram;
  	}
  
  	function quantile(array, p, f) {
  	  if (f == null) f = number$1;
  	  if (!(n = array.length)) return;
  	  if ((p = +p) <= 0 || n < 2) return +f(array[0], 0, array);
  	  if (p >= 1) return +f(array[n - 1], n - 1, array);
  	  var n,
  	      h = (n - 1) * p,
  	      i = Math.floor(h),
  	      a = +f(array[i], i, array),
  	      b = +f(array[i + 1], i + 1, array);
  	  return a + (b - a) * (h - i);
  	}
  
  	function freedmanDiaconis(values, min, max) {
  	  values.sort(ascending);
  	  return Math.ceil((max - min) / (2 * (quantile(values, 0.75) - quantile(values, 0.25)) * Math.pow(values.length, -1 / 3)));
  	}
  
  	function scott(values, min, max) {
  	  return Math.ceil((max - min) / (3.5 * deviation(values) * Math.pow(values.length, -1 / 3)));
  	}
  
  	function max(array, f) {
  	  var i = -1,
  	      n = array.length,
  	      a,
  	      b;
  
  	  if (f == null) {
  	    while (++i < n) if ((b = array[i]) != null && b >= b) { a = b; break; }
  	    while (++i < n) if ((b = array[i]) != null && b > a) a = b;
  	  }
  
  	  else {
  	    while (++i < n) if ((b = f(array[i], i, array)) != null && b >= b) { a = b; break; }
  	    while (++i < n) if ((b = f(array[i], i, array)) != null && b > a) a = b;
  	  }
  
  	  return a;
  	}
  
  	function mean(array, f) {
  	  var s = 0,
  	      n = array.length,
  	      a,
  	      i = -1,
  	      j = n;
  
  	  if (f == null) {
  	    while (++i < n) if (!isNaN(a = number$1(array[i]))) s += a; else --j;
  	  }
  
  	  else {
  	    while (++i < n) if (!isNaN(a = number$1(f(array[i], i, array)))) s += a; else --j;
  	  }
  
  	  if (j) return s / j;
  	}
  
  	function median(array, f) {
  	  var numbers = [],
  	      n = array.length,
  	      a,
  	      i = -1;
  
  	  if (f == null) {
  	    while (++i < n) if (!isNaN(a = number$1(array[i]))) numbers.push(a);
  	  }
  
  	  else {
  	    while (++i < n) if (!isNaN(a = number$1(f(array[i], i, array)))) numbers.push(a);
  	  }
  
  	  return quantile(numbers.sort(ascending), 0.5);
  	}
  
  	function merge(arrays) {
  	  var n = arrays.length,
  	      m,
  	      i = -1,
  	      j = 0,
  	      merged,
  	      array;
  
  	  while (++i < n) j += arrays[i].length;
  	  merged = new Array(j);
  
  	  while (--n >= 0) {
  	    array = arrays[n];
  	    m = array.length;
  	    while (--m >= 0) {
  	      merged[--j] = array[m];
  	    }
  	  }
  
  	  return merged;
  	}
  
  	function min(array, f) {
  	  var i = -1,
  	      n = array.length,
  	      a,
  	      b;
  
  	  if (f == null) {
  	    while (++i < n) if ((b = array[i]) != null && b >= b) { a = b; break; }
  	    while (++i < n) if ((b = array[i]) != null && a > b) a = b;
  	  }
  
  	  else {
  	    while (++i < n) if ((b = f(array[i], i, array)) != null && b >= b) { a = b; break; }
  	    while (++i < n) if ((b = f(array[i], i, array)) != null && a > b) a = b;
  	  }
  
  	  return a;
  	}
  
  	function pairs(array) {
  	  var i = 0, n = array.length - 1, p = array[0], pairs = new Array(n < 0 ? 0 : n);
  	  while (i < n) pairs[i] = [p, p = array[++i]];
  	  return pairs;
  	}
  
  	function permute(array, indexes) {
  	  var i = indexes.length, permutes = new Array(i);
  	  while (i--) permutes[i] = array[indexes[i]];
  	  return permutes;
  	}
  
  	function scan(array, compare) {
  	  if (!(n = array.length)) return;
  	  var i = 0,
  	      n,
  	      j = 0,
  	      xi,
  	      xj = array[j];
  
  	  if (!compare) compare = ascending;
  
  	  while (++i < n) if (compare(xi = array[i], xj) < 0 || compare(xj, xj) !== 0) xj = xi, j = i;
  
  	  if (compare(xj, xj) === 0) return j;
  	}
  
  	function shuffle(array, i0, i1) {
  	  var m = (i1 == null ? array.length : i1) - (i0 = i0 == null ? 0 : +i0),
  	      t,
  	      i;
  
  	  while (m) {
  	    i = Math.random() * m-- | 0;
  	    t = array[m + i0];
  	    array[m + i0] = array[i + i0];
  	    array[i + i0] = t;
  	  }
  
  	  return array;
  	}
  
  	function sum(array, f) {
  	  var s = 0,
  	      n = array.length,
  	      a,
  	      i = -1;
  
  	  if (f == null) {
  	    while (++i < n) if (a = +array[i]) s += a; // Note: zero and null are equivalent.
  	  }
  
  	  else {
  	    while (++i < n) if (a = +f(array[i], i, array)) s += a;
  	  }
  
  	  return s;
  	}
  
  	function transpose(matrix) {
  	  if (!(n = matrix.length)) return [];
  	  for (var i = -1, m = min(matrix, length), transpose = new Array(m); ++i < m;) {
  	    for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n;) {
  	      row[j] = matrix[j][i];
  	    }
  	  }
  	  return transpose;
  	}
  
  	function length(d) {
  	  return d.length;
  	}
  
  	function zip() {
  	  return transpose(arguments);
  	}
  
  	var prefix = "$";
  
  	function Map() {}
  
  	Map.prototype = map.prototype = {
  	  has: function(key) {
  	    return (prefix + key) in this;
  	  },
  	  get: function(key) {
  	    return this[prefix + key];
  	  },
  	  set: function(key, value) {
  	    this[prefix + key] = value;
  	    return this;
  	  },
  	  remove: function(key) {
  	    var property = prefix + key;
  	    return property in this && delete this[property];
  	  },
  	  clear: function() {
  	    for (var property in this) if (property[0] === prefix) delete this[property];
  	  },
  	  keys: function() {
  	    var keys = [];
  	    for (var property in this) if (property[0] === prefix) keys.push(property.slice(1));
  	    return keys;
  	  },
  	  values: function() {
  	    var values = [];
  	    for (var property in this) if (property[0] === prefix) values.push(this[property]);
  	    return values;
  	  },
  	  entries: function() {
  	    var entries = [];
  	    for (var property in this) if (property[0] === prefix) entries.push({key: property.slice(1), value: this[property]});
  	    return entries;
  	  },
  	  size: function() {
  	    var size = 0;
  	    for (var property in this) if (property[0] === prefix) ++size;
  	    return size;
  	  },
  	  empty: function() {
  	    for (var property in this) if (property[0] === prefix) return false;
  	    return true;
  	  },
  	  each: function(f) {
  	    for (var property in this) if (property[0] === prefix) f(this[property], property.slice(1), this);
  	  }
  	};
  
  	function map(object, f) {
  	  var map = new Map;
  
  	  // Copy constructor.
  	  if (object instanceof Map) object.each(function(value, key) { map.set(key, value); });
  
  	  // Index array by numeric index or specified key function.
  	  else if (Array.isArray(object)) {
  	    var i = -1,
  	        n = object.length,
  	        o;
  
  	    if (f == null) while (++i < n) map.set(i, object[i]);
  	    else while (++i < n) map.set(f(o = object[i], i, object), o);
  	  }
  
  	  // Convert object to map.
  	  else if (object) for (var key in object) map.set(key, object[key]);
  
  	  return map;
  	}
  
  	function nest() {
  	  var keys = [],
  	      sortKeys = [],
  	      sortValues,
  	      rollup,
  	      nest;
  
  	  function apply(array, depth, createResult, setResult) {
  	    if (depth >= keys.length) return rollup
  	        ? rollup(array) : (sortValues
  	        ? array.sort(sortValues)
  	        : array);
  
  	    var i = -1,
  	        n = array.length,
  	        key = keys[depth++],
  	        keyValue,
  	        value,
  	        valuesByKey = map(),
  	        values,
  	        result = createResult();
  
  	    while (++i < n) {
  	      if (values = valuesByKey.get(keyValue = key(value = array[i]) + "")) {
  	        values.push(value);
  	      } else {
  	        valuesByKey.set(keyValue, [value]);
  	      }
  	    }
  
  	    valuesByKey.each(function(values, key) {
  	      setResult(result, key, apply(values, depth, createResult, setResult));
  	    });
  
  	    return result;
  	  }
  
  	  function entries(map, depth) {
  	    if (depth >= keys.length) return map;
  
  	    var array = [],
  	        sortKey = sortKeys[depth++];
  
  	    map.each(function(value, key) {
  	      array.push({key: key, values: entries(value, depth)});
  	    });
  
  	    return sortKey
  	        ? array.sort(function(a, b) { return sortKey(a.key, b.key); })
  	        : array;
  	  }
  
  	  return nest = {
  	    object: function(array) { return apply(array, 0, createObject, setObject); },
  	    map: function(array) { return apply(array, 0, createMap, setMap); },
  	    entries: function(array) { return entries(apply(array, 0, createMap, setMap), 0); },
  	    key: function(d) { keys.push(d); return nest; },
  	    sortKeys: function(order) { sortKeys[keys.length - 1] = order; return nest; },
  	    sortValues: function(order) { sortValues = order; return nest; },
  	    rollup: function(f) { rollup = f; return nest; }
  	  };
  	}
  
  	function createObject() {
  	  return {};
  	}
  
  	function setObject(object, key, value) {
  	  object[key] = value;
  	}
  
  	function createMap() {
  	  return map();
  	}
  
  	function setMap(map, key, value) {
  	  map.set(key, value);
  	}
  
  	function Set() {}
  
  	var proto = map.prototype;
  
  	Set.prototype = set.prototype = {
  	  has: proto.has,
  	  add: function(value) {
  	    value += "";
  	    this[prefix + value] = value;
  	    return this;
  	  },
  	  remove: proto.remove,
  	  clear: proto.clear,
  	  values: proto.keys,
  	  size: proto.size,
  	  empty: proto.empty,
  	  each: proto.each
  	};
  
  	function set(object, f) {
  	  var set = new Set;
  
  	  // Copy constructor.
  	  if (object instanceof Set) object.each(function(value) { set.add(value); });
  
  	  // Otherwise, assume it’s an array.
  	  else if (object) {
  	    var i = -1, n = object.length;
  	    if (f == null) while (++i < n) set.add(object[i]);
  	    else while (++i < n) set.add(f(object[i], i, object));
  	  }
  
  	  return set;
  	}
  
  	function keys(map) {
  	  var keys = [];
  	  for (var key in map) keys.push(key);
  	  return keys;
  	}
  
  	function values(map) {
  	  var values = [];
  	  for (var key in map) values.push(map[key]);
  	  return values;
  	}
  
  	function entries(map) {
  	  var entries = [];
  	  for (var key in map) entries.push({key: key, value: map[key]});
  	  return entries;
  	}
  
  	function uniform(min, max) {
  	  min = min == null ? 0 : +min;
  	  max = max == null ? 1 : +max;
  	  if (arguments.length === 1) max = min, min = 0;
  	  else max -= min;
  	  return function() {
  	    return Math.random() * max + min;
  	  };
  	}
  
  	function normal(mu, sigma) {
  	  var x, r;
  	  mu = mu == null ? 0 : +mu;
  	  sigma = sigma == null ? 1 : +sigma;
  	  return function() {
  	    var y;
  
  	    // If available, use the second previously-generated uniform random.
  	    if (x != null) y = x, x = null;
  
  	    // Otherwise, generate a new x and y.
  	    else do {
  	      x = Math.random() * 2 - 1;
  	      y = Math.random() * 2 - 1;
  	      r = x * x + y * y;
  	    } while (!r || r > 1);
  
  	    return mu + sigma * y * Math.sqrt(-2 * Math.log(r) / r);
  	  };
  	}
  
  	function logNormal() {
  	  var randomNormal = normal.apply(this, arguments);
  	  return function() {
  	    return Math.exp(randomNormal());
  	  };
  	}
  
  	function irwinHall(n) {
  	  return function() {
  	    for (var sum = 0, i = 0; i < n; ++i) sum += Math.random();
  	    return sum;
  	  };
  	}
  
  	function bates(n) {
  	  var randomIrwinHall = irwinHall(n);
  	  return function() {
  	    return randomIrwinHall() / n;
  	  };
  	}
  
  	function exponential(lambda) {
  	  return function() {
  	    return -Math.log(1 - Math.random()) / lambda;
  	  };
  	}
  
  	var linearIn = {
  	  ease: function(t) {
  	    return +t;
  	  }
  	};
  
  	var quadIn = {
  	  ease: function(t) {
  	    return t * t;
  	  }
  	};
  
  	var quadOut = {
  	  ease: function(t) {
  	    return t * (2 - t);
  	  }
  	};
  
  	var quadInOut = {
  	  ease: function(t) {
  	    return ((t *= 2) <= 1 ? t * t : --t * (2 - t) + 1) / 2;
  	  }
  	};
  
  	var cubicIn = {
  	  ease: function(t) {
  	    return t * t * t;
  	  }
  	};
  
  	var cubicOut = {
  	  ease: function(t) {
  	    return --t * t * t + 1;
  	  }
  	};
  
  	var easeCubicInOut = {
  	  ease: function(t) {
  	    return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;
  	  }
  	};
  
  	var exponent = 3;
  
  	var polyIn = (function polyIn(e) {
  	  return e = +e, {
  	    exponent: polyIn,
  	    ease: function(t) {
  	      return Math.pow(t, e);
  	    }
  	  };
  	})(exponent);
  
  	var polyOut = (function polyOut(e) {
  	  return e = +e, {
  	    exponent: polyOut,
  	    ease: function(t) {
  	      return 1 - Math.pow(1 - t, e);
  	    }
  	  };
  	})(exponent);
  
  	var polyInOut = (function polyInOut(e) {
  	  return e = +e, {
  	    exponent: polyInOut,
  	    ease: function(t) {
  	      return ((t *= 2) <= 1 ? Math.pow(t, e) : 2 - Math.pow(2 - t, e)) / 2;
  	    }
  	  };
  	})(exponent);
  
  	var pi = Math.PI;
  	var halfPi = pi / 2;
  	var sinIn = {
  	  ease: function(t) {
  	    return 1 - Math.cos(t * halfPi);
  	  }
  	};
  
  	var sinOut = {
  	  ease: function(t) {
  	    return Math.sin(t * halfPi);
  	  }
  	};
  
  	var sinInOut = {
  	  ease: function(t) {
  	    return (1 - Math.cos(pi * t)) / 2;
  	  }
  	};
  
  	var expIn = {
  	  ease: function(t) {
  	    return Math.pow(2, 10 * t - 10);
  	  }
  	};
  
  	var expOut = {
  	  ease: function(t) {
  	    return 1 - Math.pow(2, -10 * t);
  	  }
  	};
  
  	var expInOut = {
  	  ease: function(t) {
  	    return ((t *= 2) <= 1 ? Math.pow(2, 10 * t - 10) : 2 - Math.pow(2, 10 - 10 * t)) / 2;
  	  }
  	};
  
  	var circleIn = {
  	  ease: function(t) {
  	    return 1 - Math.sqrt(1 - t * t);
  	  }
  	};
  
  	var circleOut = {
  	  ease: function(t) {
  	    return Math.sqrt(1 - --t * t);
  	  }
  	};
  
  	var circleInOut = {
  	  ease: function(t) {
  	    return ((t *= 2) <= 1 ? 1 - Math.sqrt(1 - t * t) : Math.sqrt(1 - (t -= 2) * t) + 1) / 2;
  	  }
  	};
  
  	var b1 = 4 / 11;
  	var b2 = 6 / 11;
  	var b3 = 8 / 11;
  	var b4 = 3 / 4;
  	var b5 = 9 / 11;
  	var b6 = 10 / 11;
  	var b7 = 15 / 16;
  	var b8 = 21 / 22;
  	var b9 = 63 / 64;
  	var b0 = 1 / b1 / b1;
  	function bounce(t) {
  	  return (t = +t) < b1 ? b0 * t * t : t < b3 ? b0 * (t -= b2) * t + b4 : t < b6 ? b0 * (t -= b5) * t + b7 : b0 * (t -= b8) * t + b9;
  	}
  
  	var bounceIn = {
  	  ease: function(t) {
  	    return 1 - bounce(1 - t);
  	  }
  	};
  
  	var bounceOut = {
  	  ease: bounce
  	};
  
  	var bounceInOut = {
  	  ease: function(t) {
  	    return ((t *= 2) <= 1 ? 1 - bounce(1 - t) : bounce(t - 1) + 1) / 2;
  	  }
  	};
  
  	var overshoot = 1.70158;
  
  	var backIn = (function backIn(s) {
  	  return s = +s, {
  	    overshoot: backIn,
  	    ease: function(t) {
  	      return t * t * ((s + 1) * t - s);
  	    }
  	  };
  	})(overshoot);
  
  	var backOut = (function backOut(s) {
  	  return s = +s, {
  	    overshoot: backOut,
  	    ease: function(t) {
  	      return --t * t * ((s + 1) * t + s) + 1;
  	    }
  	  };
  	})(overshoot);
  
  	var backInOut = (function backInOut(s) {
  	  return s = +s, {
  	    overshoot: backInOut,
  	    ease: function(t) {
  	      return ((t *= 2) < 1 ? t * t * ((s + 1) * t - s) : (t -= 2) * t * ((s + 1) * t + s) + 2) / 2;
  	    }
  	  };
  	})(overshoot);
  
  	var tau = 2 * Math.PI;
  	var amplitude = 1;
  	var period = 0.3;
  	var elasticIn = (function elasticIn(a, p) {
  	  var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau);
  	  return {
  	    amplitude: function(a) { return elasticIn(a, p * tau); },
  	    period: function(p) { return elasticIn(a, p); },
  	    ease: function(t) {
  	      return a * Math.pow(2, 10 * --t) * Math.sin((s - t) / p);
  	    }
  	  };
  	})(amplitude, period);
  
  	var elasticOut = (function elasticOut(a, p) {
  	  var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau);
  	  return {
  	    amplitude: function(a) { return elasticOut(a, p * tau); },
  	    period: function(p) { return elasticOut(a, p); },
  	    ease: function(t) {
  	      return 1 - a * Math.pow(2, -10 * (t = +t)) * Math.sin((t + s) / p);
  	    }
  	  };
  	})(amplitude, period);
  
  	var elasticInOut = (function elasticInOut(a, p) {
  	  var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau);
  	  return {
  	    amplitude: function(a) { return elasticInOut(a, p * tau); },
  	    period: function(p) { return elasticInOut(a, p); },
  	    ease: function(t) {
  	      return ((t = t * 2 - 1) < 0
  	          ? a * Math.pow(2, 10 * t) * Math.sin((s - t) / p)
  	          : 2 - a * Math.pow(2, -10 * t) * Math.sin((s + t) / p)) / 2;
  	    }
  	  };
  	})(amplitude, period);
  
  	function area(polygon) {
  	  var i = -1,
  	      n = polygon.length,
  	      a,
  	      b = polygon[n - 1],
  	      area = 0;
  
  	  while (++i < n) {
  	    a = b;
  	    b = polygon[i];
  	    area += a[1] * b[0] - a[0] * b[1];
  	  }
  
  	  return area / 2;
  	}
  
  	function centroid(polygon) {
  	  var i = -1,
  	      n = polygon.length,
  	      x = 0,
  	      y = 0,
  	      a,
  	      b = polygon[n - 1],
  	      c,
  	      k = 0;
  
  	  while (++i < n) {
  	    a = b;
  	    b = polygon[i];
  	    k += c = a[0] * b[1] - b[0] * a[1];
  	    x += (a[0] + b[0]) * c;
  	    y += (a[1] + b[1]) * c;
  	  }
  
  	  return k *= 3, [x / k, y / k];
  	}
  
  	// Returns the 2D cross product of AB and AC vectors, i.e., the z-component of
  	// the 3D cross product in a quadrant I Cartesian coordinate system (+x is
  	// right, +y is up). Returns a positive value if ABC is counter-clockwise,
  	// negative if clockwise, and zero if the points are collinear.
  	function cross$1(a, b, c) {
  	  return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
  	}
  
  	function lexicographicOrder(a, b) {
  	  return a[0] - b[0] || a[1] - b[1];
  	}
  
  	// Computes the upper convex hull per the monotone chain algorithm.
  	// Assumes points.length >= 3, is sorted by x, unique in y.
  	// Returns an array of indices into points in left-to-right order.
  	function computeUpperHullIndexes(points) {
  	  var n = points.length,
  	      indexes = [0, 1],
  	      size = 2;
  
  	  for (var i = 2; i < n; ++i) {
  	    while (size > 1 && cross$1(points[indexes[size - 2]], points[indexes[size - 1]], points[i]) <= 0) --size;
  	    indexes[size++] = i;
  	  }
  
  	  return indexes.slice(0, size); // remove popped points
  	}
  
  	function hull(points) {
  	  if ((n = points.length) < 3) return null;
  
  	  var i,
  	      n,
  	      sortedPoints = new Array(n),
  	      flippedPoints = new Array(n);
  
  	  for (i = 0; i < n; ++i) sortedPoints[i] = [+points[i][0], +points[i][1], i];
  	  sortedPoints.sort(lexicographicOrder);
  	  for (i = 0; i < n; ++i) flippedPoints[i] = [sortedPoints[i][0], -sortedPoints[i][1]];
  
  	  var upperIndexes = computeUpperHullIndexes(sortedPoints),
  	      lowerIndexes = computeUpperHullIndexes(flippedPoints);
  
  	  // Construct the hull polygon, removing possible duplicate endpoints.
  	  var skipLeft = lowerIndexes[0] === upperIndexes[0],
  	      skipRight = lowerIndexes[lowerIndexes.length - 1] === upperIndexes[upperIndexes.length - 1],
  	      hull = [];
  
  	  // Add upper hull in right-to-l order.
  	  // Then add lower hull in left-to-right order.
  	  for (i = upperIndexes.length - 1; i >= 0; --i) hull.push(points[sortedPoints[upperIndexes[i]][2]]);
  	  for (i = +skipLeft; i < lowerIndexes.length - skipRight; ++i) hull.push(points[sortedPoints[lowerIndexes[i]][2]]);
  
  	  return hull;
  	}
  
  	function contains(polygon, point) {
  	  var n = polygon.length,
  	      p = polygon[n - 1],
  	      x = point[0], y = point[1],
  	      x0 = p[0], y0 = p[1],
  	      x1, y1,
  	      inside = false;
  
  	  for (var i = 0; i < n; ++i) {
  	    p = polygon[i], x1 = p[0], y1 = p[1];
  	    if (((y1 > y) !== (y0 > y)) && (x < (x0 - x1) * (y - y1) / (y0 - y1) + x1)) inside = !inside;
  	    x0 = x1, y0 = y1;
  	  }
  
  	  return inside;
  	}
  
  	function length$1(polygon) {
  	  var i = -1,
  	      n = polygon.length,
  	      b = polygon[n - 1],
  	      xa,
  	      ya,
  	      xb = b[0],
  	      yb = b[1],
  	      perimeter = 0;
  
  	  while (++i < n) {
  	    xa = xb;
  	    ya = yb;
  	    b = polygon[i];
  	    xb = b[0];
  	    yb = b[1];
  	    xa -= xb;
  	    ya -= yb;
  	    perimeter += Math.sqrt(xa * xa + ya * ya);
  	  }
  
  	  return perimeter;
  	}
  
  	var pi$1 = Math.PI;
  	var tau$1 = 2 * pi$1;
  	var epsilon = 1e-6;
  	var tauEpsilon = tau$1 - epsilon;
  	function Path() {
  	  this._x0 = this._y0 = // start of current subpath
  	  this._x1 = this._y1 = null; // end of current subpath
  	  this._ = [];
  	}
  
  	function path() {
  	  return new Path;
  	}
  
  	Path.prototype = path.prototype = {
  	  moveTo: function(x, y) {
  	    this._.push("M", this._x0 = this._x1 = +x, ",", this._y0 = this._y1 = +y);
  	  },
  	  closePath: function() {
  	    if (this._x1 !== null) {
  	      this._x1 = this._x0, this._y1 = this._y0;
  	      this._.push("Z");
  	    }
  	  },
  	  lineTo: function(x, y) {
  	    this._.push("L", this._x1 = +x, ",", this._y1 = +y);
  	  },
  	  quadraticCurveTo: function(x1, y1, x, y) {
  	    this._.push("Q", +x1, ",", +y1, ",", this._x1 = +x, ",", this._y1 = +y);
  	  },
  	  bezierCurveTo: function(x1, y1, x2, y2, x, y) {
  	    this._.push("C", +x1, ",", +y1, ",", +x2, ",", +y2, ",", this._x1 = +x, ",", this._y1 = +y);
  	  },
  	  arcTo: function(x1, y1, x2, y2, r) {
  	    x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r;
  	    var x0 = this._x1,
  	        y0 = this._y1,
  	        x21 = x2 - x1,
  	        y21 = y2 - y1,
  	        x01 = x0 - x1,
  	        y01 = y0 - y1,
  	        l01_2 = x01 * x01 + y01 * y01;
  
  	    // Is the radius negative? Error.
  	    if (r < 0) throw new Error("negative radius: " + r);
  
  	    // Is this path empty? Move to (x1,y1).
  	    if (this._x1 === null) {
  	      this._.push(
  	        "M", this._x1 = x1, ",", this._y1 = y1
  	      );
  	    }
  
  	    // Or, is (x1,y1) coincident with (x0,y0)? Do nothing.
  	    else if (!(l01_2 > epsilon));
  
  	    // Or, are (x0,y0), (x1,y1) and (x2,y2) collinear?
  	    // Equivalently, is (x1,y1) coincident with (x2,y2)?
  	    // Or, is the radius zero? Line to (x1,y1).
  	    else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon) || !r) {
  	      this._.push(
  	        "L", this._x1 = x1, ",", this._y1 = y1
  	      );
  	    }
  
  	    // Otherwise, draw an arc!
  	    else {
  	      var x20 = x2 - x0,
  	          y20 = y2 - y0,
  	          l21_2 = x21 * x21 + y21 * y21,
  	          l20_2 = x20 * x20 + y20 * y20,
  	          l21 = Math.sqrt(l21_2),
  	          l01 = Math.sqrt(l01_2),
  	          l = r * Math.tan((pi$1 - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2),
  	          t01 = l / l01,
  	          t21 = l / l21;
  
  	      // If the start tangent is not coincident with (x0,y0), line to.
  	      if (Math.abs(t01 - 1) > epsilon) {
  	        this._.push(
  	          "L", x1 + t01 * x01, ",", y1 + t01 * y01
  	        );
  	      }
  
  	      this._.push(
  	        "A", r, ",", r, ",0,0,", +(y01 * x20 > x01 * y20), ",", this._x1 = x1 + t21 * x21, ",", this._y1 = y1 + t21 * y21
  	      );
  	    }
  	  },
  	  arc: function(x, y, r, a0, a1, ccw) {
  	    x = +x, y = +y, r = +r;
  	    var dx = r * Math.cos(a0),
  	        dy = r * Math.sin(a0),
  	        x0 = x + dx,
  	        y0 = y + dy,
  	        cw = 1 ^ ccw,
  	        da = ccw ? a0 - a1 : a1 - a0;
  
  	    // Is the radius negative? Error.
  	    if (r < 0) throw new Error("negative radius: " + r);
  
  	    // Is this path empty? Move to (x0,y0).
  	    if (this._x1 === null) {
  	      this._.push(
  	        "M", x0, ",", y0
  	      );
  	    }
  
  	    // Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0).
  	    else if (Math.abs(this._x1 - x0) > epsilon || Math.abs(this._y1 - y0) > epsilon) {
  	      this._.push(
  	        "L", x0, ",", y0
  	      );
  	    }
  
  	    // Is this arc empty? We’re done.
  	    if (!r) return;
  
  	    // Is this a complete circle? Draw two arcs to complete the circle.
  	    if (da > tauEpsilon) {
  	      this._.push(
  	        "A", r, ",", r, ",0,1,", cw, ",", x - dx, ",", y - dy,
  	        "A", r, ",", r, ",0,1,", cw, ",", this._x1 = x0, ",", this._y1 = y0
  	      );
  	    }
  
  	    // Otherwise, draw an arc!
  	    else {
  	      if (da < 0) da = da % tau$1 + tau$1;
  	      this._.push(
  	        "A", r, ",", r, ",0,", +(da >= pi$1), ",", cw, ",", this._x1 = x + r * Math.cos(a1), ",", this._y1 = y + r * Math.sin(a1)
  	      );
  	    }
  	  },
  	  rect: function(x, y, w, h) {
  	    this._.push("M", this._x0 = this._x1 = +x, ",", this._y0 = this._y1 = +y, "h", +w, "v", +h, "h", -w, "Z");
  	  },
  	  toString: function() {
  	    return this._.join("");
  	  }
  	};
  
  	function pointX(p) {
  	  return p[0];
  	}
  
  	function pointY(p) {
  	  return p[1];
  	}
  
  	function functor(x) {
  	  return function() {
  	    return x;
  	  };
  	}
  
  	function Node() {
  	  this.x = null;
  	  this.y = null;
  	  this.leaf = true;
  	  this.data = null;
  	  this.nodes = [];
  	}
  
  	function visit(callback, node, x1, y1, x2, y2) {
  	  if (!callback(node, x1, y1, x2, y2)) {
  	    var sx = (x1 + x2) / 2,
  	        sy = (y1 + y2) / 2,
  	        children = node.nodes;
  	    if (children[0]) visit(callback, children[0], x1, y1, sx, sy);
  	    if (children[1]) visit(callback, children[1], sx, y1, x2, sy);
  	    if (children[2]) visit(callback, children[2], x1, sy, sx, y2);
  	    if (children[3]) visit(callback, children[3], sx, sy, x2, y2);
  	  }
  	}
  
  	function find(root, x, y, x0, y0, x3, y3) {
  	  var minDistance2 = Infinity,
  	      closestNode;
  
  	  (function findChild(node, x1, y1, x2, y2) {
  
  	    // stop searching if this cell can’t contain a closer node
  	    if (x1 > x3 || y1 > y3 || x2 < x0 || y2 < y0) return;
  
  	    // visit this point
  	    if (node.x != null) {
  	      var dx = x - node.x,
  	          dy = y - node.y,
  	          distance2 = dx * dx + dy * dy;
  	      if (distance2 < minDistance2) {
  	        var distance = Math.sqrt(minDistance2 = distance2);
  	        x0 = x - distance, y0 = y - distance;
  	        x3 = x + distance, y3 = y + distance;
  	        closestNode = node;
  	      }
  	    }
  
  	    // bisect the current node
  	    var children = node.nodes,
  	        xm = (x1 + x2) / 2,
  	        ym = (y1 + y2) / 2,
  	        right = x >= xm,
  	        below = y >= ym;
  
  	    // visit closest cell first
  	    for (var i = below << 1 | right, j = i + 4; i < j; ++i) {
  	      if (node = children[i & 3]) switch (i & 3) {
  	        case 0: findChild(node, x1, y1, xm, ym); break;
  	        case 1: findChild(node, xm, y1, x2, ym); break;
  	        case 2: findChild(node, x1, ym, xm, y2); break;
  	        case 3: findChild(node, xm, ym, x2, y2); break;
  	      }
  	    }
  	  })(root, x0, y0, x3, y3);
  
  	  return closestNode && closestNode.data;
  	}
  
  	function quadtree() {
  	  var x = pointX,
  	      y = pointY,
  	      x1,
  	      x2,
  	      y1,
  	      y2;
  
  	  function quadtree(data) {
  	    var d,
  	        fx = typeof x === "function" ? x : functor(x),
  	        fy = typeof y === "function" ? y : functor(y),
  	        xs,
  	        ys,
  	        i,
  	        n,
  	        x1_,
  	        y1_,
  	        x2_,
  	        y2_;
  
  	    if (!data) data = [];
  
  	    if (x1 != null) {
  	      x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2;
  	    } else {
  	      // Compute bounds, and cache points temporarily.
  	      x2_ = y2_ = -(x1_ = y1_ = Infinity);
  	      xs = [], ys = [];
  	      n = data.length;
  	      for (i = 0; i < n; ++i) {
  	        var x_ = +fx(d = data[i], i, data),
  	            y_ = +fy(d, i, data);
  	        if (x_ < x1_) x1_ = x_;
  	        if (y_ < y1_) y1_ = y_;
  	        if (x_ > x2_) x2_ = x_;
  	        if (y_ > y2_) y2_ = y_;
  	        xs.push(x_);
  	        ys.push(y_);
  	      }
  	    }
  
  	    // Squarify the bounds.
  	    var dx = x2_ - x1_,
  	        dy = y2_ - y1_;
  	    if (isFinite(dx) && isFinite(dy)) {
  	      if (dx > dy) y2_ = y1_ + dx;
  	      else x2_ = x1_ + dy;
  	    }
  
  	    // Recursively inserts the specified point at the node or one of its
  	    // descendants. The bounds are defined by [x1, x2] and [y1, y2].
  	    function insert(node, d, x, y, x1, y1, x2, y2) {
  	      if (isNaN(x) || isNaN(y)) return; // ignore invalid points
  	      if (node.leaf) {
  	        var nx = node.x,
  	            ny = node.y;
  	        if (nx != null) {
  	          // If the point at this leaf node is at the same position as the new
  	          // point we are adding, we leave the point associated with the
  	          // internal node while adding the new point to a child node. This
  	          // avoids infinite recursion.
  	          if ((Math.abs(nx - x) + Math.abs(ny - y)) < .01) {
  	            insertChild(node, d, x, y, x1, y1, x2, y2);
  	          } else {
  	            var d0 = node.data;
  	            node.x = node.y = node.data = null;
  	            insertChild(node, d0, nx, ny, x1, y1, x2, y2);
  	            insertChild(node, d, x, y, x1, y1, x2, y2);
  	          }
  	        } else {
  	          node.x = x, node.y = y, node.data = d;
  	        }
  	      } else {
  	        insertChild(node, d, x, y, x1, y1, x2, y2);
  	      }
  	    }
  
  	    // Recursively inserts the specified point [x, y] into a descendant of node
  	    // n. The bounds are defined by [x1, x2] and [y1, y2].
  	    function insertChild(node, d, x, y, x1, y1, x2, y2) {
  	      // Compute the split point, and the quadrant in which to insert the point.
  	      var xm = (x1 + x2) / 2,
  	          ym = (y1 + y2) / 2,
  	          right = x >= xm,
  	          below = y >= ym,
  	          i = below << 1 | right;
  
  	      // Recursively insert into the child node.
  	      node.leaf = false;
  	      node = node.nodes[i] || (node.nodes[i] = new Node);
  
  	      // Update the bounds as we recurse.
  	      if (right) x1 = xm; else x2 = xm;
  	      if (below) y1 = ym; else y2 = ym;
  	      insert(node, d, x, y, x1, y1, x2, y2);
  	    }
  
  	    var root = new Node;
  
  	    root.add = function(d) {
  	      insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_);
  	      return root;
  	    };
  
  	    root.visit = function(callback) {
  	      visit(callback, root, x1_, y1_, x2_, y2_);
  	      return root;
  	    };
  
  	    // Find the closest point to the specified point.
  	    // TODO allow the initial search extent to be specified?
  	    // TODO allow the initial minimum distance to be specified?
  	    // TODO allow searching below any node?
  	    root.find = function(x, y) {
  	      return find(root, x, y, x1_, y1_, x2_, y2_);
  	    };
  
  	    // Insert all points.
  	    i = -1;
  	    if (x1 == null) {
  	      while (++i < n) {
  	        insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_);
  	      }
  	      --i; // index of last insertion
  	    } else {
  	      data.forEach(root.add);
  	    }
  
  	    // Discard captured fields.
  	    xs = ys = data = d = null;
  
  	    return root;
  	  }
  
  	  quadtree.x = function(_) {
  	    return arguments.length ? (x = _, quadtree) : x;
  	  };
  
  	  quadtree.y = function(_) {
  	    return arguments.length ? (y = _, quadtree) : y;
  	  };
  
  	  quadtree.extent = function(_) {
  	    if (!arguments.length) return x1 == null ? null : [[x1, y1], [x2, y2]];
  	    if (_ == null) x1 = y1 = x2 = y2 = null;
  	    else x1 = +_[0][0], y1 = +_[0][1], x2 = +_[1][0], y2 = +_[1][1];
  	    return quadtree;
  	  };
  
  	  quadtree.size = function(_) {
  	    if (!arguments.length) return x1 == null ? null : [x2 - x1, y2 - y1];
  	    if (_ == null) x1 = y1 = x2 = y2 = null;
  	    else x1 = y1 = 0, x2 = +_[0], y2 = +_[1];
  	    return quadtree;
  	  };
  
  	  return quadtree;
  	}
  
  	var slice = [].slice;
  
  	function noop() {}
  
  	var noabort = {};
  
  	function newQueue(concurrency) {
  	  if (!(concurrency >= 1)) throw new Error;
  
  	  var q,
  	      tasks = [],
  	      results = [],
  	      waiting = 0,
  	      active = 0,
  	      ended = 0,
  	      starting, // inside a synchronous task callback?
  	      error = null,
  	      notify = noop;
  
  	  function poke() {
  	    if (!starting) try { start(); } // let the current task complete
  	    catch (e) { if (tasks[ended + active - 1]) abort(e); } // task errored synchronously
  	  }
  
  	  function start() {
  	    while (starting = waiting && active < concurrency) {
  	      var i = ended + active,
  	          t = tasks[i],
  	          j = t.length - 1,
  	          c = t[j];
  	      t[j] = end(i);
  	      --waiting, ++active;
  	      t = c.apply(null, t);
  	      if (!tasks[i]) continue; // task finished synchronously
  	      tasks[i] = t || noabort;
  	    }
  	  }
  
  	  function end(i) {
  	    return function(e, r) {
  	      if (!tasks[i]) return; // ignore multiple callbacks
  	      --active, ++ended;
  	      tasks[i] = null;
  	      if (error != null) return; // ignore secondary errors
  	      if (e != null) {
  	        abort(e);
  	      } else {
  	        results[i] = r;
  	        if (waiting) poke();
  	        else if (!active) notify(error, results);
  	      }
  	    };
  	  }
  
  	  function abort(e) {
  	    var i = tasks.length, t;
  	    error = e; // ignore active callbacks
  	    results = undefined; // allow gc
  	    waiting = NaN; // prevent starting
  
  	    while (--i >= 0) {
  	      if (t = tasks[i]) {
  	        tasks[i] = null;
  	        if (t.abort) try { t.abort(); }
  	        catch (e) { /* ignore */ }
  	      }
  	    }
  
  	    active = NaN; // allow notification
  	    notify(error, results);
  	  }
  
  	  return q = {
  	    defer: function(callback) {
  	      if (typeof callback !== "function" || notify !== noop) throw new Error;
  	      if (error != null) return q;
  	      var t = slice.call(arguments, 1);
  	      t.push(callback);
  	      ++waiting, tasks.push(t);
  	      poke();
  	      return q;
  	    },
  	    abort: function() {
  	      if (error == null) abort(new Error("abort"));
  	      return q;
  	    },
  	    await: function(callback) {
  	      if (typeof callback !== "function" || notify !== noop) throw new Error;
  	      notify = function(error, results) { callback.apply(null, [error].concat(results)); };
  	      if (!active) notify(error, results);
  	      return q;
  	    },
  	    awaitAll: function(callback) {
  	      if (typeof callback !== "function" || notify !== noop) throw new Error;
  	      notify = callback;
  	      if (!active) notify(error, results);
  	      return q;
  	    }
  	  };
  	}
  
  	function queue(concurrency) {
  	  return newQueue(arguments.length ? +concurrency : Infinity);
  	}
  
  	function constant$1(x) {
  	  return function constant() {
  	    return x;
  	  };
  	}
  
  	var epsilon$1 = 1e-12;
  	var pi$2 = Math.PI;
  	var halfPi$1 = pi$2 / 2;
  	var tau$2 = 2 * pi$2;
  
  	function arcInnerRadius(d) {
  	  return d.innerRadius;
  	}
  
  	function arcOuterRadius(d) {
  	  return d.outerRadius;
  	}
  
  	function arcStartAngle(d) {
  	  return d.startAngle;
  	}
  
  	function arcEndAngle(d) {
  	  return d.endAngle;
  	}
  
  	function arcPadAngle(d) {
  	  return d && d.padAngle; // Note: optional!
  	}
  
  	function asin(x) {
  	  return x >= 1 ? halfPi$1 : x <= -1 ? -halfPi$1 : Math.asin(x);
  	}
  
  	function intersect(x0, y0, x1, y1, x2, y2, x3, y3) {
  	  var x10 = x1 - x0, y10 = y1 - y0,
  	      x32 = x3 - x2, y32 = y3 - y2,
  	      t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / (y32 * x10 - x32 * y10);
  	  return [x0 + t * x10, y0 + t * y10];
  	}
  
  	// Compute perpendicular offset line of length rc.
  	// http://mathworld.wolfram.com/Circle-LineIntersection.html
  	function cornerTangents(x0, y0, x1, y1, r1, rc, cw) {
  	  var x01 = x0 - x1,
  	      y01 = y0 - y1,
  	      lo = (cw ? rc : -rc) / Math.sqrt(x01 * x01 + y01 * y01),
  	      ox = lo * y01,
  	      oy = -lo * x01,
  	      x11 = x0 + ox,
  	      y11 = y0 + oy,
  	      x10 = x1 + ox,
  	      y10 = y1 + oy,
  	      x00 = (x11 + x10) / 2,
  	      y00 = (y11 + y10) / 2,
  	      dx = x10 - x11,
  	      dy = y10 - y11,
  	      d2 = dx * dx + dy * dy,
  	      r = r1 - rc,
  	      D = x11 * y10 - x10 * y11,
  	      d = (dy < 0 ? -1 : 1) * Math.sqrt(Math.max(0, r * r * d2 - D * D)),
  	      cx0 = (D * dy - dx * d) / d2,
  	      cy0 = (-D * dx - dy * d) / d2,
  	      cx1 = (D * dy + dx * d) / d2,
  	      cy1 = (-D * dx + dy * d) / d2,
  	      dx0 = cx0 - x00,
  	      dy0 = cy0 - y00,
  	      dx1 = cx1 - x00,
  	      dy1 = cy1 - y00;
  
  	  // Pick the closer of the two intersection points.
  	  // TODO Is there a faster way to determine which intersection to use?
  	  if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1;
  
  	  return {
  	    cx: cx0,
  	    cy: cy0,
  	    x01: -ox,
  	    y01: -oy,
  	    x11: cx0 * (r1 / r - 1),
  	    y11: cy0 * (r1 / r - 1)
  	  };
  	}
  
  	function arc() {
  	  var innerRadius = arcInnerRadius,
  	      outerRadius = arcOuterRadius,
  	      cornerRadius = constant$1(0),
  	      padRadius = null,
  	      startAngle = arcStartAngle,
  	      endAngle = arcEndAngle,
  	      padAngle = arcPadAngle,
  	      context = null;
  
  	  function arc() {
  	    var buffer,
  	        r,
  	        r0 = +innerRadius.apply(this, arguments),
  	        r1 = +outerRadius.apply(this, arguments),
  	        a0 = startAngle.apply(this, arguments) - halfPi$1,
  	        a1 = endAngle.apply(this, arguments) - halfPi$1,
  	        da = Math.abs(a1 - a0),
  	        cw = a1 > a0;
  
  	    if (!context) context = buffer = path();
  
  	    // Ensure that the outer radius is always larger than the inner radius.
  	    if (r1 < r0) r = r1, r1 = r0, r0 = r;
  
  	    // Is it a point?
  	    if (!(r1 > epsilon$1)) context.moveTo(0, 0);
  
  	    // Or is it a circle or annulus?
  	    else if (da > tau$2 - epsilon$1) {
  	      context.moveTo(r1 * Math.cos(a0), r1 * Math.sin(a0));
  	      context.arc(0, 0, r1, a0, a1, !cw);
  	      if (r0 > epsilon$1) {
  	        context.moveTo(r0 * Math.cos(a1), r0 * Math.sin(a1));
  	        context.arc(0, 0, r0, a1, a0, cw);
  	      }
  	    }
  
  	    // Or is it a circular or annular sector?
  	    else {
  	      var a01 = a0,
  	          a11 = a1,
  	          a00 = a0,
  	          a10 = a1,
  	          da0 = da,
  	          da1 = da,
  	          ap = padAngle.apply(this, arguments) / 2,
  	          rp = (ap > epsilon$1) && (padRadius ? +padRadius.apply(this, arguments) : Math.sqrt(r0 * r0 + r1 * r1)),
  	          rc = Math.min(Math.abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments)),
  	          rc0 = rc,
  	          rc1 = rc,
  	          t0,
  	          t1;
  
  	      // Apply padding? Note that since r1 ≥ r0, da1 ≥ da0.
  	      if (rp > epsilon$1) {
  	        var p0 = asin(rp / r0 * Math.sin(ap)),
  	            p1 = asin(rp / r1 * Math.sin(ap));
  	        if ((da0 -= p0 * 2) > epsilon$1) p0 *= (cw ? 1 : -1), a00 += p0, a10 -= p0;
  	        else da0 = 0, a00 = a10 = (a0 + a1) / 2;
  	        if ((da1 -= p1 * 2) > epsilon$1) p1 *= (cw ? 1 : -1), a01 += p1, a11 -= p1;
  	        else da1 = 0, a01 = a11 = (a0 + a1) / 2;
  	      }
  
  	      var x01 = r1 * Math.cos(a01),
  	          y01 = r1 * Math.sin(a01),
  	          x10 = r0 * Math.cos(a10),
  	          y10 = r0 * Math.sin(a10);
  
  	      // Apply rounded corners?
  	      if (rc > epsilon$1) {
  	        var x11 = r1 * Math.cos(a11),
  	            y11 = r1 * Math.sin(a11),
  	            x00 = r0 * Math.cos(a00),
  	            y00 = r0 * Math.sin(a00);
  
  	        // Restrict the corner radius according to the sector angle.
  	        if (da < pi$2) {
  	          var oc = da0 > epsilon$1 ? intersect(x01, y01, x00, y00, x11, y11, x10, y10) : [x10, y10],
  	              ax = x01 - oc[0],
  	              ay = y01 - oc[1],
  	              bx = x11 - oc[0],
  	              by = y11 - oc[1],
  	              kc = 1 / Math.sin(Math.acos((ax * bx + ay * by) / (Math.sqrt(ax * ax + ay * ay) * Math.sqrt(bx * bx + by * by))) / 2),
  	              lc = Math.sqrt(oc[0] * oc[0] + oc[1] * oc[1]);
  	          rc0 = Math.min(rc, (r0 - lc) / (kc - 1));
  	          rc1 = Math.min(rc, (r1 - lc) / (kc + 1));
  	        }
  	      }
  
  	      // Is the sector collapsed to a line?
  	      if (!(da1 > epsilon$1)) context.moveTo(x01, y01);
  
  	      // Does the sector’s outer ring have rounded corners?
  	      else if (rc1 > epsilon$1) {
  	        t0 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw);
  	        t1 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw);
  
  	        context.moveTo(t0.cx + t0.x01, t0.cy + t0.y01);
  
  	        // Have the corners merged?
  	        if (rc1 < rc) context.arc(t0.cx, t0.cy, rc1, Math.atan2(t0.y01, t0.x01), Math.atan2(t1.y01, t1.x01), !cw);
  
  	        // Otherwise, draw the two corners and the ring.
  	        else {
  	          context.arc(t0.cx, t0.cy, rc1, Math.atan2(t0.y01, t0.x01), Math.atan2(t0.y11, t0.x11), !cw);
  	          context.arc(0, 0, r1, Math.atan2(t0.cy + t0.y11, t0.cx + t0.x11), Math.atan2(t1.cy + t1.y11, t1.cx + t1.x11), !cw);
  	          context.arc(t1.cx, t1.cy, rc1, Math.atan2(t1.y11, t1.x11), Math.atan2(t1.y01, t1.x01), !cw);
  	        }
  	      }
  
  	      // Or is the outer ring just a circular arc?
  	      else context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw);
  
  	      // Is there no inner ring, and it’s a circular sector?
  	      // Or perhaps it’s an annular sector collapsed due to padding?
  	      if (!(r0 > epsilon$1) || !(da0 > epsilon$1)) context.lineTo(x10, y10);
  
  	      // Does the sector’s inner ring (or point) have rounded corners?
  	      else if (rc0 > epsilon$1) {
  	        t0 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw);
  	        t1 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw);
  
  	        context.lineTo(t0.cx + t0.x01, t0.cy + t0.y01);
  
  	        // Have the corners merged?
  	        if (rc0 < rc) context.arc(t0.cx, t0.cy, rc0, Math.atan2(t0.y01, t0.x01), Math.atan2(t1.y01, t1.x01), !cw);
  
  	        // Otherwise, draw the two corners and the ring.
  	        else {
  	          context.arc(t0.cx, t0.cy, rc0, Math.atan2(t0.y01, t0.x01), Math.atan2(t0.y11, t0.x11), !cw);
  	          context.arc(0, 0, r0, Math.atan2(t0.cy + t0.y11, t0.cx + t0.x11), Math.atan2(t1.cy + t1.y11, t1.cx + t1.x11), cw);
  	          context.arc(t1.cx, t1.cy, rc0, Math.atan2(t1.y11, t1.x11), Math.atan2(t1.y01, t1.x01), !cw);
  	        }
  	      }
  
  	      // Or is the inner ring just a circular arc?
  	      else context.arc(0, 0, r0, a10, a00, cw);
  	    }
  
  	    context.closePath();
  
  	    if (buffer) return context = null, buffer + "" || null;
  	  }
  
  	  arc.centroid = function() {
  	    var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2,
  	        a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi$2 / 2;
  	    return [Math.cos(a) * r, Math.sin(a) * r];
  	  };
  
  	  arc.innerRadius = function(_) {
  	    return arguments.length ? (innerRadius = typeof _ === "function" ? _ : constant$1(+_), arc) : innerRadius;
  	  };
  
  	  arc.outerRadius = function(_) {
  	    return arguments.length ? (outerRadius = typeof _ === "function" ? _ : constant$1(+_), arc) : outerRadius;
  	  };
  
  	  arc.cornerRadius = function(_) {
  	    return arguments.length ? (cornerRadius = typeof _ === "function" ? _ : constant$1(+_), arc) : cornerRadius;
  	  };
  
  	  arc.padRadius = function(_) {
  	    return arguments.length ? (padRadius = _ == null ? null : typeof _ === "function" ? _ : constant$1(+_), arc) : padRadius;
  	  };
  
  	  arc.startAngle = function(_) {
  	    return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$1(+_), arc) : startAngle;
  	  };
  
  	  arc.endAngle = function(_) {
  	    return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$1(+_), arc) : endAngle;
  	  };
  
  	  arc.padAngle = function(_) {
  	    return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$1(+_), arc) : padAngle;
  	  };
  
  	  arc.context = function(_) {
  	    return arguments.length ? ((context = _ == null ? null : _), arc) : context;
  	  };
  
  	  return arc;
  	}
  
  	var slice$4 = Array.prototype.slice;
  
  	function bind(curve, args) {
  	  if (args.length < 2) return curve;
  	  args = slice$4.call(args);
  	  args[0] = null;
  	  return function(context) {
  	    args[0] = context;
  	    return curve.apply(null, args);
  	  };
  	}
  
  	function Linear(context) {
  	  this._context = context;
  	}
  
  	Linear.prototype = {
  	  areaStart: function() {
  	    this._line = 0;
  	  },
  	  areaEnd: function() {
  	    this._line = NaN;
  	  },
  	  lineStart: function() {
  	    this._point = 0;
  	  },
  	  lineEnd: function() {
  	    if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
  	    this._line = 1 - this._line;
  	  },
  	  point: function(x, y) {
  	    x = +x, y = +y;
  	    switch (this._point) {
  	      case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
  	      case 1: this._point = 2; // proceed
  	      default: this._context.lineTo(x, y); break;
  	    }
  	  }
  	};
  
  	function curveLinear(context) {
  	  return new Linear(context);
  	}
  
  	function x(p) {
  	  return p[0];
  	}
  
  	function y(p) {
  	  return p[1];
  	}
  
  	function area$1() {
  	  var x0 = x,
  	      x1 = null,
  	      y0 = constant$1(0),
  	      y1 = y,
  	      defined = constant$1(true),
  	      context = null,
  	      curve = curveLinear,
  	      output = null;
  
  	  function area(data) {
  	    var i,
  	        j,
  	        k,
  	        n = data.length,
  	        d,
  	        defined0 = false,
  	        buffer,
  	        x0z = new Array(n),
  	        y0z = new Array(n);
  
  	    if (!context) output = curve(buffer = path());
  
  	    for (i = 0; i <= n; ++i) {
  	      if (!(i < n && defined(d = data[i], i, data)) === defined0) {
  	        if (defined0 = !defined0) {
  	          j = i;
  	          output.areaStart();
  	          output.lineStart();
  	        } else {
  	          output.lineEnd();
  	          output.lineStart();
  	          for (k = i - 1; k >= j; --k) {
  	            output.point(x0z[k], y0z[k]);
  	          }
  	          output.lineEnd();
  	          output.areaEnd();
  	        }
  	      }
  	      if (defined0) {
  	        x0z[i] = +x0(d, i, data), y0z[i] = +y0(d, i, data);
  	        output.point(x1 ? +x1(d, i, data) : x0z[i], y1 ? +y1(d, i, data) : y0z[i]);
  	      }
  	    }
  
  	    if (buffer) return output = null, buffer + "" || null;
  	  }
  
  	  area.x = function(_) {
  	    return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$1(+_), x1 = null, area) : x0;
  	  };
  
  	  area.x0 = function(_) {
  	    return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$1(+_), area) : x0;
  	  };
  
  	  area.x1 = function(_) {
  	    return arguments.length ? (x1 = _ == null ? null : typeof _ === "function" ? _ : constant$1(+_), area) : x1;
  	  };
  
  	  area.y = function(_) {
  	    return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$1(+_), y1 = null, area) : y0;
  	  };
  
  	  area.y0 = function(_) {
  	    return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$1(+_), area) : y0;
  	  };
  
  	  area.y1 = function(_) {
  	    return arguments.length ? (y1 = _ == null ? null : typeof _ === "function" ? _ : constant$1(+_), area) : y1;
  	  };
  
  	  area.defined = function(_) {
  	    return arguments.length ? (defined = typeof _ === "function" ? _ : constant$1(!!_), area) : defined;
  	  };
  
  	  area.curve = function(_) {
  	    return arguments.length ? (curve = bind(_, arguments), context != null && (output = curve(context)), area) : curve;
  	  };
  
  	  area.context = function(_) {
  	    return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area) : context;
  	  };
  
  	  return area;
  	}
  
  	function line() {
  	  var x$$ = x,
  	      y$$ = y,
  	      defined = constant$1(true),
  	      context = null,
  	      curve = curveLinear,
  	      output = null;
  
  	  function line(data) {
  	    var i,
  	        n = data.length,
  	        d,
  	        defined0 = false,
  	        buffer;
  
  	    if (!context) output = curve(buffer = path());
  
  	    for (i = 0; i <= n; ++i) {
  	      if (!(i < n && defined(d = data[i], i, data)) === defined0) {
  	        if (defined0 = !defined0) output.lineStart();
  	        else output.lineEnd();
  	      }
  	      if (defined0) output.point(+x$$(d, i, data), +y$$(d, i, data));
  	    }
  
  	    if (buffer) return output = null, buffer + "" || null;
  	  }
  
  	  line.x = function(_) {
  	    return arguments.length ? (x$$ = typeof _ === "function" ? _ : constant$1(+_), line) : x$$;
  	  };
  
  	  line.y = function(_) {
  	    return arguments.length ? (y$$ = typeof _ === "function" ? _ : constant$1(+_), line) : y$$;
  	  };
  
  	  line.defined = function(_) {
  	    return arguments.length ? (defined = typeof _ === "function" ? _ : constant$1(!!_), line) : defined;
  	  };
  
  	  line.curve = function(_) {
  	    return arguments.length ? (curve = bind(_, arguments), context != null && (output = curve(context)), line) : curve;
  	  };
  
  	  line.context = function(_) {
  	    return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line) : context;
  	  };
  
  	  return line;
  	}
  
  	function descending$2(a, b) {
  	  return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
  	}
  
  	function identity$4(d) {
  	  return d;
  	}
  
  	function pie() {
  	  var value = identity$4,
  	      sortValues = descending$2,
  	      sort = null,
  	      startAngle = constant$1(0),
  	      endAngle = constant$1(tau$2),
  	      padAngle = constant$1(0);
  
  	  function pie(data) {
  	    var i,
  	        n = data.length,
  	        j,
  	        k,
  	        sum = 0,
  	        index = new Array(n),
  	        arcs = new Array(n),
  	        a0 = +startAngle.apply(this, arguments),
  	        da = Math.min(tau$2, Math.max(-tau$2, endAngle.apply(this, arguments) - a0)),
  	        a1,
  	        p = Math.min(Math.abs(da) / n, padAngle.apply(this, arguments)),
  	        pa = p * (da < 0 ? -1 : 1),
  	        v;
  
  	    for (i = 0; i < n; ++i) {
  	      if ((v = arcs[index[i] = i] = +value(data[i], i, data)) > 0) {
  	        sum += v;
  	      }
  	    }
  
  	    // Optionally sort the arcs by previously-computed values or by data.
  	    if (sortValues != null) index.sort(function(i, j) { return sortValues(arcs[i], arcs[j]); });
  	    else if (sort !== null) index.sort(function(i, j) { return sort(data[i], data[j]); });
  
  	    // Compute the arcs! They are stored in the original data's order.
  	    for (i = 0, k = sum ? (da - n * pa) / sum : 0; i < n; ++i, a0 = a1) {
  	      j = index[i], v = arcs[j], a1 = a0 + (v > 0 ? v * k : 0) + pa, arcs[j] = {
  	        data: data[j],
  	        index: i,
  	        value: v,
  	        startAngle: a0,
  	        endAngle: a1,
  	        padAngle: p
  	      };
  	    }
  
  	    return arcs;
  	  }
  
  	  pie.value = function(_) {
  	    return arguments.length ? (value = typeof _ === "function" ? _ : constant$1(+_), pie) : value;
  	  };
  
  	  pie.sortValues = function(_) {
  	    return arguments.length ? (sortValues = _, sort = null, pie) : sortValues;
  	  };
  
  	  pie.sort = function(_) {
  	    return arguments.length ? (sort = _, sortValues = null, pie) : sort;
  	  };
  
  	  pie.startAngle = function(_) {
  	    return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$1(+_), pie) : startAngle;
  	  };
  
  	  pie.endAngle = function(_) {
  	    return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$1(+_), pie) : endAngle;
  	  };
  
  	  pie.padAngle = function(_) {
  	    return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$1(+_), pie) : padAngle;
  	  };
  
  	  return pie;
  	}
  
  	function Radial(curve) {
  	  this._curve = curve;
  	}
  
  	Radial.prototype = {
  	  areaStart: function() {
  	    this._curve.areaStart();
  	  },
  	  areaEnd: function() {
  	    this._curve.areaEnd();
  	  },
  	  lineStart: function() {
  	    this._curve.lineStart();
  	  },
  	  lineEnd: function() {
  	    this._curve.lineEnd();
  	  },
  	  point: function(a, r) {
  	    a -= halfPi$1, this._curve.point(r * Math.cos(a), r * Math.sin(a));
  	  }
  	};
  
  	function curveRadial(curve, args) {
  	  curve = bind(curve, args);
  
  	  function radial(context) {
  	    return new Radial(curve(context));
  	  }
  
  	  radial._curve = curve;
  
  	  return radial;
  	}
  
  	function radialArea() {
  	  var a = area$1(),
  	      c = a.curve;
  
  	  a.angle = a.x, delete a.x;
  	  a.startAngle = a.x0, delete a.x0;
  	  a.endAngle = a.x1, delete a.x1;
  	  a.radius = a.y, delete a.y;
  	  a.innerRadius = a.y0, delete a.y0;
  	  a.outerRadius = a.y1, delete a.y1;
  
  	  a.curve = function(_) {
  	    return arguments.length ? c(curveRadial(_, arguments)) : c()._curve;
  	  };
  
  	  return a.curve(curveLinear);
  	}
  
  	function radialLine() {
  	  var l = line(),
  	      c = l.curve;
  
  	  l.angle = l.x, delete l.x;
  	  l.radius = l.y, delete l.y;
  
  	  l.curve = function(_) {
  	    return arguments.length ? c(curveRadial(_, arguments)) : c()._curve;
  	  };
  
  	  return l.curve(curveLinear);
  	}
  
  	var circle = {
  	  draw: function(context, size) {
  	    var r = Math.sqrt(size / pi$2);
  	    context.moveTo(r, 0);
  	    context.arc(0, 0, r, 0, tau$2);
  	  }
  	};
  
  	var cross = {
  	  draw: function(context, size) {
  	    var r = Math.sqrt(size / 5) / 2;
  	    context.moveTo(-3 * r, -r);
  	    context.lineTo(-r, -r);
  	    context.lineTo(-r, -3 * r);
  	    context.lineTo(r, -3 * r);
  	    context.lineTo(r, -r);
  	    context.lineTo(3 * r, -r);
  	    context.lineTo(3 * r, r);
  	    context.lineTo(r, r);
  	    context.lineTo(r, 3 * r);
  	    context.lineTo(-r, 3 * r);
  	    context.lineTo(-r, r);
  	    context.lineTo(-3 * r, r);
  	    context.closePath();
  	  }
  	};
  
  	var tan30 = Math.sqrt(1 / 3);
  	var tan30_2 = tan30 * 2;
  	var diamond = {
  	  draw: function(context, size) {
  	    var y = Math.sqrt(size / tan30_2),
  	        x = y * tan30;
  	    context.moveTo(0, -y);
  	    context.lineTo(x, 0);
  	    context.lineTo(0, y);
  	    context.lineTo(-x, 0);
  	    context.closePath();
  	  }
  	};
  
  	var ka = 0.89081309152928522810;
  	var kr = Math.sin(pi$2 / 10) / Math.sin(7 * pi$2 / 10);
  	var kx = Math.sin(tau$2 / 10) * kr;
  	var ky = -Math.cos(tau$2 / 10) * kr;
  	var star = {
  	  draw: function(context, size) {
  	    var r = Math.sqrt(size * ka),
  	        x = kx * r,
  	        y = ky * r;
  	    context.moveTo(0, -r);
  	    context.lineTo(x, y);
  	    for (var i = 1; i < 5; ++i) {
  	      var a = tau$2 * i / 5,
  	          c = Math.cos(a),
  	          s = Math.sin(a);
  	      context.lineTo(s * r, -c * r);
  	      context.lineTo(c * x - s * y, s * x + c * y);
  	    }
  	    context.closePath();
  	  }
  	};
  
  	var square = {
  	  draw: function(context, size) {
  	    var w = Math.sqrt(size),
  	        x = -w / 2;
  	    context.rect(x, x, w, w);
  	  }
  	};
  
  	var sqrt3 = Math.sqrt(3);
  
  	var triangle = {
  	  draw: function(context, size) {
  	    var y = -Math.sqrt(size / (sqrt3 * 3));
  	    context.moveTo(0, y * 2);
  	    context.lineTo(-sqrt3 * y, -y);
  	    context.lineTo(sqrt3 * y, -y);
  	    context.closePath();
  	  }
  	};
  
  	var c$1 = -0.5;
  	var s = Math.sqrt(3) / 2;
  	var k = 1 / Math.sqrt(12);
  	var a$1 = (k / 2 + 1) * 3;
  	var wye = {
  	  draw: function(context, size) {
  	    var r = Math.sqrt(size / a$1),
  	        x0 = r / 2,
  	        y0 = r * k,
  	        x1 = x0,
  	        y1 = r * k + r,
  	        x2 = -x1,
  	        y2 = y1;
  	    context.moveTo(x0, y0);
  	    context.lineTo(x1, y1);
  	    context.lineTo(x2, y2);
  	    context.lineTo(c$1 * x0 - s * y0, s * x0 + c$1 * y0);
  	    context.lineTo(c$1 * x1 - s * y1, s * x1 + c$1 * y1);
  	    context.lineTo(c$1 * x2 - s * y2, s * x2 + c$1 * y2);
  	    context.lineTo(c$1 * x0 + s * y0, c$1 * y0 - s * x0);
  	    context.lineTo(c$1 * x1 + s * y1, c$1 * y1 - s * x1);
  	    context.lineTo(c$1 * x2 + s * y2, c$1 * y2 - s * x2);
  	    context.closePath();
  	  }
  	};
  
  	var symbols = [
  	  circle,
  	  cross,
  	  diamond,
  	  square,
  	  star,
  	  triangle,
  	  wye
  	];
  
  	function symbol() {
  	  var type = constant$1(circle),
  	      size = constant$1(64),
  	      context = null;
  
  	  function symbol() {
  	    var buffer;
  	    if (!context) context = buffer = path();
  	    type.apply(this, arguments).draw(context, +size.apply(this, arguments));
  	    if (buffer) return context = null, buffer + "" || null;
  	  }
  
  	  symbol.type = function(_) {
  	    return arguments.length ? (type = typeof _ === "function" ? _ : constant$1(_), symbol) : type;
  	  };
  
  	  symbol.size = function(_) {
  	    return arguments.length ? (size = typeof _ === "function" ? _ : constant$1(+_), symbol) : size;
  	  };
  
  	  symbol.context = function(_) {
  	    return arguments.length ? (context = _ == null ? null : _, symbol) : context;
  	  };
  
  	  return symbol;
  	}
  
  	function noop$1() {}
  
  	function point$1(that, x, y) {
  	  that._context.bezierCurveTo(
  	    (2 * that._x0 + that._x1) / 3,
  	    (2 * that._y0 + that._y1) / 3,
  	    (that._x0 + 2 * that._x1) / 3,
  	    (that._y0 + 2 * that._y1) / 3,
  	    (that._x0 + 4 * that._x1 + x) / 6,
  	    (that._y0 + 4 * that._y1 + y) / 6
  	  );
  	}
  
  	function Basis(context) {
  	  this._context = context;
  	}
  
  	Basis.prototype = {
  	  areaStart: function() {
  	    this._line = 0;
  	  },
  	  areaEnd: function() {
  	    this._line = NaN;
  	  },
  	  lineStart: function() {
  	    this._x0 = this._x1 =
  	    this._y0 = this._y1 = NaN;
  	    this._point = 0;
  	  },
  	  lineEnd: function() {
  	    switch (this._point) {
  	      case 3: point$1(this, this._x1, this._y1); // proceed
  	      case 2: this._context.lineTo(this._x1, this._y1); break;
  	    }
  	    if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
  	    this._line = 1 - this._line;
  	  },
  	  point: function(x, y) {
  	    x = +x, y = +y;
  	    switch (this._point) {
  	      case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
  	      case 1: this._point = 2; break;
  	      case 2: this._point = 3; this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6); // proceed
  	      default: point$1(this, x, y); break;
  	    }
  	    this._x0 = this._x1, this._x1 = x;
  	    this._y0 = this._y1, this._y1 = y;
  	  }
  	};
  
  	function basis(context) {
  	  return new Basis(context);
  	}
  
  	function BasisClosed(context) {
  	  this._context = context;
  	}
  
  	BasisClosed.prototype = {
  	  areaStart: noop$1,
  	  areaEnd: noop$1,
  	  lineStart: function() {
  	    this._x0 = this._x1 = this._x2 = this._x3 = this._x4 =
  	    this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = NaN;
  	    this._point = 0;
  	  },
  	  lineEnd: function() {
  	    switch (this._point) {
  	      case 1: {
  	        this._context.moveTo(this._x2, this._y2);
  	        this._context.closePath();
  	        break;
  	      }
  	      case 2: {
  	        this._context.moveTo((this._x2 + 2 * this._x3) / 3, (this._y2 + 2 * this._y3) / 3);
  	        this._context.lineTo((this._x3 + 2 * this._x2) / 3, (this._y3 + 2 * this._y2) / 3);
  	        this._context.closePath();
  	        break;
  	      }
  	      case 3: {
  	        this.point(this._x2, this._y2);
  	        this.point(this._x3, this._y3);
  	        this.point(this._x4, this._y4);
  	        break;
  	      }
  	    }
  	  },
  	  point: function(x, y) {
  	    x = +x, y = +y;
  	    switch (this._point) {
  	      case 0: this._point = 1; this._x2 = x, this._y2 = y; break;
  	      case 1: this._point = 2; this._x3 = x, this._y3 = y; break;
  	      case 2: this._point = 3; this._x4 = x, this._y4 = y; this._context.moveTo((this._x0 + 4 * this._x1 + x) / 6, (this._y0 + 4 * this._y1 + y) / 6); break;
  	      default: point$1(this, x, y); break;
  	    }
  	    this._x0 = this._x1, this._x1 = x;
  	    this._y0 = this._y1, this._y1 = y;
  	  }
  	};
  
  	function basisClosed(context) {
  	  return new BasisClosed(context);
  	}
  
  	function BasisOpen(context) {
  	  this._context = context;
  	}
  
  	BasisOpen.prototype = {
  	  areaStart: function() {
  	    this._line = 0;
  	  },
  	  areaEnd: function() {
  	    this._line = NaN;
  	  },
  	  lineStart: function() {
  	    this._x0 = this._x1 =
  	    this._y0 = this._y1 = NaN;
  	    this._point = 0;
  	  },
  	  lineEnd: function() {
  	    if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
  	    this._line = 1 - this._line;
  	  },
  	  point: function(x, y) {
  	    x = +x, y = +y;
  	    switch (this._point) {
  	      case 0: this._point = 1; break;
  	      case 1: this._point = 2; break;
  	      case 2: this._point = 3; var x0 = (this._x0 + 4 * this._x1 + x) / 6, y0 = (this._y0 + 4 * this._y1 + y) / 6; this._line ? this._context.lineTo(x0, y0) : this._context.moveTo(x0, y0); break;
  	      case 3: this._point = 4; // proceed
  	      default: point$1(this, x, y); break;
  	    }
  	    this._x0 = this._x1, this._x1 = x;
  	    this._y0 = this._y1, this._y1 = y;
  	  }
  	};
  
  	function basisOpen(context) {
  	  return new BasisOpen(context);
  	}
  
  	function Bundle(context, beta) {
  	  this._basis = basis(context);
  	  this._beta = beta;
  	}
  
  	Bundle.prototype = {
  	  lineStart: function() {
  	    this._x = [];
  	    this._y = [];
  	    this._basis.lineStart();
  	  },
  	  lineEnd: function() {
  	    var x = this._x,
  	        y = this._y,
  	        j = x.length - 1;
  
  	    if (j > 0) {
  	      var x0 = x[0],
  	          y0 = y[0],
  	          dx = x[j] - x0,
  	          dy = y[j] - y0,
  	          i = -1,
  	          t;
  
  	      while (++i <= j) {
  	        t = i / j;
  	        this._basis.point(
  	          this._beta * x[i] + (1 - this._beta) * (x0 + t * dx),
  	          this._beta * y[i] + (1 - this._beta) * (y0 + t * dy)
  	        );
  	      }
  	    }
  
  	    this._x = this._y = null;
  	    this._basis.lineEnd();
  	  },
  	  point: function(x, y) {
  	    this._x.push(+x);
  	    this._y.push(+y);
  	  }
  	};
  
  	function bundle(context, beta) {
  	  return beta == null ? new Bundle(context, 0.85)
  	      : (beta = +beta) === 1 ? basis(context)
  	      : new Bundle(context, beta);
  	}
  
  	function point$2(that, x, y) {
  	  that._context.bezierCurveTo(
  	    that._x1 + that._k * (that._x2 - that._x0),
  	    that._y1 + that._k * (that._y2 - that._y0),
  	    that._x2 + that._k * (that._x1 - x),
  	    that._y2 + that._k * (that._y1 - y),
  	    that._x2,
  	    that._y2
  	  );
  	}
  
  	function Cardinal(context, k) {
  	  this._context = context;
  	  this._k = k;
  	}
  
  	Cardinal.prototype = {
  	  areaStart: function() {
  	    this._line = 0;
  	  },
  	  areaEnd: function() {
  	    this._line = NaN;
  	  },
  	  lineStart: function() {
  	    this._x0 = this._x1 = this._x2 =
  	    this._y0 = this._y1 = this._y2 = NaN;
  	    this._point = 0;
  	  },
  	  lineEnd: function() {
  	    switch (this._point) {
  	      case 2: this._context.lineTo(this._x2, this._y2); break;
  	      case 3: point$2(this, this._x1, this._y1); break;
  	    }
  	    if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
  	    this._line = 1 - this._line;
  	  },
  	  point: function(x, y) {
  	    x = +x, y = +y;
  	    switch (this._point) {
  	      case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
  	      case 1: this._point = 2; this._x1 = x, this._y1 = y; break;
  	      case 2: this._point = 3; // proceed
  	      default: point$2(this, x, y); break;
  	    }
  	    this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
  	    this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
  	  }
  	};
  
  	function cardinal(context, tension) {
  	  return new Cardinal(context, (tension == null ? 1 : 1 - tension) / 6);
  	}
  
  	function CardinalClosed(context, k) {
  	  this._context = context;
  	  this._k = k;
  	}
  
  	CardinalClosed.prototype = {
  	  areaStart: noop$1,
  	  areaEnd: noop$1,
  	  lineStart: function() {
  	    this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 =
  	    this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN;
  	    this._point = 0;
  	  },
  	  lineEnd: function() {
  	    switch (this._point) {
  	      case 1: {
  	        this._context.moveTo(this._x3, this._y3);
  	        this._context.closePath();
  	        break;
  	      }
  	      case 2: {
  	        this._context.lineTo(this._x3, this._y3);
  	        this._context.closePath();
  	        break;
  	      }
  	      case 3: {
  	        this.point(this._x3, this._y3);
  	        this.point(this._x4, this._y4);
  	        this.point(this._x5, this._y5);
  	        break;
  	      }
  	    }
  	  },
  	  point: function(x, y) {
  	    x = +x, y = +y;
  	    switch (this._point) {
  	      case 0: this._point = 1; this._x3 = x, this._y3 = y; break;
  	      case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break;
  	      case 2: this._point = 3; this._x5 = x, this._y5 = y; break;
  	      default: point$2(this, x, y); break;
  	    }
  	    this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
  	    this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
  	  }
  	};
  
  	function cardinalClosed(context, tension) {
  	  return new CardinalClosed(context, (tension == null ? 1 : 1 - tension) / 6);
  	}
  
  	function CardinalOpen(context, k) {
  	  this._context = context;
  	  this._k = k;
  	}
  
  	CardinalOpen.prototype = {
  	  areaStart: function() {
  	    this._line = 0;
  	  },
  	  areaEnd: function() {
  	    this._line = NaN;
  	  },
  	  lineStart: function() {
  	    this._x0 = this._x1 = this._x2 =
  	    this._y0 = this._y1 = this._y2 = NaN;
  	    this._point = 0;
  	  },
  	  lineEnd: function() {
  	    if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
  	    this._line = 1 - this._line;
  	  },
  	  point: function(x, y) {
  	    x = +x, y = +y;
  	    switch (this._point) {
  	      case 0: this._point = 1; break;
  	      case 1: this._point = 2; break;
  	      case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break;
  	      case 3: this._point = 4; // proceed
  	      default: point$2(this, x, y); break;
  	    }
  	    this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
  	    this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
  	  }
  	};
  
  	function cardinalOpen(context, tension) {
  	  return new CardinalOpen(context, (tension == null ? 1 : 1 - tension) / 6);
  	}
  
  	function point$3(that, x, y) {
  	  var x1 = that._x1,
  	      y1 = that._y1,
  	      x2 = that._x2,
  	      y2 = that._y2;
  
  	  if (that._l01_a > epsilon$1) {
  	    var a = 2 * that._l01_2a + 3 * that._l01_a * that._l12_a + that._l12_2a,
  	        n = 3 * that._l01_a * (that._l01_a + that._l12_a);
  	    x1 = (x1 * a - that._x0 * that._l12_2a + that._x2 * that._l01_2a) / n;
  	    y1 = (y1 * a - that._y0 * that._l12_2a + that._y2 * that._l01_2a) / n;
  	  }
  
  	  if (that._l23_a > epsilon$1) {
  	    var b = 2 * that._l23_2a + 3 * that._l23_a * that._l12_a + that._l12_2a,
  	        m = 3 * that._l23_a * (that._l23_a + that._l12_a);
  	    x2 = (x2 * b + that._x1 * that._l23_2a - x * that._l12_2a) / m;
  	    y2 = (y2 * b + that._y1 * that._l23_2a - y * that._l12_2a) / m;
  	  }
  
  	  that._context.bezierCurveTo(x1, y1, x2, y2, that._x2, that._y2);
  	}
  
  	function CatmullRom(context, alpha) {
  	  this._context = context;
  	  this._alpha = alpha;
  	}
  
  	CatmullRom.prototype = {
  	  areaStart: function() {
  	    this._line = 0;
  	  },
  	  areaEnd: function() {
  	    this._line = NaN;
  	  },
  	  lineStart: function() {
  	    this._x0 = this._x1 = this._x2 =
  	    this._y0 = this._y1 = this._y2 = NaN;
  	    this._l01_a = this._l12_a = this._l23_a =
  	    this._l01_2a = this._l12_2a = this._l23_2a =
  	    this._point = 0;
  	  },
  	  lineEnd: function() {
  	    switch (this._point) {
  	      case 2: this._context.lineTo(this._x2, this._y2); break;
  	      case 3: this.point(this, this._x2, this._y2); break;
  	    }
  	    if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
  	    this._line = 1 - this._line;
  	  },
  	  point: function(x, y) {
  	    x = +x, y = +y;
  
  	    if (this._point) {
  	      var x23 = this._x2 - x,
  	          y23 = this._y2 - y;
  	      this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
  	    }
  
  	    switch (this._point) {
  	      case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
  	      case 1: this._point = 2; break;
  	      case 2: this._point = 3; // proceed
  	      default: point$3(this, x, y); break;
  	    }
  
  	    this._l01_a = this._l12_a, this._l12_a = this._l23_a;
  	    this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
  	    this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
  	    this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
  	  }
  	};
  
  	function catmullRom(context, alpha) {
  	  return (alpha = alpha == null ? 0.5 : +alpha)
  	      ? new CatmullRom(context, alpha)
  	      : cardinal(context, 0);
  	}
  
  	function CatmullRomClosed(context, alpha) {
  	  this._context = context;
  	  this._alpha = alpha;
  	}
  
  	CatmullRomClosed.prototype = {
  	  areaStart: noop$1,
  	  areaEnd: noop$1,
  	  lineStart: function() {
  	    this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 =
  	    this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN;
  	    this._l01_a = this._l12_a = this._l23_a =
  	    this._l01_2a = this._l12_2a = this._l23_2a =
  	    this._point = 0;
  	  },
  	  lineEnd: function() {
  	    switch (this._point) {
  	      case 1: {
  	        this._context.moveTo(this._x3, this._y3);
  	        this._context.closePath();
  	        break;
  	      }
  	      case 2: {
  	        this._context.lineTo(this._x3, this._y3);
  	        this._context.closePath();
  	        break;
  	      }
  	      case 3: {
  	        this.point(this._x3, this._y3);
  	        this.point(this._x4, this._y4);
  	        this.point(this._x5, this._y5);
  	        break;
  	      }
  	    }
  	  },
  	  point: function(x, y) {
  	    x = +x, y = +y;
  
  	    if (this._point) {
  	      var x23 = this._x2 - x,
  	          y23 = this._y2 - y;
  	      this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
  	    }
  
  	    switch (this._point) {
  	      case 0: this._point = 1; this._x3 = x, this._y3 = y; break;
  	      case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break;
  	      case 2: this._point = 3; this._x5 = x, this._y5 = y; break;
  	      default: point$3(this, x, y); break;
  	    }
  
  	    this._l01_a = this._l12_a, this._l12_a = this._l23_a;
  	    this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
  	    this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
  	    this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
  	  }
  	};
  
  	function catmullRomClosed(context, alpha) {
  	  return (alpha = alpha == null ? 0.5 : +alpha)
  	      ? new CatmullRomClosed(context, alpha)
  	      : cardinalClosed(context, 0);
  	}
  
  	function CatmullRomOpen(context, alpha) {
  	  this._context = context;
  	  this._alpha = alpha;
  	}
  
  	CatmullRomOpen.prototype = {
  	  areaStart: function() {
  	    this._line = 0;
  	  },
  	  areaEnd: function() {
  	    this._line = NaN;
  	  },
  	  lineStart: function() {
  	    this._x0 = this._x1 = this._x2 =
  	    this._y0 = this._y1 = this._y2 = NaN;
  	    this._l01_a = this._l12_a = this._l23_a =
  	    this._l01_2a = this._l12_2a = this._l23_2a =
  	    this._point = 0;
  	  },
  	  lineEnd: function() {
  	    if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
  	    this._line = 1 - this._line;
  	  },
  	  point: function(x, y) {
  	    x = +x, y = +y;
  
  	    if (this._point) {
  	      var x23 = this._x2 - x,
  	          y23 = this._y2 - y;
  	      this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
  	    }
  
  	    switch (this._point) {
  	      case 0: this._point = 1; break;
  	      case 1: this._point = 2; break;
  	      case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break;
  	      case 3: this._point = 4; // proceed
  	      default: point$3(this, x, y); break;
  	    }
  
  	    this._l01_a = this._l12_a, this._l12_a = this._l23_a;
  	    this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
  	    this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
  	    this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
  	  }
  	};
  
  	function catmullRomOpen(context, alpha) {
  	  return (alpha = alpha == null ? 0.5 : +alpha)
  	      ? new CatmullRomOpen(context, alpha)
  	      : cardinalOpen(context, 0);
  	}
  
  	function LinearClosed(context) {
  	  this._context = context;
  	}
  
  	LinearClosed.prototype = {
  	  areaStart: noop$1,
  	  areaEnd: noop$1,
  	  lineStart: function() {
  	    this._point = 0;
  	  },
  	  lineEnd: function() {
  	    if (this._point) this._context.closePath();
  	  },
  	  point: function(x, y) {
  	    x = +x, y = +y;
  	    if (this._point) this._context.lineTo(x, y);
  	    else this._point = 1, this._context.moveTo(x, y);
  	  }
  	};
  
  	function linearClosed(context) {
  	  return new LinearClosed(context);
  	}
  
  	function sign(x) {
  	  return x < 0 ? -1 : 1;
  	}
  
  	// Calculate the slopes of the tangents (Hermite-type interpolation) based on
  	// the following paper: Steffen, M. 1990. A Simple Method for Monotonic
  	// Interpolation in One Dimension. Astronomy and Astrophysics, Vol. 239, NO.
  	// NOV(II), P. 443, 1990.
  	function slope3(that, x2, y2) {
  	  var h0 = that._x1 - that._x0,
  	      h1 = x2 - that._x1,
  	      s0 = (that._y1 - that._y0) / (h0 || h1 < 0 && -0),
  	      s1 = (y2 - that._y1) / (h1 || h0 < 0 && -0),
  	      p = (s0 * h1 + s1 * h0) / (h0 + h1);
  	  return (sign(s0) + sign(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0;
  	}
  
  	// Calculate a one-sided slope.
  	function slope2(that, t) {
  	  var h = that._x1 - that._x0;
  	  return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t;
  	}
  
  	// According to https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Representations
  	// "you can express cubic Hermite interpolation in terms of cubic Bézier curves
  	// with respect to the four values p0, p0 + m0 / 3, p1 - m1 / 3, p1".
  	function point$4(that, t0, t1) {
  	  var x0 = that._x0,
  	      y0 = that._y0,
  	      x1 = that._x1,
  	      y1 = that._y1,
  	      dx = (x1 - x0) / 3;
  	  that._context.bezierCurveTo(x0 + dx, y0 + dx * t0, x1 - dx, y1 - dx * t1, x1, y1);
  	}
  
  	function MonotoneX(context) {
  	  this._context = context;
  	}
  
  	MonotoneX.prototype = {
  	  areaStart: function() {
  	    this._line = 0;
  	  },
  	  areaEnd: function() {
  	    this._line = NaN;
  	  },
  	  lineStart: function() {
  	    this._x0 = this._x1 =
  	    this._y0 = this._y1 =
  	    this._t0 = NaN;
  	    this._point = 0;
  	  },
  	  lineEnd: function() {
  	    switch (this._point) {
  	      case 2: this._context.lineTo(this._x1, this._y1); break;
  	      case 3: point$4(this, this._t0, slope2(this, this._t0)); break;
  	    }
  	    if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
  	    this._line = 1 - this._line;
  	  },
  	  point: function(x, y) {
  	    var t1 = NaN;
  
  	    x = +x, y = +y;
  	    if (x === this._x1 && y === this._y1) return; // Ignore coincident points.
  	    switch (this._point) {
  	      case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
  	      case 1: this._point = 2; break;
  	      case 2: this._point = 3; point$4(this, slope2(this, t1 = slope3(this, x, y)), t1); break;
  	      default: point$4(this, this._t0, t1 = slope3(this, x, y)); break;
  	    }
  
  	    this._x0 = this._x1, this._x1 = x;
  	    this._y0 = this._y1, this._y1 = y;
  	    this._t0 = t1;
  	  }
  	}
  
  	function MonotoneY(context) {
  	  this._context = new ReflectContext(context);
  	}
  
  	(MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function(x, y) {
  	  MonotoneX.prototype.point.call(this, y, x);
  	};
  
  	function ReflectContext(context) {
  	  this._context = context;
  	}
  
  	ReflectContext.prototype = {
  	  moveTo: function(x, y) { this._context.moveTo(y, x); },
  	  closePath: function() { this._context.closePath(); },
  	  lineTo: function(x, y) { this._context.lineTo(y, x); },
  	  bezierCurveTo: function(x1, y1, x2, y2, x, y) { this._context.bezierCurveTo(y1, x1, y2, x2, y, x); }
  	};
  
  	function monotoneX(context) {
  	  return new MonotoneX(context);
  	}
  
  	function monotoneY(context) {
  	  return new MonotoneY(context);
  	}
  
  	function Natural(context) {
  	  this._context = context;
  	}
  
  	Natural.prototype = {
  	  areaStart: function() {
  	    this._line = 0;
  	  },
  	  areaEnd: function() {
  	    this._line = NaN;
  	  },
  	  lineStart: function() {
  	    this._x = [];
  	    this._y = [];
  	  },
  	  lineEnd: function() {
  	    var x = this._x,
  	        y = this._y,
  	        n = x.length;
  
  	    if (n) {
  	      this._line ? this._context.lineTo(x[0], y[0]) : this._context.moveTo(x[0], y[0]);
  	      if (n === 2) {
  	        this._context.lineTo(x[1], y[1]);
  	      } else {
  	        var px = controlPoints(x),
  	            py = controlPoints(y);
  	        for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) {
  	          this._context.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x[i1], y[i1]);
  	        }
  	      }
  	    }
  
  	    if (this._line || (this._line !== 0 && n === 1)) this._context.closePath();
  	    this._line = 1 - this._line;
  	    this._x = this._y = null;
  	  },
  	  point: function(x, y) {
  	    this._x.push(+x);
  	    this._y.push(+y);
  	  }
  	};
  
  	// See https://www.particleincell.com/2012/bezier-splines/ for derivation.
  	function controlPoints(x) {
  	  var i,
  	      n = x.length - 1,
  	      m,
  	      a = new Array(n),
  	      b = new Array(n),
  	      r = new Array(n);
  	  a[0] = 0, b[0] = 2, r[0] = x[0] + 2 * x[1];
  	  for (i = 1; i < n - 1; ++i) a[i] = 1, b[i] = 4, r[i] = 4 * x[i] + 2 * x[i + 1];
  	  a[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x[n - 1] + x[n];
  	  for (i = 1; i < n; ++i) m = a[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1];
  	  a[n - 1] = r[n - 1] / b[n - 1];
  	  for (i = n - 2; i >= 0; --i) a[i] = (r[i] - a[i + 1]) / b[i];
  	  b[n - 1] = (x[n] + a[n - 1]) / 2;
  	  for (i = 0; i < n - 1; ++i) b[i] = 2 * x[i + 1] - a[i + 1];
  	  return [a, b];
  	}
  
  	function natural(context) {
  	  return new Natural(context);
  	}
  
  	function Step(context, t) {
  	  this._context = context;
  	  this._t = t;
  	}
  
  	Step.prototype = {
  	  areaStart: function() {
  	    this._line = 0;
  	  },
  	  areaEnd: function() {
  	    this._line = NaN;
  	  },
  	  lineStart: function() {
  	    this._x = this._y = NaN;
  	    this._point = 0;
  	  },
  	  lineEnd: function() {
  	    if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y);
  	    if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
  	    this._line = 1 - this._line;
  	  },
  	  point: function(x, y) {
  	    x = +x, y = +y;
  	    switch (this._point) {
  	      case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
  	      case 1: this._point = 2; // proceed
  	      default: {
  	        var t = x > this._x ? this._t : 1 - this._t;
  	        if (t <= 0) {
  	          this._context.lineTo(this._x, y);
  	          this._context.lineTo(x, y);
  	        } else if (t >= 1) {
  	          this._context.lineTo(x, this._y);
  	          this._context.lineTo(x, y);
  	        } else {
  	          var x1 = (this._x + x) * t;
  	          this._context.lineTo(x1, this._y);
  	          this._context.lineTo(x1, y);
  	        }
  	        break;
  	      }
  	    }
  	    this._x = x, this._y = y;
  	  }
  	};
  
  	function step(context) {
  	  return new Step(context, 0.5);
  	}
  
  	function stepBefore(context) {
  	  return new Step(context, 0);
  	}
  
  	function stepAfter(context) {
  	  return new Step(context, 1);
  	}
  
  	var slice$1 = Array.prototype.slice;
  
  	function none(series, order) {
  	  if (!((n = series.length) > 1)) return;
  	  for (var i = 1, s0, s1 = series[order[0]], n, m = s1.length; i < n; ++i) {
  	    s0 = s1, s1 = series[order[i]];
  	    for (var j = 0; j < m; ++j) {
  	      s1[j][1] += s1[j][0] = isNaN(s0[j][1]) ? s0[j][0] : s0[j][1];
  	    }
  	  }
  	}
  
  	function none$1(series) {
  	  var n = series.length, o = new Array(n);
  	  while (--n >= 0) o[n] = n;
  	  return o;
  	}
  
  	function stackValue(d, key) {
  	  return d[key];
  	}
  
  	function stack() {
  	  var keys = constant$1([]),
  	      order = none$1,
  	      offset = none,
  	      value = stackValue;
  
  	  function stack(data) {
  	    var kz = keys.apply(this, arguments),
  	        i,
  	        m = data.length,
  	        n = kz.length,
  	        sz = new Array(n),
  	        oz;
  
  	    for (i = 0; i < n; ++i) {
  	      for (var ki = kz[i], si = sz[i] = new Array(m), j = 0, sij; j < m; ++j) {
  	        si[j] = sij = [0, +value(data[j], ki, j, data)];
  	        sij.data = data[j];
  	      }
  	      si.key = ki;
  	    }
  
  	    for (i = 0, oz = order(sz); i < n; ++i) {
  	      sz[oz[i]].index = i;
  	    }
  
  	    offset(sz, oz);
  	    return sz;
  	  }
  
  	  stack.keys = function(_) {
  	    return arguments.length ? (keys = typeof _ === "function" ? _ : constant$1(slice$1.call(_)), stack) : keys;
  	  };
  
  	  stack.value = function(_) {
  	    return arguments.length ? (value = typeof _ === "function" ? _ : constant$1(+_), stack) : value;
  	  };
  
  	  stack.order = function(_) {
  	    return arguments.length ? (order = _ == null ? none$1 : typeof _ === "function" ? _ : constant$1(slice$1.call(_)), stack) : order;
  	  };
  
  	  stack.offset = function(_) {
  	    return arguments.length ? (offset = _ == null ? none : _, stack) : offset;
  	  };
  
  	  return stack;
  	}
  
  	function expand(series, order) {
  	  if (!((n = series.length) > 0)) return;
  	  for (var i, n, j = 0, m = series[0].length, y; j < m; ++j) {
  	    for (y = i = 0; i < n; ++i) y += series[i][j][1] || 0;
  	    if (y) for (i = 0; i < n; ++i) series[i][j][1] /= y;
  	  }
  	  none(series, order);
  	}
  
  	function silhouette(series, order) {
  	  if (!((n = series.length) > 0)) return;
  	  for (var j = 0, s0 = series[order[0]], n, m = s0.length; j < m; ++j) {
  	    for (var i = 0, y = 0; i < n; ++i) y += series[i][j][1] || 0;
  	    s0[j][1] += s0[j][0] = -y / 2;
  	  }
  	  none(series, order);
  	}
  
  	function wiggle(series, order) {
  	  if (!((n = series.length) > 0) || !((m = (s0 = series[order[0]]).length) > 0)) return;
  	  for (var y = 0, j = 1, s0, m, n; j < m; ++j) {
  	    for (var i = 0, s1 = 0, s2 = 0; i < n; ++i) {
  	      var si = series[order[i]],
  	          sij0 = si[j][1] || 0,
  	          sij1 = si[j - 1][1] || 0,
  	          s3 = (sij0 - sij1) / 2;
  	      for (var k = 0; k < i; ++k) {
  	        var sk = series[order[k]],
  	            skj0 = sk[j][1] || 0,
  	            skj1 = sk[j - 1][1] || 0;
  	        s3 += skj0 - skj1;
  	      }
  	      s1 += sij0, s2 += s3 * sij0;
  	    }
  	    s0[j - 1][1] += s0[j - 1][0] = y;
  	    if (s1) y -= s2 / s1;
  	  }
  	  s0[j - 1][1] += s0[j - 1][0] = y;
  	  none(series, order);
  	}
  
  	function ascending$1(series) {
  	  var sums = series.map(sum$1);
  	  return none$1(series).sort(function(a, b) { return sums[a] - sums[b]; });
  	}
  
  	function sum$1(series) {
  	  var s = 0, i = -1, n = series.length, v;
  	  while (++i < n) if (v = +series[i][1]) s += v;
  	  return s;
  	}
  
  	function descending$1(series) {
  	  return ascending$1(series).reverse();
  	}
  
  	function insideOut(series) {
  	  var n = series.length,
  	      i,
  	      j,
  	      sums = series.map(sum$1),
  	      order = none$1(series).sort(function(a, b) { return sums[b] - sums[a]; }),
  	      top = 0,
  	      bottom = 0,
  	      tops = [],
  	      bottoms = [];
  
  	  for (i = 0; i < n; ++i) {
  	    j = order[i];
  	    if (top < bottom) {
  	      top += sums[j];
  	      tops.push(j);
  	    } else {
  	      bottom += sums[j];
  	      bottoms.push(j);
  	    }
  	  }
  
  	  return bottoms.reverse().concat(tops);
  	}
  
  	function reverse(series) {
  	  return none$1(series).reverse();
  	}
  
  	function Color() {}
  
  	var darker = 0.7;
  	var brighter = 1 / darker;
  
  	var reHex3 = /^#([0-9a-f]{3})$/;
  	var reHex6 = /^#([0-9a-f]{6})$/;
  	var reRgbInteger = /^rgb\(\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*\)$/;
  	var reRgbPercent = /^rgb\(\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*\)$/;
  	var reRgbaInteger = /^rgba\(\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*,\s*([-+]?\d+(?:\.\d+)?)\s*\)$/;
  	var reRgbaPercent = /^rgba\(\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)\s*\)$/;
  	var reHslPercent = /^hsl\(\s*([-+]?\d+(?:\.\d+)?)\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*\)$/;
  	var reHslaPercent = /^hsla\(\s*([-+]?\d+(?:\.\d+)?)\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)\s*\)$/;
  	var named = {
  	  aliceblue: 0xf0f8ff,
  	  antiquewhite: 0xfaebd7,
  	  aqua: 0x00ffff,
  	  aquamarine: 0x7fffd4,
  	  azure: 0xf0ffff,
  	  beige: 0xf5f5dc,
  	  bisque: 0xffe4c4,
  	  black: 0x000000,
  	  blanchedalmond: 0xffebcd,
  	  blue: 0x0000ff,
  	  blueviolet: 0x8a2be2,
  	  brown: 0xa52a2a,
  	  burlywood: 0xdeb887,
  	  cadetblue: 0x5f9ea0,
  	  chartreuse: 0x7fff00,
  	  chocolate: 0xd2691e,
  	  coral: 0xff7f50,
  	  cornflowerblue: 0x6495ed,
  	  cornsilk: 0xfff8dc,
  	  crimson: 0xdc143c,
  	  cyan: 0x00ffff,
  	  darkblue: 0x00008b,
  	  darkcyan: 0x008b8b,
  	  darkgoldenrod: 0xb8860b,
  	  darkgray: 0xa9a9a9,
  	  darkgreen: 0x006400,
  	  darkgrey: 0xa9a9a9,
  	  darkkhaki: 0xbdb76b,
  	  darkmagenta: 0x8b008b,
  	  darkolivegreen: 0x556b2f,
  	  darkorange: 0xff8c00,
  	  darkorchid: 0x9932cc,
  	  darkred: 0x8b0000,
  	  darksalmon: 0xe9967a,
  	  darkseagreen: 0x8fbc8f,
  	  darkslateblue: 0x483d8b,
  	  darkslategray: 0x2f4f4f,
  	  darkslategrey: 0x2f4f4f,
  	  darkturquoise: 0x00ced1,
  	  darkviolet: 0x9400d3,
  	  deeppink: 0xff1493,
  	  deepskyblue: 0x00bfff,
  	  dimgray: 0x696969,
  	  dimgrey: 0x696969,
  	  dodgerblue: 0x1e90ff,
  	  firebrick: 0xb22222,
  	  floralwhite: 0xfffaf0,
  	  forestgreen: 0x228b22,
  	  fuchsia: 0xff00ff,
  	  gainsboro: 0xdcdcdc,
  	  ghostwhite: 0xf8f8ff,
  	  gold: 0xffd700,
  	  goldenrod: 0xdaa520,
  	  gray: 0x808080,
  	  green: 0x008000,
  	  greenyellow: 0xadff2f,
  	  grey: 0x808080,
  	  honeydew: 0xf0fff0,
  	  hotpink: 0xff69b4,
  	  indianred: 0xcd5c5c,
  	  indigo: 0x4b0082,
  	  ivory: 0xfffff0,
  	  khaki: 0xf0e68c,
  	  lavender: 0xe6e6fa,
  	  lavenderblush: 0xfff0f5,
  	  lawngreen: 0x7cfc00,
  	  lemonchiffon: 0xfffacd,
  	  lightblue: 0xadd8e6,
  	  lightcoral: 0xf08080,
  	  lightcyan: 0xe0ffff,
  	  lightgoldenrodyellow: 0xfafad2,
  	  lightgray: 0xd3d3d3,
  	  lightgreen: 0x90ee90,
  	  lightgrey: 0xd3d3d3,
  	  lightpink: 0xffb6c1,
  	  lightsalmon: 0xffa07a,
  	  lightseagreen: 0x20b2aa,
  	  lightskyblue: 0x87cefa,
  	  lightslategray: 0x778899,
  	  lightslategrey: 0x778899,
  	  lightsteelblue: 0xb0c4de,
  	  lightyellow: 0xffffe0,
  	  lime: 0x00ff00,
  	  limegreen: 0x32cd32,
  	  linen: 0xfaf0e6,
  	  magenta: 0xff00ff,
  	  maroon: 0x800000,
  	  mediumaquamarine: 0x66cdaa,
  	  mediumblue: 0x0000cd,
  	  mediumorchid: 0xba55d3,
  	  mediumpurple: 0x9370db,
  	  mediumseagreen: 0x3cb371,
  	  mediumslateblue: 0x7b68ee,
  	  mediumspringgreen: 0x00fa9a,
  	  mediumturquoise: 0x48d1cc,
  	  mediumvioletred: 0xc71585,
  	  midnightblue: 0x191970,
  	  mintcream: 0xf5fffa,
  	  mistyrose: 0xffe4e1,
  	  moccasin: 0xffe4b5,
  	  navajowhite: 0xffdead,
  	  navy: 0x000080,
  	  oldlace: 0xfdf5e6,
  	  olive: 0x808000,
  	  olivedrab: 0x6b8e23,
  	  orange: 0xffa500,
  	  orangered: 0xff4500,
  	  orchid: 0xda70d6,
  	  palegoldenrod: 0xeee8aa,
  	  palegreen: 0x98fb98,
  	  paleturquoise: 0xafeeee,
  	  palevioletred: 0xdb7093,
  	  papayawhip: 0xffefd5,
  	  peachpuff: 0xffdab9,
  	  peru: 0xcd853f,
  	  pink: 0xffc0cb,
  	  plum: 0xdda0dd,
  	  powderblue: 0xb0e0e6,
  	  purple: 0x800080,
  	  rebeccapurple: 0x663399,
  	  red: 0xff0000,
  	  rosybrown: 0xbc8f8f,
  	  royalblue: 0x4169e1,
  	  saddlebrown: 0x8b4513,
  	  salmon: 0xfa8072,
  	  sandybrown: 0xf4a460,
  	  seagreen: 0x2e8b57,
  	  seashell: 0xfff5ee,
  	  sienna: 0xa0522d,
  	  silver: 0xc0c0c0,
  	  skyblue: 0x87ceeb,
  	  slateblue: 0x6a5acd,
  	  slategray: 0x708090,
  	  slategrey: 0x708090,
  	  snow: 0xfffafa,
  	  springgreen: 0x00ff7f,
  	  steelblue: 0x4682b4,
  	  tan: 0xd2b48c,
  	  teal: 0x008080,
  	  thistle: 0xd8bfd8,
  	  tomato: 0xff6347,
  	  turquoise: 0x40e0d0,
  	  violet: 0xee82ee,
  	  wheat: 0xf5deb3,
  	  white: 0xffffff,
  	  whitesmoke: 0xf5f5f5,
  	  yellow: 0xffff00,
  	  yellowgreen: 0x9acd32
  	};
  
  	color.prototype = Color.prototype = {
  	  displayable: function() {
  	    return this.rgb().displayable();
  	  },
  	  toString: function() {
  	    return this.rgb() + "";
  	  }
  	};
  
  	function color(format) {
  	  var m;
  	  format = (format + "").trim().toLowerCase();
  	  return (m = reHex3.exec(format)) ? (m = parseInt(m[1], 16), new Rgb((m >> 8 & 0xf) | (m >> 4 & 0x0f0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf), 1)) // #f00
  	      : (m = reHex6.exec(format)) ? rgbn(parseInt(m[1], 16)) // #ff0000
  	      : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0)
  	      : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)
  	      : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)
  	      : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)
  	      : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)
  	      : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)
  	      : named.hasOwnProperty(format) ? rgbn(named[format])
  	      : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0)
  	      : null;
  	}
  
  	function rgbn(n) {
  	  return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);
  	}
  
  	function rgba(r, g, b, a) {
  	  if (a <= 0) r = g = b = NaN;
  	  return new Rgb(r, g, b, a);
  	}
  
  	function rgbConvert(o) {
  	  if (!(o instanceof Color)) o = color(o);
  	  if (!o) return new Rgb;
  	  o = o.rgb();
  	  return new Rgb(o.r, o.g, o.b, o.opacity);
  	}
  
  	function rgb(r, g, b, opacity) {
  	  return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity);
  	}
  
  	function Rgb(r, g, b, opacity) {
  	  this.r = +r;
  	  this.g = +g;
  	  this.b = +b;
  	  this.opacity = +opacity;
  	}
  
  	var _rgb = rgb.prototype = Rgb.prototype = new Color;
  
  	_rgb.brighter = function(k) {
  	  k = k == null ? brighter : Math.pow(brighter, k);
  	  return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
  	};
  
  	_rgb.darker = function(k) {
  	  k = k == null ? darker : Math.pow(darker, k);
  	  return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
  	};
  
  	_rgb.rgb = function() {
  	  return this;
  	};
  
  	_rgb.displayable = function() {
  	  return (0 <= this.r && this.r <= 255)
  	      && (0 <= this.g && this.g <= 255)
  	      && (0 <= this.b && this.b <= 255)
  	      && (0 <= this.opacity && this.opacity <= 1);
  	};
  
  	_rgb.toString = function() {
  	  var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
  	  return (a === 1 ? "rgb(" : "rgba(")
  	      + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", "
  	      + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", "
  	      + Math.max(0, Math.min(255, Math.round(this.b) || 0))
  	      + (a === 1 ? ")" : ", " + a + ")");
  	};
  
  	function hsla(h, s, l, a) {
  	  if (a <= 0) h = s = l = NaN;
  	  else if (l <= 0 || l >= 1) h = s = NaN;
  	  else if (s <= 0) h = NaN;
  	  return new Hsl(h, s, l, a);
  	}
  
  	function hslConvert(o) {
  	  if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity);
  	  if (!(o instanceof Color)) o = color(o);
  	  if (!o) return new Hsl;
  	  if (o instanceof Hsl) return o;
  	  o = o.rgb();
  	  var r = o.r / 255,
  	      g = o.g / 255,
  	      b = o.b / 255,
  	      min = Math.min(r, g, b),
  	      max = Math.max(r, g, b),
  	      h = NaN,
  	      s = max - min,
  	      l = (max + min) / 2;
  	  if (s) {
  	    if (r === max) h = (g - b) / s + (g < b) * 6;
  	    else if (g === max) h = (b - r) / s + 2;
  	    else h = (r - g) / s + 4;
  	    s /= l < 0.5 ? max + min : 2 - max - min;
  	    h *= 60;
  	  } else {
  	    s = l > 0 && l < 1 ? 0 : h;
  	  }
  	  return new Hsl(h, s, l, o.opacity);
  	}
  
  	function hsl(h, s, l, opacity) {
  	  return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity);
  	}
  
  	function Hsl(h, s, l, opacity) {
  	  this.h = +h;
  	  this.s = +s;
  	  this.l = +l;
  	  this.opacity = +opacity;
  	}
  
  	var _hsl = hsl.prototype = Hsl.prototype = new Color;
  
  	_hsl.brighter = function(k) {
  	  k = k == null ? brighter : Math.pow(brighter, k);
  	  return new Hsl(this.h, this.s, this.l * k, this.opacity);
  	};
  
  	_hsl.darker = function(k) {
  	  k = k == null ? darker : Math.pow(darker, k);
  	  return new Hsl(this.h, this.s, this.l * k, this.opacity);
  	};
  
  	_hsl.rgb = function() {
  	  var h = this.h % 360 + (this.h < 0) * 360,
  	      s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
  	      l = this.l,
  	      m2 = l + (l < 0.5 ? l : 1 - l) * s,
  	      m1 = 2 * l - m2;
  	  return new Rgb(
  	    hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2),
  	    hsl2rgb(h, m1, m2),
  	    hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2),
  	    this.opacity
  	  );
  	};
  
  	_hsl.displayable = function() {
  	  return (0 <= this.s && this.s <= 1 || isNaN(this.s))
  	      && (0 <= this.l && this.l <= 1)
  	      && (0 <= this.opacity && this.opacity <= 1);
  	};
  
  	/* From FvD 13.37, CSS Color Module Level 3 */
  	function hsl2rgb(h, m1, m2) {
  	  return (h < 60 ? m1 + (m2 - m1) * h / 60
  	      : h < 180 ? m2
  	      : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60
  	      : m1) * 255;
  	}
  
  	var deg2rad = Math.PI / 180;
  	var rad2deg$1 = 180 / Math.PI;
  
  	var Kn = 18;
  	var Xn = 0.950470;
  	var Yn = 1;
  	var Zn = 1.088830;
  	var t0 = 4 / 29;
  	var t1 = 6 / 29;
  	var t2 = 3 * t1 * t1;
  	var t3 = t1 * t1 * t1;
  	function labConvert(o) {
  	  if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity);
  	  if (o instanceof Hcl) {
  	    var h = o.h * deg2rad;
  	    return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity);
  	  }
  	  if (!(o instanceof Rgb)) o = rgbConvert(o);
  	  var b = rgb2xyz(o.r),
  	      a = rgb2xyz(o.g),
  	      l = rgb2xyz(o.b),
  	      x = xyz2lab((0.4124564 * b + 0.3575761 * a + 0.1804375 * l) / Xn),
  	      y = xyz2lab((0.2126729 * b + 0.7151522 * a + 0.0721750 * l) / Yn),
  	      z = xyz2lab((0.0193339 * b + 0.1191920 * a + 0.9503041 * l) / Zn);
  	  return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity);
  	}
  
  	function lab(l, a, b, opacity) {
  	  return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity);
  	}
  
  	function Lab(l, a, b, opacity) {
  	  this.l = +l;
  	  this.a = +a;
  	  this.b = +b;
  	  this.opacity = +opacity;
  	}
  
  	var _lab = lab.prototype = Lab.prototype = new Color;
  
  	_lab.brighter = function(k) {
  	  return new Lab(this.l + Kn * (k == null ? 1 : k), this.a, this.b, this.opacity);
  	};
  
  	_lab.darker = function(k) {
  	  return new Lab(this.l - Kn * (k == null ? 1 : k), this.a, this.b, this.opacity);
  	};
  
  	_lab.rgb = function() {
  	  var y = (this.l + 16) / 116,
  	      x = isNaN(this.a) ? y : y + this.a / 500,
  	      z = isNaN(this.b) ? y : y - this.b / 200;
  	  y = Yn * lab2xyz(y);
  	  x = Xn * lab2xyz(x);
  	  z = Zn * lab2xyz(z);
  	  return new Rgb(
  	    xyz2rgb( 3.2404542 * x - 1.5371385 * y - 0.4985314 * z), // D65 -> sRGB
  	    xyz2rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z),
  	    xyz2rgb( 0.0556434 * x - 0.2040259 * y + 1.0572252 * z),
  	    this.opacity
  	  );
  	};
  
  	function xyz2lab(t) {
  	  return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0;
  	}
  
  	function lab2xyz(t) {
  	  return t > t1 ? t * t * t : t2 * (t - t0);
  	}
  
  	function xyz2rgb(x) {
  	  return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055);
  	}
  
  	function rgb2xyz(x) {
  	  return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
  	}
  
  	function hclConvert(o) {
  	  if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity);
  	  if (!(o instanceof Lab)) o = labConvert(o);
  	  var h = Math.atan2(o.b, o.a) * rad2deg$1;
  	  return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity);
  	}
  
  	function hcl(h, c, l, opacity) {
  	  return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity);
  	}
  
  	function Hcl(h, c, l, opacity) {
  	  this.h = +h;
  	  this.c = +c;
  	  this.l = +l;
  	  this.opacity = +opacity;
  	}
  
  	var _hcl = hcl.prototype = Hcl.prototype = new Color;
  
  	_hcl.brighter = function(k) {
  	  return new Hcl(this.h, this.c, this.l + Kn * (k == null ? 1 : k), this.opacity);
  	};
  
  	_hcl.darker = function(k) {
  	  return new Hcl(this.h, this.c, this.l - Kn * (k == null ? 1 : k), this.opacity);
  	};
  
  	_hcl.rgb = function() {
  	  return labConvert(this).rgb();
  	};
  
  	var A = -0.14861;
  	var B = +1.78277;
  	var C = -0.29227;
  	var D = -0.90649;
  	var E = +1.97294;
  	var ED = E * D;
  	var EB = E * B;
  	var BC_DA = B * C - D * A;
  	function cubehelixConvert(o) {
  	  if (o instanceof Cubehelix) return new Cubehelix(o.h, o.s, o.l, o.opacity);
  	  if (!(o instanceof Rgb)) o = rgbConvert(o);
  	  var r = o.r / 255,
  	      g = o.g / 255,
  	      b = o.b / 255,
  	      l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB),
  	      bl = b - l,
  	      k = (E * (g - l) - C * bl) / D,
  	      s = Math.sqrt(k * k + bl * bl) / (E * l * (1 - l)), // NaN if l=0 or l=1
  	      h = s ? Math.atan2(k, bl) * rad2deg$1 - 120 : NaN;
  	  return new Cubehelix(h < 0 ? h + 360 : h, s, l, o.opacity);
  	}
  
  	function cubehelix(h, s, l, opacity) {
  	  return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s, l, opacity == null ? 1 : opacity);
  	}
  
  	function Cubehelix(h, s, l, opacity) {
  	  this.h = +h;
  	  this.s = +s;
  	  this.l = +l;
  	  this.opacity = +opacity;
  	}
  
  	var _cubehelix = cubehelix.prototype = Cubehelix.prototype = new Color;
  
  	_cubehelix.brighter = function(k) {
  	  k = k == null ? brighter : Math.pow(brighter, k);
  	  return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
  	};
  
  	_cubehelix.darker = function(k) {
  	  k = k == null ? darker : Math.pow(darker, k);
  	  return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
  	};
  
  	_cubehelix.rgb = function() {
  	  var h = isNaN(this.h) ? 0 : (this.h + 120) * deg2rad,
  	      l = +this.l,
  	      a = isNaN(this.s) ? 0 : this.s * l * (1 - l),
  	      cosh = Math.cos(h),
  	      sinh = Math.sin(h);
  	  return new Rgb(
  	    255 * (l + a * (A * cosh + B * sinh)),
  	    255 * (l + a * (C * cosh + D * sinh)),
  	    255 * (l + a * (E * cosh)),
  	    this.opacity
  	  );
  	};
  
  	function constant$4(x) {
  	  return function() {
  	    return x;
  	  };
  	}
  
  	function linear$1(a, d) {
  	  return function(t) {
  	    return a + t * d;
  	  };
  	}
  
  	function exponential$1(a, b, y) {
  	  return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) {
  	    return Math.pow(a + t * b, y);
  	  };
  	}
  
  	function hue(a, b) {
  	  var d = b - a;
  	  return d ? linear$1(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant$4(isNaN(a) ? b : a);
  	}
  
  	function gamma(y) {
  	  return (y = +y) === 1 ? nogamma : function(a, b) {
  	    return b - a ? exponential$1(a, b, y) : constant$4(isNaN(a) ? b : a);
  	  };
  	}
  
  	function nogamma(a, b) {
  	  var d = b - a;
  	  return d ? linear$1(a, d) : constant$4(isNaN(a) ? b : a);
  	}
  
  	var rgb$1 = (function gamma$$(y) {
  	  var interpolateColor = gamma(y);
  
  	  function interpolateRgb(start, end) {
  	    var r = interpolateColor((start = rgb(start)).r, (end = rgb(end)).r),
  	        g = interpolateColor(start.g, end.g),
  	        b = interpolateColor(start.b, end.b),
  	        opacity = interpolateColor(start.opacity, end.opacity);
  	    return function(t) {
  	      start.r = r(t);
  	      start.g = g(t);
  	      start.b = b(t);
  	      start.opacity = opacity(t);
  	      return start + "";
  	    };
  	  }
  
  	  interpolateRgb.gamma = gamma$$;
  
  	  return interpolateRgb;
  	})(1);
  
  	// TODO sparse arrays?
  	function array(a, b) {
  	  var x = [],
  	      c = [],
  	      na = a ? a.length : 0,
  	      nb = b ? b.length : 0,
  	      n0 = Math.min(na, nb),
  	      i;
  
  	  for (i = 0; i < n0; ++i) x.push(interpolate(a[i], b[i]));
  	  for (; i < na; ++i) c[i] = a[i];
  	  for (; i < nb; ++i) c[i] = b[i];
  
  	  return function(t) {
  	    for (i = 0; i < n0; ++i) c[i] = x[i](t);
  	    return c;
  	  };
  	}
  
  	function reinterpolate(a, b) {
  	  return a = +a, b -= a, function(t) {
  	    return a + b * t;
  	  };
  	}
  
  	function object(a, b) {
  	  var i = {},
  	      c = {},
  	      k;
  
  	  if (a === null || typeof a !== "object") a = {};
  	  if (b === null || typeof b !== "object") b = {};
  
  	  for (k in a) {
  	    if (k in b) {
  	      i[k] = interpolate(a[k], b[k]);
  	    } else {
  	      c[k] = a[k];
  	    }
  	  }
  
  	  for (k in b) {
  	    if (!(k in a)) {
  	      c[k] = b[k];
  	    }
  	  }
  
  	  return function(t) {
  	    for (k in i) c[k] = i[k](t);
  	    return c;
  	  };
  	}
  
  	var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;
  	var reB = new RegExp(reA.source, "g");
  	function zero(b) {
  	  return function() {
  	    return b;
  	  };
  	}
  
  	function one(b) {
  	  return function(t) {
  	    return b(t) + "";
  	  };
  	}
  
  	function string(a, b) {
  	  var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b
  	      am, // current match in a
  	      bm, // current match in b
  	      bs, // string preceding current number in b, if any
  	      i = -1, // index in s
  	      s = [], // string constants and placeholders
  	      q = []; // number interpolators
  
  	  // Coerce inputs to strings.
  	  a = a + "", b = b + "";
  
  	  // Interpolate pairs of numbers in a & b.
  	  while ((am = reA.exec(a))
  	      && (bm = reB.exec(b))) {
  	    if ((bs = bm.index) > bi) { // a string precedes the next number in b
  	      bs = b.slice(bi, bs);
  	      if (s[i]) s[i] += bs; // coalesce with previous string
  	      else s[++i] = bs;
  	    }
  	    if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match
  	      if (s[i]) s[i] += bm; // coalesce with previous string
  	      else s[++i] = bm;
  	    } else { // interpolate non-matching numbers
  	      s[++i] = null;
  	      q.push({i: i, x: reinterpolate(am, bm)});
  	    }
  	    bi = reB.lastIndex;
  	  }
  
  	  // Add remains of b.
  	  if (bi < b.length) {
  	    bs = b.slice(bi);
  	    if (s[i]) s[i] += bs; // coalesce with previous string
  	    else s[++i] = bs;
  	  }
  
  	  // Special optimization for only a single match.
  	  // Otherwise, interpolate each of the numbers and rejoin the string.
  	  return s.length < 2 ? (q[0]
  	      ? one(q[0].x)
  	      : zero(b))
  	      : (b = q.length, function(t) {
  	          for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t);
  	          return s.join("");
  	        });
  	}
  
  	var values$1 = [
  	  function(a, b) {
  	    var t = typeof b, c;
  	    return (t === "string" ? ((c = color(b)) ? (b = c, rgb$1) : string)
  	        : b instanceof color ? rgb$1
  	        : Array.isArray(b) ? array
  	        : t === "object" && isNaN(b) ? object
  	        : reinterpolate)(a, b);
  	  }
  	];
  
  	function interpolate(a, b) {
  	  var i = values$1.length, f;
  	  while (--i >= 0 && !(f = values$1[i](a, b)));
  	  return f;
  	}
  
  	function interpolateRound(a, b) {
  	  return a = +a, b -= a, function(t) {
  	    return Math.round(a + b * t);
  	  };
  	}
  
  	var rad2deg = 180 / Math.PI;
  	var identity = {a: 1, b: 0, c: 0, d: 1, e: 0, f: 0};
  	var g;
  	// Compute x-scale and normalize the first row.
  	// Compute shear and make second row orthogonal to first.
  	// Compute y-scale and normalize the second row.
  	// Finally, compute the rotation.
  	function Transform(string) {
  	  if (!g) g = document.createElementNS("http://www.w3.org/2000/svg", "g");
  	  if (string) g.setAttribute("transform", string), t = g.transform.baseVal.consolidate();
  
  	  var t,
  	      m = t ? t.matrix : identity,
  	      r0 = [m.a, m.b],
  	      r1 = [m.c, m.d],
  	      kx = normalize(r0),
  	      kz = dot(r0, r1),
  	      ky = normalize(combine(r1, r0, -kz)) || 0;
  
  	  if (r0[0] * r1[1] < r1[0] * r0[1]) {
  	    r0[0] *= -1;
  	    r0[1] *= -1;
  	    kx *= -1;
  	    kz *= -1;
  	  }
  
  	  this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * rad2deg;
  	  this.translate = [m.e, m.f];
  	  this.scale = [kx, ky];
  	  this.skew = ky ? Math.atan2(kz, ky) * rad2deg : 0;
  	}
  
  	function dot(a, b) {
  	  return a[0] * b[0] + a[1] * b[1];
  	}
  
  	function normalize(a) {
  	  var k = Math.sqrt(dot(a, a));
  	  if (k) a[0] /= k, a[1] /= k;
  	  return k;
  	}
  
  	function combine(a, b, k) {
  	  a[0] += k * b[0];
  	  a[1] += k * b[1];
  	  return a;
  	}
  
  	function pop(s) {
  	  return s.length ? s.pop() + "," : "";
  	}
  
  	function translate(ta, tb, s, q) {
  	  if (ta[0] !== tb[0] || ta[1] !== tb[1]) {
  	    var i = s.push("translate(", null, ",", null, ")");
  	    q.push({i: i - 4, x: reinterpolate(ta[0], tb[0])}, {i: i - 2, x: reinterpolate(ta[1], tb[1])});
  	  } else if (tb[0] || tb[1]) {
  	    s.push("translate(" + tb + ")");
  	  }
  	}
  
  	function rotate(ra, rb, s, q) {
  	  if (ra !== rb) {
  	    if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360; // shortest path
  	    q.push({i: s.push(pop(s) + "rotate(", null, ")") - 2, x: reinterpolate(ra, rb)});
  	  } else if (rb) {
  	    s.push(pop(s) + "rotate(" + rb + ")");
  	  }
  	}
  
  	function skew(wa, wb, s, q) {
  	  if (wa !== wb) {
  	    q.push({i: s.push(pop(s) + "skewX(", null, ")") - 2, x: reinterpolate(wa, wb)});
  	  } else if (wb) {
  	    s.push(pop(s) + "skewX(" + wb + ")");
  	  }
  	}
  
  	function scale(ka, kb, s, q) {
  	  if (ka[0] !== kb[0] || ka[1] !== kb[1]) {
  	    var i = s.push(pop(s) + "scale(", null, ",", null, ")");
  	    q.push({i: i - 4, x: reinterpolate(ka[0], kb[0])}, {i: i - 2, x: reinterpolate(ka[1], kb[1])});
  	  } else if (kb[0] !== 1 || kb[1] !== 1) {
  	    s.push(pop(s) + "scale(" + kb + ")");
  	  }
  	}
  
  	function transform(a, b) {
  	  var s = [], // string constants and placeholders
  	      q = []; // number interpolators
  	  a = new Transform(a), b = new Transform(b);
  	  translate(a.translate, b.translate, s, q);
  	  rotate(a.rotate, b.rotate, s, q);
  	  skew(a.skew, b.skew, s, q);
  	  scale(a.scale, b.scale, s, q);
  	  a = b = null; // gc
  	  return function(t) {
  	    var i = -1, n = q.length, o;
  	    while (++i < n) s[(o = q[i]).i] = o.x(t);
  	    return s.join("");
  	  };
  	}
  
  	var rho = Math.SQRT2;
  	var rho2 = 2;
  	var rho4 = 4;
  	var epsilon2 = 1e-12;
  	function cosh(x) {
  	  return ((x = Math.exp(x)) + 1 / x) / 2;
  	}
  
  	function sinh(x) {
  	  return ((x = Math.exp(x)) - 1 / x) / 2;
  	}
  
  	function tanh(x) {
  	  return ((x = Math.exp(2 * x)) - 1) / (x + 1);
  	}
  
  	// p0 = [ux0, uy0, w0]
  	// p1 = [ux1, uy1, w1]
  	function zoom(p0, p1) {
  	  var ux0 = p0[0], uy0 = p0[1], w0 = p0[2],
  	      ux1 = p1[0], uy1 = p1[1], w1 = p1[2],
  	      dx = ux1 - ux0,
  	      dy = uy1 - uy0,
  	      d2 = dx * dx + dy * dy,
  	      i,
  	      S;
  
  	  // Special case for u0 ≅ u1.
  	  if (d2 < epsilon2) {
  	    S = Math.log(w1 / w0) / rho;
  	    i = function(t) {
  	      return [
  	        ux0 + t * dx,
  	        uy0 + t * dy,
  	        w0 * Math.exp(rho * t * S)
  	      ];
  	    }
  	  }
  
  	  // General case.
  	  else {
  	    var d1 = Math.sqrt(d2),
  	        b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1),
  	        b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1),
  	        r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0),
  	        r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1);
  	    S = (r1 - r0) / rho;
  	    i = function(t) {
  	      var s = t * S,
  	          coshr0 = cosh(r0),
  	          u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0));
  	      return [
  	        ux0 + u * dx,
  	        uy0 + u * dy,
  	        w0 * coshr0 / cosh(rho * s + r0)
  	      ];
  	    }
  	  }
  
  	  i.duration = S * 1000;
  
  	  return i;
  	}
  
  	function interpolateHsl(start, end) {
  	  var h = hue((start = hsl(start)).h, (end = hsl(end)).h),
  	      s = nogamma(start.s, end.s),
  	      l = nogamma(start.l, end.l),
  	      opacity = nogamma(start.opacity, end.opacity);
  	  return function(t) {
  	    start.h = h(t);
  	    start.s = s(t);
  	    start.l = l(t);
  	    start.opacity = opacity(t);
  	    return start + "";
  	  };
  	}
  
  	function interpolateHslLong(start, end) {
  	  var h = nogamma((start = hsl(start)).h, (end = hsl(end)).h),
  	      s = nogamma(start.s, end.s),
  	      l = nogamma(start.l, end.l),
  	      opacity = nogamma(start.opacity, end.opacity);
  	  return function(t) {
  	    start.h = h(t);
  	    start.s = s(t);
  	    start.l = l(t);
  	    start.opacity = opacity(t);
  	    return start + "";
  	  };
  	}
  
  	function interpolateLab(start, end) {
  	  var l = nogamma((start = lab(start)).l, (end = lab(end)).l),
  	      a = nogamma(start.a, end.a),
  	      b = nogamma(start.b, end.b),
  	      opacity = nogamma(start.opacity, end.opacity);
  	  return function(t) {
  	    start.l = l(t);
  	    start.a = a(t);
  	    start.b = b(t);
  	    start.opacity = opacity(t);
  	    return start + "";
  	  };
  	}
  
  	function interpolateHcl(start, end) {
  	  var h = hue((start = hcl(start)).h, (end = hcl(end)).h),
  	      c = nogamma(start.c, end.c),
  	      l = nogamma(start.l, end.l),
  	      opacity = nogamma(start.opacity, end.opacity);
  	  return function(t) {
  	    start.h = h(t);
  	    start.c = c(t);
  	    start.l = l(t);
  	    start.opacity = opacity(t);
  	    return start + "";
  	  };
  	}
  
  	function interpolateHclLong(start, end) {
  	  var h = nogamma((start = hcl(start)).h, (end = hcl(end)).h),
  	      c = nogamma(start.c, end.c),
  	      l = nogamma(start.l, end.l),
  	      opacity = nogamma(start.opacity, end.opacity);
  	  return function(t) {
  	    start.h = h(t);
  	    start.c = c(t);
  	    start.l = l(t);
  	    start.opacity = opacity(t);
  	    return start + "";
  	  };
  	}
  
  	var cubehelix$1 = (function gamma(y) {
  	  y = +y;
  
  	  function interpolateCubehelix(start, end) {
  	    var h = hue((start = cubehelix(start)).h, (end = cubehelix(end)).h),
  	        s = nogamma(start.s, end.s),
  	        l = nogamma(start.l, end.l),
  	        opacity = nogamma(start.opacity, end.opacity);
  	    return function(t) {
  	      start.h = h(t);
  	      start.s = s(t);
  	      start.l = l(Math.pow(t, y));
  	      start.opacity = opacity(t);
  	      return start + "";
  	    };
  	  }
  
  	  interpolateCubehelix.gamma = gamma;
  
  	  return interpolateCubehelix;
  	})(1);
  
  	var interpolateCubehelixLong = (function gamma(y) {
  	  y = +y;
  
  	  function interpolateCubehelixLong(start, end) {
  	    var h = nogamma((start = cubehelix(start)).h, (end = cubehelix(end)).h),
  	        s = nogamma(start.s, end.s),
  	        l = nogamma(start.l, end.l),
  	        opacity = nogamma(start.opacity, end.opacity);
  	    return function(t) {
  	      start.h = h(t);
  	      start.s = s(t);
  	      start.l = l(Math.pow(t, y));
  	      start.opacity = opacity(t);
  	      return start + "";
  	    };
  	  }
  
  	  interpolateCubehelixLong.gamma = gamma;
  
  	  return interpolateCubehelixLong;
  	})(1);
  
  	function dispatch() {
  	  return new Dispatch(arguments);
  	}
  
  	function Dispatch(types) {
  	  var i = -1,
  	      n = types.length,
  	      callbacksByType = {},
  	      callbackByName = {},
  	      type,
  	      that = this;
  
  	  that.on = function(type, callback) {
  	    type = parseType(type);
  
  	    // Return the current callback, if any.
  	    if (arguments.length < 2) {
  	      return (callback = callbackByName[type.name]) && callback.value;
  	    }
  
  	    // If a type was specified…
  	    if (type.type) {
  	      var callbacks = callbacksByType[type.type],
  	          callback0 = callbackByName[type.name],
  	          i;
  
  	      // Remove the current callback, if any, using copy-on-remove.
  	      if (callback0) {
  	        callback0.value = null;
  	        i = callbacks.indexOf(callback0);
  	        callbacksByType[type.type] = callbacks = callbacks.slice(0, i).concat(callbacks.slice(i + 1));
  	        delete callbackByName[type.name];
  	      }
  
  	      // Add the new callback, if any.
  	      if (callback) {
  	        callback = {value: callback};
  	        callbackByName[type.name] = callback;
  	        callbacks.push(callback);
  	      }
  	    }
  
  	    // Otherwise, if a null callback was specified, remove all callbacks with the given name.
  	    else if (callback == null) {
  	      for (var otherType in callbacksByType) {
  	        if (callback = callbackByName[otherType + type.name]) {
  	          callback.value = null;
  	          callbacks = callbacksByType[otherType];
  	          i = callbacks.indexOf(callback);
  	          callbacksByType[otherType] = callbacks.slice(0, i).concat(callbacks.slice(i + 1));
  	          delete callbackByName[callback.name];
  	        }
  	      }
  	    }
  
  	    return that;
  	  };
  
  	  while (++i < n) {
  	    type = types[i] + "";
  	    if (!type || (type in that)) throw new Error("illegal or duplicate type: " + type);
  	    callbacksByType[type] = [];
  	    that[type] = applier(type);
  	  }
  
  	  function parseType(type) {
  	    var i = (type += "").indexOf("."), name = type;
  	    if (i >= 0) type = type.slice(0, i); else name += ".";
  	    if (type && !callbacksByType.hasOwnProperty(type)) throw new Error("unknown type: " + type);
  	    return {type: type, name: name};
  	  }
  
  	  function applier(type) {
  	    return function() {
  	      var callbacks = callbacksByType[type], // Defensive reference; copy-on-remove.
  	          callbackValue,
  	          i = -1,
  	          n = callbacks.length;
  
  	      while (++i < n) {
  	        if (callbackValue = callbacks[i].value) {
  	          callbackValue.apply(this, arguments);
  	        }
  	      }
  
  	      return that;
  	    };
  	  }
  	}
  
  	dispatch.prototype = Dispatch.prototype;
  
  	function dsv(delimiter) {
  	  return new Dsv(delimiter);
  	}
  
  	function objectConverter(columns) {
  	  return new Function("d", "return {" + columns.map(function(name, i) {
  	    return JSON.stringify(name) + ": d[" + i + "]";
  	  }).join(",") + "}");
  	}
  
  	function customConverter(columns, f) {
  	  var object = objectConverter(columns);
  	  return function(row, i) {
  	    return f(object(row), i, columns);
  	  };
  	}
  
  	// Compute unique columns in order of discovery.
  	function inferColumns(rows) {
  	  var columnSet = Object.create(null),
  	      columns = [];
  
  	  rows.forEach(function(row) {
  	    for (var column in row) {
  	      if (!(column in columnSet)) {
  	        columns.push(columnSet[column] = column);
  	      }
  	    }
  	  });
  
  	  return columns;
  	}
  
  	function Dsv(delimiter) {
  	  var reFormat = new RegExp("[\"" + delimiter + "\n]"),
  	      delimiterCode = delimiter.charCodeAt(0);
  
  	  this.parse = function(text, f) {
  	    var convert, columns, rows = this.parseRows(text, function(row, i) {
  	      if (convert) return convert(row, i - 1);
  	      columns = row, convert = f ? customConverter(row, f) : objectConverter(row);
  	    });
  	    rows.columns = columns;
  	    return rows;
  	  };
  
  	  this.parseRows = function(text, f) {
  	    var EOL = {}, // sentinel value for end-of-line
  	        EOF = {}, // sentinel value for end-of-file
  	        rows = [], // output rows
  	        N = text.length,
  	        I = 0, // current character index
  	        n = 0, // the current line number
  	        t, // the current token
  	        eol; // is the current token followed by EOL?
  
  	    function token() {
  	      if (I >= N) return EOF; // special case: end of file
  	      if (eol) return eol = false, EOL; // special case: end of line
  
  	      // special case: quotes
  	      var j = I, c;
  	      if (text.charCodeAt(j) === 34) {
  	        var i = j;
  	        while (i++ < N) {
  	          if (text.charCodeAt(i) === 34) {
  	            if (text.charCodeAt(i + 1) !== 34) break;
  	            ++i;
  	          }
  	        }
  	        I = i + 2;
  	        c = text.charCodeAt(i + 1);
  	        if (c === 13) {
  	          eol = true;
  	          if (text.charCodeAt(i + 2) === 10) ++I;
  	        } else if (c === 10) {
  	          eol = true;
  	        }
  	        return text.slice(j + 1, i).replace(/""/g, "\"");
  	      }
  
  	      // common case: find next delimiter or newline
  	      while (I < N) {
  	        var k = 1;
  	        c = text.charCodeAt(I++);
  	        if (c === 10) eol = true; // \n
  	        else if (c === 13) { eol = true; if (text.charCodeAt(I) === 10) ++I, ++k; } // \r|\r\n
  	        else if (c !== delimiterCode) continue;
  	        return text.slice(j, I - k);
  	      }
  
  	      // special case: last token before EOF
  	      return text.slice(j);
  	    }
  
  	    while ((t = token()) !== EOF) {
  	      var a = [];
  	      while (t !== EOL && t !== EOF) {
  	        a.push(t);
  	        t = token();
  	      }
  	      if (f && (a = f(a, n++)) == null) continue;
  	      rows.push(a);
  	    }
  
  	    return rows;
  	  }
  
  	  this.format = function(rows, columns) {
  	    if (columns == null) columns = inferColumns(rows);
  	    return [columns.map(formatValue).join(delimiter)].concat(rows.map(function(row) {
  	      return columns.map(function(column) {
  	        return formatValue(row[column]);
  	      }).join(delimiter);
  	    })).join("\n");
  	  };
  
  	  this.formatRows = function(rows) {
  	    return rows.map(formatRow).join("\n");
  	  };
  
  	  function formatRow(row) {
  	    return row.map(formatValue).join(delimiter);
  	  }
  
  	  function formatValue(text) {
  	    return reFormat.test(text) ? "\"" + text.replace(/\"/g, "\"\"") + "\"" : text;
  	  }
  	}
  
  	dsv.prototype = Dsv.prototype;
  
  	var csv = dsv(",");
  	var tsv = dsv("\t");
  
  	function request(url, callback) {
  	  var request,
  	      event = dispatch("beforesend", "progress", "load", "error"),
  	      mimeType,
  	      headers = map(),
  	      xhr = new XMLHttpRequest,
  	      response,
  	      responseType,
  	      timeout = 0;
  
  	  // If IE does not support CORS, use XDomainRequest.
  	  if (typeof XDomainRequest !== "undefined"
  	      && !("withCredentials" in xhr)
  	      && /^(http(s)?:)?\/\//.test(url)) xhr = new XDomainRequest;
  
  	  "onload" in xhr
  	      ? xhr.onload = xhr.onerror = xhr.ontimeout = respond
  	      : xhr.onreadystatechange = function(o) { xhr.readyState > 3 && respond(o); };
  
  	  function respond(o) {
  	    var status = xhr.status, result;
  	    if (!status && hasResponse(xhr)
  	        || status >= 200 && status < 300
  	        || status === 304) {
  	      if (response) {
  	        try {
  	          result = response.call(request, xhr);
  	        } catch (e) {
  	          event.error.call(request, e);
  	          return;
  	        }
  	      } else {
  	        result = xhr;
  	      }
  	      event.load.call(request, result);
  	    } else {
  	      event.error.call(request, o);
  	    }
  	  }
  
  	  xhr.onprogress = function(e) {
  	    event.progress.call(request, e);
  	  };
  
  	  request = {
  	    header: function(name, value) {
  	      name = (name + "").toLowerCase();
  	      if (arguments.length < 2) return headers.get(name);
  	      if (value == null) headers.remove(name);
  	      else headers.set(name, value + "");
  	      return request;
  	    },
  
  	    // If mimeType is non-null and no Accept header is set, a default is used.
  	    mimeType: function(value) {
  	      if (!arguments.length) return mimeType;
  	      mimeType = value == null ? null : value + "";
  	      return request;
  	    },
  
  	    // Specifies what type the response value should take;
  	    // for instance, arraybuffer, blob, document, or text.
  	    responseType: function(value) {
  	      if (!arguments.length) return responseType;
  	      responseType = value;
  	      return request;
  	    },
  
  	    timeout: function(value) {
  	      if (!arguments.length) return timeout;
  	      timeout = +value;
  	      return request;
  	    },
  
  	    // Specify how to convert the response content to a specific type;
  	    // changes the callback value on "load" events.
  	    response: function(value) {
  	      response = value;
  	      return request;
  	    },
  
  	    // Alias for send("GET", …).
  	    get: function(data, callback) {
  	      return request.send("GET", data, callback);
  	    },
  
  	    // Alias for send("POST", …).
  	    post: function(data, callback) {
  	      return request.send("POST", data, callback);
  	    },
  
  	    // If callback is non-null, it will be used for error and load events.
  	    send: function(method, data, callback) {
  	      if (!callback && typeof data === "function") callback = data, data = null;
  	      if (callback && callback.length === 1) callback = fixCallback(callback);
  	      xhr.open(method, url, true);
  	      if (mimeType != null && !headers.has("accept")) headers.set("accept", mimeType + ",*/*");
  	      if (xhr.setRequestHeader) headers.each(function(value, name) { xhr.setRequestHeader(name, value); });
  	      if (mimeType != null && xhr.overrideMimeType) xhr.overrideMimeType(mimeType);
  	      if (responseType != null) xhr.responseType = responseType;
  	      if (timeout > 0) xhr.timeout = timeout;
  	      if (callback) request.on("error", callback).on("load", function(xhr) { callback(null, xhr); });
  	      event.beforesend.call(request, xhr);
  	      xhr.send(data == null ? null : data);
  	      return request;
  	    },
  
  	    abort: function() {
  	      xhr.abort();
  	      return request;
  	    },
  
  	    on: function() {
  	      var value = event.on.apply(event, arguments);
  	      return value === event ? request : value;
  	    }
  	  };
  
  	  return callback
  	      ? request.get(callback)
  	      : request;
  	}
  
  	function fixCallback(callback) {
  	  return function(error, xhr) {
  	    callback(error == null ? xhr : null);
  	  };
  	}
  
  	function hasResponse(xhr) {
  	  var type = xhr.responseType;
  	  return type && type !== "text"
  	      ? xhr.response // null on error
  	      : xhr.responseText; // "" on error
  	}
  
  	function requestType(defaultMimeType, response) {
  	  return function(url, callback) {
  	    var r = request(url).mimeType(defaultMimeType).response(response);
  	    return callback ? r.get(callback) : r;
  	  };
  	}
  
  	var html = requestType("text/html", function(xhr) {
  	  return document.createRange().createContextualFragment(xhr.responseText);
  	});
  
  	var json = requestType("application/json", function(xhr) {
  	  return JSON.parse(xhr.responseText);
  	});
  
  	var text = requestType("text/plain", function(xhr) {
  	  return xhr.responseText;
  	});
  
  	var xml = requestType("application/xml", function(xhr) {
  	  var xml = xhr.responseXML;
  	  if (!xml) throw new Error("parse error");
  	  return xml;
  	});
  
  	function requestDsv(defaultMimeType, dsv) {
  	  return function(url, row, callback) {
  	    if (arguments.length < 3) callback = row, row = null;
  	    var r = request(url).mimeType(defaultMimeType);
  	    r.row = function(_) { return arguments.length ? r.response(responseOf(dsv, row = _)) : row; };
  	    r.row(row);
  	    return callback ? r.get(callback) : r;
  	  };
  	}
  
  	function responseOf(dsv, row) {
  	  return function(request) {
  	    return dsv.parse(request.responseText, row);
  	  };
  	}
  
  	var csv$1 = requestDsv("text/csv", csv);
  
  	var tsv$1 = requestDsv("text/tab-separated-values", tsv);
  
  	var frame = 0;
  	var timeout = 0;
  	var taskHead;
  	var taskTail;
  	var taskId = 0;
  	var taskById = {};
  	var setFrame = typeof window !== "undefined"
  	    && (window.requestAnimationFrame
  	      || window.msRequestAnimationFrame
  	      || window.mozRequestAnimationFrame
  	      || window.webkitRequestAnimationFrame
  	      || window.oRequestAnimationFrame)
  	      || function(callback) { return setTimeout(callback, 17); };
  
  	function Timer() {
  	  this.id = ++taskId;
  	}
  
  	Timer.prototype = timer.prototype = {
  	  restart: function(callback, delay, time) {
  	    if (typeof callback !== "function") throw new TypeError("callback is not a function");
  	    time = (time == null ? Date.now() : +time) + (delay == null ? 0 : +delay);
  	    var i = this.id, t = taskById[i];
  	    if (t) {
  	      t.callback = callback, t.time = time;
  	    } else {
  	      t = {next: null, callback: callback, time: time};
  	      if (taskTail) taskTail.next = t; else taskHead = t;
  	      taskById[i] = taskTail = t;
  	    }
  	    sleep();
  	  },
  	  stop: function() {
  	    var i = this.id, t = taskById[i];
  	    if (t) {
  	      t.callback = null, t.time = Infinity;
  	      delete taskById[i];
  	      sleep();
  	    }
  	  }
  	};
  
  	function timer(callback, delay, time) {
  	  var t = new Timer;
  	  t.restart(callback, delay, time);
  	  return t;
  	}
  
  	function timerOnce(callback, delay, time) {
  	  var t = new Timer;
  	  t.restart(function(elapsed, now) { t.stop(); callback(elapsed, now); }, delay, time);
  	  return t;
  	}
  
  	function timerFlush(now) {
  	  now = now == null ? Date.now() : +now;
  	  ++frame; // Pretend we’ve set an alarm, if we haven’t already.
  	  try {
  	    var t = taskHead, c;
  	    while (t) {
  	      if (now >= t.time) c = t.callback, c(now - t.time, now);
  	      t = t.next;
  	    }
  	  } finally {
  	    --frame;
  	  }
  	}
  
  	function wake() {
  	  frame = timeout = 0;
  	  try {
  	    timerFlush();
  	  } finally {
  	    var t0, t1 = taskHead, time = Infinity;
  	    while (t1) {
  	      if (t1.callback) {
  	        if (time > t1.time) time = t1.time;
  	        t1 = (t0 = t1).next;
  	      } else {
  	        t1 = t0 ? t0.next = t1.next : taskHead = t1.next;
  	      }
  	    }
  	    taskTail = t0;
  	    sleep(time);
  	  }
  	}
  
  	function sleep(time) {
  	  if (frame) return; // Soonest alarm already set, or will be.
  	  if (timeout) timeout = clearTimeout(timeout);
  	  var delay = time - Date.now();
  	  if (delay > 24) { if (time < Infinity) timeout = setTimeout(wake, delay); }
  	  else frame = 1, setFrame(wake);
  	}
  
  	var t0$1 = new Date;
  	var t1$1 = new Date;
  	function newInterval(floori, offseti, count, field) {
  
  	  function interval(date) {
  	    return floori(date = new Date(+date)), date;
  	  }
  
  	  interval.floor = interval;
  
  	  interval.round = function(date) {
  	    var d0 = new Date(+date),
  	        d1 = new Date(date - 1);
  	    floori(d0), floori(d1), offseti(d1, 1);
  	    return date - d0 < d1 - date ? d0 : d1;
  	  };
  
  	  interval.ceil = function(date) {
  	    return floori(date = new Date(date - 1)), offseti(date, 1), date;
  	  };
  
  	  interval.offset = function(date, step) {
  	    return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date;
  	  };
  
  	  interval.range = function(start, stop, step) {
  	    var range = [];
  	    start = new Date(start - 1);
  	    stop = new Date(+stop);
  	    step = step == null ? 1 : Math.floor(step);
  	    if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date
  	    offseti(start, 1), floori(start);
  	    if (start < stop) range.push(new Date(+start));
  	    while (offseti(start, step), floori(start), start < stop) range.push(new Date(+start));
  	    return range;
  	  };
  
  	  interval.filter = function(test) {
  	    return newInterval(function(date) {
  	      while (floori(date), !test(date)) date.setTime(date - 1);
  	    }, function(date, step) {
  	      while (--step >= 0) while (offseti(date, 1), !test(date));
  	    });
  	  };
  
  	  if (count) {
  	    interval.count = function(start, end) {
  	      t0$1.setTime(+start), t1$1.setTime(+end);
  	      floori(t0$1), floori(t1$1);
  	      return Math.floor(count(t0$1, t1$1));
  	    };
  
  	    interval.every = function(step) {
  	      step = Math.floor(step);
  	      return !isFinite(step) || !(step > 0) ? null
  	          : !(step > 1) ? interval
  	          : interval.filter(field
  	              ? function(d) { return field(d) % step === 0; }
  	              : function(d) { return interval.count(0, d) % step === 0; });
  	    };
  	  }
  
  	  return interval;
  	}
  
  	var millisecond = newInterval(function() {
  	  // noop
  	}, function(date, step) {
  	  date.setTime(+date + step);
  	}, function(start, end) {
  	  return end - start;
  	});
  
  	// An optimized implementation for this simple case.
  	millisecond.every = function(k) {
  	  k = Math.floor(k);
  	  if (!isFinite(k) || !(k > 0)) return null;
  	  if (!(k > 1)) return millisecond;
  	  return newInterval(function(date) {
  	    date.setTime(Math.floor(date / k) * k);
  	  }, function(date, step) {
  	    date.setTime(+date + step * k);
  	  }, function(start, end) {
  	    return (end - start) / k;
  	  });
  	};
  
  	var timeSecond = newInterval(function(date) {
  	  date.setMilliseconds(0);
  	}, function(date, step) {
  	  date.setTime(+date + step * 1e3);
  	}, function(start, end) {
  	  return (end - start) / 1e3;
  	}, function(date) {
  	  return date.getSeconds();
  	});
  
  	var timeMinute = newInterval(function(date) {
  	  date.setSeconds(0, 0);
  	}, function(date, step) {
  	  date.setTime(+date + step * 6e4);
  	}, function(start, end) {
  	  return (end - start) / 6e4;
  	}, function(date) {
  	  return date.getMinutes();
  	});
  
  	var timeHour = newInterval(function(date) {
  	  date.setMinutes(0, 0, 0);
  	}, function(date, step) {
  	  date.setTime(+date + step * 36e5);
  	}, function(start, end) {
  	  return (end - start) / 36e5;
  	}, function(date) {
  	  return date.getHours();
  	});
  
  	var timeDay = newInterval(function(date) {
  	  date.setHours(0, 0, 0, 0);
  	}, function(date, step) {
  	  date.setDate(date.getDate() + step);
  	}, function(start, end) {
  	  return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 864e5;
  	}, function(date) {
  	  return date.getDate() - 1;
  	});
  
  	function weekday(i) {
  	  return newInterval(function(date) {
  	    date.setHours(0, 0, 0, 0);
  	    date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7);
  	  }, function(date, step) {
  	    date.setDate(date.getDate() + step * 7);
  	  }, function(start, end) {
  	    return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 6048e5;
  	  });
  	}
  
  	var timeSunday = weekday(0);
  	var timeMonday = weekday(1);
  	var tuesday = weekday(2);
  	var wednesday = weekday(3);
  	var thursday = weekday(4);
  	var friday = weekday(5);
  	var saturday = weekday(6);
  
  	var timeMonth = newInterval(function(date) {
  	  date.setHours(0, 0, 0, 0);
  	  date.setDate(1);
  	}, function(date, step) {
  	  date.setMonth(date.getMonth() + step);
  	}, function(start, end) {
  	  return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12;
  	}, function(date) {
  	  return date.getMonth();
  	});
  
  	var timeYear = newInterval(function(date) {
  	  date.setHours(0, 0, 0, 0);
  	  date.setMonth(0, 1);
  	}, function(date, step) {
  	  date.setFullYear(date.getFullYear() + step);
  	}, function(start, end) {
  	  return end.getFullYear() - start.getFullYear();
  	}, function(date) {
  	  return date.getFullYear();
  	});
  
  	var utcSecond = newInterval(function(date) {
  	  date.setUTCMilliseconds(0);
  	}, function(date, step) {
  	  date.setTime(+date + step * 1e3);
  	}, function(start, end) {
  	  return (end - start) / 1e3;
  	}, function(date) {
  	  return date.getUTCSeconds();
  	});
  
  	var utcMinute = newInterval(function(date) {
  	  date.setUTCSeconds(0, 0);
  	}, function(date, step) {
  	  date.setTime(+date + step * 6e4);
  	}, function(start, end) {
  	  return (end - start) / 6e4;
  	}, function(date) {
  	  return date.getUTCMinutes();
  	});
  
  	var utcHour = newInterval(function(date) {
  	  date.setUTCMinutes(0, 0, 0);
  	}, function(date, step) {
  	  date.setTime(+date + step * 36e5);
  	}, function(start, end) {
  	  return (end - start) / 36e5;
  	}, function(date) {
  	  return date.getUTCHours();
  	});
  
  	var utcDay = newInterval(function(date) {
  	  date.setUTCHours(0, 0, 0, 0);
  	}, function(date, step) {
  	  date.setUTCDate(date.getUTCDate() + step);
  	}, function(start, end) {
  	  return (end - start) / 864e5;
  	}, function(date) {
  	  return date.getUTCDate() - 1;
  	});
  
  	function utcWeekday(i) {
  	  return newInterval(function(date) {
  	    date.setUTCHours(0, 0, 0, 0);
  	    date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7);
  	  }, function(date, step) {
  	    date.setUTCDate(date.getUTCDate() + step * 7);
  	  }, function(start, end) {
  	    return (end - start) / 6048e5;
  	  });
  	}
  
  	var utcSunday = utcWeekday(0);
  	var utcMonday = utcWeekday(1);
  	var utcTuesday = utcWeekday(2);
  	var utcWednesday = utcWeekday(3);
  	var utcThursday = utcWeekday(4);
  	var utcFriday = utcWeekday(5);
  	var utcSaturday = utcWeekday(6);
  
  	var utcMonth = newInterval(function(date) {
  	  date.setUTCHours(0, 0, 0, 0);
  	  date.setUTCDate(1);
  	}, function(date, step) {
  	  date.setUTCMonth(date.getUTCMonth() + step);
  	}, function(start, end) {
  	  return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12;
  	}, function(date) {
  	  return date.getUTCMonth();
  	});
  
  	var utcYear = newInterval(function(date) {
  	  date.setUTCHours(0, 0, 0, 0);
  	  date.setUTCMonth(0, 1);
  	}, function(date, step) {
  	  date.setUTCFullYear(date.getUTCFullYear() + step);
  	}, function(start, end) {
  	  return end.getUTCFullYear() - start.getUTCFullYear();
  	}, function(date) {
  	  return date.getUTCFullYear();
  	});
  
  	var timeMilliseconds = millisecond.range;
  	var timeSeconds = timeSecond.range;
  	var timeMinutes = timeMinute.range;
  	var timeHours = timeHour.range;
  	var timeDays = timeDay.range;
  	var timeSundays = timeSunday.range;
  	var timeMondays = timeMonday.range;
  	var timeTuesdays = tuesday.range;
  	var timeWednesdays = wednesday.range;
  	var timeThursdays = thursday.range;
  	var timeFridays = friday.range;
  	var timeSaturdays = saturday.range;
  	var timeWeeks = timeSunday.range;
  	var timeMonths = timeMonth.range;
  	var timeYears = timeYear.range;
  
  	var utcMillisecond = millisecond;
  	var utcMilliseconds = timeMilliseconds;
  	var utcSeconds = utcSecond.range;
  	var utcMinutes = utcMinute.range;
  	var utcHours = utcHour.range;
  	var utcDays = utcDay.range;
  	var utcSundays = utcSunday.range;
  	var utcMondays = utcMonday.range;
  	var utcTuesdays = utcTuesday.range;
  	var utcWednesdays = utcWednesday.range;
  	var utcThursdays = utcThursday.range;
  	var utcFridays = utcFriday.range;
  	var utcSaturdays = utcSaturday.range;
  	var utcWeeks = utcSunday.range;
  	var utcMonths = utcMonth.range;
  	var utcYears = utcYear.range;
  
  	// Computes the decimal coefficient and exponent of the specified number x with
  	// significant digits p, where x is positive and p is in [1, 21] or undefined.
  	// For example, formatDecimal(1.23) returns ["123", 0].
  	function formatDecimal(x, p) {
  	  if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity
  	  var i, coefficient = x.slice(0, i);
  
  	  // The string returned by toExponential either has the form \d\.\d+e[-+]\d+
  	  // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
  	  return [
  	    coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,
  	    +x.slice(i + 1)
  	  ];
  	}
  
  	function exponent$1(x) {
  	  return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN;
  	}
  
  	function formatGroup(grouping, thousands) {
  	  return function(value, width) {
  	    var i = value.length,
  	        t = [],
  	        j = 0,
  	        g = grouping[0],
  	        length = 0;
  
  	    while (i > 0 && g > 0) {
  	      if (length + g + 1 > width) g = Math.max(1, width - length);
  	      t.push(value.substring(i -= g, i + g));
  	      if ((length += g + 1) > width) break;
  	      g = grouping[j = (j + 1) % grouping.length];
  	    }
  
  	    return t.reverse().join(thousands);
  	  };
  	}
  
  	function formatDefault(x, p) {
  	  x = x.toPrecision(p);
  
  	  out: for (var n = x.length, i = 1, i0 = -1, i1; i < n; ++i) {
  	    switch (x[i]) {
  	      case ".": i0 = i1 = i; break;
  	      case "0": if (i0 === 0) i0 = i; i1 = i; break;
  	      case "e": break out;
  	      default: if (i0 > 0) i0 = 0; break;
  	    }
  	  }
  
  	  return i0 > 0 ? x.slice(0, i0) + x.slice(i1 + 1) : x;
  	}
  
  	var prefixExponent;
  
  	function formatPrefixAuto(x, p) {
  	  var d = formatDecimal(x, p);
  	  if (!d) return x + "";
  	  var coefficient = d[0],
  	      exponent = d[1],
  	      i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1,
  	      n = coefficient.length;
  	  return i === n ? coefficient
  	      : i > n ? coefficient + new Array(i - n + 1).join("0")
  	      : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i)
  	      : "0." + new Array(1 - i).join("0") + formatDecimal(x, Math.max(0, p + i - 1))[0]; // less than 1y!
  	}
  
  	function formatRounded(x, p) {
  	  var d = formatDecimal(x, p);
  	  if (!d) return x + "";
  	  var coefficient = d[0],
  	      exponent = d[1];
  	  return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient
  	      : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1)
  	      : coefficient + new Array(exponent - coefficient.length + 2).join("0");
  	}
  
  	var formatTypes = {
  	  "": formatDefault,
  	  "%": function(x, p) { return (x * 100).toFixed(p); },
  	  "b": function(x) { return Math.round(x).toString(2); },
  	  "c": function(x) { return x + ""; },
  	  "d": function(x) { return Math.round(x).toString(10); },
  	  "e": function(x, p) { return x.toExponential(p); },
  	  "f": function(x, p) { return x.toFixed(p); },
  	  "g": function(x, p) { return x.toPrecision(p); },
  	  "o": function(x) { return Math.round(x).toString(8); },
  	  "p": function(x, p) { return formatRounded(x * 100, p); },
  	  "r": formatRounded,
  	  "s": formatPrefixAuto,
  	  "X": function(x) { return Math.round(x).toString(16).toUpperCase(); },
  	  "x": function(x) { return Math.round(x).toString(16); }
  	};
  
  	// [[fill]align][sign][symbol][0][width][,][.precision][type]
  	var re = /^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i;
  
  	function formatSpecifier(specifier) {
  	  return new FormatSpecifier(specifier);
  	}
  
  	function FormatSpecifier(specifier) {
  	  if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier);
  
  	  var match,
  	      fill = match[1] || " ",
  	      align = match[2] || ">",
  	      sign = match[3] || "-",
  	      symbol = match[4] || "",
  	      zero = !!match[5],
  	      width = match[6] && +match[6],
  	      comma = !!match[7],
  	      precision = match[8] && +match[8].slice(1),
  	      type = match[9] || "";
  
  	  // The "n" type is an alias for ",g".
  	  if (type === "n") comma = true, type = "g";
  
  	  // Map invalid types to the default format.
  	  else if (!formatTypes[type]) type = "";
  
  	  // If zero fill is specified, padding goes after sign and before digits.
  	  if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "=";
  
  	  this.fill = fill;
  	  this.align = align;
  	  this.sign = sign;
  	  this.symbol = symbol;
  	  this.zero = zero;
  	  this.width = width;
  	  this.comma = comma;
  	  this.precision = precision;
  	  this.type = type;
  	}
  
  	FormatSpecifier.prototype.toString = function() {
  	  return this.fill
  	      + this.align
  	      + this.sign
  	      + this.symbol
  	      + (this.zero ? "0" : "")
  	      + (this.width == null ? "" : Math.max(1, this.width | 0))
  	      + (this.comma ? "," : "")
  	      + (this.precision == null ? "" : "." + Math.max(0, this.precision | 0))
  	      + this.type;
  	};
  
  	var prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];
  
  	function identity$1(x) {
  	  return x;
  	}
  
  	function locale(locale) {
  	  var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity$1,
  	      currency = locale.currency,
  	      decimal = locale.decimal;
  
  	  function newFormat(specifier) {
  	    specifier = formatSpecifier(specifier);
  
  	    var fill = specifier.fill,
  	        align = specifier.align,
  	        sign = specifier.sign,
  	        symbol = specifier.symbol,
  	        zero = specifier.zero,
  	        width = specifier.width,
  	        comma = specifier.comma,
  	        precision = specifier.precision,
  	        type = specifier.type;
  
  	    // Compute the prefix and suffix.
  	    // For SI-prefix, the suffix is lazily computed.
  	    var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
  	        suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? "%" : "";
  
  	    // What format function should we use?
  	    // Is this an integer type?
  	    // Can this type generate exponential notation?
  	    var formatType = formatTypes[type],
  	        maybeSuffix = !type || /[defgprs%]/.test(type);
  
  	    // Set the default precision if not specified,
  	    // or clamp the specified precision to the supported range.
  	    // For significant precision, it must be in [1, 21].
  	    // For fixed precision, it must be in [0, 20].
  	    precision = precision == null ? (type ? 6 : 12)
  	        : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision))
  	        : Math.max(0, Math.min(20, precision));
  
  	    function format(value) {
  	      var valuePrefix = prefix,
  	          valueSuffix = suffix,
  	          i, n, c;
  
  	      if (type === "c") {
  	        valueSuffix = formatType(value) + valueSuffix;
  	        value = "";
  	      } else {
  	        value = +value;
  
  	        // Convert negative to positive, and compute the prefix.
  	        // Note that -0 is not less than 0, but 1 / -0 is!
  	        var valueNegative = (value < 0 || 1 / value < 0) && (value *= -1, true);
  
  	        // Perform the initial formatting.
  	        value = formatType(value, precision);
  
  	        // If the original value was negative, it may be rounded to zero during
  	        // formatting; treat this as (positive) zero.
  	        if (valueNegative) {
  	          i = -1, n = value.length;
  	          valueNegative = false;
  	          while (++i < n) {
  	            if (c = value.charCodeAt(i), (48 < c && c < 58)
  	                || (type === "x" && 96 < c && c < 103)
  	                || (type === "X" && 64 < c && c < 71)) {
  	              valueNegative = true;
  	              break;
  	            }
  	          }
  	        }
  
  	        // Compute the prefix and suffix.
  	        valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
  	        valueSuffix = valueSuffix + (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + (valueNegative && sign === "(" ? ")" : "");
  
  	        // Break the formatted value into the integer “value” part that can be
  	        // grouped, and fractional or exponential “suffix” part that is not.
  	        if (maybeSuffix) {
  	          i = -1, n = value.length;
  	          while (++i < n) {
  	            if (c = value.charCodeAt(i), 48 > c || c > 57) {
  	              valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
  	              value = value.slice(0, i);
  	              break;
  	            }
  	          }
  	        }
  	      }
  
  	      // If the fill character is not "0", grouping is applied before padding.
  	      if (comma && !zero) value = group(value, Infinity);
  
  	      // Compute the padding.
  	      var length = valuePrefix.length + value.length + valueSuffix.length,
  	          padding = length < width ? new Array(width - length + 1).join(fill) : "";
  
  	      // If the fill character is "0", grouping is applied after padding.
  	      if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = "";
  
  	      // Reconstruct the final output based on the desired alignment.
  	      switch (align) {
  	        case "<": return valuePrefix + value + valueSuffix + padding;
  	        case "=": return valuePrefix + padding + value + valueSuffix;
  	        case "^": return padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length);
  	      }
  	      return padding + valuePrefix + value + valueSuffix;
  	    }
  
  	    format.toString = function() {
  	      return specifier + "";
  	    };
  
  	    return format;
  	  }
  
  	  function formatPrefix(specifier, value) {
  	    var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)),
  	        e = Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3,
  	        k = Math.pow(10, -e),
  	        prefix = prefixes[8 + e / 3];
  	    return function(value) {
  	      return f(k * value) + prefix;
  	    };
  	  }
  
  	  return {
  	    format: newFormat,
  	    formatPrefix: formatPrefix
  	  };
  	}
  
  	var defaultLocale = locale({
  	  decimal: ".",
  	  thousands: ",",
  	  grouping: [3],
  	  currency: ["$", ""]
  	});
  
  	var caES = locale({
  	  decimal: ",",
  	  thousands: ".",
  	  grouping: [3],
  	  currency: ["", "\xa0€"]
  	});
  
  	var csCZ = locale({
  	  decimal: ",",
  	  thousands: "\xa0",
  	  grouping: [3],
  	  currency: ["", "\xa0Kč"]
  	});
  
  	var deCH = locale({
  	  decimal: ",",
  	  thousands: "'",
  	  grouping: [3],
  	  currency: ["", "\xa0CHF"]
  	});
  
  	var deDE = locale({
  	  decimal: ",",
  	  thousands: ".",
  	  grouping: [3],
  	  currency: ["", "\xa0€"]
  	});
  
  	var enCA = locale({
  	  decimal: ".",
  	  thousands: ",",
  	  grouping: [3],
  	  currency: ["$", ""]
  	});
  
  	var enGB = locale({
  	  decimal: ".",
  	  thousands: ",",
  	  grouping: [3],
  	  currency: ["£", ""]
  	});
  
  	var esES = locale({
  	  decimal: ",",
  	  thousands: ".",
  	  grouping: [3],
  	  currency: ["", "\xa0€"]
  	});
  
  	var fiFI = locale({
  	  decimal: ",",
  	  thousands: "\xa0",
  	  grouping: [3],
  	  currency: ["", "\xa0€"]
  	});
  
  	var frCA = locale({
  	  decimal: ",",
  	  thousands: "\xa0",
  	  grouping: [3],
  	  currency: ["", "$"]
  	});
  
  	var frFR = locale({
  	  decimal: ",",
  	  thousands: ".",
  	  grouping: [3],
  	  currency: ["", "\xa0€"]
  	});
  
  	var heIL = locale({
  	  decimal: ".",
  	  thousands: ",",
  	  grouping: [3],
  	  currency: ["₪", ""]
  	});
  
  	var huHU = locale({
  	  decimal: ",",
  	  thousands: "\xa0",
  	  grouping: [3],
  	  currency: ["", "\xa0Ft"]
  	});
  
  	var itIT = locale({
  	  decimal: ",",
  	  thousands: ".",
  	  grouping: [3],
  	  currency: ["€", ""]
  	});
  
  	var jaJP = locale({
  	  decimal: ".",
  	  thousands: ",",
  	  grouping: [3],
  	  currency: ["", "円"]
  	});
  
  	var koKR = locale({
  	  decimal: ".",
  	  thousands: ",",
  	  grouping: [3],
  	  currency: ["₩", ""]
  	});
  
  	var mkMK = locale({
  	  decimal: ",",
  	  thousands: ".",
  	  grouping: [3],
  	  currency: ["", "\xa0ден."]
  	});
  
  	var nlNL = locale({
  	  decimal: ",",
  	  thousands: ".",
  	  grouping: [3],
  	  currency: ["€\xa0", ""]
  	});
  
  	var plPL = locale({
  	  decimal: ",",
  	  thousands: ".",
  	  grouping: [3],
  	  currency: ["", "zł"]
  	});
  
  	var ptBR = locale({
  	  decimal: ",",
  	  thousands: ".",
  	  grouping: [3],
  	  currency: ["R$", ""]
  	});
  
  	var ruRU = locale({
  	  decimal: ",",
  	  thousands: "\xa0",
  	  grouping: [3],
  	  currency: ["", "\xa0руб."]
  	});
  
  	var svSE = locale({
  	  decimal: ",",
  	  thousands: "\xa0",
  	  grouping: [3],
  	  currency: ["", "SEK"]
  	});
  
  	var zhCN = locale({
  	  decimal: ".",
  	  thousands: ",",
  	  grouping: [3],
  	  currency: ["¥", ""]
  	});
  
  	function precisionFixed(step) {
  	  return Math.max(0, -exponent$1(Math.abs(step)));
  	}
  
  	function precisionPrefix(step, value) {
  	  return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3 - exponent$1(Math.abs(step)));
  	}
  
  	function precisionRound(step, max) {
  	  step = Math.abs(step), max = Math.abs(max) - step;
  	  return Math.max(0, exponent$1(max) - exponent$1(step)) + 1;
  	}
  
  	var format = defaultLocale.format;
  	var formatPrefix = defaultLocale.formatPrefix;
  
  	function localDate(d) {
  	  if (0 <= d.y && d.y < 100) {
  	    var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L);
  	    date.setFullYear(d.y);
  	    return date;
  	  }
  	  return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L);
  	}
  
  	function utcDate(d) {
  	  if (0 <= d.y && d.y < 100) {
  	    var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L));
  	    date.setUTCFullYear(d.y);
  	    return date;
  	  }
  	  return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L));
  	}
  
  	function newYear(y) {
  	  return {y: y, m: 0, d: 1, H: 0, M: 0, S: 0, L: 0};
  	}
  
  	function locale$1(locale) {
  	  var locale_dateTime = locale.dateTime,
  	      locale_date = locale.date,
  	      locale_time = locale.time,
  	      locale_periods = locale.periods,
  	      locale_weekdays = locale.days,
  	      locale_shortWeekdays = locale.shortDays,
  	      locale_months = locale.months,
  	      locale_shortMonths = locale.shortMonths;
  
  	  var periodRe = formatRe(locale_periods),
  	      periodLookup = formatLookup(locale_periods),
  	      weekdayRe = formatRe(locale_weekdays),
  	      weekdayLookup = formatLookup(locale_weekdays),
  	      shortWeekdayRe = formatRe(locale_shortWeekdays),
  	      shortWeekdayLookup = formatLookup(locale_shortWeekdays),
  	      monthRe = formatRe(locale_months),
  	      monthLookup = formatLookup(locale_months),
  	      shortMonthRe = formatRe(locale_shortMonths),
  	      shortMonthLookup = formatLookup(locale_shortMonths);
  
  	  var formats = {
  	    "a": formatShortWeekday,
  	    "A": formatWeekday,
  	    "b": formatShortMonth,
  	    "B": formatMonth,
  	    "c": null,
  	    "d": formatDayOfMonth,
  	    "e": formatDayOfMonth,
  	    "H": formatHour24,
  	    "I": formatHour12,
  	    "j": formatDayOfYear,
  	    "L": formatMilliseconds,
  	    "m": formatMonthNumber,
  	    "M": formatMinutes,
  	    "p": formatPeriod,
  	    "S": formatSeconds,
  	    "U": formatWeekNumberSunday,
  	    "w": formatWeekdayNumber,
  	    "W": formatWeekNumberMonday,
  	    "x": null,
  	    "X": null,
  	    "y": formatYear,
  	    "Y": formatFullYear,
  	    "Z": formatZone,
  	    "%": formatLiteralPercent
  	  };
  
  	  var utcFormats = {
  	    "a": formatUTCShortWeekday,
  	    "A": formatUTCWeekday,
  	    "b": formatUTCShortMonth,
  	    "B": formatUTCMonth,
  	    "c": null,
  	    "d": formatUTCDayOfMonth,
  	    "e": formatUTCDayOfMonth,
  	    "H": formatUTCHour24,
  	    "I": formatUTCHour12,
  	    "j": formatUTCDayOfYear,
  	    "L": formatUTCMilliseconds,
  	    "m": formatUTCMonthNumber,
  	    "M": formatUTCMinutes,
  	    "p": formatUTCPeriod,
  	    "S": formatUTCSeconds,
  	    "U": formatUTCWeekNumberSunday,
  	    "w": formatUTCWeekdayNumber,
  	    "W": formatUTCWeekNumberMonday,
  	    "x": null,
  	    "X": null,
  	    "y": formatUTCYear,
  	    "Y": formatUTCFullYear,
  	    "Z": formatUTCZone,
  	    "%": formatLiteralPercent
  	  };
  
  	  var parses = {
  	    "a": parseShortWeekday,
  	    "A": parseWeekday,
  	    "b": parseShortMonth,
  	    "B": parseMonth,
  	    "c": parseLocaleDateTime,
  	    "d": parseDayOfMonth,
  	    "e": parseDayOfMonth,
  	    "H": parseHour24,
  	    "I": parseHour24,
  	    "j": parseDayOfYear,
  	    "L": parseMilliseconds,
  	    "m": parseMonthNumber,
  	    "M": parseMinutes,
  	    "p": parsePeriod,
  	    "S": parseSeconds,
  	    "U": parseWeekNumberSunday,
  	    "w": parseWeekdayNumber,
  	    "W": parseWeekNumberMonday,
  	    "x": parseLocaleDate,
  	    "X": parseLocaleTime,
  	    "y": parseYear,
  	    "Y": parseFullYear,
  	    "Z": parseZone,
  	    "%": parseLiteralPercent
  	  };
  
  	  // These recursive directive definitions must be deferred.
  	  formats.x = newFormat(locale_date, formats);
  	  formats.X = newFormat(locale_time, formats);
  	  formats.c = newFormat(locale_dateTime, formats);
  	  utcFormats.x = newFormat(locale_date, utcFormats);
  	  utcFormats.X = newFormat(locale_time, utcFormats);
  	  utcFormats.c = newFormat(locale_dateTime, utcFormats);
  
  	  function newFormat(specifier, formats) {
  	    return function(date) {
  	      var string = [],
  	          i = -1,
  	          j = 0,
  	          n = specifier.length,
  	          c,
  	          pad,
  	          format;
  
  	      if (!(date instanceof Date)) date = new Date(+date);
  
  	      while (++i < n) {
  	        if (specifier.charCodeAt(i) === 37) {
  	          string.push(specifier.slice(j, i));
  	          if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i);
  	          else pad = c === "e" ? " " : "0";
  	          if (format = formats[c]) c = format(date, pad);
  	          string.push(c);
  	          j = i + 1;
  	        }
  	      }
  
  	      string.push(specifier.slice(j, i));
  	      return string.join("");
  	    };
  	  }
  
  	  function newParse(specifier, newDate) {
  	    return function(string) {
  	      var d = newYear(1900),
  	          i = parseSpecifier(d, specifier, string += "", 0);
  	      if (i != string.length) return null;
  
  	      // The am-pm flag is 0 for AM, and 1 for PM.
  	      if ("p" in d) d.H = d.H % 12 + d.p * 12;
  
  	      // Convert day-of-week and week-of-year to day-of-year.
  	      if ("W" in d || "U" in d) {
  	        if (!("w" in d)) d.w = "W" in d ? 1 : 0;
  	        var day = "Z" in d ? utcDate(newYear(d.y)).getUTCDay() : newDate(newYear(d.y)).getDay();
  	        d.m = 0;
  	        d.d = "W" in d ? (d.w + 6) % 7 + d.W * 7 - (day + 5) % 7 : d.w + d.U * 7 - (day + 6) % 7;
  	      }
  
  	      // If a time zone is specified, all fields are interpreted as UTC and then
  	      // offset according to the specified time zone.
  	      if ("Z" in d) {
  	        d.H += d.Z / 100 | 0;
  	        d.M += d.Z % 100;
  	        return utcDate(d);
  	      }
  
  	      // Otherwise, all fields are in local time.
  	      return newDate(d);
  	    };
  	  }
  
  	  function parseSpecifier(d, specifier, string, j) {
  	    var i = 0,
  	        n = specifier.length,
  	        m = string.length,
  	        c,
  	        parse;
  
  	    while (i < n) {
  	      if (j >= m) return -1;
  	      c = specifier.charCodeAt(i++);
  	      if (c === 37) {
  	        c = specifier.charAt(i++);
  	        parse = parses[c in pads ? specifier.charAt(i++) : c];
  	        if (!parse || ((j = parse(d, string, j)) < 0)) return -1;
  	      } else if (c != string.charCodeAt(j++)) {
  	        return -1;
  	      }
  	    }
  
  	    return j;
  	  }
  
  	  function parsePeriod(d, string, i) {
  	    var n = periodRe.exec(string.slice(i));
  	    return n ? (d.p = periodLookup[n[0].toLowerCase()], i + n[0].length) : -1;
  	  }
  
  	  function parseShortWeekday(d, string, i) {
  	    var n = shortWeekdayRe.exec(string.slice(i));
  	    return n ? (d.w = shortWeekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1;
  	  }
  
  	  function parseWeekday(d, string, i) {
  	    var n = weekdayRe.exec(string.slice(i));
  	    return n ? (d.w = weekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1;
  	  }
  
  	  function parseShortMonth(d, string, i) {
  	    var n = shortMonthRe.exec(string.slice(i));
  	    return n ? (d.m = shortMonthLookup[n[0].toLowerCase()], i + n[0].length) : -1;
  	  }
  
  	  function parseMonth(d, string, i) {
  	    var n = monthRe.exec(string.slice(i));
  	    return n ? (d.m = monthLookup[n[0].toLowerCase()], i + n[0].length) : -1;
  	  }
  
  	  function parseLocaleDateTime(d, string, i) {
  	    return parseSpecifier(d, locale_dateTime, string, i);
  	  }
  
  	  function parseLocaleDate(d, string, i) {
  	    return parseSpecifier(d, locale_date, string, i);
  	  }
  
  	  function parseLocaleTime(d, string, i) {
  	    return parseSpecifier(d, locale_time, string, i);
  	  }
  
  	  function formatShortWeekday(d) {
  	    return locale_shortWeekdays[d.getDay()];
  	  }
  
  	  function formatWeekday(d) {
  	    return locale_weekdays[d.getDay()];
  	  }
  
  	  function formatShortMonth(d) {
  	    return locale_shortMonths[d.getMonth()];
  	  }
  
  	  function formatMonth(d) {
  	    return locale_months[d.getMonth()];
  	  }
  
  	  function formatPeriod(d) {
  	    return locale_periods[+(d.getHours() >= 12)];
  	  }
  
  	  function formatUTCShortWeekday(d) {
  	    return locale_shortWeekdays[d.getUTCDay()];
  	  }
  
  	  function formatUTCWeekday(d) {
  	    return locale_weekdays[d.getUTCDay()];
  	  }
  
  	  function formatUTCShortMonth(d) {
  	    return locale_shortMonths[d.getUTCMonth()];
  	  }
  
  	  function formatUTCMonth(d) {
  	    return locale_months[d.getUTCMonth()];
  	  }
  
  	  function formatUTCPeriod(d) {
  	    return locale_periods[+(d.getUTCHours() >= 12)];
  	  }
  
  	  return {
  	    format: function(specifier) {
  	      var f = newFormat(specifier += "", formats);
  	      f.toString = function() { return specifier; };
  	      return f;
  	    },
  	    parse: function(specifier) {
  	      var p = newParse(specifier += "", localDate);
  	      p.toString = function() { return specifier; };
  	      return p;
  	    },
  	    utcFormat: function(specifier) {
  	      var f = newFormat(specifier += "", utcFormats);
  	      f.toString = function() { return specifier; };
  	      return f;
  	    },
  	    utcParse: function(specifier) {
  	      var p = newParse(specifier, utcDate);
  	      p.toString = function() { return specifier; };
  	      return p;
  	    }
  	  };
  	}
  
  	var pads = {"-": "", "_": " ", "0": "0"};
  	var numberRe = /^\s*\d+/;
  	var percentRe = /^%/;
  	var requoteRe = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
  	function pad(value, fill, width) {
  	  var sign = value < 0 ? "-" : "",
  	      string = (sign ? -value : value) + "",
  	      length = string.length;
  	  return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);
  	}
  
  	function requote(s) {
  	  return s.replace(requoteRe, "\\$&");
  	}
  
  	function formatRe(names) {
  	  return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i");
  	}
  
  	function formatLookup(names) {
  	  var map = {}, i = -1, n = names.length;
  	  while (++i < n) map[names[i].toLowerCase()] = i;
  	  return map;
  	}
  
  	function parseWeekdayNumber(d, string, i) {
  	  var n = numberRe.exec(string.slice(i, i + 1));
  	  return n ? (d.w = +n[0], i + n[0].length) : -1;
  	}
  
  	function parseWeekNumberSunday(d, string, i) {
  	  var n = numberRe.exec(string.slice(i));
  	  return n ? (d.U = +n[0], i + n[0].length) : -1;
  	}
  
  	function parseWeekNumberMonday(d, string, i) {
  	  var n = numberRe.exec(string.slice(i));
  	  return n ? (d.W = +n[0], i + n[0].length) : -1;
  	}
  
  	function parseFullYear(d, string, i) {
  	  var n = numberRe.exec(string.slice(i, i + 4));
  	  return n ? (d.y = +n[0], i + n[0].length) : -1;
  	}
  
  	function parseYear(d, string, i) {
  	  var n = numberRe.exec(string.slice(i, i + 2));
  	  return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1;
  	}
  
  	function parseZone(d, string, i) {
  	  var n = /^(Z)|([+-]\d\d)(?:\:?(\d\d))?/.exec(string.slice(i, i + 6));
  	  return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || "00")), i + n[0].length) : -1;
  	}
  
  	function parseMonthNumber(d, string, i) {
  	  var n = numberRe.exec(string.slice(i, i + 2));
  	  return n ? (d.m = n[0] - 1, i + n[0].length) : -1;
  	}
  
  	function parseDayOfMonth(d, string, i) {
  	  var n = numberRe.exec(string.slice(i, i + 2));
  	  return n ? (d.d = +n[0], i + n[0].length) : -1;
  	}
  
  	function parseDayOfYear(d, string, i) {
  	  var n = numberRe.exec(string.slice(i, i + 3));
  	  return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1;
  	}
  
  	function parseHour24(d, string, i) {
  	  var n = numberRe.exec(string.slice(i, i + 2));
  	  return n ? (d.H = +n[0], i + n[0].length) : -1;
  	}
  
  	function parseMinutes(d, string, i) {
  	  var n = numberRe.exec(string.slice(i, i + 2));
  	  return n ? (d.M = +n[0], i + n[0].length) : -1;
  	}
  
  	function parseSeconds(d, string, i) {
  	  var n = numberRe.exec(string.slice(i, i + 2));
  	  return n ? (d.S = +n[0], i + n[0].length) : -1;
  	}
  
  	function parseMilliseconds(d, string, i) {
  	  var n = numberRe.exec(string.slice(i, i + 3));
  	  return n ? (d.L = +n[0], i + n[0].length) : -1;
  	}
  
  	function parseLiteralPercent(d, string, i) {
  	  var n = percentRe.exec(string.slice(i, i + 1));
  	  return n ? i + n[0].length : -1;
  	}
  
  	function formatDayOfMonth(d, p) {
  	  return pad(d.getDate(), p, 2);
  	}
  
  	function formatHour24(d, p) {
  	  return pad(d.getHours(), p, 2);
  	}
  
  	function formatHour12(d, p) {
  	  return pad(d.getHours() % 12 || 12, p, 2);
  	}
  
  	function formatDayOfYear(d, p) {
  	  return pad(1 + timeDay.count(timeYear(d), d), p, 3);
  	}
  
  	function formatMilliseconds(d, p) {
  	  return pad(d.getMilliseconds(), p, 3);
  	}
  
  	function formatMonthNumber(d, p) {
  	  return pad(d.getMonth() + 1, p, 2);
  	}
  
  	function formatMinutes(d, p) {
  	  return pad(d.getMinutes(), p, 2);
  	}
  
  	function formatSeconds(d, p) {
  	  return pad(d.getSeconds(), p, 2);
  	}
  
  	function formatWeekNumberSunday(d, p) {
  	  return pad(timeSunday.count(timeYear(d), d), p, 2);
  	}
  
  	function formatWeekdayNumber(d) {
  	  return d.getDay();
  	}
  
  	function formatWeekNumberMonday(d, p) {
  	  return pad(timeMonday.count(timeYear(d), d), p, 2);
  	}
  
  	function formatYear(d, p) {
  	  return pad(d.getFullYear() % 100, p, 2);
  	}
  
  	function formatFullYear(d, p) {
  	  return pad(d.getFullYear() % 10000, p, 4);
  	}
  
  	function formatZone(d) {
  	  var z = d.getTimezoneOffset();
  	  return (z > 0 ? "-" : (z *= -1, "+"))
  	      + pad(z / 60 | 0, "0", 2)
  	      + pad(z % 60, "0", 2);
  	}
  
  	function formatUTCDayOfMonth(d, p) {
  	  return pad(d.getUTCDate(), p, 2);
  	}
  
  	function formatUTCHour24(d, p) {
  	  return pad(d.getUTCHours(), p, 2);
  	}
  
  	function formatUTCHour12(d, p) {
  	  return pad(d.getUTCHours() % 12 || 12, p, 2);
  	}
  
  	function formatUTCDayOfYear(d, p) {
  	  return pad(1 + utcDay.count(utcYear(d), d), p, 3);
  	}
  
  	function formatUTCMilliseconds(d, p) {
  	  return pad(d.getUTCMilliseconds(), p, 3);
  	}
  
  	function formatUTCMonthNumber(d, p) {
  	  return pad(d.getUTCMonth() + 1, p, 2);
  	}
  
  	function formatUTCMinutes(d, p) {
  	  return pad(d.getUTCMinutes(), p, 2);
  	}
  
  	function formatUTCSeconds(d, p) {
  	  return pad(d.getUTCSeconds(), p, 2);
  	}
  
  	function formatUTCWeekNumberSunday(d, p) {
  	  return pad(utcSunday.count(utcYear(d), d), p, 2);
  	}
  
  	function formatUTCWeekdayNumber(d) {
  	  return d.getUTCDay();
  	}
  
  	function formatUTCWeekNumberMonday(d, p) {
  	  return pad(utcMonday.count(utcYear(d), d), p, 2);
  	}
  
  	function formatUTCYear(d, p) {
  	  return pad(d.getUTCFullYear() % 100, p, 2);
  	}
  
  	function formatUTCFullYear(d, p) {
  	  return pad(d.getUTCFullYear() % 10000, p, 4);
  	}
  
  	function formatUTCZone() {
  	  return "+0000";
  	}
  
  	function formatLiteralPercent() {
  	  return "%";
  	}
  
  	var locale$2 = locale$1({
  	  dateTime: "%a %b %e %X %Y",
  	  date: "%m/%d/%Y",
  	  time: "%H:%M:%S",
  	  periods: ["AM", "PM"],
  	  days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
  	  shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
  	  months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
  	  shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
  	});
  
  	var caES$1 = locale$1({
  	  dateTime: "%A, %e de %B de %Y, %X",
  	  date: "%d/%m/%Y",
  	  time: "%H:%M:%S",
  	  periods: ["AM", "PM"],
  	  days: ["diumenge", "dilluns", "dimarts", "dimecres", "dijous", "divendres", "dissabte"],
  	  shortDays: ["dg.", "dl.", "dt.", "dc.", "dj.", "dv.", "ds."],
  	  months: ["gener", "febrer", "març", "abril", "maig", "juny", "juliol", "agost", "setembre", "octubre", "novembre", "desembre"],
  	  shortMonths: ["gen.", "febr.", "març", "abr.", "maig", "juny", "jul.", "ag.", "set.", "oct.", "nov.", "des."]
  	});
  
  	var deCH$1 = locale$1({
  	  dateTime: "%A, der %e. %B %Y, %X",
  	  date: "%d.%m.%Y",
  	  time: "%H:%M:%S",
  	  periods: ["AM", "PM"], // unused
  	  days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"],
  	  shortDays: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"],
  	  months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"],
  	  shortMonths: ["Jan", "Feb", "Mrz", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"]
  	});
  
  	var deDE$1 = locale$1({
  	  dateTime: "%A, der %e. %B %Y, %X",
  	  date: "%d.%m.%Y",
  	  time: "%H:%M:%S",
  	  periods: ["AM", "PM"], // unused
  	  days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"],
  	  shortDays: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"],
  	  months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"],
  	  shortMonths: ["Jan", "Feb", "Mrz", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"]
  	});
  
  	var enCA$1 = locale$1({
  	  dateTime: "%a %b %e %X %Y",
  	  date: "%Y-%m-%d",
  	  time: "%H:%M:%S",
  	  periods: ["AM", "PM"],
  	  days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
  	  shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
  	  months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
  	  shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
  	});
  
  	var enGB$1 = locale$1({
  	  dateTime: "%a %e %b %X %Y",
  	  date: "%d/%m/%Y",
  	  time: "%H:%M:%S",
  	  periods: ["AM", "PM"],
  	  days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
  	  shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
  	  months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
  	  shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
  	});
  
  	var esES$1 = locale$1({
  	  dateTime: "%A, %e de %B de %Y, %X",
  	  date: "%d/%m/%Y",
  	  time: "%H:%M:%S",
  	  periods: ["AM", "PM"],
  	  days: ["domingo", "lunes", "martes", "miércoles", "jueves", "viernes", "sábado"],
  	  shortDays: ["dom", "lun", "mar", "mié", "jue", "vie", "sáb"],
  	  months: ["enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"],
  	  shortMonths: ["ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sep", "oct", "nov", "dic"]
  	});
  
  	var fiFI$1 = locale$1({
  	  dateTime: "%A, %-d. %Bta %Y klo %X",
  	  date: "%-d.%-m.%Y",
  	  time: "%H:%M:%S",
  	  periods: ["a.m.", "p.m."],
  	  days: ["sunnuntai", "maanantai", "tiistai", "keskiviikko", "torstai", "perjantai", "lauantai"],
  	  shortDays: ["Su", "Ma", "Ti", "Ke", "To", "Pe", "La"],
  	  months: ["tammikuu", "helmikuu", "maaliskuu", "huhtikuu", "toukokuu", "kesäkuu", "heinäkuu", "elokuu", "syyskuu", "lokakuu", "marraskuu", "joulukuu"],
  	  shortMonths: ["Tammi", "Helmi", "Maalis", "Huhti", "Touko", "Kesä", "Heinä", "Elo", "Syys", "Loka", "Marras", "Joulu"]
  	});
  
  	var frCA$1 = locale$1({
  	  dateTime: "%a %e %b %Y %X",
  	  date: "%Y-%m-%d",
  	  time: "%H:%M:%S",
  	  periods: ["", ""],
  	  days: ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"],
  	  shortDays: ["dim", "lun", "mar", "mer", "jeu", "ven", "sam"],
  	  months: ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"],
  	  shortMonths: ["jan", "fév", "mar", "avr", "mai", "jui", "jul", "aoû", "sep", "oct", "nov", "déc"]
  	});
  
  	var frFR$1 = locale$1({
  	  dateTime: "%A, le %e %B %Y, %X",
  	  date: "%d/%m/%Y",
  	  time: "%H:%M:%S",
  	  periods: ["AM", "PM"], // unused
  	  days: ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"],
  	  shortDays: ["dim.", "lun.", "mar.", "mer.", "jeu.", "ven.", "sam."],
  	  months: ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"],
  	  shortMonths: ["janv.", "févr.", "mars", "avr.", "mai", "juin", "juil.", "août", "sept.", "oct.", "nov.", "déc."]
  	});
  
  	var heIL$1 = locale$1({
  	  dateTime: "%A, %e ב%B %Y %X",
  	  date: "%d.%m.%Y",
  	  time: "%H:%M:%S",
  	  periods: ["AM", "PM"],
  	  days: ["ראשון", "שני", "שלישי", "רביעי", "חמישי", "שישי", "שבת"],
  	  shortDays: ["א׳", "ב׳", "ג׳", "ד׳", "ה׳", "ו׳", "ש׳"],
  	  months: ["ינואר", "פברואר", "מרץ", "אפריל", "מאי", "יוני", "יולי", "אוגוסט", "ספטמבר", "אוקטובר", "נובמבר", "דצמבר"],
  	  shortMonths: ["ינו׳", "פבר׳", "מרץ", "אפר׳", "מאי", "יוני", "יולי", "אוג׳", "ספט׳", "אוק׳", "נוב׳", "דצמ׳"]
  	});
  
  	var huHU$1 = locale$1({
  	  dateTime: "%Y. %B %-e., %A %X",
  	  date: "%Y. %m. %d.",
  	  time: "%H:%M:%S",
  	  periods: ["de.", "du."], // unused
  	  days: ["vasárnap", "hétfő", "kedd", "szerda", "csütörtök", "péntek", "szombat"],
  	  shortDays: ["V", "H", "K", "Sze", "Cs", "P", "Szo"],
  	  months: ["január", "február", "március", "április", "május", "június", "július", "augusztus", "szeptember", "október", "november", "december"],
  	  shortMonths: ["jan.", "feb.", "már.", "ápr.", "máj.", "jún.", "júl.", "aug.", "szept.", "okt.", "nov.", "dec."]
  	});
  
  	var itIT$1 = locale$1({
  	  dateTime: "%A %e %B %Y, %X",
  	  date: "%d/%m/%Y",
  	  time: "%H:%M:%S",
  	  periods: ["AM", "PM"], // unused
  	  days: ["Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato"],
  	  shortDays: ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"],
  	  months: ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"],
  	  shortMonths: ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"]
  	});
  
  	var jaJP$1 = locale$1({
  	  dateTime: "%Y %b %e %a %X",
  	  date: "%Y/%m/%d",
  	  time: "%H:%M:%S",
  	  periods: ["AM", "PM"],
  	  days: ["日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"],
  	  shortDays: ["日", "月", "火", "水", "木", "金", "土"],
  	  months: ["睦月", "如月", "弥生", "卯月", "皐月", "水無月", "文月", "葉月", "長月", "神無月", "霜月", "師走"],
  	  shortMonths: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"]
  	});
  
  	var koKR$1 = locale$1({
  	  dateTime: "%Y/%m/%d %a %X",
  	  date: "%Y/%m/%d",
  	  time: "%H:%M:%S",
  	  periods: ["오전", "오후"],
  	  days: ["일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일"],
  	  shortDays: ["일", "월", "화", "수", "목", "금", "토"],
  	  months: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"],
  	  shortMonths: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"]
  	});
  
  	var mkMK$1 = locale$1({
  	  dateTime: "%A, %e %B %Y г. %X",
  	  date: "%d.%m.%Y",
  	  time: "%H:%M:%S",
  	  periods: ["AM", "PM"],
  	  days: ["недела", "понеделник", "вторник", "среда", "четврток", "петок", "сабота"],
  	  shortDays: ["нед", "пон", "вто", "сре", "чет", "пет", "саб"],
  	  months: ["јануари", "февруари", "март", "април", "мај", "јуни", "јули", "август", "септември", "октомври", "ноември", "декември"],
  	  shortMonths: ["јан", "фев", "мар", "апр", "мај", "јун", "јул", "авг", "сеп", "окт", "ное", "дек"]
  	});
  
  	var nlNL$1 = locale$1({
  	  dateTime: "%a %e %B %Y %T",
  	  date: "%d-%m-%Y",
  	  time: "%H:%M:%S",
  	  periods: ["AM", "PM"], // unused
  	  days: ["zondag", "maandag", "dinsdag", "woensdag", "donderdag", "vrijdag", "zaterdag"],
  	  shortDays: ["zo", "ma", "di", "wo", "do", "vr", "za"],
  	  months: ["januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"],
  	  shortMonths: ["jan", "feb", "mrt", "apr", "mei", "jun", "jul", "aug", "sep", "okt", "nov", "dec"]
  	});
  
  	var plPL$1 = locale$1({
  	  dateTime: "%A, %e %B %Y, %X",
  	  date: "%d/%m/%Y",
  	  time: "%H:%M:%S",
  	  periods: ["AM", "PM"], // unused
  	  days: ["Niedziela", "Poniedziałek", "Wtorek", "Środa", "Czwartek", "Piątek", "Sobota"],
  	  shortDays: ["Niedz.", "Pon.", "Wt.", "Śr.", "Czw.", "Pt.", "Sob."],
  	  months: ["Styczeń", "Luty", "Marzec", "Kwiecień", "Maj", "Czerwiec", "Lipiec", "Sierpień", "Wrzesień", "Październik", "Listopad", "Grudzień"],
  	  shortMonths: ["Stycz.", "Luty", "Marz.", "Kwie.", "Maj", "Czerw.", "Lipc.", "Sierp.", "Wrz.", "Paźdz.", "Listop.", "Grudz."]/* In Polish language abbraviated months are not commonly used so there is a dispute about the proper abbraviations. */
  	});
  
  	var ptBR$1 = locale$1({
  	  dateTime: "%A, %e de %B de %Y. %X",
  	  date: "%d/%m/%Y",
  	  time: "%H:%M:%S",
  	  periods: ["AM", "PM"],
  	  days: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado"],
  	  shortDays: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"],
  	  months: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"],
  	  shortMonths: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"]
  	});
  
  	var ruRU$1 = locale$1({
  	  dateTime: "%A, %e %B %Y г. %X",
  	  date: "%d.%m.%Y",
  	  time: "%H:%M:%S",
  	  periods: ["AM", "PM"],
  	  days: ["воскресенье", "понедельник", "вторник", "среда", "четверг", "пятница", "суббота"],
  	  shortDays: ["вс", "пн", "вт", "ср", "чт", "пт", "сб"],
  	  months: ["января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября", "декабря"],
  	  shortMonths: ["янв", "фев", "мар", "апр", "май", "июн", "июл", "авг", "сен", "окт", "ноя", "дек"]
  	});
  
  	var svSE$1 = locale$1({
  	  dateTime: "%A den %d %B %Y %X",
  	  date: "%Y-%m-%d",
  	  time: "%H:%M:%S",
  	  periods: ["fm", "em"],
  	  days: ["Söndag", "Måndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag"],
  	  shortDays: ["Sön", "Mån", "Tis", "Ons", "Tor", "Fre", "Lör"],
  	  months: ["Januari", "Februari", "Mars", "April", "Maj", "Juni", "Juli", "Augusti", "September", "Oktober", "November", "December"],
  	  shortMonths: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"]
  	});
  
  	var zhCN$1 = locale$1({
  	  dateTime: "%a %b %e %X %Y",
  	  date: "%Y/%-m/%-d",
  	  time: "%H:%M:%S",
  	  periods: ["上午", "下午"],
  	  days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
  	  shortDays: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
  	  months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
  	  shortMonths: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"]
  	});
  
  	var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ";
  
  	function formatIsoNative(date) {
  	  return date.toISOString();
  	}
  
  	var formatIso = Date.prototype.toISOString
  	    ? formatIsoNative
  	    : locale$2.utcFormat(isoSpecifier);
  
  	function parseIsoNative(string) {
  	  var date = new Date(string);
  	  return isNaN(date) ? null : date;
  	}
  
  	var parseIso = +new Date("2000-01-01T00:00:00.000Z")
  	    ? parseIsoNative
  	    : locale$2.utcParse(isoSpecifier);
  
  	var timeFormat = locale$2.format;
  	var timeParse = locale$2.parse;
  	var utcFormat = locale$2.utcFormat;
  	var utcParse = locale$2.utcParse;
  
  	var array$1 = Array.prototype;
  
  	var map$1 = array$1.map;
  	var slice$2 = array$1.slice;
  
  	var implicit = {name: "implicit"};
  
  	function ordinal() {
  	  var index = map(),
  	      domain = [],
  	      range = [],
  	      unknown = implicit;
  
  	  function scale(d) {
  	    var key = d + "", i = index.get(key);
  	    if (!i) {
  	      if (unknown !== implicit) return unknown;
  	      index.set(key, i = domain.push(d));
  	    }
  	    return range[(i - 1) % range.length];
  	  }
  
  	  scale.domain = function(_) {
  	    if (!arguments.length) return domain.slice();
  	    domain = [], index = map();
  	    var i = -1, n = _.length, d, key;
  	    while (++i < n) if (!index.has(key = (d = _[i]) + "")) index.set(key, domain.push(d));
  	    return scale;
  	  };
  
  	  scale.range = function(_) {
  	    return arguments.length ? (range = slice$2.call(_), scale) : range.slice();
  	  };
  
  	  scale.unknown = function(_) {
  	    return arguments.length ? (unknown = _, scale) : unknown;
  	  };
  
  	  scale.copy = function() {
  	    return ordinal()
  	        .domain(domain)
  	        .range(range)
  	        .unknown(unknown);
  	  };
  
  	  return scale;
  	}
  
  	function band() {
  	  var scale = ordinal().unknown(undefined),
  	      domain = scale.domain,
  	      ordinalRange = scale.range,
  	      range = [0, 1],
  	      step,
  	      bandwidth,
  	      round = false,
  	      paddingInner = 0,
  	      paddingOuter = 0,
  	      align = 0.5;
  
  	  delete scale.unknown;
  
  	  function rescale() {
  	    var n = domain().length,
  	        reverse = range[1] < range[0],
  	        start = range[reverse - 0],
  	        stop = range[1 - reverse];
  	    step = (stop - start) / Math.max(1, n - paddingInner + paddingOuter * 2);
  	    if (round) step = Math.floor(step);
  	    start += (stop - start - step * (n - paddingInner)) * align;
  	    bandwidth = step * (1 - paddingInner);
  	    if (round) start = Math.round(start), bandwidth = Math.round(bandwidth);
  	    var values = sequence(n).map(function(i) { return start + step * i; });
  	    return ordinalRange(reverse ? values.reverse() : values);
  	  }
  
  	  scale.domain = function(_) {
  	    return arguments.length ? (domain(_), rescale()) : domain();
  	  };
  
  	  scale.range = function(_) {
  	    return arguments.length ? (range = [+_[0], +_[1]], rescale()) : range.slice();
  	  };
  
  	  scale.rangeRound = function(_) {
  	    return range = [+_[0], +_[1]], round = true, rescale();
  	  };
  
  	  scale.bandwidth = function() {
  	    return bandwidth;
  	  };
  
  	  scale.step = function() {
  	    return step;
  	  };
  
  	  scale.round = function(_) {
  	    return arguments.length ? (round = !!_, rescale()) : round;
  	  };
  
  	  scale.padding = function(_) {
  	    return arguments.length ? (paddingInner = paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingInner;
  	  };
  
  	  scale.paddingInner = function(_) {
  	    return arguments.length ? (paddingInner = Math.max(0, Math.min(1, _)), rescale()) : paddingInner;
  	  };
  
  	  scale.paddingOuter = function(_) {
  	    return arguments.length ? (paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingOuter;
  	  };
  
  	  scale.align = function(_) {
  	    return arguments.length ? (align = Math.max(0, Math.min(1, _)), rescale()) : align;
  	  };
  
  	  scale.copy = function() {
  	    return band()
  	        .domain(domain())
  	        .range(range)
  	        .round(round)
  	        .paddingInner(paddingInner)
  	        .paddingOuter(paddingOuter)
  	        .align(align);
  	  };
  
  	  return rescale();
  	}
  
  	function pointish(scale) {
  	  var copy = scale.copy;
  
  	  scale.padding = scale.paddingOuter;
  	  delete scale.paddingInner;
  	  delete scale.paddingOuter;
  
  	  scale.copy = function() {
  	    return pointish(copy());
  	  };
  
  	  return scale;
  	}
  
  	function point() {
  	  return pointish(band().paddingInner(1));
  	}
  
  	function constant$2(x) {
  	  return function() {
  	    return x;
  	  };
  	}
  
  	function number$2(x) {
  	  return +x;
  	}
  
  	var unit = [0, 1];
  
  	function deinterpolateLinear(a, b) {
  	  return (b -= (a = +a))
  	      ? function(x) { return (x - a) / b; }
  	      : constant$2(b);
  	}
  
  	function deinterpolateClamp(deinterpolate) {
  	  return function(a, b) {
  	    var d = deinterpolate(a = +a, b = +b);
  	    return function(x) { return x <= a ? 0 : x >= b ? 1 : d(x); };
  	  };
  	}
  
  	function reinterpolateClamp(reinterpolate) {
  	  return function(a, b) {
  	    var r = reinterpolate(a = +a, b = +b);
  	    return function(t) { return t <= 0 ? a : t >= 1 ? b : r(t); };
  	  };
  	}
  
  	function bimap(domain, range, deinterpolate, reinterpolate) {
  	  var d0 = domain[0], d1 = domain[1], r0 = range[0], r1 = range[1];
  	  if (d1 < d0) d0 = deinterpolate(d1, d0), r0 = reinterpolate(r1, r0);
  	  else d0 = deinterpolate(d0, d1), r0 = reinterpolate(r0, r1);
  	  return function(x) { return r0(d0(x)); };
  	}
  
  	function polymap(domain, range, deinterpolate, reinterpolate) {
  	  var j = Math.min(domain.length, range.length) - 1,
  	      d = new Array(j),
  	      r = new Array(j),
  	      i = -1;
  
  	  // Reverse descending domains.
  	  if (domain[j] < domain[0]) {
  	    domain = domain.slice().reverse();
  	    range = range.slice().reverse();
  	  }
  
  	  while (++i < j) {
  	    d[i] = deinterpolate(domain[i], domain[i + 1]);
  	    r[i] = reinterpolate(range[i], range[i + 1]);
  	  }
  
  	  return function(x) {
  	    var i = bisectRight(domain, x, 1, j) - 1;
  	    return r[i](d[i](x));
  	  };
  	}
  
  	function copy(source, target) {
  	  return target
  	      .domain(source.domain())
  	      .range(source.range())
  	      .interpolate(source.interpolate())
  	      .clamp(source.clamp());
  	}
  
  	// deinterpolate(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1].
  	// reinterpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding domain value x in [a,b].
  	function continuous(deinterpolate, reinterpolate) {
  	  var domain = unit,
  	      range = unit,
  	      interpolate$$ = interpolate,
  	      clamp = false,
  	      output,
  	      input;
  
  	  function rescale() {
  	    var map = Math.min(domain.length, range.length) > 2 ? polymap : bimap;
  	    output = map(domain, range, clamp ? deinterpolateClamp(deinterpolate) : deinterpolate, interpolate$$);
  	    input = map(range, domain, deinterpolateLinear, clamp ? reinterpolateClamp(reinterpolate) : reinterpolate);
  	    return scale;
  	  }
  
  	  function scale(x) {
  	    return output(+x);
  	  }
  
  	  scale.invert = function(y) {
  	    return input(+y);
  	  };
  
  	  scale.domain = function(_) {
  	    return arguments.length ? (domain = map$1.call(_, number$2), rescale()) : domain.slice();
  	  };
  
  	  scale.range = function(_) {
  	    return arguments.length ? (range = slice$2.call(_), rescale()) : range.slice();
  	  };
  
  	  scale.rangeRound = function(_) {
  	    return range = slice$2.call(_), interpolate$$ = interpolateRound, rescale();
  	  };
  
  	  scale.clamp = function(_) {
  	    return arguments.length ? (clamp = !!_, rescale()) : clamp;
  	  };
  
  	  scale.interpolate = function(_) {
  	    return arguments.length ? (interpolate$$ = _, rescale()) : interpolate$$;
  	  };
  
  	  return rescale();
  	}
  
  	function tickFormat(domain, count, specifier) {
  	  var start = domain[0],
  	      stop = domain[domain.length - 1],
  	      step = tickStep(start, stop, count == null ? 10 : count),
  	      precision;
  	  specifier = formatSpecifier(specifier == null ? ",f" : specifier);
  	  switch (specifier.type) {
  	    case "s": {
  	      var value = Math.max(Math.abs(start), Math.abs(stop));
  	      if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision;
  	      return formatPrefix(specifier, value);
  	    }
  	    case "":
  	    case "e":
  	    case "g":
  	    case "p":
  	    case "r": {
  	      if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e");
  	      break;
  	    }
  	    case "f":
  	    case "%": {
  	      if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2;
  	      break;
  	    }
  	  }
  	  return format(specifier);
  	}
  
  	function linearish(scale) {
  	  var domain = scale.domain;
  
  	  scale.ticks = function(count) {
  	    var d = domain();
  	    return ticks(d[0], d[d.length - 1], count == null ? 10 : count);
  	  };
  
  	  scale.tickFormat = function(count, specifier) {
  	    return tickFormat(domain(), count, specifier);
  	  };
  
  	  scale.nice = function(count) {
  	    var d = domain(),
  	        i = d.length - 1,
  	        n = count == null ? 10 : count,
  	        start = d[0],
  	        stop = d[i],
  	        step = tickStep(start, stop, n);
  
  	    if (step) {
  	      step = tickStep(Math.floor(start / step) * step, Math.ceil(stop / step) * step, n);
  	      d[0] = Math.floor(start / step) * step;
  	      d[i] = Math.ceil(stop / step) * step;
  	      domain(d);
  	    }
  
  	    return scale;
  	  };
  
  	  return scale;
  	}
  
  	function linear() {
  	  var scale = continuous(deinterpolateLinear, reinterpolate);
  
  	  scale.copy = function() {
  	    return copy(scale, linear());
  	  };
  
  	  return linearish(scale);
  	}
  
  	function identity$2() {
  	  var domain = [0, 1];
  
  	  function scale(x) {
  	    return +x;
  	  }
  
  	  scale.invert = scale;
  
  	  scale.domain = scale.range = function(_) {
  	    return arguments.length ? (domain = map$1.call(_, number$2), scale) : domain.slice();
  	  };
  
  	  scale.copy = function() {
  	    return identity$2().domain(domain);
  	  };
  
  	  return linearish(scale);
  	}
  
  	function nice(domain, interval) {
  	  domain = domain.slice();
  
  	  var i0 = 0,
  	      i1 = domain.length - 1,
  	      x0 = domain[i0],
  	      x1 = domain[i1],
  	      t;
  
  	  if (x1 < x0) {
  	    t = i0, i0 = i1, i1 = t;
  	    t = x0, x0 = x1, x1 = t;
  	  }
  
  	  domain[i0] = interval.floor(x0);
  	  domain[i1] = interval.ceil(x1);
  	  return domain;
  	}
  
  	var tickFormat10 = format(".0e");
  	var tickFormatOther = format(",");
  	function deinterpolate(a, b) {
  	  return (b = Math.log(b / a))
  	      ? function(x) { return Math.log(x / a) / b; }
  	      : constant$2(b);
  	}
  
  	function reinterpolate$1(a, b) {
  	  return a < 0
  	      ? function(t) { return -Math.pow(-b, t) * Math.pow(-a, 1 - t); }
  	      : function(t) { return Math.pow(b, t) * Math.pow(a, 1 - t); };
  	}
  
  	function pow10(x) {
  	  return isFinite(x) ? +("1e" + x) : x < 0 ? 0 : x;
  	}
  
  	function powp(base) {
  	  return base === 10 ? pow10
  	      : base === Math.E ? Math.exp
  	      : function(x) { return Math.pow(base, x); };
  	}
  
  	function logp(base) {
  	  return base === Math.E ? Math.log
  	      : base === 10 && Math.log10
  	      || base === 2 && Math.log2
  	      || (base = Math.log(base), function(x) { return Math.log(x) / base; });
  	}
  
  	function reflect(f) {
  	  return function(x) {
  	    return -f(-x);
  	  };
  	}
  
  	function log() {
  	  var scale = continuous(deinterpolate, reinterpolate$1).domain([1, 10]),
  	      domain = scale.domain,
  	      base = 10,
  	      logs = logp(10),
  	      pows = powp(10);
  
  	  function rescale() {
  	    logs = logp(base), pows = powp(base);
  	    if (domain()[0] < 0) logs = reflect(logs), pows = reflect(pows);
  	    return scale;
  	  }
  
  	  scale.base = function(_) {
  	    return arguments.length ? (base = +_, rescale()) : base;
  	  };
  
  	  scale.domain = function(_) {
  	    return arguments.length ? (domain(_), rescale()) : domain();
  	  };
  
  	  scale.ticks = function(count) {
  	    var d = domain(),
  	        u = d[0],
  	        v = d[d.length - 1],
  	        r;
  
  	    if (r = v < u) i = u, u = v, v = i;
  
  	    var i = logs(u),
  	        j = logs(v),
  	        p,
  	        k,
  	        t,
  	        n = count == null ? 10 : +count,
  	        z = [];
  
  	    if (!(base % 1) && j - i < n) {
  	      i = Math.round(i) - 1, j = Math.round(j) + 1;
  	      if (u > 0) for (; i < j; ++i) {
  	        for (k = 1, p = pows(i); k < base; ++k) {
  	          t = p * k;
  	          if (t < u) continue;
  	          if (t > v) break;
  	          z.push(t);
  	        }
  	      } else for (; i < j; ++i) {
  	        for (k = base - 1, p = pows(i); k >= 1; --k) {
  	          t = p * k;
  	          if (t < u) continue;
  	          if (t > v) break;
  	          z.push(t);
  	        }
  	      }
  	      if (r) z.reverse();
  	    } else {
  	      z = ticks(i, j, Math.min(j - i, n)).map(pows);
  	    }
  
  	    return z;
  	  };
  
  	  scale.tickFormat = function(count, specifier) {
  	    if (specifier == null) specifier = base === 10 ? tickFormat10 : tickFormatOther;
  	    else if (typeof specifier !== "function") specifier = format(specifier);
  	    if (count === Infinity) return specifier;
  	    if (count == null) count = 10;
  	    var k = Math.max(1, base * count / scale.ticks().length); // TODO fast estimate?
  	    return function(d) {
  	      var i = d / pows(Math.round(logs(d)));
  	      if (i * base < base - 0.5) i *= base;
  	      return i <= k ? specifier(d) : "";
  	    };
  	  };
  
  	  scale.nice = function() {
  	    return domain(nice(domain(), {
  	      floor: function(x) { return pows(Math.floor(logs(x))); },
  	      ceil: function(x) { return pows(Math.ceil(logs(x))); }
  	    }));
  	  };
  
  	  scale.copy = function() {
  	    return copy(scale, log().base(base));
  	  };
  
  	  return scale;
  	}
  
  	function raise(x, exponent) {
  	  return x < 0 ? -Math.pow(-x, exponent) : Math.pow(x, exponent);
  	}
  
  	function pow() {
  	  var exponent = 1,
  	      scale = continuous(deinterpolate, reinterpolate),
  	      domain = scale.domain;
  
  	  function deinterpolate(a, b) {
  	    return (b = raise(b, exponent) - (a = raise(a, exponent)))
  	        ? function(x) { return (raise(x, exponent) - a) / b; }
  	        : constant$2(b);
  	  }
  
  	  function reinterpolate(a, b) {
  	    b = raise(b, exponent) - (a = raise(a, exponent));
  	    return function(t) { return raise(a + b * t, 1 / exponent); };
  	  }
  
  	  scale.exponent = function(_) {
  	    return arguments.length ? (exponent = +_, domain(domain())) : exponent;
  	  };
  
  	  scale.copy = function() {
  	    return copy(scale, pow().exponent(exponent));
  	  };
  
  	  return linearish(scale);
  	}
  
  	function sqrt() {
  	  return pow().exponent(0.5);
  	}
  
  	function quantile$1() {
  	  var domain = [],
  	      range = [],
  	      thresholds = [];
  
  	  function rescale() {
  	    var i = 0, n = Math.max(1, range.length);
  	    thresholds = new Array(n - 1);
  	    while (++i < n) thresholds[i - 1] = quantile(domain, i / n);
  	    return scale;
  	  }
  
  	  function scale(x) {
  	    if (!isNaN(x = +x)) return range[bisectRight(thresholds, x)];
  	  }
  
  	  scale.invertExtent = function(y) {
  	    var i = range.indexOf(y);
  	    return i < 0 ? [NaN, NaN] : [
  	      i > 0 ? thresholds[i - 1] : domain[0],
  	      i < thresholds.length ? thresholds[i] : domain[domain.length - 1]
  	    ];
  	  };
  
  	  scale.domain = function(_) {
  	    if (!arguments.length) return domain.slice();
  	    domain = [];
  	    for (var i = 0, n = _.length, d; i < n; ++i) if (d = _[i], d != null && !isNaN(d = +d)) domain.push(d);
  	    domain.sort(ascending);
  	    return rescale();
  	  };
  
  	  scale.range = function(_) {
  	    return arguments.length ? (range = slice$2.call(_), rescale()) : range.slice();
  	  };
  
  	  scale.quantiles = function() {
  	    return thresholds.slice();
  	  };
  
  	  scale.copy = function() {
  	    return quantile$1()
  	        .domain(domain)
  	        .range(range);
  	  };
  
  	  return scale;
  	}
  
  	function quantize() {
  	  var x0 = 0,
  	      x1 = 1,
  	      n = 1,
  	      domain = [0.5],
  	      range = [0, 1];
  
  	  function scale(x) {
  	    if (x <= x) return range[bisectRight(domain, x, 0, n)];
  	  }
  
  	  function rescale() {
  	    var i = -1;
  	    domain = new Array(n);
  	    while (++i < n) domain[i] = ((i + 1) * x1 - (i - n) * x0) / (n + 1);
  	    return scale;
  	  }
  
  	  scale.domain = function(_) {
  	    return arguments.length ? (x0 = +_[0], x1 = +_[1], rescale()) : [x0, x1];
  	  };
  
  	  scale.range = function(_) {
  	    return arguments.length ? (n = (range = slice$2.call(_)).length - 1, rescale()) : range.slice();
  	  };
  
  	  scale.invertExtent = function(y) {
  	    var i = range.indexOf(y);
  	    return i < 0 ? [NaN, NaN]
  	        : i < 1 ? [x0, domain[0]]
  	        : i >= n ? [domain[n - 1], x1]
  	        : [domain[i - 1], domain[i]];
  	  };
  
  	  scale.copy = function() {
  	    return quantize()
  	        .domain([x0, x1])
  	        .range(range);
  	  };
  
  	  return linearish(scale);
  	}
  
  	function threshold() {
  	  var domain = [0.5],
  	      range = [0, 1],
  	      n = 1;
  
  	  function scale(x) {
  	    if (x <= x) return range[bisectRight(domain, x, 0, n)];
  	  }
  
  	  scale.domain = function(_) {
  	    return arguments.length ? (domain = slice$2.call(_), n = Math.min(domain.length, range.length - 1), scale) : domain.slice();
  	  };
  
  	  scale.range = function(_) {
  	    return arguments.length ? (range = slice$2.call(_), n = Math.min(domain.length, range.length - 1), scale) : range.slice();
  	  };
  
  	  scale.invertExtent = function(y) {
  	    var i = range.indexOf(y);
  	    return [domain[i - 1], domain[i]];
  	  };
  
  	  scale.copy = function() {
  	    return threshold()
  	        .domain(domain)
  	        .range(range);
  	  };
  
  	  return scale;
  	}
  
  	var millisecondsPerSecond = 1000;
  	var millisecondsPerMinute = millisecondsPerSecond * 60;
  	var millisecondsPerHour = millisecondsPerMinute * 60;
  	var millisecondsPerDay = millisecondsPerHour * 24;
  	var millisecondsPerWeek = millisecondsPerDay * 7;
  	var millisecondsPerMonth = millisecondsPerDay * 30;
  	var millisecondsPerYear = millisecondsPerDay * 365;
  	var bisectTickIntervals = bisector(function(method) { return method[2]; }).right;
  	function newDate(t) {
  	  return new Date(t);
  	}
  
  	function calendar(year, month, week, day, hour, minute, second, millisecond, format) {
  	  var scale = continuous(deinterpolateLinear, reinterpolate),
  	      invert = scale.invert,
  	      domain = scale.domain;
  
  	  var formatMillisecond = format(".%L"),
  	      formatSecond = format(":%S"),
  	      formatMinute = format("%I:%M"),
  	      formatHour = format("%I %p"),
  	      formatDay = format("%a %d"),
  	      formatWeek = format("%b %d"),
  	      formatMonth = format("%B"),
  	      formatYear = format("%Y");
  
  	  var tickIntervals = [
  	    [second,  1,      millisecondsPerSecond],
  	    [second,  5,  5 * millisecondsPerSecond],
  	    [second, 15, 15 * millisecondsPerSecond],
  	    [second, 30, 30 * millisecondsPerSecond],
  	    [minute,  1,      millisecondsPerMinute],
  	    [minute,  5,  5 * millisecondsPerMinute],
  	    [minute, 15, 15 * millisecondsPerMinute],
  	    [minute, 30, 30 * millisecondsPerMinute],
  	    [  hour,  1,      millisecondsPerHour  ],
  	    [  hour,  3,  3 * millisecondsPerHour  ],
  	    [  hour,  6,  6 * millisecondsPerHour  ],
  	    [  hour, 12, 12 * millisecondsPerHour  ],
  	    [   day,  1,      millisecondsPerDay   ],
  	    [   day,  2,  2 * millisecondsPerDay   ],
  	    [  week,  1,      millisecondsPerWeek  ],
  	    [ month,  1,      millisecondsPerMonth ],
  	    [ month,  3,  3 * millisecondsPerMonth ],
  	    [  year,  1,      millisecondsPerYear  ]
  	  ];
  
  	  function tickFormat(date) {
  	    return (second(date) < date ? formatMillisecond
  	        : minute(date) < date ? formatSecond
  	        : hour(date) < date ? formatMinute
  	        : day(date) < date ? formatHour
  	        : month(date) < date ? (week(date) < date ? formatDay : formatWeek)
  	        : year(date) < date ? formatMonth
  	        : formatYear)(date);
  	  }
  
  	  function tickInterval(interval, start, stop, step) {
  	    if (interval == null) interval = 10;
  
  	    // If a desired tick count is specified, pick a reasonable tick interval
  	    // based on the extent of the domain and a rough estimate of tick size.
  	    // Otherwise, assume interval is already a time interval and use it.
  	    if (typeof interval === "number") {
  	      var target = Math.abs(stop - start) / interval,
  	          i = bisectTickIntervals(tickIntervals, target);
  	      if (i === tickIntervals.length) {
  	        step = tickStep(start / millisecondsPerYear, stop / millisecondsPerYear, interval);
  	        interval = year;
  	      } else if (i) {
  	        i = tickIntervals[target / tickIntervals[i - 1][2] < tickIntervals[i][2] / target ? i - 1 : i];
  	        step = i[1];
  	        interval = i[0];
  	      } else {
  	        step = tickStep(start, stop, interval);
  	        interval = millisecond;
  	      }
  	    }
  
  	    return step == null ? interval : interval.every(step);
  	  }
  
  	  scale.invert = function(y) {
  	    return new Date(invert(y));
  	  };
  
  	  scale.domain = function(_) {
  	    return arguments.length ? domain(_) : domain().map(newDate);
  	  };
  
  	  scale.ticks = function(interval, step) {
  	    var d = domain(),
  	        t0 = d[0],
  	        t1 = d[d.length - 1],
  	        r = t1 < t0,
  	        t;
  	    if (r) t = t0, t0 = t1, t1 = t;
  	    t = tickInterval(interval, t0, t1, step);
  	    t = t ? t.range(t0, t1 + 1) : []; // inclusive stop
  	    return r ? t.reverse() : t;
  	  };
  
  	  scale.tickFormat = function(specifier) {
  	    return specifier == null ? tickFormat : format(specifier);
  	  };
  
  	  scale.nice = function(interval, step) {
  	    var d = domain();
  	    return (interval = tickInterval(interval, d[0], d[d.length - 1], step))
  	        ? domain(nice(d, interval))
  	        : scale;
  	  };
  
  	  scale.copy = function() {
  	    return copy(scale, calendar(year, month, week, day, hour, minute, second, millisecond, format));
  	  };
  
  	  return scale;
  	}
  
  	function time() {
  	  return calendar(timeYear, timeMonth, timeSunday, timeDay, timeHour, timeMinute, timeSecond, millisecond, timeFormat).domain([new Date(2000, 0, 1), new Date(2000, 0, 2)]);
  	}
  
  	function utcTime() {
  	  return calendar(utcYear, utcMonth, utcSunday, utcDay, utcHour, utcMinute, utcSecond, utcMillisecond, utcFormat).domain([Date.UTC(2000, 0, 1), Date.UTC(2000, 0, 2)]);
  	}
  
  	function colors(s) {
  	  return s.match(/.{6}/g).map(function(x) {
  	    return "#" + x;
  	  });
  	}
  
  	function category10() {
  	  return ordinal().range(colors("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf"));
  	}
  
  	function category20b() {
  	  return ordinal().range(colors("393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6"));
  	}
  
  	function category20c() {
  	  return ordinal().range(colors("3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9"));
  	}
  
  	function category20() {
  	  return ordinal().range(colors("1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5"));
  	}
  
  	function Color$1() {}
  
  	var darker$1 = 0.7;
  	var brighter$1 = 1 / darker$1;
  
  	var reHex3$1 = /^#([0-9a-f]{3})$/;
  	var reHex6$1 = /^#([0-9a-f]{6})$/;
  	var reRgbInteger$1 = /^rgb\(\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*\)$/;
  	var reRgbPercent$1 = /^rgb\(\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*\)$/;
  	var reHslPercent$1 = /^hsl\(\s*([-+]?\d+(?:\.\d+)?)\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*\)$/;
  	var named$1 = {
  	  aliceblue: 0xf0f8ff,
  	  antiquewhite: 0xfaebd7,
  	  aqua: 0x00ffff,
  	  aquamarine: 0x7fffd4,
  	  azure: 0xf0ffff,
  	  beige: 0xf5f5dc,
  	  bisque: 0xffe4c4,
  	  black: 0x000000,
  	  blanchedalmond: 0xffebcd,
  	  blue: 0x0000ff,
  	  blueviolet: 0x8a2be2,
  	  brown: 0xa52a2a,
  	  burlywood: 0xdeb887,
  	  cadetblue: 0x5f9ea0,
  	  chartreuse: 0x7fff00,
  	  chocolate: 0xd2691e,
  	  coral: 0xff7f50,
  	  cornflowerblue: 0x6495ed,
  	  cornsilk: 0xfff8dc,
  	  crimson: 0xdc143c,
  	  cyan: 0x00ffff,
  	  darkblue: 0x00008b,
  	  darkcyan: 0x008b8b,
  	  darkgoldenrod: 0xb8860b,
  	  darkgray: 0xa9a9a9,
  	  darkgreen: 0x006400,
  	  darkgrey: 0xa9a9a9,
  	  darkkhaki: 0xbdb76b,
  	  darkmagenta: 0x8b008b,
  	  darkolivegreen: 0x556b2f,
  	  darkorange: 0xff8c00,
  	  darkorchid: 0x9932cc,
  	  darkred: 0x8b0000,
  	  darksalmon: 0xe9967a,
  	  darkseagreen: 0x8fbc8f,
  	  darkslateblue: 0x483d8b,
  	  darkslategray: 0x2f4f4f,
  	  darkslategrey: 0x2f4f4f,
  	  darkturquoise: 0x00ced1,
  	  darkviolet: 0x9400d3,
  	  deeppink: 0xff1493,
  	  deepskyblue: 0x00bfff,
  	  dimgray: 0x696969,
  	  dimgrey: 0x696969,
  	  dodgerblue: 0x1e90ff,
  	  firebrick: 0xb22222,
  	  floralwhite: 0xfffaf0,
  	  forestgreen: 0x228b22,
  	  fuchsia: 0xff00ff,
  	  gainsboro: 0xdcdcdc,
  	  ghostwhite: 0xf8f8ff,
  	  gold: 0xffd700,
  	  goldenrod: 0xdaa520,
  	  gray: 0x808080,
  	  green: 0x008000,
  	  greenyellow: 0xadff2f,
  	  grey: 0x808080,
  	  honeydew: 0xf0fff0,
  	  hotpink: 0xff69b4,
  	  indianred: 0xcd5c5c,
  	  indigo: 0x4b0082,
  	  ivory: 0xfffff0,
  	  khaki: 0xf0e68c,
  	  lavender: 0xe6e6fa,
  	  lavenderblush: 0xfff0f5,
  	  lawngreen: 0x7cfc00,
  	  lemonchiffon: 0xfffacd,
  	  lightblue: 0xadd8e6,
  	  lightcoral: 0xf08080,
  	  lightcyan: 0xe0ffff,
  	  lightgoldenrodyellow: 0xfafad2,
  	  lightgray: 0xd3d3d3,
  	  lightgreen: 0x90ee90,
  	  lightgrey: 0xd3d3d3,
  	  lightpink: 0xffb6c1,
  	  lightsalmon: 0xffa07a,
  	  lightseagreen: 0x20b2aa,
  	  lightskyblue: 0x87cefa,
  	  lightslategray: 0x778899,
  	  lightslategrey: 0x778899,
  	  lightsteelblue: 0xb0c4de,
  	  lightyellow: 0xffffe0,
  	  lime: 0x00ff00,
  	  limegreen: 0x32cd32,
  	  linen: 0xfaf0e6,
  	  magenta: 0xff00ff,
  	  maroon: 0x800000,
  	  mediumaquamarine: 0x66cdaa,
  	  mediumblue: 0x0000cd,
  	  mediumorchid: 0xba55d3,
  	  mediumpurple: 0x9370db,
  	  mediumseagreen: 0x3cb371,
  	  mediumslateblue: 0x7b68ee,
  	  mediumspringgreen: 0x00fa9a,
  	  mediumturquoise: 0x48d1cc,
  	  mediumvioletred: 0xc71585,
  	  midnightblue: 0x191970,
  	  mintcream: 0xf5fffa,
  	  mistyrose: 0xffe4e1,
  	  moccasin: 0xffe4b5,
  	  navajowhite: 0xffdead,
  	  navy: 0x000080,
  	  oldlace: 0xfdf5e6,
  	  olive: 0x808000,
  	  olivedrab: 0x6b8e23,
  	  orange: 0xffa500,
  	  orangered: 0xff4500,
  	  orchid: 0xda70d6,
  	  palegoldenrod: 0xeee8aa,
  	  palegreen: 0x98fb98,
  	  paleturquoise: 0xafeeee,
  	  palevioletred: 0xdb7093,
  	  papayawhip: 0xffefd5,
  	  peachpuff: 0xffdab9,
  	  peru: 0xcd853f,
  	  pink: 0xffc0cb,
  	  plum: 0xdda0dd,
  	  powderblue: 0xb0e0e6,
  	  purple: 0x800080,
  	  rebeccapurple: 0x663399,
  	  red: 0xff0000,
  	  rosybrown: 0xbc8f8f,
  	  royalblue: 0x4169e1,
  	  saddlebrown: 0x8b4513,
  	  salmon: 0xfa8072,
  	  sandybrown: 0xf4a460,
  	  seagreen: 0x2e8b57,
  	  seashell: 0xfff5ee,
  	  sienna: 0xa0522d,
  	  silver: 0xc0c0c0,
  	  skyblue: 0x87ceeb,
  	  slateblue: 0x6a5acd,
  	  slategray: 0x708090,
  	  slategrey: 0x708090,
  	  snow: 0xfffafa,
  	  springgreen: 0x00ff7f,
  	  steelblue: 0x4682b4,
  	  tan: 0xd2b48c,
  	  teal: 0x008080,
  	  thistle: 0xd8bfd8,
  	  tomato: 0xff6347,
  	  turquoise: 0x40e0d0,
  	  violet: 0xee82ee,
  	  wheat: 0xf5deb3,
  	  white: 0xffffff,
  	  whitesmoke: 0xf5f5f5,
  	  yellow: 0xffff00,
  	  yellowgreen: 0x9acd32
  	};
  
  	color$1.prototype = Color$1.prototype = {
  	  displayable: function() {
  	    return this.rgb().displayable();
  	  },
  	  toString: function() {
  	    return this.rgb() + "";
  	  }
  	};
  
  	function color$1(format) {
  	  var m;
  	  format = (format + "").trim().toLowerCase();
  	  return (m = reHex3$1.exec(format)) ? (m = parseInt(m[1], 16), new Rgb$1((m >> 8 & 0xf) | (m >> 4 & 0x0f0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf))) // #f00
  	      : (m = reHex6$1.exec(format)) ? rgbn$1(parseInt(m[1], 16)) // #ff0000
  	      : (m = reRgbInteger$1.exec(format)) ? new Rgb$1(m[1], m[2], m[3]) // rgb(255,0,0)
  	      : (m = reRgbPercent$1.exec(format)) ? new Rgb$1(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100) // rgb(100%,0%,0%)
  	      : (m = reHslPercent$1.exec(format)) ? new Hsl$1(m[1], m[2] / 100, m[3] / 100) // hsl(120,50%,50%)
  	      : named$1.hasOwnProperty(format) ? rgbn$1(named$1[format])
  	      : null;
  	}
  
  	function rgbn$1(n) {
  	  return new Rgb$1(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff);
  	}
  
  	function rgb$2(r, g, b) {
  	  if (arguments.length === 1) {
  	    if (!(r instanceof Color$1)) r = color$1(r);
  	    if (r) {
  	      r = r.rgb();
  	      b = r.b;
  	      g = r.g;
  	      r = r.r;
  	    } else {
  	      r = g = b = NaN;
  	    }
  	  }
  	  return new Rgb$1(r, g, b);
  	}
  
  	function Rgb$1(r, g, b) {
  	  this.r = +r;
  	  this.g = +g;
  	  this.b = +b;
  	}
  
  	var _rgb$1 = rgb$2.prototype = Rgb$1.prototype = new Color$1;
  
  	_rgb$1.brighter = function(k) {
  	  k = k == null ? brighter$1 : Math.pow(brighter$1, k);
  	  return new Rgb$1(this.r * k, this.g * k, this.b * k);
  	};
  
  	_rgb$1.darker = function(k) {
  	  k = k == null ? darker$1 : Math.pow(darker$1, k);
  	  return new Rgb$1(this.r * k, this.g * k, this.b * k);
  	};
  
  	_rgb$1.rgb = function() {
  	  return this;
  	};
  
  	_rgb$1.displayable = function() {
  	  return (0 <= this.r && this.r <= 255)
  	      && (0 <= this.g && this.g <= 255)
  	      && (0 <= this.b && this.b <= 255);
  	};
  
  	_rgb$1.toString = function() {
  	  var r = Math.round(this.r),
  	      g = Math.round(this.g),
  	      b = Math.round(this.b);
  	  return "#"
  	      + (isNaN(r) || r <= 0 ? "00" : r < 16 ? "0" + r.toString(16) : r >= 255 ? "ff" : r.toString(16))
  	      + (isNaN(g) || g <= 0 ? "00" : g < 16 ? "0" + g.toString(16) : g >= 255 ? "ff" : g.toString(16))
  	      + (isNaN(b) || b <= 0 ? "00" : b < 16 ? "0" + b.toString(16) : b >= 255 ? "ff" : b.toString(16));
  	};
  
  	function hsl$1(h, s, l) {
  	  if (arguments.length === 1) {
  	    if (h instanceof Hsl$1) {
  	      l = h.l;
  	      s = h.s;
  	      h = h.h;
  	    } else {
  	      if (!(h instanceof Color$1)) h = color$1(h);
  	      if (h) {
  	        if (h instanceof Hsl$1) return h;
  	        h = h.rgb();
  	        var r = h.r / 255,
  	            g = h.g / 255,
  	            b = h.b / 255,
  	            min = Math.min(r, g, b),
  	            max = Math.max(r, g, b),
  	            range = max - min;
  	        l = (max + min) / 2;
  	        if (range) {
  	          s = l < 0.5 ? range / (max + min) : range / (2 - max - min);
  	          if (r === max) h = (g - b) / range + (g < b) * 6;
  	          else if (g === max) h = (b - r) / range + 2;
  	          else h = (r - g) / range + 4;
  	          h *= 60;
  	        } else {
  	          h = NaN;
  	          s = l > 0 && l < 1 ? 0 : h;
  	        }
  	      } else {
  	        h = s = l = NaN;
  	      }
  	    }
  	  }
  	  return new Hsl$1(h, s, l);
  	}
  
  	function Hsl$1(h, s, l) {
  	  this.h = +h;
  	  this.s = +s;
  	  this.l = +l;
  	}
  
  	var _hsl$1 = hsl$1.prototype = Hsl$1.prototype = new Color$1;
  
  	_hsl$1.brighter = function(k) {
  	  k = k == null ? brighter$1 : Math.pow(brighter$1, k);
  	  return new Hsl$1(this.h, this.s, this.l * k);
  	};
  
  	_hsl$1.darker = function(k) {
  	  k = k == null ? darker$1 : Math.pow(darker$1, k);
  	  return new Hsl$1(this.h, this.s, this.l * k);
  	};
  
  	_hsl$1.rgb = function() {
  	  var h = this.h % 360 + (this.h < 0) * 360,
  	      s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
  	      l = this.l,
  	      m2 = l + (l < 0.5 ? l : 1 - l) * s,
  	      m1 = 2 * l - m2;
  	  return new Rgb$1(
  	    hsl2rgb$1(h >= 240 ? h - 240 : h + 120, m1, m2),
  	    hsl2rgb$1(h, m1, m2),
  	    hsl2rgb$1(h < 120 ? h + 240 : h - 120, m1, m2)
  	  );
  	};
  
  	_hsl$1.displayable = function() {
  	  return (0 <= this.s && this.s <= 1 || isNaN(this.s))
  	      && (0 <= this.l && this.l <= 1);
  	};
  
  	/* From FvD 13.37, CSS Color Module Level 3 */
  	function hsl2rgb$1(h, m1, m2) {
  	  return (h < 60 ? m1 + (m2 - m1) * h / 60
  	      : h < 180 ? m2
  	      : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60
  	      : m1) * 255;
  	}
  
  	var deg2rad$1 = Math.PI / 180;
  	var rad2deg$2 = 180 / Math.PI;
  
  	var Kn$1 = 18;
  	var Xn$1 = 0.950470;
  	var Yn$1 = 1;
  	var Zn$1 = 1.088830;
  	var t0$2 = 4 / 29;
  	var t1$2 = 6 / 29;
  	var t2$1 = 3 * t1$2 * t1$2;
  	var t3$1 = t1$2 * t1$2 * t1$2;
  	function lab$1(l, a, b) {
  	  if (arguments.length === 1) {
  	    if (l instanceof Lab$1) {
  	      b = l.b;
  	      a = l.a;
  	      l = l.l;
  	    } else if (l instanceof Hcl$1) {
  	      var h = l.h * deg2rad$1;
  	      b = Math.sin(h) * l.c;
  	      a = Math.cos(h) * l.c;
  	      l = l.l;
  	    } else {
  	      if (!(l instanceof Rgb$1)) l = rgb$2(l);
  	      b = rgb2xyz$1(l.r);
  	      a = rgb2xyz$1(l.g);
  	      l = rgb2xyz$1(l.b);
  	      var x = xyz2lab$1((0.4124564 * b + 0.3575761 * a + 0.1804375 * l) / Xn$1),
  	          y = xyz2lab$1((0.2126729 * b + 0.7151522 * a + 0.0721750 * l) / Yn$1),
  	          z = xyz2lab$1((0.0193339 * b + 0.1191920 * a + 0.9503041 * l) / Zn$1);
  	      b = 200 * (y - z);
  	      a = 500 * (x - y);
  	      l = 116 * y - 16;
  	    }
  	  }
  	  return new Lab$1(l, a, b);
  	}
  
  	function Lab$1(l, a, b) {
  	  this.l = +l;
  	  this.a = +a;
  	  this.b = +b;
  	}
  
  	var _lab$1 = lab$1.prototype = Lab$1.prototype = new Color$1;
  
  	_lab$1.brighter = function(k) {
  	  return new Lab$1(this.l + Kn$1 * (k == null ? 1 : k), this.a, this.b);
  	};
  
  	_lab$1.darker = function(k) {
  	  return new Lab$1(this.l - Kn$1 * (k == null ? 1 : k), this.a, this.b);
  	};
  
  	_lab$1.rgb = function() {
  	  var y = (this.l + 16) / 116,
  	      x = isNaN(this.a) ? y : y + this.a / 500,
  	      z = isNaN(this.b) ? y : y - this.b / 200;
  	  y = Yn$1 * lab2xyz$1(y);
  	  x = Xn$1 * lab2xyz$1(x);
  	  z = Zn$1 * lab2xyz$1(z);
  	  return new Rgb$1(
  	    xyz2rgb$1( 3.2404542 * x - 1.5371385 * y - 0.4985314 * z), // D65 -> sRGB
  	    xyz2rgb$1(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z),
  	    xyz2rgb$1( 0.0556434 * x - 0.2040259 * y + 1.0572252 * z)
  	  );
  	};
  
  	function xyz2lab$1(t) {
  	  return t > t3$1 ? Math.pow(t, 1 / 3) : t / t2$1 + t0$2;
  	}
  
  	function lab2xyz$1(t) {
  	  return t > t1$2 ? t * t * t : t2$1 * (t - t0$2);
  	}
  
  	function xyz2rgb$1(x) {
  	  return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055);
  	}
  
  	function rgb2xyz$1(x) {
  	  return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
  	}
  
  	function hcl$1(h, c, l) {
  	  if (arguments.length === 1) {
  	    if (h instanceof Hcl$1) {
  	      l = h.l;
  	      c = h.c;
  	      h = h.h;
  	    } else {
  	      if (!(h instanceof Lab$1)) h = lab$1(h);
  	      l = h.l;
  	      c = Math.sqrt(h.a * h.a + h.b * h.b);
  	      h = Math.atan2(h.b, h.a) * rad2deg$2;
  	      if (h < 0) h += 360;
  	    }
  	  }
  	  return new Hcl$1(h, c, l);
  	}
  
  	function Hcl$1(h, c, l) {
  	  this.h = +h;
  	  this.c = +c;
  	  this.l = +l;
  	}
  
  	var _hcl$1 = hcl$1.prototype = Hcl$1.prototype = new Color$1;
  
  	_hcl$1.brighter = function(k) {
  	  return new Hcl$1(this.h, this.c, this.l + Kn$1 * (k == null ? 1 : k));
  	};
  
  	_hcl$1.darker = function(k) {
  	  return new Hcl$1(this.h, this.c, this.l - Kn$1 * (k == null ? 1 : k));
  	};
  
  	_hcl$1.rgb = function() {
  	  return lab$1(this).rgb();
  	};
  
  	var A$1 = -0.14861;
  	var B$1 = +1.78277;
  	var C$1 = -0.29227;
  	var D$1 = -0.90649;
  	var E$1 = +1.97294;
  	var ED$1 = E$1 * D$1;
  	var EB$1 = E$1 * B$1;
  	var BC_DA$1 = B$1 * C$1 - D$1 * A$1;
  	function cubehelix$3(h, s, l) {
  	  if (arguments.length === 1) {
  	    if (h instanceof Cubehelix$1) {
  	      l = h.l;
  	      s = h.s;
  	      h = h.h;
  	    } else {
  	      if (!(h instanceof Rgb$1)) h = rgb$2(h);
  	      var r = h.r / 255, g = h.g / 255, b = h.b / 255;
  	      l = (BC_DA$1 * b + ED$1 * r - EB$1 * g) / (BC_DA$1 + ED$1 - EB$1);
  	      var bl = b - l, k = (E$1 * (g - l) - C$1 * bl) / D$1;
  	      s = Math.sqrt(k * k + bl * bl) / (E$1 * l * (1 - l)); // NaN if l=0 or l=1
  	      h = s ? Math.atan2(k, bl) * rad2deg$2 - 120 : NaN;
  	      if (h < 0) h += 360;
  	    }
  	  }
  	  return new Cubehelix$1(h, s, l);
  	}
  
  	function Cubehelix$1(h, s, l) {
  	  this.h = +h;
  	  this.s = +s;
  	  this.l = +l;
  	}
  
  	var _cubehelix$1 = cubehelix$3.prototype = Cubehelix$1.prototype = new Color$1;
  
  	_cubehelix$1.brighter = function(k) {
  	  k = k == null ? brighter$1 : Math.pow(brighter$1, k);
  	  return new Cubehelix$1(this.h, this.s, this.l * k);
  	};
  
  	_cubehelix$1.darker = function(k) {
  	  k = k == null ? darker$1 : Math.pow(darker$1, k);
  	  return new Cubehelix$1(this.h, this.s, this.l * k);
  	};
  
  	_cubehelix$1.rgb = function() {
  	  var h = isNaN(this.h) ? 0 : (this.h + 120) * deg2rad$1,
  	      l = +this.l,
  	      a = isNaN(this.s) ? 0 : this.s * l * (1 - l),
  	      cosh = Math.cos(h),
  	      sinh = Math.sin(h);
  	  return new Rgb$1(
  	    255 * (l + a * (A$1 * cosh + B$1 * sinh)),
  	    255 * (l + a * (C$1 * cosh + D$1 * sinh)),
  	    255 * (l + a * (E$1 * cosh))
  	  );
  	};
  
  	function cubehelix$2() {
  	  return linear()
  	      .interpolate(interpolateCubehelixLong)
  	      .range([cubehelix$3(300, 0.5, 0.0), cubehelix$3(-240, 0.5, 1.0)]);
  	}
  
  	function sequential(interpolate) {
  	  var x0 = 0,
  	      x1 = 1,
  	      clamp = false;
  
  	  function scale(x) {
  	    var t = (x - x0) / (x1 - x0);
  	    return interpolate(clamp ? Math.max(0, Math.min(1, t)) : t);
  	  }
  
  	  scale.domain = function(_) {
  	    return arguments.length ? (x0 = +_[0], x1 = +_[1], scale) : [x0, x1];
  	  };
  
  	  scale.clamp = function(_) {
  	    return arguments.length ? (clamp = !!_, scale) : clamp;
  	  };
  
  	  scale.copy = function() {
  	    return sequential(interpolate).domain([x0, x1]).clamp(clamp);
  	  };
  
  	  return linearish(scale);
  	}
  
  	var a = cubehelix$3(-100, 0.75, 0.35);
  	var b = cubehelix$3(80, 1.50, 0.8);
  	var c = cubehelix$3(260, 0.75, 0.35);
  	var d = cubehelix$3();
  	var interpolateWarm = interpolateCubehelixLong(a, b);
  	var interpolateCool = interpolateCubehelixLong(c, b);
  	function interpolateRainbow(t) {
  	  if (t < 0 || t > 1) t -= Math.floor(t);
  	  var ts = Math.abs(t - 0.5);
  	  d.h = 360 * t - 100;
  	  d.s = 1.5 - 1.5 * ts;
  	  d.l = 0.8 - 0.9 * ts;
  	  return d + "";
  	}
  
  	function warm() {
  	  return sequential(interpolateWarm);
  	}
  
  	function cool() {
  	  return sequential(interpolateCool);
  	}
  
  	function rainbow() {
  	  return sequential(interpolateRainbow);
  	}
  
  	var rangeViridis = colors("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725");
  	var rangeMagma = colors("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf");
  	var rangeInferno = colors("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4");
  	var rangePlasma = colors("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921");
  	function ramp(range) {
  	  var s = sequential(function(t) { return range[Math.round(t * range.length - t)]; }).clamp(true);
  	  delete s.clamp;
  	  return s;
  	}
  
  	function viridis() {
  	  return ramp(rangeViridis);
  	}
  
  	function magma() {
  	  return ramp(rangeMagma);
  	}
  
  	function inferno() {
  	  return ramp(rangeInferno);
  	}
  
  	function plasma() {
  	  return ramp(rangePlasma);
  	}
  
  	var namespaces = {
  	  svg: "http://www.w3.org/2000/svg",
  	  xhtml: "http://www.w3.org/1999/xhtml",
  	  xlink: "http://www.w3.org/1999/xlink",
  	  xml: "http://www.w3.org/XML/1998/namespace",
  	  xmlns: "http://www.w3.org/2000/xmlns/"
  	};
  
  	function namespace(name) {
  	  var prefix = name += "", i = prefix.indexOf(":");
  	  if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1);
  	  return namespaces.hasOwnProperty(prefix) ? {space: namespaces[prefix], local: name} : name;
  	}
  
  	function creatorInherit(name) {
  	  return function() {
  	    var document = this.ownerDocument,
  	        uri = this.namespaceURI;
  	    return uri && uri !== document.documentElement.namespaceURI
  	        ? document.createElementNS(uri, name)
  	        : document.createElement(name);
  	  };
  	}
  
  	function creatorFixed(fullname) {
  	  return function() {
  	    return this.ownerDocument.createElementNS(fullname.space, fullname.local);
  	  };
  	}
  
  	function creator(name) {
  	  var fullname = namespace(name);
  	  return (fullname.local
  	      ? creatorFixed
  	      : creatorInherit)(fullname);
  	}
  
  	var matcher = function(selector) {
  	  return function() {
  	    return this.matches(selector);
  	  };
  	};
  
  	if (typeof document !== "undefined") {
  	  var element = document.documentElement;
  	  if (!element.matches) {
  	    var vendorMatches = element.webkitMatchesSelector
  	        || element.msMatchesSelector
  	        || element.mozMatchesSelector
  	        || element.oMatchesSelector;
  	    matcher = function(selector) {
  	      return function() {
  	        return vendorMatches.call(this, selector);
  	      };
  	    };
  	  }
  	}
  
  	var matcher$1 = matcher;
  
  	var requoteRe$1 = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
  
  	function requote$1(string) {
  	  return string.replace(requoteRe$1, "\\$&");
  	}
  
  	function noop$2() {}
  
  	var filterEvents = {};
  
  	exports.event = null;
  
  	if (typeof document !== "undefined") {
  	  var element$1 = document.documentElement;
  	  if (!("onmouseenter" in element$1)) {
  	    filterEvents = {mouseenter: "mouseover", mouseleave: "mouseout"};
  	  }
  	}
  
  	function contextListener(listener, index, group) {
  	  return function(event1) {
  	    var event0 = exports.event; // Events can be reentrant (e.g., focus).
  	    exports.event = event1;
  	    try {
  	      listener.call(this, this.__data__, index, group);
  	    } finally {
  	      exports.event = event0;
  	    }
  	  };
  	}
  
  	function filterListener(listener) {
  	  return function(event) {
  	    var related = event.relatedTarget;
  	    if (!related || (related !== this && !(related.compareDocumentPosition(this) & 8))) {
  	      listener(event);
  	    }
  	  };
  	}
  
  	function onRemove(key, type) {
  	  return function() {
  	    var l = this[key];
  	    if (l) {
  	      this.removeEventListener(type, l, l._capture);
  	      delete this[key];
  	    }
  	  };
  	}
  
  	function onRemoveAll(dotname) {
  	  var re = new RegExp("^__on([^.]+)" + requote$1(dotname) + "$");
  	  return function() {
  	    for (var key in this) {
  	      var match = key.match(re);
  	      if (match) {
  	        var l = this[key];
  	        this.removeEventListener(match[1], l, l._capture);
  	        delete this[key];
  	      }
  	    }
  	  };
  	}
  
  	function onAdd(filter, key, type, listener, capture) {
  	  return function(d, i, group) {
  	    var value = this[key];
  	    if (value) this.removeEventListener(type, value, value._capture);
  	    value = contextListener(listener, i, group);
  	    if (filter) value = filterListener(value);
  	    value._listener = listener;
  	    this.addEventListener(type, this[key] = value, value._capture = capture);
  	  };
  	}
  
  	function selection_on(type, listener, capture) {
  	  var value,
  	      name = type + "",
  	      key = "__on" + name,
  	      filter;
  
  	  if (arguments.length < 2) return (value = this.node()[key]) && value._listener;
  	  if ((value = name.indexOf(".")) > 0) name = name.slice(0, value);
  	  if (filter = filterEvents.hasOwnProperty(name)) name = filterEvents[name];
  
  	  return this.each(listener
  	      ? (value ? onAdd(filter, key, name, listener, capture == null ? false : capture) : noop$2) // Attempt to add untyped listener is ignored.
  	      : (value ? onRemove(key, name) : onRemoveAll(name)));
  	}
  
  	function sourceEvent() {
  	  var current = exports.event, source;
  	  while (source = current.sourceEvent) current = source;
  	  return current;
  	}
  
  	function defaultView$1(node) {
  	  return node
  	      && ((node.ownerDocument && node.ownerDocument.defaultView) // node is a Node
  	          || (node.document && node) // node is a Window
  	          || node.defaultView); // node is a Document
  	}
  
  	function selector(selector) {
  	  return function() {
  	    return this.querySelector(selector);
  	  };
  	}
  
  	function selection_select(select) {
  	  if (typeof select !== "function") select = selector(select);
  
  	  for (var groups = this._groups, update = this._update, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
  	    for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
  	      if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) {
  	        if ("__data__" in node) subnode.__data__ = node.__data__;
  	        if (update) update._groups[j][i] = subnode;
  	        subgroup[i] = subnode;
  	      }
  	    }
  	  }
  
  	  return new Selection(subgroups, this._parents);
  	}
  
  	function selectorAll(selector) {
  	  return function() {
  	    return this.querySelectorAll(selector);
  	  };
  	}
  
  	function selection_selectAll(select) {
  	  if (typeof select !== "function") select = selectorAll(select);
  
  	  for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
  	    for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
  	      if (node = group[i]) {
  	        subgroups.push(select.call(node, node.__data__, i, group));
  	        parents.push(node);
  	      }
  	    }
  	  }
  
  	  return new Selection(subgroups, parents);
  	}
  
  	function selection_filter(match) {
  	  if (typeof match !== "function") match = matcher$1(match);
  
  	  for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
  	    for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
  	      if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
  	        subgroup.push(node);
  	      }
  	    }
  	  }
  
  	  return new Selection(subgroups, this._parents);
  	}
  
  	function arrayify(selection) {
  
  	  for (var groups = selection._groups, j = 0, m = groups.length; j < m; ++j) {
  	    if (!Array.isArray(group = groups[j])) {
  	      for (var n = group.length, array = groups[j] = new Array(n), group, i = 0; i < n; ++i) {
  	        array[i] = group[i];
  	      }
  	    }
  	  }
  
  	  return groups;
  	}
  
  	function constant$5(x) {
  	  return function() {
  	    return x;
  	  };
  	}
  
  	var keyPrefix = "$"; // Protect against keys like “__proto__”.
  
  	function bindIndex(parent, update, enter, exit, data) {
  	  var i = 0,
  	      node,
  	      nodeLength = update.length,
  	      dataLength = data.length,
  	      minLength = Math.min(nodeLength, dataLength);
  
  	  // Clear the enter and exit arrays, and then initialize to the new length.
  	  enter.length = 0, enter.length = dataLength;
  	  exit.length = 0, exit.length = nodeLength;
  
  	  for (; i < minLength; ++i) {
  	    if (node = update[i]) {
  	      node.__data__ = data[i];
  	    } else {
  	      enter[i] = new EnterNode(parent, data[i]);
  	    }
  	  }
  
  	  // Note: we don’t need to delete update[i] here because this loop only
  	  // runs when the data length is greater than the node length.
  	  for (; i < dataLength; ++i) {
  	    enter[i] = new EnterNode(parent, data[i]);
  	  }
  
  	  // Note: and, we don’t need to delete update[i] here because immediately
  	  // following this loop we set the update length to data length.
  	  for (; i < nodeLength; ++i) {
  	    if (node = update[i]) {
  	      exit[i] = update[i];
  	    }
  	  }
  
  	  update.length = dataLength;
  	}
  
  	function bindKey(parent, update, enter, exit, data, key) {
  	  var i,
  	      node,
  	      dataLength = data.length,
  	      nodeLength = update.length,
  	      nodeByKeyValue = {},
  	      keyValues = new Array(nodeLength),
  	      keyValue;
  
  	  // Clear the enter and exit arrays, and then initialize to the new length.
  	  enter.length = 0, enter.length = dataLength;
  	  exit.length = 0, exit.length = nodeLength;
  
  	  // Compute the keys for each node.
  	  for (i = 0; i < nodeLength; ++i) {
  	    if (node = update[i]) {
  	      keyValues[i] = keyValue = keyPrefix + key.call(node, node.__data__, i, update);
  
  	      // Is this a duplicate of a key we’ve previously seen?
  	      // If so, this node is moved to the exit selection.
  	      if (nodeByKeyValue[keyValue]) {
  	        exit[i] = node;
  	      }
  
  	      // Otherwise, record the mapping from key to node.
  	      else {
  	        nodeByKeyValue[keyValue] = node;
  	      }
  	    }
  	  }
  
  	  // Now clear the update array and initialize to the new length.
  	  update.length = 0, update.length = dataLength;
  
  	  // Compute the keys for each datum.
  	  for (i = 0; i < dataLength; ++i) {
  	    keyValue = keyPrefix + key.call(parent, data[i], i, data);
  
  	    // Is there a node associated with this key?
  	    // If not, this datum is added to the enter selection.
  	    if (!(node = nodeByKeyValue[keyValue])) {
  	      enter[i] = new EnterNode(parent, data[i]);
  	    }
  
  	    // Did we already bind a node using this key? (Or is a duplicate?)
  	    // If unique, the node and datum are joined in the update selection.
  	    // Otherwise, the datum is ignored, neither entering nor exiting.
  	    else if (node !== true) {
  	      update[i] = node;
  	      node.__data__ = data[i];
  	    }
  
  	    // Record that we consumed this key, either to enter or update.
  	    nodeByKeyValue[keyValue] = true;
  	  }
  
  	  // Take any remaining nodes that were not bound to data,
  	  // and place them in the exit selection.
  	  for (i = 0; i < nodeLength; ++i) {
  	    if ((node = nodeByKeyValue[keyValues[i]]) !== true) {
  	      exit[i] = node;
  	    }
  	  }
  	}
  
  	function selection_data(value, key) {
  	  if (!value) {
  	    var data = new Array(this.size()), i = -1;
  	    this.each(function(d) { data[++i] = d; });
  	    return data;
  	  }
  
  	  var bind = key ? bindKey : bindIndex,
  	      parents = this._parents,
  	      update = arrayify(this),
  	      enter = (this._enter = this.enter())._groups,
  	      exit = (this._exit = this.exit())._groups;
  
  	  if (typeof value !== "function") value = constant$5(value);
  
  	  for (var m = update.length, j = 0; j < m; ++j) {
  	    var group = update[j],
  	        parent = parents[j];
  
  	    bind(parent, group, enter[j], exit[j], value.call(parent, parent && parent.__data__, j, parents), key);
  
  	    // Now connect the enter nodes to their following update node, such that
  	    // appendChild can insert the materialized enter node before this node,
  	    // rather than at the end of the parent node.
  	    for (var n = group.length, i0 = 0, i1 = 0, previous, next; i0 < n; ++i0) {
  	      if (previous = enter[j][i0]) {
  	        if (i0 >= i1) i1 = i0 + 1;
  	        while (!(next = group[i1]) && ++i1 < n);
  	        previous._next = next || null;
  	      }
  	    }
  	  }
  
  	  return this;
  	}
  
  	function EnterNode(parent, datum) {
  	  this.ownerDocument = parent.ownerDocument;
  	  this.namespaceURI = parent.namespaceURI;
  	  this._next = null;
  	  this._parent = parent;
  	  this.__data__ = datum;
  	}
  
  	EnterNode.prototype = {
  	  appendChild: function(child) { return this._parent.insertBefore(child, this._next); },
  	  insertBefore: function(child, next) { return this._parent.insertBefore(child, next); },
  	  querySelector: function(selector) { return this._parent.querySelector(selector); },
  	  querySelectorAll: function(selector) { return this._parent.querySelectorAll(selector); }
  	};
  
  	function sparse(update) {
  	  return new Array(update.length);
  	}
  
  	function selection_enter() {
  	  var enter = this._enter;
  	  if (enter) return this._enter = null, enter;
  	  enter = new Selection(this._groups.map(sparse), this._parents);
  	  enter._update = this;
  	  return enter;
  	}
  
  	function selection_exit() {
  	  var exit = this._exit;
  	  if (exit) return this._exit = null, exit;
  	  return new Selection(this._groups.map(sparse), this._parents);
  	}
  
  	function selection_order() {
  
  	  for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) {
  	    for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) {
  	      if (node = group[i]) {
  	        if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
  	        next = node;
  	      }
  	    }
  	  }
  
  	  return this;
  	}
  
  	function selection_sort(compare) {
  	  if (!compare) compare = ascending$2;
  
  	  function compareNode(a, b) {
  	    return a && b ? compare(a.__data__, b.__data__) : !a - !b;
  	  }
  
  	  for (var groups = arrayify(this), j = 0, m = groups.length; j < m; ++j) {
  	    groups[j].sort(compareNode);
  	  }
  
  	  return this.order();
  	}
  
  	function ascending$2(a, b) {
  	  return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
  	}
  
  	function selection_call() {
  	  var callback = arguments[0];
  	  arguments[0] = this;
  	  callback.apply(null, arguments);
  	  return this;
  	}
  
  	function selection_nodes() {
  	  var nodes = new Array(this.size()), i = -1;
  	  this.each(function() { nodes[++i] = this; });
  	  return nodes;
  	}
  
  	function selection_node() {
  
  	  for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
  	    for (var group = groups[j], i = 0, n = group.length; i < n; ++i) {
  	      var node = group[i];
  	      if (node) return node;
  	    }
  	  }
  
  	  return null;
  	}
  
  	function selection_size() {
  	  var size = 0;
  	  this.each(function() { ++size; });
  	  return size;
  	}
  
  	function selection_empty() {
  	  return !this.node();
  	}
  
  	function selection_each(callback) {
  
  	  for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
  	    for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) {
  	      if (node = group[i]) callback.call(node, node.__data__, i, group);
  	    }
  	  }
  
  	  return this;
  	}
  
  	function attrRemove(name) {
  	  return function() {
  	    this.removeAttribute(name);
  	  };
  	}
  
  	function attrRemoveNS(fullname) {
  	  return function() {
  	    this.removeAttributeNS(fullname.space, fullname.local);
  	  };
  	}
  
  	function attrConstant(name, value) {
  	  return function() {
  	    this.setAttribute(name, value);
  	  };
  	}
  
  	function attrConstantNS(fullname, value) {
  	  return function() {
  	    this.setAttributeNS(fullname.space, fullname.local, value);
  	  };
  	}
  
  	function attrFunction(name, value) {
  	  return function() {
  	    var v = value.apply(this, arguments);
  	    if (v == null) this.removeAttribute(name);
  	    else this.setAttribute(name, v);
  	  };
  	}
  
  	function attrFunctionNS(fullname, value) {
  	  return function() {
  	    var v = value.apply(this, arguments);
  	    if (v == null) this.removeAttributeNS(fullname.space, fullname.local);
  	    else this.setAttributeNS(fullname.space, fullname.local, v);
  	  };
  	}
  
  	function selection_attr(name, value) {
  	  var fullname = namespace(name);
  
  	  if (arguments.length < 2) {
  	    var node = this.node();
  	    return fullname.local
  	        ? node.getAttributeNS(fullname.space, fullname.local)
  	        : node.getAttribute(fullname);
  	  }
  
  	  return this.each((value == null
  	      ? (fullname.local ? attrRemoveNS : attrRemove) : (typeof value === "function"
  	      ? (fullname.local ? attrFunctionNS : attrFunction)
  	      : (fullname.local ? attrConstantNS : attrConstant)))(fullname, value));
  	}
  
  	function styleRemove(name) {
  	  return function() {
  	    this.style.removeProperty(name);
  	  };
  	}
  
  	function styleConstant(name, value, priority) {
  	  return function() {
  	    this.style.setProperty(name, value, priority);
  	  };
  	}
  
  	function styleFunction(name, value, priority) {
  	  return function() {
  	    var v = value.apply(this, arguments);
  	    if (v == null) this.style.removeProperty(name);
  	    else this.style.setProperty(name, v, priority);
  	  };
  	}
  
  	function selection_style(name, value, priority) {
  	  var node;
  	  return arguments.length > 1
  	      ? this.each((value == null
  	            ? styleRemove : typeof value === "function"
  	            ? styleFunction
  	            : styleConstant)(name, value, priority == null ? "" : priority))
  	      : defaultView$1(node = this.node())
  	          .getComputedStyle(node, null)
  	          .getPropertyValue(name);
  	}
  
  	function propertyRemove(name) {
  	  return function() {
  	    delete this[name];
  	  };
  	}
  
  	function propertyConstant(name, value) {
  	  return function() {
  	    this[name] = value;
  	  };
  	}
  
  	function propertyFunction(name, value) {
  	  return function() {
  	    var v = value.apply(this, arguments);
  	    if (v == null) delete this[name];
  	    else this[name] = v;
  	  };
  	}
  
  	function selection_property(name, value) {
  	  return arguments.length > 1
  	      ? this.each((value == null
  	          ? propertyRemove : typeof value === "function"
  	          ? propertyFunction
  	          : propertyConstant)(name, value))
  	      : this.node()[name];
  	}
  
  	function classArray(string) {
  	  return string.trim().split(/^|\s+/);
  	}
  
  	function classList(node) {
  	  return node.classList || new ClassList(node);
  	}
  
  	function ClassList(node) {
  	  this._node = node;
  	  this._names = classArray(node.getAttribute("class") || "");
  	}
  
  	ClassList.prototype = {
  	  add: function(name) {
  	    var i = this._names.indexOf(name);
  	    if (i < 0) {
  	      this._names.push(name);
  	      this._node.setAttribute("class", this._names.join(" "));
  	    }
  	  },
  	  remove: function(name) {
  	    var i = this._names.indexOf(name);
  	    if (i >= 0) {
  	      this._names.splice(i, 1);
  	      this._node.setAttribute("class", this._names.join(" "));
  	    }
  	  },
  	  contains: function(name) {
  	    return this._names.indexOf(name) >= 0;
  	  }
  	};
  
  	function classedAdd(node, names) {
  	  var list = classList(node), i = -1, n = names.length;
  	  while (++i < n) list.add(names[i]);
  	}
  
  	function classedRemove(node, names) {
  	  var list = classList(node), i = -1, n = names.length;
  	  while (++i < n) list.remove(names[i]);
  	}
  
  	function classedTrue(names) {
  	  return function() {
  	    classedAdd(this, names);
  	  };
  	}
  
  	function classedFalse(names) {
  	  return function() {
  	    classedRemove(this, names);
  	  };
  	}
  
  	function classedFunction(names, value) {
  	  return function() {
  	    (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names);
  	  };
  	}
  
  	function selection_classed(name, value) {
  	  var names = classArray(name + "");
  
  	  if (arguments.length < 2) {
  	    var list = classList(this.node()), i = -1, n = names.length;
  	    while (++i < n) if (!list.contains(names[i])) return false;
  	    return true;
  	  }
  
  	  return this.each((typeof value === "function"
  	      ? classedFunction : value
  	      ? classedTrue
  	      : classedFalse)(names, value));
  	}
  
  	function textRemove() {
  	  this.textContent = "";
  	}
  
  	function textConstant(value) {
  	  return function() {
  	    this.textContent = value;
  	  };
  	}
  
  	function textFunction(value) {
  	  return function() {
  	    var v = value.apply(this, arguments);
  	    this.textContent = v == null ? "" : v;
  	  };
  	}
  
  	function selection_text(value) {
  	  return arguments.length
  	      ? this.each(value == null
  	          ? textRemove : (typeof value === "function"
  	          ? textFunction
  	          : textConstant)(value))
  	      : this.node().textContent;
  	}
  
  	function htmlRemove() {
  	  this.innerHTML = "";
  	}
  
  	function htmlConstant(value) {
  	  return function() {
  	    this.innerHTML = value;
  	  };
  	}
  
  	function htmlFunction(value) {
  	  return function() {
  	    var v = value.apply(this, arguments);
  	    this.innerHTML = v == null ? "" : v;
  	  };
  	}
  
  	function selection_html(value) {
  	  return arguments.length
  	      ? this.each(value == null
  	          ? htmlRemove : (typeof value === "function"
  	          ? htmlFunction
  	          : htmlConstant)(value))
  	      : this.node().innerHTML;
  	}
  
  	function raise$1() {
  	  this.parentNode.appendChild(this);
  	}
  
  	function selection_raise() {
  	  return this.each(raise$1);
  	}
  
  	function lower() {
  	  this.parentNode.insertBefore(this, this.parentNode.firstChild);
  	}
  
  	function selection_lower() {
  	  return this.each(lower);
  	}
  
  	function append(create) {
  	  return function() {
  	    return this.appendChild(create.apply(this, arguments));
  	  };
  	}
  
  	function insert(create, select) {
  	  return function() {
  	    return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null);
  	  };
  	}
  
  	function constantNull() {
  	  return null;
  	}
  
  	function selection_append(name, before) {
  	  var create = typeof name === "function" ? name : creator(name);
  	  return this.select(arguments.length < 2
  	      ? append(create)
  	      : insert(create, before == null
  	          ? constantNull : typeof before === "function"
  	          ? before
  	          : selector(before)));
  	}
  
  	function remove() {
  	  var parent = this.parentNode;
  	  if (parent) parent.removeChild(this);
  	}
  
  	function selection_remove() {
  	  return this.each(remove);
  	}
  
  	function selection_datum(value) {
  	  return arguments.length
  	      ? this.property("__data__", value)
  	      : this.node().__data__;
  	}
  
  	function dispatchEvent(node, type, params) {
  	  var window = defaultView$1(node),
  	      event = window.CustomEvent;
  
  	  if (event) {
  	    event = new event(type, params);
  	  } else {
  	    event = window.document.createEvent("Event");
  	    if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail;
  	    else event.initEvent(type, false, false);
  	  }
  
  	  node.dispatchEvent(event);
  	}
  
  	function dispatchConstant(type, params) {
  	  return function() {
  	    return dispatchEvent(this, type, params);
  	  };
  	}
  
  	function dispatchFunction(type, params) {
  	  return function() {
  	    return dispatchEvent(this, type, params.apply(this, arguments));
  	  };
  	}
  
  	function selection_dispatch(type, params) {
  	  return this.each((typeof params === "function"
  	      ? dispatchFunction
  	      : dispatchConstant)(type, params));
  	}
  
  	var root = [null];
  
  	function Selection(groups, parents) {
  	  this._groups = groups;
  	  this._parents = parents;
  	}
  
  	function selection() {
  	  return new Selection([[document.documentElement]], root);
  	}
  
  	Selection.prototype = selection.prototype = {
  	  select: selection_select,
  	  selectAll: selection_selectAll,
  	  filter: selection_filter,
  	  data: selection_data,
  	  enter: selection_enter,
  	  exit: selection_exit,
  	  order: selection_order,
  	  sort: selection_sort,
  	  call: selection_call,
  	  nodes: selection_nodes,
  	  node: selection_node,
  	  size: selection_size,
  	  empty: selection_empty,
  	  each: selection_each,
  	  attr: selection_attr,
  	  style: selection_style,
  	  property: selection_property,
  	  classed: selection_classed,
  	  text: selection_text,
  	  html: selection_html,
  	  raise: selection_raise,
  	  lower: selection_lower,
  	  append: selection_append,
  	  remove: selection_remove,
  	  datum: selection_datum,
  	  on: selection_on,
  	  dispatch: selection_dispatch
  	};
  
  	function select(selector) {
  	  return typeof selector === "string"
  	      ? new Selection([[document.querySelector(selector)]], [document.documentElement])
  	      : new Selection([[selector]], root);
  	}
  
  	var bug44083 = typeof navigator !== "undefined" && /WebKit/.test(navigator.userAgent) ? -1 : 0; // https://bugs.webkit.org/show_bug.cgi?id=44083
  
  	function point$5(node, event) {
  	  var svg = node.ownerSVGElement || node;
  
  	  if (svg.createSVGPoint) {
  	    var point = svg.createSVGPoint();
  
  	    if (bug44083 < 0) {
  	      var window = defaultView$1(node);
  	      if (window.scrollX || window.scrollY) {
  	        svg = select(window.document.body).append("svg").style({position: "absolute", top: 0, left: 0, margin: 0, padding: 0, border: "none"}, "important");
  	        var ctm = svg.node().getScreenCTM();
  	        bug44083 = !(ctm.f || ctm.e);
  	        svg.remove();
  	      }
  	    }
  
  	    if (bug44083) point.x = event.pageX, point.y = event.pageY;
  	    else point.x = event.clientX, point.y = event.clientY;
  
  	    point = point.matrixTransform(node.getScreenCTM().inverse());
  	    return [point.x, point.y];
  	  }
  
  	  var rect = node.getBoundingClientRect();
  	  return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop];
  	}
  
  	function mouse(node, event) {
  	  if (event == null) event = sourceEvent();
  	  if (event.changedTouches) event = event.changedTouches[0];
  	  return point$5(node, event);
  	}
  
  	function selectAll(selector) {
  	  return typeof selector === "string"
  	      ? new Selection([document.querySelectorAll(selector)], [document.documentElement])
  	      : new Selection([selector], root);
  	}
  
  	function touch(node, touches, identifier) {
  	  if (arguments.length < 3) identifier = touches, touches = sourceEvent().changedTouches;
  
  	  for (var i = 0, n = touches ? touches.length : 0, touch; i < n; ++i) {
  	    if ((touch = touches[i]).identifier === identifier) {
  	      return point$5(node, touch);
  	    }
  	  }
  
  	  return null;
  	}
  
  	function touches(node, touches) {
  	  if (touches == null) touches = sourceEvent().touches;
  
  	  for (var i = 0, n = touches ? touches.length : 0, points = new Array(n); i < n; ++i) {
  	    points[i] = point$5(node, touches[i]);
  	  }
  
  	  return points;
  	}
  
  	function selection_interrupt(/* TODO name */) {
  	  return this.each(function() {
  	    // TODO
  	  });
  	}
  
  	// TODO transform interpolation
  
  	function attrRemove$1(name) {
  	  return function() {
  	    this.removeAttribute(name);
  	  };
  	}
  
  	function attrRemoveNS$1(fullname) {
  	  return function() {
  	    this.removeAttributeNS(fullname.space, fullname.local);
  	  };
  	}
  
  	function attrConstant$1(name, value1) {
  	  return value1 += "", function() {
  	    var node = this, value0 = node.getAttribute(name), i;
  	    return value0 !== value1 && (i = interpolate(value0, value1), function(t) {
  	      node.setAttribute(name, i(t));
  	    });
  	  };
  	}
  
  	function attrConstantNS$1(fullname, value1) {
  	  return value1 += "", function() {
  	    var node = this, value0 = node.getAttributeNS(fullname.space, fullname.local), i;
  	    return value0 !== value1 && (i = interpolate(value0, value1), function(t) {
  	      node.setAttributeNS(fullname.space, fullname.local, i(t));
  	    });
  	  };
  	}
  
  	function attrFunction$1(name, value) {
  	  return function() {
  	    var node = this, value0, value1 = value.apply(node, arguments), i;
  	    if (value1 == null) return node.removeAttribute(name);
  	    value0 = node.getAttribute(name), value1 += "";
  	    return value0 !== value1 && (i = interpolate(value0, value1), function(t) {
  	      node.setAttribute(name, i(t));
  	    });
  	  };
  	}
  
  	function attrFunctionNS$1(fullname, value) {
  	  return function() {
  	    var node = this, value0, value1 = value.apply(node, arguments), i;
  	    if (value1 == null) return node.removeAttributeNS(fullname.space, fullname.local);
  	    value0 = node.getAttributeNS(fullname.space, fullname.local), value1 += "";
  	    return value0 !== value1 && (i = interpolate(value0, value1), function(t) {
  	      node.setAttributeNS(fullname.space, fullname.local, i(t));
  	    });
  	  };
  	}
  
  	function transition_attr(name, value) {
  	  if (arguments.length < 2) return this.tween("attr." + name);
  	  var fullname = namespace(name);
  	  return this.tween("attr." + name, (value == null
  	      ? (fullname.local ? attrRemoveNS$1 : attrRemove$1) : (typeof value === "function"
  	      ? (fullname.local ? attrFunctionNS$1 : attrFunction$1)
  	      : (fullname.local ? attrConstantNS$1 : attrConstant$1)))(fullname, value));
  	}
  
  	function initializeScheduleEntry(node, key, id, index, group, timing) {
  	  var schedule = node[key];
  	  if (!schedule) node[key] = schedule = {active: null, pending: []};
  	  else if (getScheduleEntry(node, key, id)) return;
  	  addScheduleEntry(node, key, {
  	    id: id,
  	    index: index, // For restoring context during callbacks.
  	    group: group, // For restoring context during callbacks.
  	    tweens: [],
  	    time: timing.time,
  	    delay: timing.delay,
  	    duration: timing.duration,
  	    ease: timing.ease,
  	    timer: null
  	  });
  	}
  
  	function getScheduleEntry(node, key, id) {
  	  var schedule = node[key], entry = schedule.active;
  	  if (entry && entry.id === id) return entry;
  	  var pending = schedule.pending, i = pending.length;
  	  while (--i >= 0) if ((entry = pending[i]).id === id) return entry;
  	}
  
  	function addScheduleEntry(node, key, entry) {
  	  var schedule = node[key];
  
  	  // Initialize the entry timer when the transition is created. The delay is not
  	  // known until the first callback! If the delay is greater than this first
  	  // sleep, sleep again; otherwise, start immediately.
  	  schedule.pending.push(entry);
  	  entry.timer = timer(function(elapsed, now) {
  	    if (entry.delay <= elapsed) start(elapsed - entry.delay, now);
  	    else entry.timer.restart(start, entry.delay, entry.time);
  	  }, 0, entry.time);
  
  	  function start(elapsed, now) {
  	    var pending = schedule.pending,
  	        tweens = entry.tweens,
  	        i, j, n, o;
  
  	    // Interrupt the active transition, if any.
  	    // TODO Dispatch the interrupt event (within try-catch).
  	    if (schedule.active) {
  	      schedule.active.timer.stop();
  	    }
  
  	    // Cancel any pre-empted transitions. No interrupt event is dispatched
  	    // because the cancelled transitions never started. Note that this also
  	    // removes this transition from the pending list!
  	    // TODO Would a map or linked list be more efficient here?
  	    for (i = 0, j = -1, n = pending.length; i < n; ++i) {
  	      o = pending[i];
  	      if (o.id < entry.id) o.timer.stop();
  	      else if (o.id > entry.id) pending[++j] = o;
  	    }
  	    pending.length = j + 1;
  
  	    // Mark this transition as active.
  	    schedule.active = entry;
  
  	    // Defer the first tick to end of the current frame; see mbostock/d3#1576.
  	    // Note the transition may be canceled after start and before the first tick!
  	    // Note this must be scheduled before the start event; see d3/d3-transition#16!
  	    // Assuming this is successful, subsequent callbacks go straight to tick.
  	    timerOnce(function() {
  	      if (schedule.active === entry) {
  	        entry.timer.restart(tick, entry.delay, entry.time);
  	        tick(elapsed);
  	      }
  	    }, 0, now);
  
  	    // TODO Dispatch the start event (within try-catch).
  	    // Note this must be done before the tweens are initialized.
  
  	    // Initialize the tweens, deleting null tweens.
  	    for (i = 0, j = -1, n = tweens.length; i < n; ++i) {
  	      if (o = tweens[i].value.call(node, node.__data__, entry.index, entry.group)) {
  	        tweens[++j] = o;
  	      }
  	    }
  	    tweens.length = j + 1;
  	  }
  
  	  function tween(t) {
  	    for (var tweens = entry.tweens, i = 0, n = tweens.length; i < n; ++i) {
  	      tweens[i].call(node, t); // TODO tween could throw
  	    }
  	  }
  
  	  // TODO Dispatch the end event (within try-catch).
  	  function tick(elapsed) {
  	    if (elapsed >= entry.duration) { // TODO capture duration to ensure immutability?
  	      tween(1);
  	      schedule.active = null;
  	      if (!schedule.pending.length) delete node[key];
  	      entry.timer.stop();
  	    } else {
  	      tween(entry.ease.ease(elapsed / entry.duration)); // TODO ease could throw
  	    }
  	  }
  	}
  
  	function delayFunction(key, id, value) {
  	  return function() {
  	    getScheduleEntry(this, key, id).delay = +value.apply(this, arguments);
  	  };
  	}
  
  	function delayConstant(key, id, value) {
  	  return value = +value, function() {
  	    getScheduleEntry(this, key, id).delay = value;
  	  };
  	}
  
  	function transition_delay(value) {
  	  var id = this._id,
  	      key = this._key;
  
  	  return arguments.length
  	      ? this.each((typeof value === "function"
  	          ? delayFunction
  	          : delayConstant)(key, id, value))
  	      : getScheduleEntry(this.node(), key, id).delay;
  	}
  
  	function durationFunction(key, id, value) {
  	  return function() {
  	    getScheduleEntry(this, key, id).duration = +value.apply(this, arguments);
  	  };
  	}
  
  	function durationConstant(key, id, value) {
  	  return value = +value, function() {
  	    getScheduleEntry(this, key, id).duration = value;
  	  };
  	}
  
  	function transition_duration(value) {
  	  var id = this._id,
  	      key = this._key;
  
  	  return arguments.length
  	      ? this.each((typeof value === "function"
  	          ? durationFunction
  	          : durationConstant)(key, id, value))
  	      : getScheduleEntry(this.node(), key, id).duration;
  	}
  
  	function easeFunction(key, id, value) {
  	  return function() {
  	    getScheduleEntry(this, key, id).ease = value.apply(this, arguments);
  	  };
  	}
  
  	function easeConstant(key, id, value) {
  	  return function() {
  	    getScheduleEntry(this, key, id).ease = value;
  	  };
  	}
  
  	function transition_ease(value) {
  	  var id = this._id,
  	      key = this._key;
  
  	  return arguments.length
  	      ? this.each((typeof value === "function"
  	          ? easeFunction
  	          : easeConstant)(key, id, value))
  	      : getScheduleEntry(this.node(), key, id).ease;
  	}
  
  	function transition_filter(match) {
  	  if (typeof match !== "function") match = matcher$1(match);
  
  	  for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
  	    for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
  	      if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
  	        subgroup.push(node);
  	      }
  	    }
  	  }
  
  	  return new Transition(subgroups, this._parents, this._key, this._id);
  	}
  
  	function transition_select(select) {
  	  var id = this._id,
  	      key = this._key;
  
  	  if (typeof select !== "function") select = selector(select);
  
  	  for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
  	    for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
  	      if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) {
  	        if ("__data__" in node) subnode.__data__ = node.__data__;
  	        subgroup[i] = subnode;
  	        initializeScheduleEntry(subgroup[i], key, id, i, subgroup, getScheduleEntry(node, key, id));
  	      }
  	    }
  	  }
  
  	  return new Transition(subgroups, this._parents, key, id);
  	}
  
  	function transition_selectAll(select) {
  	  var id = this._id,
  	      key = this._key;
  
  	  if (typeof select !== "function") select = selectorAll(select);
  
  	  for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
  	    for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
  	      if (node = group[i]) {
  	        for (var children = select.call(node, node.__data__, i, group), child, timing = getScheduleEntry(node, key, id), k = 0, l = children.length; k < l; ++k) {
  	          if (child = children[k]) {
  	            initializeScheduleEntry(child, key, id, k, children, timing);
  	          }
  	        }
  	        subgroups.push(children);
  	        parents.push(node);
  	      }
  	    }
  	  }
  
  	  return new Transition(groups, parents, key, id);
  	}
  
  	// TODO export from d3-selection
  	function defaultView(node) {
  	  return node
  	      && ((node.ownerDocument && node.ownerDocument.defaultView) // node is a Node
  	          || (node.document && node) // node is a Window
  	          || node.defaultView); // node is a Document
  	}
  
  	function styleRemove$1(name, value, priority) {
  	  return function() {
  	    var node = this, style = defaultView(node).getComputedStyle(node, null), value0 = style.getPropertyValue(name), value1 = (node.style.removeProperty(name), style.getPropertyValue(name)), i;
  	    return value0 !== value1 && (i = interpolate(value0, value1), function(t) {
  	      if (t === 1) node.style.removeProperty(name);
  	      else node.style.setProperty(name, i(t), priority);
  	    });
  	  };
  	}
  
  	function styleConstant$1(name, value1, priority) {
  	  return value1 += "", function() {
  	    var node = this, value0 = defaultView(node).getComputedStyle(node, null).getPropertyValue(name), i;
  	    return value0 !== value1 && (i = interpolate(value0, value1), function(t) {
  	      node.style.setProperty(name, i(t), priority);
  	    });
  	  };
  	}
  
  	function styleFunction$1(name, value, priority) {
  	  return function() {
  	    var node = this, value0, value1 = value.apply(node, arguments), i;
  	    if (value1 == null) return node.style.removeProperty(name);
  	    value0 = defaultView(node).getComputedStyle(node, null).getPropertyValue(name), value1 += "";
  	    return value0 !== value1 && (i = interpolate(value0, value1), function(t) {
  	      node.style.setProperty(name, i(t), priority);
  	    });
  	  };
  	}
  
  	function transition_style(name, value, priority) {
  	  return arguments.length < 2
  	      ? this.tween("style." + name)
  	      : this.tween("style." + name, (value == null
  	          ? styleRemove$1 : (typeof value === "function"
  	          ? styleFunction$1
  	          : styleConstant$1))(name, value, priority == null ? "" : priority));
  	}
  
  	function tweenFunction(key, id, name, value) {
  	  return function() {
  	    var tweens = getScheduleEntry(this, key, id).tweens;
  
  	    for (var i = 0, n = tweens.length, t; i < n; ++i) {
  	      if ((t = tweens[i]).name === name) {
  	        return t.value = value;
  	      }
  	    }
  
  	    tweens.push({name: name, value: value});
  	  };
  	}
  
  	function transition_tween(name, value) {
  	  var sname = name + "";
  
  	  if (arguments.length < 2) {
  	    var tweens = getScheduleEntry(this.node(), this._key, this._id).tweens;
  	    for (var i = 0, n = tweens.length, t; i < n; ++i) {
  	      if ((t = tweens[i]).name === sname) {
  	        return t;
  	      }
  	    }
  	    return null;
  	  }
  
  	  return this.each(tweenFunction(this._key, this._id, sname, value));
  	}
  
  	var root$1 = [null];
  
  	function Transition(groups, parents, key, id) {
  	  this._groups = groups;
  	  this._parents = parents;
  	  this._key = key;
  	  this._id = id;
  	}
  
  	function transition(name) {
  	  return new Transition([[document.documentElement]], root$1, namekey(name));
  	}
  
  	function namekey(name) {
  	  return name ? "__transition_" + name + "__" : "__transition__";
  	}
  
  	var selection_prototype = selection.prototype;
  
  	Transition.prototype = transition.prototype = {
  	  select: transition_select,
  	  selectAll: transition_selectAll,
  	  filter: transition_filter,
  	  // TODO transition
  	  call: selection_prototype.call,
  	  nodes: selection_prototype.nodes,
  	  node: selection_prototype.node,
  	  size: selection_prototype.size,
  	  empty: selection_prototype.empty,
  	  each: selection_prototype.each,
  	  // TODO each("event"), or on("event")?
  	  attr: transition_attr,
  	  // TODO attrTween
  	  style: transition_style,
  	  // TODO styleTween
  	  // TODO text
  	  // TODO remove
  	  tween: transition_tween,
  	  delay: transition_delay,
  	  duration: transition_duration,
  	  ease: transition_ease
  	};
  
  	var nextId = 0;
  
  	function selection_transition(name) {
  	  var id = ++nextId,
  	      key = namekey(name),
  	      timing = {time: Date.now(), delay: 0, duration: 250, ease: easeCubicInOut};
  
  	  for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
  	    for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, i = 0; i < n; ++i) {
  	      if (node = group[i]) {
  	        initializeScheduleEntry(subgroup[i] = node, key, id, i, subgroup, timing);
  	      }
  	    }
  	  }
  
  	  return new Transition(subgroups, this._parents, key, id);
  	}
  
  	selection.prototype.interrupt = selection_interrupt;
  	selection.prototype.transition = selection_transition;
  
  	var slice$3 = Array.prototype.slice;
  
  	function identity$5(x) {
  	  return x;
  	}
  
  	var top = {};
  	var right = {};
  	var bottom = {};
  	var left = {};
  	function translateX(scale) {
  	  return function(d) {
  	    return "translate(" + scale(d) + ",0)";
  	  };
  	}
  
  	function translateY(scale) {
  	  return function(d) {
  	    return "translate(0," + scale(d) + ")";
  	  };
  	}
  
  	function center(scale) {
  	  var width = scale.bandwidth() / 2;
  	  return function(d) {
  	    return scale(d) + width;
  	  };
  	}
  
  	function pathUpdate(path) {
  	  path.enter().append("path").attr("class", "domain");
  	}
  
  	function tickUpdate(tick) {
  	  tick.exit().remove();
  	  var tickEnter = tick.enter().append("g", ".domain").attr("class", "tick");
  	  tickEnter.append("line");
  	  tickEnter.append("text");
  	  tick.order();
  	}
  
  	function axis(orient, scale) {
  	  var tickArguments = [],
  	      tickValues = null,
  	      tickFormat = null,
  	      tickSizeInner = 6,
  	      tickSizeOuter = 6,
  	      tickPadding = 3;
  
  	  function axis(g) {
  	    var values = tickValues == null ? (scale.ticks ? scale.ticks.apply(scale, tickArguments) : scale.domain()) : tickValues,
  	        format = tickFormat == null ? (scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments) : identity$5) : tickFormat,
  	        spacing = Math.max(tickSizeInner, 0) + tickPadding,
  	        position = scale.bandwidth ? center(scale) : scale,
  	        range = scale.range();
  
  	    g.each(function() {
  	      var g = select(this),
  	          path = g.selectAll(".domain").data([null]).call(pathUpdate),
  	          tick = g.selectAll(".tick").data(values, scale).call(tickUpdate),
  	          line = tick.select("line"),
  	          text = tick.select("text").text(format);
  
  	      switch (orient) {
  	        case top: {
  	          path.attr("d", "M" + range[0] + "," + -tickSizeOuter + "V0H" + range[1] + "V" + -tickSizeOuter);
  	          tick.attr("transform", translateX(position));
  	          line.attr("x2", 0).attr("y2", -tickSizeInner);
  	          text.attr("x", 0).attr("y", -spacing).attr("dy", "0em").style("text-anchor", "middle");
  	          break;
  	        }
  	        case right: {
  	          path.attr("d", "M" + tickSizeOuter + "," + range[0] + "H0V" + range[1] + "H" + tickSizeOuter);
  	          tick.attr("transform", translateY(position));
  	          line.attr("y2", 0).attr("x2", tickSizeInner);
  	          text.attr("y", 0).attr("x", spacing).attr("dy", ".32em").style("text-anchor", "start");
  	          break;
  	        }
  	        case bottom: {
  	          path.attr("d", "M" + range[0] + "," + tickSizeOuter + "V0H" + range[1] + "V" + tickSizeOuter);
  	          tick.attr("transform", translateX(position));
  	          line.attr("x2", 0).attr("y2", tickSizeInner);
  	          text.attr("x", 0).attr("y", spacing).attr("dy", ".71em").style("text-anchor", "middle");
  	          break;
  	        }
  	        case left: {
  	          path.attr("d", "M" + -tickSizeOuter + "," + range[0] + "H0V" + range[1] + "H" + -tickSizeOuter);
  	          tick.attr("transform", translateY(position));
  	          line.attr("y2", 0).attr("x2", -tickSizeInner);
  	          text.attr("y", 0).attr("x", -spacing).attr("dy", ".32em").style("text-anchor", "end");
  	          break;
  	        }
  	      }
  	    });
  	  }
  
  	  axis.scale = function(_) {
  	    return arguments.length ? (scale = _, axis) : scale;
  	  };
  
  	  axis.ticks = function() {
  	    return tickArguments = slice$3.call(arguments), axis;
  	  };
  
  	  axis.tickArguments = function(_) {
  	    return arguments.length ? (tickArguments = _ == null ? [] : slice$3.call(_), axis) : tickArguments.slice();
  	  };
  
  	  axis.tickValues = function(_) {
  	    return arguments.length ? (tickValues = _ == null ? null : slice$3.call(_), axis) : tickValues && tickValues.slice();
  	  };
  
  	  axis.tickFormat = function(_) {
  	    return arguments.length ? (tickFormat = _, axis) : tickFormat;
  	  };
  
  	  axis.tickSize = function(_) {
  	    return arguments.length ? (tickSizeInner = tickSizeOuter = +_, axis) : tickSizeInner;
  	  };
  
  	  axis.tickSizeInner = function(_) {
  	    return arguments.length ? (tickSizeInner = +_, axis) : tickSizeInner;
  	  };
  
  	  axis.tickSizeOuter = function(_) {
  	    return arguments.length ? (tickSizeOuter = +_, axis) : tickSizeOuter;
  	  };
  
  	  axis.tickPadding = function(_) {
  	    return arguments.length ? (tickPadding = +_, axis) : tickPadding;
  	  };
  
  	  return axis;
  	}
  
  	function axisTop(scale) {
  	  return axis(top, scale);
  	}
  
  	function axisRight(scale) {
  	  return axis(right, scale);
  	}
  
  	function axisBottom(scale) {
  	  return axis(bottom, scale);
  	}
  
  	function axisLeft(scale) {
  	  return axis(left, scale);
  	}
  
  	function constant$3(x) {
  	  return function() {
  	    return x;
  	  };
  	}
  
  	function x$1(d) {
  	  return d[0];
  	}
  
  	function y$1(d) {
  	  return d[1];
  	}
  
  	function RedBlackTree() {
  	  this._ = null; // root node
  	}
  
  	function RedBlackNode(node) {
  	  node.U = // parent node
  	  node.C = // color - true for red, false for black
  	  node.L = // left node
  	  node.R = // right node
  	  node.P = // previous node
  	  node.N = null; // next node
  	}
  
  	RedBlackTree.prototype = {
  
  	  insert: function(after, node) {
  	    var parent, grandpa, uncle;
  
  	    if (after) {
  	      node.P = after;
  	      node.N = after.N;
  	      if (after.N) after.N.P = node;
  	      after.N = node;
  	      if (after.R) {
  	        after = after.R;
  	        while (after.L) after = after.L;
  	        after.L = node;
  	      } else {
  	        after.R = node;
  	      }
  	      parent = after;
  	    } else if (this._) {
  	      after = RedBlackFirst(this._);
  	      node.P = null;
  	      node.N = after;
  	      after.P = after.L = node;
  	      parent = after;
  	    } else {
  	      node.P = node.N = null;
  	      this._ = node;
  	      parent = null;
  	    }
  	    node.L = node.R = null;
  	    node.U = parent;
  	    node.C = true;
  
  	    after = node;
  	    while (parent && parent.C) {
  	      grandpa = parent.U;
  	      if (parent === grandpa.L) {
  	        uncle = grandpa.R;
  	        if (uncle && uncle.C) {
  	          parent.C = uncle.C = false;
  	          grandpa.C = true;
  	          after = grandpa;
  	        } else {
  	          if (after === parent.R) {
  	            RedBlackRotateLeft(this, parent);
  	            after = parent;
  	            parent = after.U;
  	          }
  	          parent.C = false;
  	          grandpa.C = true;
  	          RedBlackRotateRight(this, grandpa);
  	        }
  	      } else {
  	        uncle = grandpa.L;
  	        if (uncle && uncle.C) {
  	          parent.C = uncle.C = false;
  	          grandpa.C = true;
  	          after = grandpa;
  	        } else {
  	          if (after === parent.L) {
  	            RedBlackRotateRight(this, parent);
  	            after = parent;
  	            parent = after.U;
  	          }
  	          parent.C = false;
  	          grandpa.C = true;
  	          RedBlackRotateLeft(this, grandpa);
  	        }
  	      }
  	      parent = after.U;
  	    }
  	    this._.C = false;
  	  },
  
  	  remove: function(node) {
  	    if (node.N) node.N.P = node.P;
  	    if (node.P) node.P.N = node.N;
  	    node.N = node.P = null;
  
  	    var parent = node.U,
  	        sibling,
  	        left = node.L,
  	        right = node.R,
  	        next,
  	        red;
  
  	    if (!left) next = right;
  	    else if (!right) next = left;
  	    else next = RedBlackFirst(right);
  
  	    if (parent) {
  	      if (parent.L === node) parent.L = next;
  	      else parent.R = next;
  	    } else {
  	      this._ = next;
  	    }
  
  	    if (left && right) {
  	      red = next.C;
  	      next.C = node.C;
  	      next.L = left;
  	      left.U = next;
  	      if (next !== right) {
  	        parent = next.U;
  	        next.U = node.U;
  	        node = next.R;
  	        parent.L = node;
  	        next.R = right;
  	        right.U = next;
  	      } else {
  	        next.U = parent;
  	        parent = next;
  	        node = next.R;
  	      }
  	    } else {
  	      red = node.C;
  	      node = next;
  	    }
  
  	    if (node) node.U = parent;
  	    if (red) return;
  	    if (node && node.C) { node.C = false; return; }
  
  	    do {
  	      if (node === this._) break;
  	      if (node === parent.L) {
  	        sibling = parent.R;
  	        if (sibling.C) {
  	          sibling.C = false;
  	          parent.C = true;
  	          RedBlackRotateLeft(this, parent);
  	          sibling = parent.R;
  	        }
  	        if ((sibling.L && sibling.L.C)
  	            || (sibling.R && sibling.R.C)) {
  	          if (!sibling.R || !sibling.R.C) {
  	            sibling.L.C = false;
  	            sibling.C = true;
  	            RedBlackRotateRight(this, sibling);
  	            sibling = parent.R;
  	          }
  	          sibling.C = parent.C;
  	          parent.C = sibling.R.C = false;
  	          RedBlackRotateLeft(this, parent);
  	          node = this._;
  	          break;
  	        }
  	      } else {
  	        sibling = parent.L;
  	        if (sibling.C) {
  	          sibling.C = false;
  	          parent.C = true;
  	          RedBlackRotateRight(this, parent);
  	          sibling = parent.L;
  	        }
  	        if ((sibling.L && sibling.L.C)
  	          || (sibling.R && sibling.R.C)) {
  	          if (!sibling.L || !sibling.L.C) {
  	            sibling.R.C = false;
  	            sibling.C = true;
  	            RedBlackRotateLeft(this, sibling);
  	            sibling = parent.L;
  	          }
  	          sibling.C = parent.C;
  	          parent.C = sibling.L.C = false;
  	          RedBlackRotateRight(this, parent);
  	          node = this._;
  	          break;
  	        }
  	      }
  	      sibling.C = true;
  	      node = parent;
  	      parent = parent.U;
  	    } while (!node.C);
  
  	    if (node) node.C = false;
  	  }
  
  	};
  
  	function RedBlackRotateLeft(tree, node) {
  	  var p = node,
  	      q = node.R,
  	      parent = p.U;
  
  	  if (parent) {
  	    if (parent.L === p) parent.L = q;
  	    else parent.R = q;
  	  } else {
  	    tree._ = q;
  	  }
  
  	  q.U = parent;
  	  p.U = q;
  	  p.R = q.L;
  	  if (p.R) p.R.U = p;
  	  q.L = p;
  	}
  
  	function RedBlackRotateRight(tree, node) {
  	  var p = node,
  	      q = node.L,
  	      parent = p.U;
  
  	  if (parent) {
  	    if (parent.L === p) parent.L = q;
  	    else parent.R = q;
  	  } else {
  	    tree._ = q;
  	  }
  
  	  q.U = parent;
  	  p.U = q;
  	  p.L = q.R;
  	  if (p.L) p.L.U = p;
  	  q.R = p;
  	}
  
  	function RedBlackFirst(node) {
  	  while (node.L) node = node.L;
  	  return node;
  	}
  
  	function createEdge(left, right, v0, v1) {
  	  var edge = [null, null],
  	      index = edges.push(edge) - 1;
  	  edge.left = left;
  	  edge.right = right;
  	  if (v0) setEdgeEnd(edge, left, right, v0);
  	  if (v1) setEdgeEnd(edge, right, left, v1);
  	  cells[left.index].halfedges.push(index);
  	  cells[right.index].halfedges.push(index);
  	  return edge;
  	}
  
  	function createBorderEdge(left, v0, v1) {
  	  var edge = [v0, v1];
  	  edge.left = left;
  	  return edge;
  	}
  
  	function setEdgeEnd(edge, left, right, vertex) {
  	  if (!edge[0] && !edge[1]) {
  	    edge[0] = vertex;
  	    edge.left = left;
  	    edge.right = right;
  	  } else if (edge.left === right) {
  	    edge[1] = vertex;
  	  } else {
  	    edge[0] = vertex;
  	  }
  	}
  
  	// Liang–Barsky line clipping.
  	function clippedEdge(edge, x0, y0, x1, y1) {
  	  var a = edge[0],
  	      b = edge[1],
  	      ax = a[0],
  	      ay = a[1],
  	      bx = b[0],
  	      by = b[1],
  	      t0 = 0,
  	      t1 = 1,
  	      dx = bx - ax,
  	      dy = by - ay,
  	      l,
  	      r;
  
  	  r = x0 - ax;
  	  if (!dx && r > 0) return;
  	  r /= dx;
  	  if (dx < 0) {
  	    if (r < t0) return;
  	    if (r < t1) t1 = r;
  	  } else if (dx > 0) {
  	    if (r > t1) return;
  	    if (r > t0) t0 = r;
  	  }
  
  	  r = x1 - ax;
  	  if (!dx && r < 0) return;
  	  r /= dx;
  	  if (dx < 0) {
  	    if (r > t1) return;
  	    if (r > t0) t0 = r;
  	  } else if (dx > 0) {
  	    if (r < t0) return;
  	    if (r < t1) t1 = r;
  	  }
  
  	  r = y0 - ay;
  	  if (!dy && r > 0) return;
  	  r /= dy;
  	  if (dy < 0) {
  	    if (r < t0) return;
  	    if (r < t1) t1 = r;
  	  } else if (dy > 0) {
  	    if (r > t1) return;
  	    if (r > t0) t0 = r;
  	  }
  
  	  r = y1 - ay;
  	  if (!dy && r < 0) return;
  	  r /= dy;
  	  if (dy < 0) {
  	    if (r > t1) return;
  	    if (r > t0) t0 = r;
  	  } else if (dy > 0) {
  	    if (r < t0) return;
  	    if (r < t1) t1 = r;
  	  }
  
  	  if (!(t0 > 0) && !(t1 < 1)) return edge; // TODO Better check?
  
  	  l = edge.left, r = edge.right;
  	  if (t0 > 0) a = [ax + t0 * dx, ay + t0 * dy];
  	  if (t1 < 1) b = [ax + t1 * dx, ay + t1 * dy];
  	  edge = [a, b];
  	  edge.left = l;
  	  edge.right = r;
  	  return edge;
  	}
  
  	function connectedEdge(edge, x0, y0, x1, y1) {
  	  var v1 = edge[1];
  	  if (v1) return edge;
  
  	  var v0 = edge[0],
  	      left = edge.left,
  	      right = edge.right,
  	      lx = left[0],
  	      ly = left[1],
  	      rx = right[0],
  	      ry = right[1],
  	      fx = (lx + rx) / 2,
  	      fy = (ly + ry) / 2,
  	      fm,
  	      fb;
  
  	  if (ry === ly) {
  	    if (fx < x0 || fx >= x1) return;
  	    if (lx > rx) {
  	      if (!v0) v0 = [fx, y0];
  	      else if (v0[1] >= y1) return;
  	      v1 = [fx, y1];
  	    } else {
  	      if (!v0) v0 = [fx, y1];
  	      else if (v0[1] < y0) return;
  	      v1 = [fx, y0];
  	    }
  	  } else {
  	    fm = (lx - rx) / (ry - ly);
  	    fb = fy - fm * fx;
  	    if (fm < -1 || fm > 1) {
  	      if (lx > rx) {
  	        if (!v0) v0 = [(y0 - fb) / fm, y0];
  	        else if (v0[1] >= y1) return;
  	        v1 = [(y1 - fb) / fm, y1];
  	      } else {
  	        if (!v0) v0 = [(y1 - fb) / fm, y1];
  	        else if (v0[1] < y0) return;
  	        v1 = [(y0 - fb) / fm, y0];
  	      }
  	    } else {
  	      if (ly < ry) {
  	        if (!v0) v0 = [x0, fm * x0 + fb];
  	        else if (v0[0] >= x1) return;
  	        v1 = [x1, fm * x1 + fb];
  	      } else {
  	        if (!v0) v0 = [x1, fm * x1 + fb];
  	        else if (v0[0] < x0) return;
  	        v1 = [x0, fm * x0 + fb];
  	      }
  	    }
  	  }
  
  	  edge = [v0, v1];
  	  edge.left = left;
  	  edge.right = right;
  	  return edge;
  	}
  
  	function clippedEdges(x0, y0, x1, y1) {
  	  var i = edges.length,
  	      clippedEdges = new Array(i),
  	      edge;
  
  	  while (i--) {
  	    if ((edge = connectedEdge(edges[i], x0, y0, x1, y1))
  	        && (edge = clippedEdge(edge, x0, y0, x1, y1))
  	        && (Math.abs(edge[0][0] - edge[1][0]) > epsilon$2
  	            || Math.abs(edge[0][1] - edge[1][1]) > epsilon$2)) {
  	      clippedEdges[i] = edge;
  	    }
  	  }
  
  	  return clippedEdges;
  	}
  
  	function createCell(site) {
  	  return cells[site.index] = {
  	    site: site,
  	    halfedges: []
  	  };
  	}
  
  	function cellHalfedgeAngle(cell, edge) {
  	  var site = cell.site,
  	      va = edge.left,
  	      vb = edge.right;
  	  if (site === vb) vb = va, va = site;
  	  if (vb) return Math.atan2(vb[1] - va[1], vb[0] - va[0]);
  	  if (site === va) va = edge[1], vb = edge[0];
  	  else va = edge[0], vb = edge[1];
  	  return Math.atan2(va[0] - vb[0], vb[1] - va[1]);
  	}
  
  	function cellHalfedgeStart(cell, edge) {
  	  return edge[+(edge.left !== cell.site)];
  	}
  
  	function cellHalfedgeEnd(cell, edge) {
  	  return edge[+(edge.left === cell.site)];
  	}
  
  	function sortCellHalfedges() {
  	  for (var i = 0, n = cells.length, cell, halfedges, j, m; i < n; ++i) {
  	    if ((cell = cells[i]) && (m = (halfedges = cell.halfedges).length)) {
  	      var index = new Array(m),
  	          array = new Array(m);
  	      for (j = 0; j < m; ++j) index[j] = j, array[j] = cellHalfedgeAngle(cell, edges[halfedges[j]]);
  	      index.sort(function(i, j) { return array[j] - array[i]; });
  	      for (j = 0; j < m; ++j) array[j] = halfedges[index[j]];
  	      for (j = 0; j < m; ++j) halfedges[j] = array[j];
  	    }
  	  }
  	}
  
  	function clipCells(edges, x0, y0, x1, y1) {
  	  var iCell = cells.length,
  	      cell,
  	      iHalfedge,
  	      halfedges,
  	      nHalfedges,
  	      start,
  	      startX,
  	      startY,
  	      end,
  	      endX,
  	      endY;
  
  	  while (iCell--) {
  	    if (cell = cells[iCell]) {
  	      halfedges = cell.halfedges;
  	      iHalfedge = halfedges.length;
  
  	      // Remove any dangling clipped edges.
  	      while (iHalfedge--) {
  	        if (!edges[halfedges[iHalfedge]]) {
  	          halfedges.splice(iHalfedge, 1);
  	        }
  	      }
  
  	      // Insert any border edges as necessary.
  	      iHalfedge = 0, nHalfedges = halfedges.length;
  	      while (iHalfedge < nHalfedges) {
  	        end = cellHalfedgeEnd(cell, edges[halfedges[iHalfedge]]), endX = end[0], endY = end[1];
  	        start = cellHalfedgeStart(cell, edges[halfedges[++iHalfedge % nHalfedges]]), startX = start[0], startY = start[1];
  	        if (Math.abs(endX - startX) > epsilon$2 || Math.abs(endY - startY) > epsilon$2) {
  	          halfedges.splice(iHalfedge, 0, edges.push(createBorderEdge(cell.site, end,
  	              Math.abs(endX - x0) < epsilon$2 && y1 - endY > epsilon$2 ? [x0, Math.abs(startX - x0) < epsilon$2 ? startY : y1]
  	              : Math.abs(endY - y1) < epsilon$2 && x1 - endX > epsilon$2 ? [Math.abs(startY - y1) < epsilon$2 ? startX : x1, y1]
  	              : Math.abs(endX - x1) < epsilon$2 && endY - y0 > epsilon$2 ? [x1, Math.abs(startX - x1) < epsilon$2 ? startY : y0]
  	              : Math.abs(endY - y0) < epsilon$2 && endX - x0 > epsilon$2 ? [Math.abs(startY - y0) < epsilon$2 ? startX : x0, y0]
  	              : null)) - 1);
  	          ++nHalfedges;
  	        }
  	      }
  	    }
  	  }
  	}
  
  	var circlePool = [];
  
  	var firstCircle;
  
  	function Circle() {
  	  RedBlackNode(this);
  	  this.x =
  	  this.y =
  	  this.arc =
  	  this.site =
  	  this.cy = null;
  	}
  
  	function attachCircle(arc) {
  	  var lArc = arc.P,
  	      rArc = arc.N;
  
  	  if (!lArc || !rArc) return;
  
  	  var lSite = lArc.site,
  	      cSite = arc.site,
  	      rSite = rArc.site;
  
  	  if (lSite === rSite) return;
  
  	  var bx = cSite[0],
  	      by = cSite[1],
  	      ax = lSite[0] - bx,
  	      ay = lSite[1] - by,
  	      cx = rSite[0] - bx,
  	      cy = rSite[1] - by;
  
  	  var d = 2 * (ax * cy - ay * cx);
  	  if (d >= -epsilon2$1) return;
  
  	  var ha = ax * ax + ay * ay,
  	      hc = cx * cx + cy * cy,
  	      x = (cy * ha - ay * hc) / d,
  	      y = (ax * hc - cx * ha) / d;
  
  	  var circle = circlePool.pop() || new Circle;
  	  circle.arc = arc;
  	  circle.site = cSite;
  	  circle.x = x + bx;
  	  circle.y = (circle.cy = y + by) + Math.sqrt(x * x + y * y); // y bottom
  
  	  arc.circle = circle;
  
  	  var before = null,
  	      node = circles._;
  
  	  while (node) {
  	    if (circle.y < node.y || (circle.y === node.y && circle.x <= node.x)) {
  	      if (node.L) node = node.L;
  	      else { before = node.P; break; }
  	    } else {
  	      if (node.R) node = node.R;
  	      else { before = node; break; }
  	    }
  	  }
  
  	  circles.insert(before, circle);
  	  if (!before) firstCircle = circle;
  	}
  
  	function detachCircle(arc) {
  	  var circle = arc.circle;
  	  if (circle) {
  	    if (!circle.P) firstCircle = circle.N;
  	    circles.remove(circle);
  	    circlePool.push(circle);
  	    RedBlackNode(circle);
  	    arc.circle = null;
  	  }
  	}
  
  	var beachPool = [];
  
  	function Beach() {
  	  RedBlackNode(this);
  	  this.edge =
  	  this.site =
  	  this.circle = null;
  	}
  
  	function createBeach(site) {
  	  var beach = beachPool.pop() || new Beach;
  	  beach.site = site;
  	  return beach;
  	}
  
  	function detachBeach(beach) {
  	  detachCircle(beach);
  	  beaches.remove(beach);
  	  beachPool.push(beach);
  	  RedBlackNode(beach);
  	}
  
  	function removeBeach(beach) {
  	  var circle = beach.circle,
  	      x = circle.x,
  	      y = circle.cy,
  	      vertex = [x, y],
  	      previous = beach.P,
  	      next = beach.N,
  	      disappearing = [beach];
  
  	  detachBeach(beach);
  
  	  var lArc = previous;
  	  while (lArc.circle
  	      && Math.abs(x - lArc.circle.x) < epsilon$2
  	      && Math.abs(y - lArc.circle.cy) < epsilon$2) {
  	    previous = lArc.P;
  	    disappearing.unshift(lArc);
  	    detachBeach(lArc);
  	    lArc = previous;
  	  }
  
  	  disappearing.unshift(lArc);
  	  detachCircle(lArc);
  
  	  var rArc = next;
  	  while (rArc.circle
  	      && Math.abs(x - rArc.circle.x) < epsilon$2
  	      && Math.abs(y - rArc.circle.cy) < epsilon$2) {
  	    next = rArc.N;
  	    disappearing.push(rArc);
  	    detachBeach(rArc);
  	    rArc = next;
  	  }
  
  	  disappearing.push(rArc);
  	  detachCircle(rArc);
  
  	  var nArcs = disappearing.length,
  	      iArc;
  	  for (iArc = 1; iArc < nArcs; ++iArc) {
  	    rArc = disappearing[iArc];
  	    lArc = disappearing[iArc - 1];
  	    setEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex);
  	  }
  
  	  lArc = disappearing[0];
  	  rArc = disappearing[nArcs - 1];
  	  rArc.edge = createEdge(lArc.site, rArc.site, null, vertex);
  
  	  attachCircle(lArc);
  	  attachCircle(rArc);
  	}
  
  	function addBeach(site) {
  	  var x = site[0],
  	      directrix = site[1],
  	      lArc,
  	      rArc,
  	      dxl,
  	      dxr,
  	      node = beaches._;
  
  	  while (node) {
  	    dxl = leftBreakPoint(node, directrix) - x;
  	    if (dxl > epsilon$2) node = node.L; else {
  	      dxr = x - rightBreakPoint(node, directrix);
  	      if (dxr > epsilon$2) {
  	        if (!node.R) {
  	          lArc = node;
  	          break;
  	        }
  	        node = node.R;
  	      } else {
  	        if (dxl > -epsilon$2) {
  	          lArc = node.P;
  	          rArc = node;
  	        } else if (dxr > -epsilon$2) {
  	          lArc = node;
  	          rArc = node.N;
  	        } else {
  	          lArc = rArc = node;
  	        }
  	        break;
  	      }
  	    }
  	  }
  
  	  createCell(site);
  	  var newArc = createBeach(site);
  	  beaches.insert(lArc, newArc);
  
  	  if (!lArc && !rArc) return;
  
  	  if (lArc === rArc) {
  	    detachCircle(lArc);
  	    rArc = createBeach(lArc.site);
  	    beaches.insert(newArc, rArc);
  	    newArc.edge = rArc.edge = createEdge(lArc.site, newArc.site);
  	    attachCircle(lArc);
  	    attachCircle(rArc);
  	    return;
  	  }
  
  	  if (!rArc) { // && lArc
  	    newArc.edge = createEdge(lArc.site, newArc.site);
  	    return;
  	  }
  
  	  // else lArc !== rArc
  	  detachCircle(lArc);
  	  detachCircle(rArc);
  
  	  var lSite = lArc.site,
  	      ax = lSite[0],
  	      ay = lSite[1],
  	      bx = site[0] - ax,
  	      by = site[1] - ay,
  	      rSite = rArc.site,
  	      cx = rSite[0] - ax,
  	      cy = rSite[1] - ay,
  	      d = 2 * (bx * cy - by * cx),
  	      hb = bx * bx + by * by,
  	      hc = cx * cx + cy * cy,
  	      vertex = {x: (cy * hb - by * hc) / d + ax, y: (bx * hc - cx * hb) / d + ay};
  
  	  setEdgeEnd(rArc.edge, lSite, rSite, vertex);
  	  newArc.edge = createEdge(lSite, site, null, vertex);
  	  rArc.edge = createEdge(site, rSite, null, vertex);
  	  attachCircle(lArc);
  	  attachCircle(rArc);
  	}
  
  	function leftBreakPoint(arc, directrix) {
  	  var site = arc.site,
  	      rfocx = site[0],
  	      rfocy = site[1],
  	      pby2 = rfocy - directrix;
  
  	  if (!pby2) return rfocx;
  
  	  var lArc = arc.P;
  	  if (!lArc) return -Infinity;
  
  	  site = lArc.site;
  	  var lfocx = site[0],
  	      lfocy = site[1],
  	      plby2 = lfocy - directrix;
  
  	  if (!plby2) return lfocx;
  
  	  var hl = lfocx - rfocx,
  	      aby2 = 1 / pby2 - 1 / plby2,
  	      b = hl / plby2;
  
  	  if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx;
  
  	  return (rfocx + lfocx) / 2;
  	}
  
  	function rightBreakPoint(arc, directrix) {
  	  var rArc = arc.N;
  	  if (rArc) return leftBreakPoint(rArc, directrix);
  	  var site = arc.site;
  	  return site[1] === directrix ? site[0] : Infinity;
  	}
  
  	var epsilon$2 = 1e-6;
  	var epsilon2$1 = 1e-12;
  	var beaches;
  	var cells;
  	var circles;
  	var edges;
  
  	function triangleArea(a, b, c) {
  	  return (a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1]);
  	}
  
  	function lexicographic(a, b) {
  	  return b[1] - a[1]
  	      || b[0] - a[0];
  	}
  
  	function Diagram(sites, extent) {
  	  var site = sites.sort(lexicographic).pop(),
  	      x,
  	      y,
  	      circle;
  
  	  edges = [];
  	  cells = new Array(sites.length);
  	  beaches = new RedBlackTree;
  	  circles = new RedBlackTree;
  
  	  while (true) {
  	    circle = firstCircle;
  	    if (site && (!circle || site[1] < circle.y || (site[1] === circle.y && site[0] < circle.x))) {
  	      if (site[0] !== x || site[1] !== y) {
  	        addBeach(site);
  	        x = site[0], y = site[1];
  	      }
  	      site = sites.pop();
  	    } else if (circle) {
  	      removeBeach(circle.arc);
  	    } else {
  	      break;
  	    }
  	  }
  
  	  sortCellHalfedges();
  
  	  if (extent) {
  	    var x0 = extent[0][0],
  	        y0 = extent[0][1],
  	        x1 = extent[1][0],
  	        y1 = extent[1][1];
  	    this.extent = [[x0, y0], [x1, y1]];
  	    this.cellEdges = clippedEdges(x0, y0, x1, y1);
  	    clipCells(this.cellEdges, x0, y0, x1, y1);
  	  } else {
  	    this.cellEdges = edges;
  	  }
  
  	  this.cells = cells;
  	  this.edges = edges;
  
  	  beaches =
  	  circles =
  	  edges =
  	  cells = null;
  	}
  
  	Diagram.prototype = {
  	  polygons: function() {
  	    var cells = this.cells,
  	        edges = this.cellEdges,
  	        extent = this.extent,
  	        x0 = extent[0][0],
  	        y0 = extent[0][1],
  	        x1 = extent[1][0],
  	        y1 = extent[1][1],
  	        polygons = new Array(cells.length);
  
  	    cells.forEach(function(cell, i) {
  	      var site = cell.site,
  	          halfedges = cell.halfedges,
  	          polygon;
  	      if (halfedges.length) polygon = halfedges.map(function(index) { return cellHalfedgeStart(cell, edges[index]); });
  	      else if (site[0] >= x0 && site[0] <= x1 && site[1] >= y0 && site[1] <= y1) polygon = [[x0, y1], [x1, y1], [x1, y0], [x0, y0]];
  	      else return;
  	      polygons[i] = polygon;
  	      polygon.data = site.data;
  	    });
  
  	    return polygons;
  	  },
  	  triangles: function() {
  	    var triangles = [],
  	        edges = this.edges;
  
  	    this.cells.forEach(function(cell, i) {
  	      var site = cell.site,
  	          halfedges = cell.halfedges,
  	          j = -1,
  	          m = halfedges.length,
  	          s0,
  	          e1 = edges[halfedges[m - 1]],
  	          s1 = e1.left === site ? e1.right : e1.left;
  
  	      while (++j < m) {
  	        s0 = s1;
  	        e1 = edges[halfedges[j]];
  	        s1 = e1.left === site ? e1.right : e1.left;
  	        if (i < s0.index && i < s1.index && triangleArea(site, s0, s1) < 0) {
  	          triangles.push([site.data, s0.data, s1.data]);
  	        }
  	      }
  	    });
  
  	    return triangles;
  	  },
  	  links: function() {
  	    return this.edges.filter(function(edge) {
  	      return edge.right;
  	    }).map(function(edge) {
  	      return {
  	        source: edge.left.data,
  	        target: edge.right.data
  	      };
  	    });
  	  }
  	}
  
  	function voronoi() {
  	  var x = x$1,
  	      y = y$1,
  	      extent = null;
  
  	  function voronoi(data) {
  	    return new Diagram(data.map(function(d, i) {
  	      var s = [Math.round(x(d, i, data) / epsilon$2) * epsilon$2, Math.round(y(d, i, data) / epsilon$2) * epsilon$2];
  	      s.index = i;
  	      s.data = d;
  	      return s;
  	    }), extent);
  	  }
  	  voronoi.polygons = function(data) {
  	    return voronoi(data).polygons();
  	  };
  
  	  voronoi.links = function(data) {
  	    return voronoi(data).links();
  	  };
  
  	  voronoi.triangles = function(data) {
  	    return voronoi(data).triangles();
  	  };
  
  	  voronoi.x = function(_) {
  	    return arguments.length ? (x = typeof _ === "function" ? _ : constant$3(+_), voronoi) : x;
  	  };
  
  	  voronoi.y = function(_) {
  	    return arguments.length ? (y = typeof _ === "function" ? _ : constant$3(+_), voronoi) : y;
  	  };
  
  	  voronoi.extent = function(_) {
  	    return arguments.length ? (extent = _ == null ? null : [[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]], voronoi) : extent && [[extent[0][0], extent[0][1]], [extent[1][0], extent[1][1]]];
  	  };
  
  	  voronoi.size = function(_) {
  	    return arguments.length ? (extent = _ == null ? null : [[0, 0], [+_[0], +_[1]]], voronoi) : extent && [extent[1][0], extent[1][1]];
  	  };
  
  	  return voronoi;
  	}
  
  	exports.version = version;
  	exports.bisect = bisectRight;
  	exports.bisectRight = bisectRight;
  	exports.bisectLeft = bisectLeft;
  	exports.ascending = ascending;
  	exports.bisector = bisector;
  	exports.descending = descending;
  	exports.deviation = deviation;
  	exports.extent = extent;
  	exports.histogram = histogram;
  	exports.thresholdFreedmanDiaconis = freedmanDiaconis;
  	exports.thresholdScott = scott;
  	exports.thresholdSturges = sturges;
  	exports.max = max;
  	exports.mean = mean;
  	exports.median = median;
  	exports.merge = merge;
  	exports.min = min;
  	exports.pairs = pairs;
  	exports.permute = permute;
  	exports.quantile = quantile;
  	exports.range = sequence;
  	exports.scan = scan;
  	exports.shuffle = shuffle;
  	exports.sum = sum;
  	exports.ticks = ticks;
  	exports.transpose = transpose;
  	exports.variance = variance;
  	exports.zip = zip;
  	exports.entries = entries;
  	exports.keys = keys;
  	exports.values = values;
  	exports.map = map;
  	exports.set = set;
  	exports.nest = nest;
  	exports.randomUniform = uniform;
  	exports.randomNormal = normal;
  	exports.randomLogNormal = logNormal;
  	exports.randomBates = bates;
  	exports.randomIrwinHall = irwinHall;
  	exports.randomExponential = exponential;
  	exports.easeLinearIn = linearIn;
  	exports.easeLinearOut = linearIn;
  	exports.easeLinearInOut = linearIn;
  	exports.easeQuadIn = quadIn;
  	exports.easeQuadOut = quadOut;
  	exports.easeQuadInOut = quadInOut;
  	exports.easeCubicIn = cubicIn;
  	exports.easeCubicOut = cubicOut;
  	exports.easeCubicInOut = easeCubicInOut;
  	exports.easePolyIn = polyIn;
  	exports.easePolyOut = polyOut;
  	exports.easePolyInOut = polyInOut;
  	exports.easeSinIn = sinIn;
  	exports.easeSinOut = sinOut;
  	exports.easeSinInOut = sinInOut;
  	exports.easeExpIn = expIn;
  	exports.easeExpOut = expOut;
  	exports.easeExpInOut = expInOut;
  	exports.easeCircleIn = circleIn;
  	exports.easeCircleOut = circleOut;
  	exports.easeCircleInOut = circleInOut;
  	exports.easeBounceIn = bounceIn;
  	exports.easeBounceOut = bounceOut;
  	exports.easeBounceInOut = bounceInOut;
  	exports.easeBackIn = backIn;
  	exports.easeBackOut = backOut;
  	exports.easeBackInOut = backInOut;
  	exports.easeElasticIn = elasticIn;
  	exports.easeElasticOut = elasticOut;
  	exports.easeElasticInOut = elasticInOut;
  	exports.polygonArea = area;
  	exports.polygonCentroid = centroid;
  	exports.polygonHull = hull;
  	exports.polygonContains = contains;
  	exports.polygonLength = length$1;
  	exports.path = path;
  	exports.quadtree = quadtree;
  	exports.queue = queue;
  	exports.arc = arc;
  	exports.area = area$1;
  	exports.line = line;
  	exports.pie = pie;
  	exports.radialArea = radialArea;
  	exports.radialLine = radialLine;
  	exports.symbol = symbol;
  	exports.symbols = symbols;
  	exports.symbolCircle = circle;
  	exports.symbolCross = cross;
  	exports.symbolDiamond = diamond;
  	exports.symbolSquare = square;
  	exports.symbolStar = star;
  	exports.symbolTriangle = triangle;
  	exports.symbolWye = wye;
  	exports.curveBasisClosed = basisClosed;
  	exports.curveBasisOpen = basisOpen;
  	exports.curveBasis = basis;
  	exports.curveBundle = bundle;
  	exports.curveCardinalClosed = cardinalClosed;
  	exports.curveCardinalOpen = cardinalOpen;
  	exports.curveCardinal = cardinal;
  	exports.curveCatmullRomClosed = catmullRomClosed;
  	exports.curveCatmullRomOpen = catmullRomOpen;
  	exports.curveCatmullRom = catmullRom;
  	exports.curveLinearClosed = linearClosed;
  	exports.curveLinear = curveLinear;
  	exports.curveMonotoneX = monotoneX;
  	exports.curveMonotoneY = monotoneY;
  	exports.curveNatural = natural;
  	exports.curveStep = step;
  	exports.curveStepAfter = stepAfter;
  	exports.curveStepBefore = stepBefore;
  	exports.stack = stack;
  	exports.stackOffsetExpand = expand;
  	exports.stackOffsetNone = none;
  	exports.stackOffsetSilhouette = silhouette;
  	exports.stackOffsetWiggle = wiggle;
  	exports.stackOrderAscending = ascending$1;
  	exports.stackOrderDescending = descending$1;
  	exports.stackOrderInsideOut = insideOut;
  	exports.stackOrderNone = none$1;
  	exports.stackOrderReverse = reverse;
  	exports.color = color;
  	exports.rgb = rgb;
  	exports.hsl = hsl;
  	exports.lab = lab;
  	exports.hcl = hcl;
  	exports.cubehelix = cubehelix;
  	exports.interpolate = interpolate;
  	exports.interpolators = values$1;
  	exports.interpolateArray = array;
  	exports.interpolateNumber = reinterpolate;
  	exports.interpolateObject = object;
  	exports.interpolateRound = interpolateRound;
  	exports.interpolateString = string;
  	exports.interpolateTransform = transform;
  	exports.interpolateZoom = zoom;
  	exports.interpolateRgb = rgb$1;
  	exports.interpolateHsl = interpolateHsl;
  	exports.interpolateHslLong = interpolateHslLong;
  	exports.interpolateLab = interpolateLab;
  	exports.interpolateHcl = interpolateHcl;
  	exports.interpolateHclLong = interpolateHclLong;
  	exports.interpolateCubehelix = cubehelix$1;
  	exports.interpolateCubehelixLong = interpolateCubehelixLong;
  	exports.dispatch = dispatch;
  	exports.dsv = dsv;
  	exports.csv = csv;
  	exports.tsv = tsv;
  	exports.request = request;
  	exports.requestHtml = html;
  	exports.requestJson = json;
  	exports.requestText = text;
  	exports.requestXml = xml;
  	exports.requestCsv = csv$1;
  	exports.requestTsv = tsv$1;
  	exports.timer = timer;
  	exports.timerOnce = timerOnce;
  	exports.timerFlush = timerFlush;
  	exports.timeInterval = newInterval;
  	exports.timeMillisecond = millisecond;
  	exports.timeMilliseconds = timeMilliseconds;
  	exports.timeSecond = timeSecond;
  	exports.timeSeconds = timeSeconds;
  	exports.timeMinute = timeMinute;
  	exports.timeMinutes = timeMinutes;
  	exports.timeHour = timeHour;
  	exports.timeHours = timeHours;
  	exports.timeDay = timeDay;
  	exports.timeDays = timeDays;
  	exports.timeWeek = timeSunday;
  	exports.timeWeeks = timeWeeks;
  	exports.timeSunday = timeSunday;
  	exports.timeSundays = timeSundays;
  	exports.timeMonday = timeMonday;
  	exports.timeMondays = timeMondays;
  	exports.timeTuesday = tuesday;
  	exports.timeTuesdays = timeTuesdays;
  	exports.timeWednesday = wednesday;
  	exports.timeWednesdays = timeWednesdays;
  	exports.timeThursday = thursday;
  	exports.timeThursdays = timeThursdays;
  	exports.timeFriday = friday;
  	exports.timeFridays = timeFridays;
  	exports.timeSaturday = saturday;
  	exports.timeSaturdays = timeSaturdays;
  	exports.timeMonth = timeMonth;
  	exports.timeMonths = timeMonths;
  	exports.timeYear = timeYear;
  	exports.timeYears = timeYears;
  	exports.utcMillisecond = utcMillisecond;
  	exports.utcMilliseconds = utcMilliseconds;
  	exports.utcSecond = utcSecond;
  	exports.utcSeconds = utcSeconds;
  	exports.utcMinute = utcMinute;
  	exports.utcMinutes = utcMinutes;
  	exports.utcHour = utcHour;
  	exports.utcHours = utcHours;
  	exports.utcDay = utcDay;
  	exports.utcDays = utcDays;
  	exports.utcWeek = utcSunday;
  	exports.utcWeeks = utcWeeks;
  	exports.utcSunday = utcSunday;
  	exports.utcSundays = utcSundays;
  	exports.utcMonday = utcMonday;
  	exports.utcMondays = utcMondays;
  	exports.utcTuesday = utcTuesday;
  	exports.utcTuesdays = utcTuesdays;
  	exports.utcWednesday = utcWednesday;
  	exports.utcWednesdays = utcWednesdays;
  	exports.utcThursday = utcThursday;
  	exports.utcThursdays = utcThursdays;
  	exports.utcFriday = utcFriday;
  	exports.utcFridays = utcFridays;
  	exports.utcSaturday = utcSaturday;
  	exports.utcSaturdays = utcSaturdays;
  	exports.utcMonth = utcMonth;
  	exports.utcMonths = utcMonths;
  	exports.utcYear = utcYear;
  	exports.utcYears = utcYears;
  	exports.format = format;
  	exports.formatPrefix = formatPrefix;
  	exports.formatLocale = locale;
  	exports.formatCaEs = caES;
  	exports.formatCsCz = csCZ;
  	exports.formatDeCh = deCH;
  	exports.formatDeDe = deDE;
  	exports.formatEnCa = enCA;
  	exports.formatEnGb = enGB;
  	exports.formatEnUs = defaultLocale;
  	exports.formatEsEs = esES;
  	exports.formatFiFi = fiFI;
  	exports.formatFrCa = frCA;
  	exports.formatFrFr = frFR;
  	exports.formatHeIl = heIL;
  	exports.formatHuHu = huHU;
  	exports.formatItIt = itIT;
  	exports.formatJaJp = jaJP;
  	exports.formatKoKr = koKR;
  	exports.formatMkMk = mkMK;
  	exports.formatNlNl = nlNL;
  	exports.formatPlPl = plPL;
  	exports.formatPtBr = ptBR;
  	exports.formatRuRu = ruRU;
  	exports.formatSvSe = svSE;
  	exports.formatZhCn = zhCN;
  	exports.formatSpecifier = formatSpecifier;
  	exports.precisionFixed = precisionFixed;
  	exports.precisionPrefix = precisionPrefix;
  	exports.precisionRound = precisionRound;
  	exports.timeFormat = timeFormat;
  	exports.timeParse = timeParse;
  	exports.utcFormat = utcFormat;
  	exports.utcParse = utcParse;
  	exports.isoFormat = formatIso;
  	exports.isoParse = parseIso;
  	exports.timeFormatLocale = locale$1;
  	exports.timeFormatCaEs = caES$1;
  	exports.timeFormatDeCh = deCH$1;
  	exports.timeFormatDeDe = deDE$1;
  	exports.timeFormatEnCa = enCA$1;
  	exports.timeFormatEnGb = enGB$1;
  	exports.timeFormatEnUs = locale$2;
  	exports.timeFormatEsEs = esES$1;
  	exports.timeFormatFiFi = fiFI$1;
  	exports.timeFormatFrCa = frCA$1;
  	exports.timeFormatFrFr = frFR$1;
  	exports.timeFormatHeIl = heIL$1;
  	exports.timeFormatHuHu = huHU$1;
  	exports.timeFormatItIt = itIT$1;
  	exports.timeFormatJaJp = jaJP$1;
  	exports.timeFormatKoKr = koKR$1;
  	exports.timeFormatMkMk = mkMK$1;
  	exports.timeFormatNlNl = nlNL$1;
  	exports.timeFormatPlPl = plPL$1;
  	exports.timeFormatPtBr = ptBR$1;
  	exports.timeFormatRuRu = ruRU$1;
  	exports.timeFormatSvSe = svSE$1;
  	exports.timeFormatZhCn = zhCN$1;
  	exports.scaleBand = band;
  	exports.scalePoint = point;
  	exports.scaleIdentity = identity$2;
  	exports.scaleLinear = linear;
  	exports.scaleLog = log;
  	exports.scaleOrdinal = ordinal;
  	exports.scaleImplicit = implicit;
  	exports.scalePow = pow;
  	exports.scaleSqrt = sqrt;
  	exports.scaleQuantile = quantile$1;
  	exports.scaleQuantize = quantize;
  	exports.scaleThreshold = threshold;
  	exports.scaleTime = time;
  	exports.scaleUtc = utcTime;
  	exports.scaleCategory10 = category10;
  	exports.scaleCategory20b = category20b;
  	exports.scaleCategory20c = category20c;
  	exports.scaleCategory20 = category20;
  	exports.scaleCubehelix = cubehelix$2;
  	exports.scaleRainbow = rainbow;
  	exports.scaleWarm = warm;
  	exports.scaleCool = cool;
  	exports.scaleViridis = viridis;
  	exports.scaleMagma = magma;
  	exports.scaleInferno = inferno;
  	exports.scalePlasma = plasma;
  	exports.mouse = mouse;
  	exports.namespace = namespace;
  	exports.namespaces = namespaces;
  	exports.select = select;
  	exports.selectAll = selectAll;
  	exports.selection = selection;
  	exports.touch = touch;
  	exports.touches = touches;
  	exports.transition = transition;
  	exports.axisTop = axisTop;
  	exports.axisRight = axisRight;
  	exports.axisBottom = axisBottom;
  	exports.axisLeft = axisLeft;
  	exports.voronoi = voronoi;
  
  }));