/*! @license ScrollReveal v4.0.7

	Copyright 2020 Fisssion LLC.

	Licensed under the GNU General Public License 3.0 for
	compatible open source projects and non-commercial use.

	For commercial sites, themes, projects, and applications,
	keep your source code private/proprietary by purchasing
	a commercial license from https://scrollrevealjs.org/
*/
(function (global, factory) {
	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
	typeof define === 'function' && define.amd ? define(factory) :
	(global = global || self, global.ScrollReveal = factory());
}(this, function () { 'use strict';

	var defaults = {
		delay: 0,
		distance: '0',
		duration: 600,
		easing: 'cubic-bezier(0.5, 0, 0, 1)',
		interval: 0,
		opacity: 0,
		origin: 'bottom',
		rotate: {
			x: 0,
			y: 0,
			z: 0
		},
		scale: 1,
		cleanup: false,
		container: document.documentElement,
		desktop: true,
		mobile: true,
		reset: false,
		useDelay: 'always',
		viewFactor: 0.0,
		viewOffset: {
			top: 0,
			right: 0,
			bottom: 0,
			left: 0
		},
		afterReset: function afterReset() {},
		afterReveal: function afterReveal() {},
		beforeReset: function beforeReset() {},
		beforeReveal: function beforeReveal() {}
	};

	function failure() {
		document.documentElement.classList.remove('sr');

		return {
			clean: function clean() {},
			destroy: function destroy() {},
			reveal: function reveal() {},
			sync: function sync() {},
			get noop() {
				return true
			}
		}
	}

	function success() {
		document.documentElement.classList.add('sr');

		if (document.body) {
			document.body.style.height = '100%';
		} else {
			document.addEventListener('DOMContentLoaded', function () {
				document.body.style.height = '100%';
			});
		}
	}

	var mount = { success: success, failure: failure };

	/*! @license is-dom-node v1.0.4

		Copyright 2018 Fisssion LLC.

		Permission is hereby granted, free of charge, to any person obtaining a copy
		of this software and associated documentation files (the "Software"), to deal
		in the Software without restriction, including without limitation the rights
		to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
		copies of the Software, and to permit persons to whom the Software is
		furnished to do so, subject to the following conditions:

		The above copyright notice and this permission notice shall be included in all
		copies or substantial portions of the Software.

		THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
		IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
		FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
		AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
		LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
		OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
		SOFTWARE.

	*/
	function isDomNode(x) {
		return typeof window.Node === 'object'
			? x instanceof window.Node
			: x !== null &&
					typeof x === 'object' &&
					typeof x.nodeType === 'number' &&
					typeof x.nodeName === 'string'
	}

	/*! @license is-dom-node-list v1.2.1

		Copyright 2018 Fisssion LLC.

		Permission is hereby granted, free of charge, to any person obtaining a copy
		of this software and associated documentation files (the "Software"), to deal
		in the Software without restriction, including without limitation the rights
		to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
		copies of the Software, and to permit persons to whom the Software is
		furnished to do so, subject to the following conditions:

		The above copyright notice and this permission notice shall be included in all
		copies or substantial portions of the Software.

		THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
		IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
		FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
		AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
		LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
		OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
		SOFTWARE.

	*/

	function isDomNodeList(x) {
		var prototypeToString = Object.prototype.toString.call(x);
		var regex = /^\[object (HTMLCollection|NodeList|Object)\]$/;

		return typeof window.NodeList === 'object'
			? x instanceof window.NodeList
			: x !== null &&
					typeof x === 'object' &&
					typeof x.length === 'number' &&
					regex.test(prototypeToString) &&
					(x.length === 0 || isDomNode(x[0]))
	}

	/*! @license Tealight v0.3.6

		Copyright 2018 Fisssion LLC.

		Permission is hereby granted, free of charge, to any person obtaining a copy
		of this software and associated documentation files (the "Software"), to deal
		in the Software without restriction, including without limitation the rights
		to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
		copies of the Software, and to permit persons to whom the Software is
		furnished to do so, subject to the following conditions:

		The above copyright notice and this permission notice shall be included in all
		copies or substantial portions of the Software.

		THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
		IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
		FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
		AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
		LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
		OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
		SOFTWARE.

	*/

	function tealight(target, context) {
	  if ( context === void 0 ) { context = document; }

	  if (target instanceof Array) { return target.filter(isDomNode); }
	  if (isDomNode(target)) { return [target]; }
	  if (isDomNodeList(target)) { return Array.prototype.slice.call(target); }
	  if (typeof target === "string") {
	    try {
	      var query = context.querySelectorAll(target);
	      return Array.prototype.slice.call(query);
	    } catch (err) {
	      return [];
	    }
	  }
	  return [];
	}

	function isObject(x) {
		return (
			x !== null &&
			x instanceof Object &&
			(x.constructor === Object ||
				Object.prototype.toString.call(x) === '[object Object]')
		)
	}

	function each(collection, callback) {
		if (isObject(collection)) {
			var keys = Object.keys(collection);
			return keys.forEach(function (key) { return callback(collection[key], key, collection); })
		}
		if (collection instanceof Array) {
			return collection.forEach(function (item, i) { return callback(item, i, collection); })
		}
		throw new TypeError('Expected either an array or object literal.')
	}

	function logger(message) {
		var details = [], len = arguments.length - 1;
		while ( len-- > 0 ) details[ len ] = arguments[ len + 1 ];

		if (this.constructor.debug && console) {
			var report = "%cScrollReveal: " + message;
			details.forEach(function (detail) { return (report += "\n — " + detail); });
			console.log(report, 'color: #ea654b;'); // eslint-disable-line no-console
		}
	}

	function rinse() {
		var this$1 = this;

		var struct = function () { return ({
			active: [],
			stale: []
		}); };

		var elementIds = struct();
		var sequenceIds = struct();
		var containerIds = struct();

		/**
		 * Take stock of active element IDs.
		 */
		try {
			each(tealight('[data-sr-id]'), function (node) {
				var id = parseInt(node.getAttribute('data-sr-id'));
				elementIds.active.push(id);
			});
		} catch (e) {
			throw e
		}
		/**
		 * Destroy stale elements.
		 */
		each(this.store.elements, function (element) {
			if (elementIds.active.indexOf(element.id) === -1) {
				elementIds.stale.push(element.id);
			}
		});

		each(elementIds.stale, function (staleId) { return delete this$1.store.elements[staleId]; });

		/**
		 * Take stock of active container and sequence IDs.
		 */
		each(this.store.elements, function (element) {
			if (containerIds.active.indexOf(element.containerId) === -1) {
				containerIds.active.push(element.containerId);
			}
			if (element.hasOwnProperty('sequence')) {
				if (sequenceIds.active.indexOf(element.sequence.id) === -1) {
					sequenceIds.active.push(element.sequence.id);
				}
			}
		});

		/**
		 * Destroy stale containers.
		 */
		each(this.store.containers, function (container) {
			if (containerIds.active.indexOf(container.id) === -1) {
				containerIds.stale.push(container.id);
			}
		});

		each(containerIds.stale, function (staleId) {
			var stale = this$1.store.containers[staleId].node;
			stale.removeEventListener('scroll', this$1.delegate);
			stale.removeEventListener('resize', this$1.delegate);
			delete this$1.store.containers[staleId];
		});

		/**
		 * Destroy stale sequences.
		 */
		each(this.store.sequences, function (sequence) {
			if (sequenceIds.active.indexOf(sequence.id) === -1) {
				sequenceIds.stale.push(sequence.id);
			}
		});

		each(sequenceIds.stale, function (staleId) { return delete this$1.store.sequences[staleId]; });
	}

	function clean(target) {
		var this$1 = this;

		var dirty;
		try {
			each(tealight(target), function (node) {
				var id = node.getAttribute('data-sr-id');
				if (id !== null) {
					dirty = true;
					var element = this$1.store.elements[id];
					if (element.callbackTimer) {
						window.clearTimeout(element.callbackTimer.clock);
					}
					node.setAttribute('style', element.styles.inline.generated);
					node.removeAttribute('data-sr-id');
					delete this$1.store.elements[id];
				}
			});
		} catch (e) {
			return logger.call(this, 'Clean failed.', e.message)
		}

		if (dirty) {
			try {
				rinse.call(this);
			} catch (e) {
				return logger.call(this, 'Clean failed.', e.message)
			}
		}
	}

	function destroy() {
		var this$1 = this;

		/**
		 * Remove all generated styles and element ids
		 */
		each(this.store.elements, function (element) {
			element.node.setAttribute('style', element.styles.inline.generated);
			element.node.removeAttribute('data-sr-id');
		});

		/**
		 * Remove all event listeners.
		 */
		each(this.store.containers, function (container) {
			var target =
				container.node === document.documentElement ? window : container.node;
			target.removeEventListener('scroll', this$1.delegate);
			target.removeEventListener('resize', this$1.delegate);
		});

		/**
		 * Clear all data from the store
		 */
		this.store = {
			containers: {},
			elements: {},
			history: [],
			sequences: {}
		};
	}

	/*! @license Rematrix v0.3.0

		Copyright 2018 Julian Lloyd.

		Permission is hereby granted, free of charge, to any person obtaining a copy
		of this software and associated documentation files (the "Software"), to deal
		in the Software without restriction, including without limitation the rights
		to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
		copies of the Software, and to permit persons to whom the Software is
		furnished to do so, subject to the following conditions:

		The above copyright notice and this permission notice shall be included in
		all copies or substantial portions of the Software.

		THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
		IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
		FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
		AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
		LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
		OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
		THE SOFTWARE.
	*/
	/**
	 * @module Rematrix
	 */

	/**
	 * Transformation matrices in the browser come in two flavors:
	 *
	 *  - `matrix` using 6 values (short)
	 *  - `matrix3d` using 16 values (long)
	 *
	 * This utility follows this [conversion guide](https://goo.gl/EJlUQ1)
	 * to expand short form matrices to their equivalent long form.
	 *
	 * @param  {array} source - Accepts both short and long form matrices.
	 * @return {array}
	 */
	function format(source) {
		if (source.constructor !== Array) {
			throw new TypeError('Expected array.')
		}
		if (source.length === 16) {
			return source
		}
		if (source.length === 6) {
			var matrix = identity();
			matrix[0] = source[0];
			matrix[1] = source[1];
			matrix[4] = source[2];
			matrix[5] = source[3];
			matrix[12] = source[4];
			matrix[13] = source[5];
			return matrix
		}
		throw new RangeError('Expected array with either 6 or 16 values.')
	}

	/**
	 * Returns a matrix representing no transformation. The product of any matrix
	 * multiplied by the identity matrix will be the original matrix.
	 *
	 * > **Tip:** Similar to how `5 * 1 === 5`, where `1` is the identity.
	 *
	 * @return {array}
	 */
	function identity() {
		var matrix = [];
		for (var i = 0; i < 16; i++) {
			i % 5 == 0 ? matrix.push(1) : matrix.push(0);
		}
		return matrix
	}

	/**
	 * Returns a 4x4 matrix describing the combined transformations
	 * of both arguments.
	 *
	 * > **Note:** Order is very important. For example, rotating 45°
	 * along the Z-axis, followed by translating 500 pixels along the
	 * Y-axis... is not the same as translating 500 pixels along the
	 * Y-axis, followed by rotating 45° along on the Z-axis.
	 *
	 * @param  {array} m - Accepts both short and long form matrices.
	 * @param  {array} x - Accepts both short and long form matrices.
	 * @return {array}
	 */
	function multiply(m, x) {
		var fm = format(m);
		var fx = format(x);
		var product = [];

		for (var i = 0; i < 4; i++) {
			var row = [fm[i], fm[i + 4], fm[i + 8], fm[i + 12]];
			for (var j = 0; j < 4; j++) {
				var k = j * 4;
				var col = [fx[k], fx[k + 1], fx[k + 2], fx[k + 3]];
				var result =
					row[0] * col[0] + row[1] * col[1] + row[2] * col[2] + row[3] * col[3];

				product[i + k] = result;
			}
		}

		return product
	}

	/**
	 * Attempts to return a 4x4 matrix describing the CSS transform
	 * matrix passed in, but will return the identity matrix as a
	 * fallback.
	 *
	 * > **Tip:** This method is used to convert a CSS matrix (retrieved as a
	 * `string` from computed styles) to its equivalent array format.
	 *
	 * @param  {string} source - `matrix` or `matrix3d` CSS Transform value.
	 * @return {array}
	 */
	function parse(source) {
		if (typeof source === 'string') {
			var match = source.match(/matrix(3d)?\(([^)]+)\)/);
			if (match) {
				var raw = match[2].split(', ').map(parseFloat);
				return format(raw)
			}
		}
		return identity()
	}

	/**
	 * Returns a 4x4 matrix describing X-axis rotation.
	 *
	 * @param  {number} angle - Measured in degrees.
	 * @return {array}
	 */
	function rotateX(angle) {
		var theta = Math.PI / 180 * angle;
		var matrix = identity();

		matrix[5] = matrix[10] = Math.cos(theta);
		matrix[6] = matrix[9] = Math.sin(theta);
		matrix[9] *= -1;

		return matrix
	}

	/**
	 * Returns a 4x4 matrix describing Y-axis rotation.
	 *
	 * @param  {number} angle - Measured in degrees.
	 * @return {array}
	 */
	function rotateY(angle) {
		var theta = Math.PI / 180 * angle;
		var matrix = identity();

		matrix[0] = matrix[10] = Math.cos(theta);
		matrix[2] = matrix[8] = Math.sin(theta);
		matrix[2] *= -1;

		return matrix
	}

	/**
	 * Returns a 4x4 matrix describing Z-axis rotation.
	 *
	 * @param  {number} angle - Measured in degrees.
	 * @return {array}
	 */
	function rotateZ(angle) {
		var theta = Math.PI / 180 * angle;
		var matrix = identity();

		matrix[0] = matrix[5] = Math.cos(theta);
		matrix[1] = matrix[4] = Math.sin(theta);
		matrix[4] *= -1;

		return matrix
	}

	/**
	 * Returns a 4x4 matrix describing 2D scaling. The first argument
	 * is used for both X and Y-axis scaling, unless an optional
	 * second argument is provided to explicitly define Y-axis scaling.
	 *
	 * @param  {number} scalar    - Decimal multiplier.
	 * @param  {number} [scalarY] - Decimal multiplier.
	 * @return {array}
	 */
	function scale(scalar, scalarY) {
		var matrix = identity();

		matrix[0] = scalar;
		matrix[5] = typeof scalarY === 'number' ? scalarY : scalar;

		return matrix
	}

	/**
	 * Returns a 4x4 matrix describing X-axis translation.
	 *
	 * @param  {number} distance - Measured in pixels.
	 * @return {array}
	 */
	function translateX(distance) {
		var matrix = identity();
		matrix[12] = distance;
		return matrix
	}

	/**
	 * Returns a 4x4 matrix describing Y-axis translation.
	 *
	 * @param  {number} distance - Measured in pixels.
	 * @return {array}
	 */
	function translateY(distance) {
		var matrix = identity();
		matrix[13] = distance;
		return matrix
	}

	var getPrefixedCssProp = (function () {
		var properties = {};
		var style = document.documentElement.style;

		function getPrefixedCssProperty(name, source) {
			if ( source === void 0 ) source = style;

			if (name && typeof name === 'string') {
				if (properties[name]) {
					return properties[name]
				}
				if (typeof source[name] === 'string') {
					return (properties[name] = name)
				}
				if (typeof source[("-webkit-" + name)] === 'string') {
					return (properties[name] = "-webkit-" + name)
				}
				throw new RangeError(("Unable to find \"" + name + "\" style property."))
			}
			throw new TypeError('Expected a string.')
		}

		getPrefixedCssProperty.clearCache = function () { return (properties = {}); };

		return getPrefixedCssProperty
	})();

	function style(element) {
		var computed = window.getComputedStyle(element.node);
		var position = computed.position;
		var config = element.config;

		/**
		 * Generate inline styles
		 */
		var inline = {};
		var inlineStyle = element.node.getAttribute('style') || '';
		var inlineMatch = inlineStyle.match(/[\w-]+\s*:\s*[^;]+\s*/gi) || [];

		inline.computed = inlineMatch ? inlineMatch.map(function (m) { return m.trim(); }).join('; ') + ';' : '';

		inline.generated = inlineMatch.some(function (m) { return m.match(/visibility\s?:\s?visible/i); })
			? inline.computed
			: inlineMatch.concat( ['visibility: visible']).map(function (m) { return m.trim(); }).join('; ') + ';';

		/**
		 * Generate opacity styles
		 */
		var computedOpacity = parseFloat(computed.opacity);
		var configOpacity = !isNaN(parseFloat(config.opacity))
			? parseFloat(config.opacity)
			: parseFloat(computed.opacity);

		var opacity = {
			computed: computedOpacity !== configOpacity ? ("opacity: " + computedOpacity + ";") : '',
			generated: computedOpacity !== configOpacity ? ("opacity: " + configOpacity + ";") : ''
		};

		/**
		 * Generate transformation styles
		 */
		var transformations = [];

		if (parseFloat(config.distance)) {
			var axis = config.origin === 'top' || config.origin === 'bottom' ? 'Y' : 'X';

			/**
			 * Let’s make sure our our pixel distances are negative for top and left.
			 * e.g. { origin: 'top', distance: '25px' } starts at `top: -25px` in CSS.
			 */
			var distance = config.distance;
			if (config.origin === 'top' || config.origin === 'left') {
				distance = /^-/.test(distance) ? distance.substr(1) : ("-" + distance);
			}

			var ref = distance.match(/(^-?\d+\.?\d?)|(em$|px$|%$)/g);
			var value = ref[0];
			var unit = ref[1];

			switch (unit) {
				case 'em':
					distance = parseInt(computed.fontSize) * value;
					break
				case 'px':
					distance = value;
					break
				case '%':
					/**
					 * Here we use `getBoundingClientRect` instead of
					 * the existing data attached to `element.geometry`
					 * because only the former includes any transformations
					 * current applied to the element.
					 *
					 * If that behavior ends up being unintuitive, this
					 * logic could instead utilize `element.geometry.height`
					 * and `element.geoemetry.width` for the distance calculation
					 */
					distance =
						axis === 'Y'
							? (element.node.getBoundingClientRect().height * value) / 100
							: (element.node.getBoundingClientRect().width * value) / 100;
					break
				default:
					throw new RangeError('Unrecognized or missing distance unit.')
			}

			if (axis === 'Y') {
				transformations.push(translateY(distance));
			} else {
				transformations.push(translateX(distance));
			}
		}

		if (config.rotate.x) { transformations.push(rotateX(config.rotate.x)); }
		if (config.rotate.y) { transformations.push(rotateY(config.rotate.y)); }
		if (config.rotate.z) { transformations.push(rotateZ(config.rotate.z)); }
		if (config.scale !== 1) {
			if (config.scale === 0) {
				/**
				 * The CSS Transforms matrix interpolation specification
				 * basically disallows transitions of non-invertible
				 * matrixes, which means browsers won't transition
				 * elements with zero scale.
				 *
				 * That’s inconvenient for the API and developer
				 * experience, so we simply nudge their value
				 * slightly above zero; this allows browsers
				 * to transition our element as expected.
				 *
				 * `0.0002` was the smallest number
				 * that performed across browsers.
				 */
				transformations.push(scale(0.0002));
			} else {
				transformations.push(scale(config.scale));
			}
		}

		var transform = {};
		if (transformations.length) {
			transform.property = getPrefixedCssProp('transform');
			/**
			 * The default computed transform value should be one of:
			 * undefined || 'none' || 'matrix()' || 'matrix3d()'
			 */
			transform.computed = {
				raw: computed[transform.property],
				matrix: parse(computed[transform.property])
			};

			transformations.unshift(transform.computed.matrix);
			var product = transformations.reduce(multiply);

			transform.generated = {
				initial: ((transform.property) + ": matrix3d(" + (product.join(', ')) + ");"),
				final: ((transform.property) + ": matrix3d(" + (transform.computed.matrix.join(', ')) + ");")
			};
		} else {
			transform.generated = {
				initial: '',
				final: ''
			};
		}

		/**
		 * Generate transition styles
		 */
		var transition = {};
		if (opacity.generated || transform.generated.initial) {
			transition.property = getPrefixedCssProp('transition');
			transition.computed = computed[transition.property];
			transition.fragments = [];

			var delay = config.delay;
			var duration = config.duration;
			var easing = config.easing;

			if (opacity.generated) {
				transition.fragments.push({
					delayed: ("opacity " + (duration / 1000) + "s " + easing + " " + (delay / 1000) + "s"),
					instant: ("opacity " + (duration / 1000) + "s " + easing + " 0s")
				});
			}

			if (transform.generated.initial) {
				transition.fragments.push({
					delayed: ((transform.property) + " " + (duration / 1000) + "s " + easing + " " + (delay / 1000) + "s"),
					instant: ((transform.property) + " " + (duration / 1000) + "s " + easing + " 0s")
				});
			}

			/**
			 * The default computed transition property should be undefined, or one of:
			 * '' || 'none 0s ease 0s' || 'all 0s ease 0s' || 'all 0s 0s cubic-bezier()'
			 */
			var hasCustomTransition =
				transition.computed && !transition.computed.match(/all 0s|none 0s/);

			if (hasCustomTransition) {
				transition.fragments.unshift({
					delayed: transition.computed,
					instant: transition.computed
				});
			}

			var composed = transition.fragments.reduce(
				function (composition, fragment, i) {
					composition.delayed += i === 0 ? fragment.delayed : (", " + (fragment.delayed));
					composition.instant += i === 0 ? fragment.instant : (", " + (fragment.instant));
					return composition
				},
				{
					delayed: '',
					instant: ''
				}
			);

			transition.generated = {
				delayed: ((transition.property) + ": " + (composed.delayed) + ";"),
				instant: ((transition.property) + ": " + (composed.instant) + ";")
			};
		} else {
			transition.generated = {
				delayed: '',
				instant: ''
			};
		}

		return {
			inline: inline,
			opacity: opacity,
			position: position,
			transform: transform,
			transition: transition
		}
	}

	function animate(element, force) {
		if ( force === void 0 ) force = {};

		var pristine = force.pristine || this.pristine;
		var delayed =
			element.config.useDelay === 'always' ||
			(element.config.useDelay === 'onload' && pristine) ||
			(element.config.useDelay === 'once' && !element.seen);

		var shouldReveal = element.visible && !element.revealed;
		var shouldReset = !element.visible && element.revealed && element.config.reset;

		if (force.reveal || shouldReveal) {
			return triggerReveal.call(this, element, delayed)
		}

		if (force.reset || shouldReset) {
			return triggerReset.call(this, element)
		}
	}

	function triggerReveal(element, delayed) {
		var styles = [
			element.styles.inline.generated,
			element.styles.opacity.computed,
			element.styles.transform.generated.final
		];
		if (delayed) {
			styles.push(element.styles.transition.generated.delayed);
		} else {
			styles.push(element.styles.transition.generated.instant);
		}
		element.revealed = element.seen = true;
		element.node.setAttribute('style', styles.filter(function (s) { return s !== ''; }).join(' '));
		registerCallbacks.call(this, element, delayed);
	}

	function triggerReset(element) {
		var styles = [
			element.styles.inline.generated,
			element.styles.opacity.generated,
			element.styles.transform.generated.initial,
			element.styles.transition.generated.instant
		];
		element.revealed = false;
		element.node.setAttribute('style', styles.filter(function (s) { return s !== ''; }).join(' '));
		registerCallbacks.call(this, element);
	}

	function registerCallbacks(element, isDelayed) {
		var this$1 = this;

		var duration = isDelayed
			? element.config.duration + element.config.delay
			: element.config.duration;

		var beforeCallback = element.revealed
			? element.config.beforeReveal
			: element.config.beforeReset;

		var afterCallback = element.revealed
			? element.config.afterReveal
			: element.config.afterReset;

		var elapsed = 0;
		if (element.callbackTimer) {
			elapsed = Date.now() - element.callbackTimer.start;
			window.clearTimeout(element.callbackTimer.clock);
		}

		beforeCallback(element.node);

		element.callbackTimer = {
			start: Date.now(),
			clock: window.setTimeout(function () {
				afterCallback(element.node);
				element.callbackTimer = null;
				if (element.revealed && !element.config.reset && element.config.cleanup) {
					clean.call(this$1, element.node);
				}
			}, duration - elapsed)
		};
	}

	var nextUniqueId = (function () {
		var uid = 0;
		return function () { return uid++; }
	})();

	function sequence(element, pristine) {
		if ( pristine === void 0 ) pristine = this.pristine;

		/**
		 * We first check if the element should reset.
		 */
		if (!element.visible && element.revealed && element.config.reset) {
			return animate.call(this, element, { reset: true })
		}

		var seq = this.store.sequences[element.sequence.id];
		var i = element.sequence.index;

		if (seq) {
			var visible = new SequenceModel(seq, 'visible', this.store);
			var revealed = new SequenceModel(seq, 'revealed', this.store);

			seq.models = { visible: visible, revealed: revealed };

			/**
			 * If the sequence has no revealed members,
			 * then we reveal the first visible element
			 * within that sequence.
			 *
			 * The sequence then cues a recursive call
			 * in both directions.
			 */
			if (!revealed.body.length) {
				var nextId = seq.members[visible.body[0]];
				var nextElement = this.store.elements[nextId];

				if (nextElement) {
					cue.call(this, seq, visible.body[0], -1, pristine);
					cue.call(this, seq, visible.body[0], +1, pristine);
					return animate.call(this, nextElement, { reveal: true, pristine: pristine })
				}
			}

			/**
			 * If our element isn’t resetting, we check the
			 * element sequence index against the head, and
			 * then the foot of the sequence.
			 */
			if (
				!seq.blocked.head &&
				i === [].concat( revealed.head ).pop() &&
				i >= [].concat( visible.body ).shift()
			) {
				cue.call(this, seq, i, -1, pristine);
				return animate.call(this, element, { reveal: true, pristine: pristine })
			}

			if (
				!seq.blocked.foot &&
				i === [].concat( revealed.foot ).shift() &&
				i <= [].concat( visible.body ).pop()
			) {
				cue.call(this, seq, i, +1, pristine);
				return animate.call(this, element, { reveal: true, pristine: pristine })
			}
		}
	}

	function Sequence(interval) {
		var i = Math.abs(interval);
		if (!isNaN(i)) {
			this.id = nextUniqueId();
			this.interval = Math.max(i, 16);
			this.members = [];
			this.models = {};
			this.blocked = {
				head: false,
				foot: false
			};
		} else {
			throw new RangeError('Invalid sequence interval.')
		}
	}

	function SequenceModel(seq, prop, store) {
		var this$1 = this;

		this.head = [];
		this.body = [];
		this.foot = [];

		each(seq.members, function (id, index) {
			var element = store.elements[id];
			if (element && element[prop]) {
				this$1.body.push(index);
			}
		});

		if (this.body.length) {
			each(seq.members, function (id, index) {
				var element = store.elements[id];
				if (element && !element[prop]) {
					if (index < this$1.body[0]) {
						this$1.head.push(index);
					} else {
						this$1.foot.push(index);
					}
				}
			});
		}
	}

	function cue(seq, i, direction, pristine) {
		var this$1 = this;

		var blocked = ['head', null, 'foot'][1 + direction];
		var nextId = seq.members[i + direction];
		var nextElement = this.store.elements[nextId];

		seq.blocked[blocked] = true;

		setTimeout(function () {
			seq.blocked[blocked] = false;
			if (nextElement) {
				sequence.call(this$1, nextElement, pristine);
			}
		}, seq.interval);
	}

	function initialize() {
		var this$1 = this;

		rinse.call(this);

		each(this.store.elements, function (element) {
			var styles = [element.styles.inline.generated];

			if (element.visible) {
				styles.push(element.styles.opacity.computed);
				styles.push(element.styles.transform.generated.final);
				element.revealed = true;
			} else {
				styles.push(element.styles.opacity.generated);
				styles.push(element.styles.transform.generated.initial);
				element.revealed = false;
			}

			element.node.setAttribute('style', styles.filter(function (s) { return s !== ''; }).join(' '));
		});

		each(this.store.containers, function (container) {
			var target =
				container.node === document.documentElement ? window : container.node;
			target.addEventListener('scroll', this$1.delegate);
			target.addEventListener('resize', this$1.delegate);
		});

		/**
		 * Manually invoke delegate once to capture
		 * element and container dimensions, container
		 * scroll position, and trigger any valid reveals
		 */
		this.delegate();

		/**
		 * Wipe any existing `setTimeout` now
		 * that initialization has completed.
		 */
		this.initTimeout = null;
	}

	function isMobile(agent) {
		if ( agent === void 0 ) agent = navigator.userAgent;

		return /Android|iPhone|iPad|iPod/i.test(agent)
	}

	function deepAssign(target) {
		var sources = [], len = arguments.length - 1;
		while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ];

		if (isObject(target)) {
			each(sources, function (source) {
				each(source, function (data, key) {
					if (isObject(data)) {
						if (!target[key] || !isObject(target[key])) {
							target[key] = {};
						}
						deepAssign(target[key], data);
					} else {
						target[key] = data;
					}
				});
			});
			return target
		} else {
			throw new TypeError('Target must be an object literal.')
		}
	}

	function reveal(target, options, syncing) {
		var this$1 = this;
		if ( options === void 0 ) options = {};
		if ( syncing === void 0 ) syncing = false;

		var containerBuffer = [];
		var sequence$$1;
		var interval = options.interval || defaults.interval;

		try {
			if (interval) {
				sequence$$1 = new Sequence(interval);
			}

			var nodes = tealight(target);
			if (!nodes.length) {
				throw new Error('Invalid reveal target.')
			}

			var elements = nodes.reduce(function (elementBuffer, elementNode) {
				var element = {};
				var existingId = elementNode.getAttribute('data-sr-id');

				if (existingId) {
					deepAssign(element, this$1.store.elements[existingId]);

					/**
					 * In order to prevent previously generated styles
					 * from throwing off the new styles, the style tag
					 * has to be reverted to its pre-reveal state.
					 */
					element.node.setAttribute('style', element.styles.inline.computed);
				} else {
					element.id = nextUniqueId();
					element.node = elementNode;
					element.seen = false;
					element.revealed = false;
					element.visible = false;
				}

				var config = deepAssign({}, element.config || this$1.defaults, options);

				if ((!config.mobile && isMobile()) || (!config.desktop && !isMobile())) {
					if (existingId) {
						clean.call(this$1, element);
					}
					return elementBuffer // skip elements that are disabled
				}

				var containerNode = tealight(config.container)[0];
				if (!containerNode) {
					throw new Error('Invalid container.')
				}
				if (!containerNode.contains(elementNode)) {
					return elementBuffer // skip elements found outside the container
				}

				var containerId;
				{
					containerId = getContainerId(
						containerNode,
						containerBuffer,
						this$1.store.containers
					);
					if (containerId === null) {
						containerId = nextUniqueId();
						containerBuffer.push({ id: containerId, node: containerNode });
					}
				}

				element.config = config;
				element.containerId = containerId;
				element.styles = style(element);

				if (sequence$$1) {
					element.sequence = {
						id: sequence$$1.id,
						index: sequence$$1.members.length
					};
					sequence$$1.members.push(element.id);
				}

				elementBuffer.push(element);
				return elementBuffer
			}, []);

			/**
			 * Modifying the DOM via setAttribute needs to be handled
			 * separately from reading computed styles in the map above
			 * for the browser to batch DOM changes (limiting reflows)
			 */
			each(elements, function (element) {
				this$1.store.elements[element.id] = element;
				element.node.setAttribute('data-sr-id', element.id);
			});
		} catch (e) {
			return logger.call(this, 'Reveal failed.', e.message)
		}

		/**
		 * Now that element set-up is complete...
		 * Let’s commit any container and sequence data we have to the store.
		 */
		each(containerBuffer, function (container) {
			this$1.store.containers[container.id] = {
				id: container.id,
				node: container.node
			};
		});
		if (sequence$$1) {
			this.store.sequences[sequence$$1.id] = sequence$$1;
		}

		/**
		 * If reveal wasn't invoked by sync, we want to
		 * make sure to add this call to the history.
		 */
		if (syncing !== true) {
			this.store.history.push({ target: target, options: options });

			/**
			 * Push initialization to the event queue, giving
			 * multiple reveal calls time to be interpreted.
			 */
			if (this.initTimeout) {
				window.clearTimeout(this.initTimeout);
			}
			this.initTimeout = window.setTimeout(initialize.bind(this), 0);
		}
	}

	function getContainerId(node) {
		var collections = [], len = arguments.length - 1;
		while ( len-- > 0 ) collections[ len ] = arguments[ len + 1 ];

		var id = null;
		each(collections, function (collection) {
			each(collection, function (container) {
				if (id === null && container.node === node) {
					id = container.id;
				}
			});
		});
		return id
	}

	/**
	 * Re-runs the reveal method for each record stored in history,
	 * for capturing new content asynchronously loaded into the DOM.
	 */
	function sync() {
		var this$1 = this;

		each(this.store.history, function (record) {
			reveal.call(this$1, record.target, record.options, true);
		});

		initialize.call(this);
	}

	var polyfill = function (x) { return (x > 0) - (x < 0) || +x; };
	var mathSign = Math.sign || polyfill;

	/*! @license miniraf v1.0.1

		Copyright 2018 Fisssion LLC.

		Permission is hereby granted, free of charge, to any person obtaining a copy
		of this software and associated documentation files (the "Software"), to deal
		in the Software without restriction, including without limitation the rights
		to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
		copies of the Software, and to permit persons to whom the Software is
		furnished to do so, subject to the following conditions:

		The above copyright notice and this permission notice shall be included in all
		copies or substantial portions of the Software.

		THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
		IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
		FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
		AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
		LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
		OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
		SOFTWARE.

	*/
	var polyfill$1 = (function () {
		var clock = Date.now();

		return function (callback) {
			var currentTime = Date.now();
			if (currentTime - clock > 16) {
				clock = currentTime;
				callback(currentTime);
			} else {
				setTimeout(function () { return polyfill$1(callback); }, 0);
			}
		}
	})();

	var miniraf = window.requestAnimationFrame ||
		window.webkitRequestAnimationFrame ||
		window.mozRequestAnimationFrame ||
		polyfill$1;

	function getGeometry(target, isContainer) {
		/**
		 * We want to ignore padding and scrollbars for container elements.
		 * More information here: https://goo.gl/vOZpbz
		 */
		var height = isContainer ? target.node.clientHeight : target.node.offsetHeight;
		var width = isContainer ? target.node.clientWidth : target.node.offsetWidth;

		var offsetTop = 0;
		var offsetLeft = 0;
		var node = target.node;

		do {
			if (!isNaN(node.offsetTop)) {
				offsetTop += node.offsetTop;
			}
			if (!isNaN(node.offsetLeft)) {
				offsetLeft += node.offsetLeft;
			}
			node = node.offsetParent;
		} while (node)

		return {
			bounds: {
				top: offsetTop,
				right: offsetLeft + width,
				bottom: offsetTop + height,
				left: offsetLeft
			},
			height: height,
			width: width
		}
	}

	function getScrolled(container) {
		var top, left;
		if (container.node === document.documentElement) {
			top = window.pageYOffset;
			left = window.pageXOffset;
		} else {
			top = container.node.scrollTop;
			left = container.node.scrollLeft;
		}
		return { top: top, left: left }
	}

	function isElementVisible(element) {
		if ( element === void 0 ) element = {};

		var container = this.store.containers[element.containerId];
		if (!container) { return }

		var viewFactor = Math.max(0, Math.min(1, element.config.viewFactor));
		var viewOffset = element.config.viewOffset;

		var elementBounds = {
			top: element.geometry.bounds.top + element.geometry.height * viewFactor,
			right: element.geometry.bounds.right - element.geometry.width * viewFactor,
			bottom: element.geometry.bounds.bottom - element.geometry.height * viewFactor,
			left: element.geometry.bounds.left + element.geometry.width * viewFactor
		};

		var containerBounds = {
			top: container.geometry.bounds.top + container.scroll.top + viewOffset.top,
			right: container.geometry.bounds.right + container.scroll.left - viewOffset.right,
			bottom:
				container.geometry.bounds.bottom + container.scroll.top - viewOffset.bottom,
			left: container.geometry.bounds.left + container.scroll.left + viewOffset.left
		};

		return (
			(elementBounds.top < containerBounds.bottom &&
				elementBounds.right > containerBounds.left &&
				elementBounds.bottom > containerBounds.top &&
				elementBounds.left < containerBounds.right) ||
			element.styles.position === 'fixed'
		)
	}

	function delegate(
		event,
		elements
	) {
		var this$1 = this;
		if ( event === void 0 ) event = { type: 'init' };
		if ( elements === void 0 ) elements = this.store.elements;

		miniraf(function () {
			var stale = event.type === 'init' || event.type === 'resize';

			each(this$1.store.containers, function (container) {
				if (stale) {
					container.geometry = getGeometry.call(this$1, container, true);
				}
				var scroll = getScrolled.call(this$1, container);
				if (container.scroll) {
					container.direction = {
						x: mathSign(scroll.left - container.scroll.left),
						y: mathSign(scroll.top - container.scroll.top)
					};
				}
				container.scroll = scroll;
			});

			/**
			 * Due to how the sequencer is implemented, it’s
			 * important that we update the state of all
			 * elements, before any animation logic is
			 * evaluated (in the second loop below).
			 */
			each(elements, function (element) {
				if (stale || element.geometry === undefined) {
					element.geometry = getGeometry.call(this$1, element);
				}
				element.visible = isElementVisible.call(this$1, element);
			});

			each(elements, function (element) {
				if (element.sequence) {
					sequence.call(this$1, element);
				} else {
					animate.call(this$1, element);
				}
			});

			this$1.pristine = false;
		});
	}

	function isTransformSupported() {
		var style = document.documentElement.style;
		return 'transform' in style || 'WebkitTransform' in style
	}

	function isTransitionSupported() {
		var style = document.documentElement.style;
		return 'transition' in style || 'WebkitTransition' in style
	}

	var version = "4.0.7";

	var boundDelegate;
	var boundDestroy;
	var boundReveal;
	var boundClean;
	var boundSync;
	var config;
	var debug;
	var instance;

	function ScrollReveal(options) {
		if ( options === void 0 ) options = {};

		var invokedWithoutNew =
			typeof this === 'undefined' ||
			Object.getPrototypeOf(this) !== ScrollReveal.prototype;

		if (invokedWithoutNew) {
			return new ScrollReveal(options)
		}

		if (!ScrollReveal.isSupported()) {
			logger.call(this, 'Instantiation failed.', 'This browser is not supported.');
			return mount.failure()
		}

		var buffer;
		try {
			buffer = config
				? deepAssign({}, config, options)
				: deepAssign({}, defaults, options);
		} catch (e) {
			logger.call(this, 'Invalid configuration.', e.message);
			return mount.failure()
		}

		try {
			var container = tealight(buffer.container)[0];
			if (!container) {
				throw new Error('Invalid container.')
			}
		} catch (e) {
			logger.call(this, e.message);
			return mount.failure()
		}

		config = buffer;

		if ((!config.mobile && isMobile()) || (!config.desktop && !isMobile())) {
			logger.call(
				this,
				'This device is disabled.',
				("desktop: " + (config.desktop)),
				("mobile: " + (config.mobile))
			);
			return mount.failure()
		}

		mount.success();

		this.store = {
			containers: {},
			elements: {},
			history: [],
			sequences: {}
		};

		this.pristine = true;

		boundDelegate = boundDelegate || delegate.bind(this);
		boundDestroy = boundDestroy || destroy.bind(this);
		boundReveal = boundReveal || reveal.bind(this);
		boundClean = boundClean || clean.bind(this);
		boundSync = boundSync || sync.bind(this);

		Object.defineProperty(this, 'delegate', { get: function () { return boundDelegate; } });
		Object.defineProperty(this, 'destroy', { get: function () { return boundDestroy; } });
		Object.defineProperty(this, 'reveal', { get: function () { return boundReveal; } });
		Object.defineProperty(this, 'clean', { get: function () { return boundClean; } });
		Object.defineProperty(this, 'sync', { get: function () { return boundSync; } });

		Object.defineProperty(this, 'defaults', { get: function () { return config; } });
		Object.defineProperty(this, 'version', { get: function () { return version; } });
		Object.defineProperty(this, 'noop', { get: function () { return false; } });

		return instance ? instance : (instance = this)
	}

	ScrollReveal.isSupported = function () { return isTransformSupported() && isTransitionSupported(); };

	Object.defineProperty(ScrollReveal, 'debug', {
		get: function () { return debug || false; },
		set: function (value) { return (debug = typeof value === 'boolean' ? value : debug); }
	});

	ScrollReveal();

	return ScrollReveal;

}));
