text: 
  function Util () {};
  
  /* 
  	class manipulation functions
  */
  Util.hasClass = function(el, className) {
  	return el.classList.contains(className);
  };
  
  Util.addClass = function(el, className) {
  	var classList = className.split(' ');
   	el.classList.add(classList[0]);
   	if (classList.length > 1) Util.addClass(el, classList.slice(1).join(' '));
  };
  
  Util.removeClass = function(el, className) {
  	var classList = className.split(' ');
  	el.classList.remove(classList[0]);	
  	if (classList.length > 1) Util.removeClass(el, classList.slice(1).join(' '));
  };
  
  Util.toggleClass = function(el, className, bool) {
  	if(bool) Util.addClass(el, className);
  	else Util.removeClass(el, className);
  };
  
  Util.setAttributes = function(el, attrs) {
    for(var key in attrs) {
      el.setAttribute(key, attrs[key]);
    }
  };
  
  /* 
    DOM manipulation
  */
  Util.getChildrenByClassName = function(el, className) {
    var children = el.children,
      childrenByClass = [];
    for (var i = 0; i < children.length; i++) {
      if (Util.hasClass(children[i], className)) childrenByClass.push(children[i]);
    }
    return childrenByClass;
  };
  
  Util.is = function(elem, selector) {
    if(selector.nodeType){
      return elem === selector;
    }
  
    var qa = (typeof(selector) === 'string' ? document.querySelectorAll(selector) : selector),
      length = qa.length,
      returnArr = [];
  
    while(length--){
      if(qa[length] === elem){
        return true;
      }
    }
  
    return false;
  };
  
  /* 
  	Animate height of an element
  */
  Util.setHeight = function(start, to, element, duration, cb, timeFunction) {
  	var change = to - start,
  	    currentTime = null;
  
    var animateHeight = function(timestamp){  
      if (!currentTime) currentTime = timestamp;         
      var progress = timestamp - currentTime;
      if(progress > duration) progress = duration;
      var val = parseInt((progress/duration)*change + start);
      if(timeFunction) {
        val = Math[timeFunction](progress, start, to - start, duration);
      }
      element.style.height = val+"px";
      if(progress < duration) {
          window.requestAnimationFrame(animateHeight);
      } else {
      	if(cb) cb();
      }
    };
    
    //set the height of the element before starting animation -> fix bug on Safari
    element.style.height = start+"px";
    window.requestAnimationFrame(animateHeight);
  };
  
  /* 
  	Smooth Scroll
  */
  
  Util.scrollTo = function(final, duration, cb, scrollEl) {
    var element = scrollEl || window;
    var start = element.scrollTop || document.documentElement.scrollTop,
      currentTime = null;
  
    if(!scrollEl) start = window.scrollY || document.documentElement.scrollTop;
        
    var animateScroll = function(timestamp){
    	if (!currentTime) currentTime = timestamp;        
      var progress = timestamp - currentTime;
      if(progress > duration) progress = duration;
      var val = Math.easeInOutQuad(progress, start, final-start, duration);
      element.scrollTo(0, val);
      if(progress < duration) {
        window.requestAnimationFrame(animateScroll);
      } else {
        cb && cb();
      }
    };
  
    window.requestAnimationFrame(animateScroll);
  };
  
  /* 
    Focus utility classes
  */
  
  //Move focus to an element
  Util.moveFocus = function (element) {
    if( !element ) element = document.getElementsByTagName("body")[0];
    element.focus();
    if (document.activeElement !== element) {
      element.setAttribute('tabindex','-1');
      element.focus();
    }
  };
  
  /* 
    Misc
  */
  
  Util.getIndexInArray = function(array, el) {
    return Array.prototype.indexOf.call(array, el);
  };
  
  Util.cssSupports = function(property, value) {
    if('CSS' in window) {
      return CSS.supports(property, value);
    } else {
      var jsProperty = property.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase();});
      return jsProperty in document.body.style;
    }
  };
  
  // merge a set of user options into plugin defaults
  // https://gomakethings.com/vanilla-javascript-version-of-jquery-extend/
  Util.extend = function() {
    // Variables
    var extended = {};
    var deep = false;
    var i = 0;
    var length = arguments.length;
  
    // Check if a deep merge
    if ( Object.prototype.toString.call( arguments[0] ) === '[object Boolean]' ) {
      deep = arguments[0];
      i++;
    }
  
    // Merge the object into the extended object
    var merge = function (obj) {
      for ( var prop in obj ) {
        if ( Object.prototype.hasOwnProperty.call( obj, prop ) ) {
          // If deep merge and property is an object, merge properties
          if ( deep && Object.prototype.toString.call(obj[prop]) === '[object Object]' ) {
            extended[prop] = extend( true, extended[prop], obj[prop] );
          } else {
            extended[prop] = obj[prop];
          }
        }
      }
    };
  
    // Loop through each object and conduct a merge
    for ( ; i < length; i++ ) {
      var obj = arguments[i];
      merge(obj);
    }
  
    return extended;
  };
  
  // Check if Reduced Motion is enabled
  Util.osHasReducedMotion = function() {
    if(!window.matchMedia) return false;
    var matchMediaObj = window.matchMedia('(prefers-reduced-motion: reduce)');
    if(matchMediaObj) return matchMediaObj.matches;
    return false; // return false if not supported
  }; 
  
  /* 
  	Polyfills
  */
  //Closest() method
  if (!Element.prototype.matches) {
  	Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
  }
  
  if (!Element.prototype.closest) {
  	Element.prototype.closest = function(s) {
  		var el = this;
  		if (!document.documentElement.contains(el)) return null;
  		do {
  			if (el.matches(s)) return el;
  			el = el.parentElement || el.parentNode;
  		} while (el !== null && el.nodeType === 1); 
  		return null;
  	};
  }
  
  //Custom Event() constructor
  if ( typeof window.CustomEvent !== "function" ) {
  
    function CustomEvent ( event, params ) {
      params = params || { bubbles: false, cancelable: false, detail: undefined };
      var evt = document.createEvent( 'CustomEvent' );
      evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
      return evt;
     }
  
    CustomEvent.prototype = window.Event.prototype;
  
    window.CustomEvent = CustomEvent;
  }
  
  /* 
  	Animation curves
  */
  Math.easeInOutQuad = function (t, b, c, d) {
  	t /= d/2;
  	if (t < 1) return c/2*t*t + b;
  	t--;
  	return -c/2 * (t*(t-2) - 1) + b;
  };
  
  Math.easeInQuart = function (t, b, c, d) {
  	t /= d;
  	return c*t*t*t*t + b;
  };
  
  Math.easeOutQuart = function (t, b, c, d) { 
    t /= d;
  	t--;
  	return -c * (t*t*t*t - 1) + b;
  };
  
  Math.easeInOutQuart = function (t, b, c, d) {
  	t /= d/2;
  	if (t < 1) return c/2*t*t*t*t + b;
  	t -= 2;
  	return -c/2 * (t*t*t*t - 2) + b;
  };
  
  Math.easeOutElastic = function (t, b, c, d) {
    var s=1.70158;var p=d*0.7;var a=c;
    if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
    if (a < Math.abs(c)) { a=c; var s=p/4; }
    else var s = p/(2*Math.PI) * Math.asin (c/a);
    return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
  };
  
  /*HEADER*/ 
  (function() {
      var menuBtns = document.getElementsByClassName('js-anim-menu-btn');
  	if( menuBtns.length > 0 ) {
  		for(var i = 0; i < menuBtns.length; i++) {(function(i){
  			initMenuBtn(menuBtns[i]);
  		})(i);}
  
  		function initMenuBtn(btn) {
  			btn.addEventListener('click', function(event){	
  				event.preventDefault();
  				var status = !Util.hasClass(btn, 'anim-menu-btn--state-b');
  				Util.toggleClass(btn, 'anim-menu-btn--state-b', status);
  				// emit custom event
  				var event = new CustomEvent('anim-menu-btn-clicked', {detail: status});
  				btn.dispatchEvent(event);
  			});
  		};
  	};
  
    
    var flexHeader = document.getElementsByClassName('js-f-header');
    if(flexHeader.length > 0) {
      var menuTrigger = flexHeader[0].getElementsByClassName('js-anim-menu-btn')[0],
        firstFocusableElement = getMenuFirstFocusable();
  
      // we'll use these to store the node that needs to receive focus when the mobile menu is closed 
      var focusMenu = false;
  
      resetFlexHeaderOffset();
      setAriaButtons();
  
      menuTrigger.addEventListener('anim-menu-btn-clicked', function(event){
        toggleMenuNavigation(event.detail);
      });
  
      // listen for key events
      window.addEventListener('keyup', function(event){
        // listen for esc key
        if( (event.keyCode && event.keyCode == 27) || (event.key && event.key.toLowerCase() == 'escape' )) {
          // close navigation on mobile if open
          if(menuTrigger.getAttribute('aria-expanded') == 'true' && isVisible(menuTrigger)) {
            focusMenu = menuTrigger; // move focus to menu trigger when menu is close
            menuTrigger.click();
          }
        }
        // listen for tab key
        if( (event.keyCode && event.keyCode == 9) || (event.key && event.key.toLowerCase() == 'tab' )) {
          // close navigation on mobile if open when nav loses focus
          if(menuTrigger.getAttribute('aria-expanded') == 'true' && isVisible(menuTrigger) && !document.activeElement.closest('.js-f-header')) menuTrigger.click();
        }
      });
  
      // detect click on a dropdown control button - expand-on-mobile only
      flexHeader[0].addEventListener('click', function(event){
        var btnLink = event.target.closest('.js-f-header__dropdown-control');
        if(!btnLink) return;
        !btnLink.getAttribute('aria-expanded') ? btnLink.setAttribute('aria-expanded', 'true') : btnLink.removeAttribute('aria-expanded');
      });
  
      // detect mouseout from a dropdown control button - expand-on-mobile only
      flexHeader[0].addEventListener('mouseout', function(event){
        var btnLink = event.target.closest('.js-f-header__dropdown-control');
        if(!btnLink) return;
        // check layout type
        if(getLayout() == 'mobile') return;
        btnLink.removeAttribute('aria-expanded');
      });
  
      // close dropdown on focusout - expand-on-mobile only
      flexHeader[0].addEventListener('focusin', function(event){
        var btnLink = event.target.closest('.js-f-header__dropdown-control'),
          dropdown = event.target.closest('.f-header__dropdown');
        if(dropdown) return;
        if(btnLink && btnLink.hasAttribute('aria-expanded')) return;
        // check layout type
        if(getLayout() == 'mobile') return;
        var openDropdown = flexHeader[0].querySelector('.js-f-header__dropdown-control[aria-expanded="true"]');
        if(openDropdown) openDropdown.removeAttribute('aria-expanded');
      });
  
      // listen for resize
      var resizingId = false;
      window.addEventListener('resize', function() {
        clearTimeout(resizingId);
        resizingId = setTimeout(doneResizing, 500);
      });
  
      function getMenuFirstFocusable() {
        var focusableEle = flexHeader[0].getElementsByClassName('f-header__nav')[0].querySelectorAll('[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex]:not([tabindex="-1"]), [contenteditable], audio[controls], video[controls], summary'),
          firstFocusable = false;
        for(var i = 0; i < focusableEle.length; i++) {
          if( focusableEle[i].offsetWidth || focusableEle[i].offsetHeight || focusableEle[i].getClientRects().length ) {
            firstFocusable = focusableEle[i];
            break;
          }
        }
  
        return firstFocusable;
      };
      
      function isVisible(element) {
        return (element.offsetWidth || element.offsetHeight || element.getClientRects().length);
      };
  
      function doneResizing() {
        if( !isVisible(menuTrigger) && Util.hasClass(flexHeader[0], 'f-header--expanded')) {
          menuTrigger.click();
        }
        resetFlexHeaderOffset();
      };
      
      function toggleMenuNavigation(bool) { // toggle menu visibility on small devices
        Util.toggleClass(document.getElementsByClassName('f-header__nav')[0], 'f-header__nav--is-visible', bool);
        Util.toggleClass(flexHeader[0], 'f-header--expanded', bool);
        menuTrigger.setAttribute('aria-expanded', bool);
        if(bool) firstFocusableElement.focus(); // move focus to first focusable element
        else if(focusMenu) {
          focusMenu.focus();
          focusMenu = false;
        }
      };
  
      function resetFlexHeaderOffset() {
        // on mobile -> update max height of the flexi header based on its offset value (e.g., if there's a fixed pre-header element)
        document.documentElement.style.setProperty('--f-header-offset', flexHeader[0].getBoundingClientRect().top+'px');
      };
  
      function setAriaButtons() {
        var btnDropdown = flexHeader[0].getElementsByClassName('js-f-header__dropdown-control');
        for(var i = 0; i < btnDropdown.length; i++) {
          var id = 'f-header-dropdown-'+i,
            dropdown = btnDropdown[i].nextElementSibling;
          if(dropdown.hasAttribute('id')) {
            id = dropdown.getAttribute('id');
          } else {
            dropdown.setAttribute('id', id);
          }
          btnDropdown[i].setAttribute('aria-controls', id);	
        }
      };
  
      function getLayout() {
        return getComputedStyle(flexHeader[0], ':before').getPropertyValue('content').replace(/\'|"/g, '');
      };
    }
  
    var hidingNav = document.getElementsByClassName('js-hide-nav');
    if(hidingNav.length > 0 && window.requestAnimationFrame) {
      var mainNav = Array.prototype.filter.call(hidingNav, function(element) {
        return Util.hasClass(element, 'js-hide-nav--main');
      }),
      subNav = Array.prototype.filter.call(hidingNav, function(element) {
        return Util.hasClass(element, 'js-hide-nav--sub');
      });
      
      var scrolling = false,
        previousTop = window.scrollY,
        currentTop = window.scrollY,
        scrollDelta = 10,
        scrollOffset = 150, // scrollY needs to be bigger than scrollOffset to hide navigation
        headerHeight = 0; 
  
      var navIsFixed = false; // check if main navigation is fixed
      if(mainNav.length > 0 && Util.hasClass(mainNav[0], 'hide-nav--fixed')) navIsFixed = true;
  
      // store button that triggers navigation on mobile
      var triggerMobile = getTriggerMobileMenu();
      var prevElement = createPrevElement();
      var mainNavTop = 0;
      // list of classes the hide-nav has when it is expanded -> do not hide if it has those classes
      var navOpenClasses = hidingNav[0].getAttribute('data-nav-target-class'),
        navOpenArrayClasses = [];
      if(navOpenClasses) navOpenArrayClasses = navOpenClasses.split(' ');
      getMainNavTop();
      if(mainNavTop > 0) {
        scrollOffset = scrollOffset + mainNavTop;
      }
      
      // init navigation and listen to window scroll event
      getHeaderHeight();
      initSecondaryNav();
      initFixedNav();
      resetHideNav();
      window.addEventListener('scroll', function(event){
        if(scrolling) return;
        scrolling = true;
        window.requestAnimationFrame(resetHideNav);
      });
  
      window.addEventListener('resize', function(event){
        if(scrolling) return;
        scrolling = true;
        window.requestAnimationFrame(function(){
          if(headerHeight > 0) {
            getMainNavTop();
            getHeaderHeight();
            initSecondaryNav();
            initFixedNav();
          }
          // reset both navigation
          hideNavScrollUp();
  
          scrolling = false;
        });
      });
  
      function getHeaderHeight() {
        headerHeight = mainNav[0].offsetHeight;
      };
  
      function initSecondaryNav() { // if there's a secondary nav, set its top equal to the header height
        if(subNav.length < 1 || mainNav.length < 1) return;
        subNav[0].style.top = (headerHeight - 1)+'px';
      };
  
      function initFixedNav() {
        if(!navIsFixed || mainNav.length < 1) return;
        mainNav[0].style.marginBottom = '-'+headerHeight+'px';
      };
  
      function resetHideNav() { // check if navs need to be hidden/revealed
        currentTop = window.scrollY;
        if(currentTop - previousTop > scrollDelta && currentTop > scrollOffset) {
          hideNavScrollDown();
        } else if( previousTop - currentTop > scrollDelta || (previousTop - currentTop > 0 && currentTop < scrollOffset) ) {
          hideNavScrollUp();
        } else if( previousTop - currentTop > 0 && subNav.length > 0 && subNav[0].getBoundingClientRect().top > 0) {
          setTranslate(subNav[0], '0%');
        }
        // if primary nav is fixed -> toggle bg class
        if(navIsFixed) {
          var scrollTop = window.scrollY || window.pageYOffset;
          Util.toggleClass(mainNav[0], 'hide-nav--has-bg', (scrollTop > headerHeight + mainNavTop));
        }
        previousTop = currentTop;
        scrolling = false;
      };
  
      function hideNavScrollDown() {
        // if there's a secondary nav -> it has to reach the top before hiding nav
        if( subNav.length  > 0 && subNav[0].getBoundingClientRect().top > headerHeight) return;
        // on mobile -> hide navigation only if dropdown is not open
        if(triggerMobile && triggerMobile.getAttribute('aria-expanded') == "true") return;
        // check if main nav has one of the following classes
        if( mainNav.length > 0 && (!navOpenClasses || !checkNavExpanded())) {
          setTranslate(mainNav[0], '-100%'); 
          mainNav[0].addEventListener('transitionend', addOffCanvasClass);
        }
        if( subNav.length  > 0 ) setTranslate(subNav[0], '-'+headerHeight+'px');
      };
  
      function hideNavScrollUp() {
        if( mainNav.length > 0 ) {setTranslate(mainNav[0], '0%'); Util.removeClass(mainNav[0], 'hide-nav--off-canvas');mainNav[0].removeEventListener('transitionend', addOffCanvasClass);}
        if( subNav.length  > 0 ) setTranslate(subNav[0], '0%');
      };
  
      function addOffCanvasClass() {
        mainNav[0].removeEventListener('transitionend', addOffCanvasClass);
        Util.addClass(mainNav[0], 'hide-nav--off-canvas');
      };
  
      function setTranslate(element, val) {
        element.style.transform = 'translateY('+val+')';
      };
  
      function getTriggerMobileMenu() {
        // store trigger that toggle mobile navigation dropdown
        var triggerMobileClass = hidingNav[0].getAttribute('data-mobile-trigger');
        if(!triggerMobileClass) return false;
        if(triggerMobileClass.indexOf('#') == 0) { // get trigger by ID
          var trigger = document.getElementById(triggerMobileClass.replace('#', ''));
          if(trigger) return trigger;
        } else { // get trigger by class name
          var trigger = hidingNav[0].getElementsByClassName(triggerMobileClass);
          if(trigger.length > 0) return trigger[0];
        }
        
        return false;
      };
  
      function createPrevElement() {
        // create element to be inserted right before the mainNav to get its top value
        if( mainNav.length < 1) return false;
        var newElement = document.createElement("div"); 
        newElement.setAttribute('aria-hidden', 'true');
        mainNav[0].parentElement.insertBefore(newElement, mainNav[0]);
        var prevElement =  mainNav[0].previousElementSibling;
        prevElement.style.opacity = '0';
        return prevElement;
      };
  
      function getMainNavTop() {
        if(!prevElement) return;
        mainNavTop = prevElement.getBoundingClientRect().top + window.scrollY;
      };
  
      function checkNavExpanded() {
        var navIsOpen = false;
        for(var i = 0; i < navOpenArrayClasses.length; i++){
          if(Util.hasClass(mainNav[0], navOpenArrayClasses[i].trim())) {
            navIsOpen = true;
            break;
          }
        }
        return navIsOpen;
      };
      
    } else {
      // if window requestAnimationFrame is not supported -> add bg class to fixed header
      var mainNav = document.getElementsByClassName('js-hide-nav--main');
      if(mainNav.length < 1) return;
      if(Util.hasClass(mainNav[0], 'hide-nav--fixed')) Util.addClass(mainNav[0], 'hide-nav--has-bg');
    }
  }());
  
  