(function () {
 var defaultOptions = {
  frameRate: 150,
  animationTime: 380,
  stepSize: 80,
  pulseAlgorithm: true,
  pulseScale: 4,
  pulseNormalize: 1,
  accelerationDelta: 50,
  accelerationMax: 3,
  keyboardSupport: true,
  arrowScroll: 50,
  fixedBackground: true,
  excluded: ''
 };
 var options = defaultOptions;
 var isExcluded = false;
 var isFrame = false;
 var direction = {
  x: 0,
  y: 0
 };
 var initDone = false;
 var root = document.documentElement;
 var activeElement;
 var observer;
 var refreshSize;
 var deltaBuffer = [];
 var deltaBufferTimer;
 var isMac = /^Mac/.test(navigator.platform);
 var key = {
  left: 37,
  up: 38,
  right: 39,
  down: 40,
  spacebar: 32,
  pageup: 33,
  pagedown: 34,
  end: 35,
  home: 36
 };
 var arrowKeys = {
  37: 1,
  38: 1,
  39: 1,
  40: 1
 };
 function initTest() {
  if (options.keyboardSupport) {
   addEvent('keydown', keydown);
  }
 }
 function init() {
  if (initDone || !document.body)
   return;
  initDone = true;
  var body = document.body;
  var html = document.documentElement;
  var windowHeight = window.innerHeight;
  var scrollHeight = body.scrollHeight;
  root = (document.compatMode.indexOf('CSS') >= 0) ? html : body;
  activeElement = body;
  initTest();
  if (top != self) {
   isFrame = true;
  } else if (isOldSafari && scrollHeight > windowHeight && (body.offsetHeight <= windowHeight || html.offsetHeight <= windowHeight)) {
   var fullPageElem = document.createElement('div');
   fullPageElem.style.cssText = 'position:absolute; z-index:-10000; ' + 'top:0; left:0; right:0; height:' + root.scrollHeight + 'px';
   document.body.appendChild(fullPageElem);
   var pendingRefresh;
   refreshSize = function () {
    if (pendingRefresh)
     return;
    pendingRefresh = setTimeout(function () {
     if (isExcluded)
      return;
     fullPageElem.style.height = '0';
     fullPageElem.style.height = root.scrollHeight + 'px';
     pendingRefresh = null;
    }, 500);
   }
   ;
   setTimeout(refreshSize, 10);
   addEvent('resize', refreshSize);
   var config = {
    attributes: true,
    childList: true,
    characterData: false
   };
   observer = new MutationObserver(refreshSize);
   observer.observe(body, config);
   if (root.offsetHeight <= windowHeight) {
    var clearfix = document.createElement('div');
    clearfix.style.clear = 'both';
    body.appendChild(clearfix);
   }
  }
  if (!options.fixedBackground && !isExcluded) {
   body.style.backgroundAttachment = 'scroll';
   html.style.backgroundAttachment = 'scroll';
  }
 }
 function cleanup() {
  observer && observer.disconnect();
  removeEvent(wheelEvent, wheel);
  removeEvent('mousedown', mousedown);
  removeEvent('keydown', keydown);
  removeEvent('resize', refreshSize);
  removeEvent('load', init);
 }
 var que = [];
 var pending = false;
 var lastScroll = Date.now();
 function scrollArray(elem, left, top) {
  directionCheck(left, top);
  if (options.accelerationMax != 1) {
   var now = Date.now();
   var elapsed = now - lastScroll;
   if (elapsed < options.accelerationDelta) {
    var factor = (1 + (50 / elapsed)) / 2;
    if (factor > 1) {
     factor = Math.min(factor, options.accelerationMax);
     left *= factor;
     top *= factor;
    }
   }
   lastScroll = Date.now();
  }
  que.push({
   x: left,
   y: top,
   lastX: (left < 0) ? 0.99 : -0.99,
   lastY: (top < 0) ? 0.99 : -0.99,
   start: Date.now()
  });
  if (pending) {
   return;
  }
  var scrollRoot = getScrollRoot();
  var isWindowScroll = (elem === scrollRoot || elem === document.body);
  if (elem.$scrollBehavior == null && isScrollBehaviorSmooth(elem)) {
   elem.$scrollBehavior = elem.style.scrollBehavior;
   elem.style.scrollBehavior = 'auto';
  }
  var step = function (time) {
   var now = Date.now();
   var scrollX = 0;
   var scrollY = 0;
   for (var i = 0; i < que.length; i++) {
    var item = que[i];
    var elapsed = now - item.start;
    var finished = (elapsed >= options.animationTime);
    var position = (finished) ? 1 : elapsed / options.animationTime;
    if (options.pulseAlgorithm) {
     position = pulse(position);
    }
    var x = (item.x * position - item.lastX) >> 0;
    var y = (item.y * position - item.lastY) >> 0;
    scrollX += x;
    scrollY += y;
    item.lastX += x;
    item.lastY += y;
    if (finished) {
     que.splice(i, 1);
     i--;
    }
   }
   if (isWindowScroll) {
    window.scrollBy(scrollX, scrollY);
   } else {
    if (scrollX)
     elem.scrollLeft += scrollX;
    if (scrollY)
     elem.scrollTop += scrollY;
   }
   if (!left && !top) {
    que = [];
   }
   if (que.length) {
    requestFrame(step, elem, (1000 / options.frameRate + 1));
   } else {
    pending = false;
    if (elem.$scrollBehavior != null) {
     elem.style.scrollBehavior = elem.$scrollBehavior;
     elem.$scrollBehavior = null;
    }
   }
  };
  requestFrame(step, elem, 0);
  pending = true;
 }
 function wheel(event) {
  if (!initDone) {
   init();
  }
  var target = event.target;
  if (event.defaultPrevented || event.ctrlKey) {
   return true;
  }
  if (isNodeName(activeElement, 'embed') || (isNodeName(target, 'embed') && /\.pdf/i.test(target.src)) || isNodeName(activeElement, 'object') || target.shadowRoot) {
   return true;
  }
  var deltaX = -event.wheelDeltaX || event.deltaX || 0;
  var deltaY = -event.wheelDeltaY || event.deltaY || 0;
  if (isMac) {
   if (event.wheelDeltaX && isDivisible(event.wheelDeltaX, 120)) {
    deltaX = -120 * (event.wheelDeltaX / Math.abs(event.wheelDeltaX));
   }
   if (event.wheelDeltaY && isDivisible(event.wheelDeltaY, 120)) {
    deltaY = -120 * (event.wheelDeltaY / Math.abs(event.wheelDeltaY));
   }
  }
  if (!deltaX && !deltaY) {
   deltaY = -event.wheelDelta || 0;
  }
  if (event.deltaMode === 1) {
   deltaX *= 40;
   deltaY *= 40;
  }
  var overflowing = overflowingAncestor(target);
  if (!overflowing) {
   if (isFrame && isChrome) {
    Object.defineProperty(event, "target", {
     value: window.frameElement
    });
    return parent.wheel(event);
   }
   return true;
  }
  if (isTouchpad(deltaY)) {
   return true;
  }
  if (Math.abs(deltaX) > 1.2) {
   deltaX *= options.stepSize / 120;
  }
  if (Math.abs(deltaY) > 1.2) {
   deltaY *= options.stepSize / 120;
  }
  scrollArray(overflowing, deltaX, deltaY);
  event.preventDefault();
  scheduleClearCache();
 }
 function keydown(event) {
  var target = event.target;
  var modifier = event.ctrlKey || event.altKey || event.metaKey || (event.shiftKey && event.keyCode !== key.spacebar);
  if (!document.body.contains(activeElement)) {
   activeElement = document.activeElement;
  }
  var inputNodeNames = /^(textarea|select|embed|object)$/i;
  var buttonTypes = /^(button|submit|radio|checkbox|file|color|image)$/i;
  if (event.defaultPrevented || inputNodeNames.test(target.nodeName) || isNodeName(target, 'input') && !buttonTypes.test(target.type) || isNodeName(activeElement, 'video') || isInsideYoutubeVideo(event) || target.isContentEditable || modifier) {
   return true;
  }
  if ((isNodeName(target, 'button') || isNodeName(target, 'input') && buttonTypes.test(target.type)) && event.keyCode === key.spacebar) {
   return true;
  }
  if (isNodeName(target, 'input') && target.type == 'radio' && arrowKeys[event.keyCode]) {
   return true;
  }
  var shift, x = 0, y = 0;
  var overflowing = overflowingAncestor(activeElement);
  if (!overflowing) {
   return (isFrame && isChrome) ? parent.keydown(event) : true;
  }
  var clientHeight = overflowing.clientHeight;
  if (overflowing == document.body) {
   clientHeight = window.innerHeight;
  }
  switch (event.keyCode) {
   case key.up:
    y = -options.arrowScroll;
    break;
   case key.down:
    y = options.arrowScroll;
    break;
   case key.spacebar:
    shift = event.shiftKey ? 1 : -1;
    y = -shift * clientHeight * 0.9;
    break;
   case key.pageup:
    y = -clientHeight * 0.9;
    break;
   case key.pagedown:
    y = clientHeight * 0.9;
    break;
   case key.home:
    if (overflowing == document.body && document.scrollingElement)
     overflowing = document.scrollingElement;
    y = -overflowing.scrollTop;
    break;
   case key.end:
    var scroll = overflowing.scrollHeight - overflowing.scrollTop;
    var scrollRemaining = scroll - clientHeight;
    y = (scrollRemaining > 0) ? scrollRemaining + 10 : 0;
    break;
   case key.left:
    x = -options.arrowScroll;
    break;
   case key.right:
    x = options.arrowScroll;
    break;
   default:
    return true;
  }
  scrollArray(overflowing, x, y);
  event.preventDefault();
  scheduleClearCache();
 }
 function mousedown(event) {
  activeElement = event.target;
 }
 var uniqueID = (function () {
  var i = 0;
  return function (el) {
   return el.uniqueID || (el.uniqueID = i++);
  }
  ;
 }
 )();
 var cacheX = {};
 var cacheY = {};
 var clearCacheTimer;
 var smoothBehaviorForElement = {};
 function scheduleClearCache() {
  clearTimeout(clearCacheTimer);
  clearCacheTimer = setInterval(function () {
   cacheX = cacheY = smoothBehaviorForElement = {};
  }, 1 * 1000);
 }
 function setCache(elems, overflowing, x) {
  var cache = x ? cacheX : cacheY;
  for (var i = elems.length; i--; )
   cache[uniqueID(elems[i])] = overflowing;
  return overflowing;
 }
 function getCache(el, x) {
  return (x ? cacheX : cacheY)[uniqueID(el)];
 }
 function overflowingAncestor(el) {
  var elems = [];
  var body = document.body;
  var rootScrollHeight = root.scrollHeight;
  do {
   var cached = getCache(el, false);
   if (cached) {
    return setCache(elems, cached);
   }
   elems.push(el);
   if (rootScrollHeight === el.scrollHeight) {
    var topOverflowsNotHidden = overflowNotHidden(root) && overflowNotHidden(body);
    var isOverflowCSS = topOverflowsNotHidden || overflowAutoOrScroll(root);
    if (isFrame && isContentOverflowing(root) || !isFrame && isOverflowCSS) {
     return setCache(elems, getScrollRoot());
    }
   } else if (isContentOverflowing(el) && overflowAutoOrScroll(el)) {
    return setCache(elems, el);
   }
  } while ((el = el.parentElement));
 }
 function isContentOverflowing(el) {
  return (el.clientHeight + 10 < el.scrollHeight);
 }
 function overflowNotHidden(el) {
  var overflow = getComputedStyle(el, '').getPropertyValue('overflow-y');
  return (overflow !== 'hidden');
 }
 function overflowAutoOrScroll(el) {
  var overflow = getComputedStyle(el, '').getPropertyValue('overflow-y');
  return (overflow === 'scroll' || overflow === 'auto');
 }
 function isScrollBehaviorSmooth(el) {
  var id = uniqueID(el);
  if (smoothBehaviorForElement[id] == null) {
   var scrollBehavior = getComputedStyle(el, '')['scroll-behavior'];
   smoothBehaviorForElement[id] = ('smooth' == scrollBehavior);
  }
  return smoothBehaviorForElement[id];
 }
 function addEvent(type, fn, arg) {
  window.addEventListener(type, fn, arg || false);
 }
 function removeEvent(type, fn, arg) {
  window.removeEventListener(type, fn, arg || false);
 }
 function isNodeName(el, tag) {
  return el && (el.nodeName || '').toLowerCase() === tag.toLowerCase();
 }
 function directionCheck(x, y) {
  x = (x > 0) ? 1 : -1;
  y = (y > 0) ? 1 : -1;
  if (direction.x !== x || direction.y !== y) {
   direction.x = x;
   direction.y = y;
   que = [];
   lastScroll = 0;
  }
 }
 var hasLocalStorage = !!function () {
  try {
   return localStorage
  } catch (e) {
  }
 }();
 if (hasLocalStorage && window.localStorage && localStorage.SS_deltaBuffer) {
  try {
   deltaBuffer = localStorage.SS_deltaBuffer.split(',');
  } catch (e) {
  }
 }
 function isTouchpad(deltaY) {
  if (!deltaY)
   return;
  if (!deltaBuffer.length) {
   deltaBuffer = [deltaY, deltaY, deltaY];
  }
  deltaY = Math.abs(deltaY);
  deltaBuffer.push(deltaY);
  deltaBuffer.shift();
  clearTimeout(deltaBufferTimer);
  deltaBufferTimer = setTimeout(function () {
   try {
    if (hasLocalStorage) {
     localStorage.SS_deltaBuffer = deltaBuffer.join(',');
    }
   } catch (e) {
   }
  }, 1000);
  var dpiScaledWheelDelta = deltaY > 120 && allDeltasDivisableBy(deltaY);
  var tp = !allDeltasDivisableBy(120) && !allDeltasDivisableBy(100) && !dpiScaledWheelDelta;
  if (deltaY < 50)
   return true;
  return tp;
 }
 function isDivisible(n, divisor) {
  return (Math.floor(n / divisor) == n / divisor);
 }
 function allDeltasDivisableBy(divisor) {
  return (isDivisible(deltaBuffer[0], divisor) && isDivisible(deltaBuffer[1], divisor) && isDivisible(deltaBuffer[2], divisor));
 }
 function isInsideYoutubeVideo(event) {
  var elem = event.target;
  var isControl = false;
  if (document.URL.indexOf('www.youtube.com/watch') != -1) {
   do {
    isControl = (elem.classList && elem.classList.contains('html5-video-controls'));
    if (isControl)
     break;
   } while ((elem = elem.parentNode));
  }
  return isControl;
 }
 var requestFrame = (function () {
  return (window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function (callback, element, delay) {
   window.setTimeout(callback, delay || (1000 / 60));
  }
  );
 }
 )();
 var MutationObserver = (window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver);
 var getScrollRoot = (function () {
  var SCROLL_ROOT = document.scrollingElement;
  return function () {
   if (!SCROLL_ROOT) {
    var dummy = document.createElement('div');
    dummy.style.cssText = 'height:10000px;width:1px;';
    document.body.appendChild(dummy);
    var bodyScrollTop = document.body.scrollTop;
    var docElScrollTop = document.documentElement.scrollTop;
    window.scrollBy(0, 3);
    if (document.body.scrollTop != bodyScrollTop)
     (SCROLL_ROOT = document.body);
    else
     (SCROLL_ROOT = document.documentElement);
    window.scrollBy(0, -3);
    document.body.removeChild(dummy);
   }
   return SCROLL_ROOT;
  }
  ;
 }
 )();
 function pulse_(x) {
  var val, start, expx;
  x = x * options.pulseScale;
  if (x < 1) {
   val = x - (1 - Math.exp(-x));
  } else {
   start = Math.exp(-1);
   x -= 1;
   expx = 1 - Math.exp(-x);
   val = start + (expx * (1 - start));
  }
  return val * options.pulseNormalize;
 }
 function pulse(x) {
  if (x >= 1)
   return 1;
  if (x <= 0)
   return 0;
  if (options.pulseNormalize == 1) {
   options.pulseNormalize /= pulse_(1);
  }
  return pulse_(x);
 }
 var userAgent = window.navigator.userAgent;
 var isEdge = /Edge/.test(userAgent);
 var isChrome = /chrome/i.test(userAgent) && !isEdge;
 var isSafari = /safari/i.test(userAgent) && !isEdge;
 var isMobile = /mobile/i.test(userAgent);
 var isIEWin7 = /Windows NT 6.1/i.test(userAgent) && /rv:11/i.test(userAgent);
 var isOldSafari = isSafari && (/Version\/8/i.test(userAgent) || /Version\/9/i.test(userAgent));
 var isEnabledForBrowser = (isChrome || isSafari || isIEWin7) && !isMobile;
 var supportsPassive = false;
 try {
  window.addEventListener("test", null, Object.defineProperty({}, 'passive', {
   get: function () {
    supportsPassive = true;
   }
  }));
 } catch (e) {
 }
 var wheelOpt = supportsPassive ? {
  passive: false
 } : false;
 var wheelEvent = 'onwheel'in document.createElement('div') ? 'wheel' : 'mousewheel';
 if (wheelEvent && isEnabledForBrowser) {
  addEvent(wheelEvent, wheel, wheelOpt);
  addEvent('mousedown', mousedown);
  addEvent('load', init);
 }
 function SmoothScroll(optionsToSet) {
  for (var key in optionsToSet)
   if (defaultOptions.hasOwnProperty(key))
    options[key] = optionsToSet[key];
 }
 SmoothScroll.destroy = cleanup;
 if (window.SmoothScrollOptions)
  SmoothScroll(window.SmoothScrollOptions);
 if (typeof define === 'function' && define.amd)
  define(function () {
   return SmoothScroll;
  });
 else if ('object' == typeof exports)
  module.exports = SmoothScroll;
 else
  window.SmoothScroll = SmoothScroll;
}
)();
