import SlideContent from './controllers/slidecontent.js'
import SlideNumber from './controllers/slidenumber.js'
import JumpToSlide from './controllers/jumptoslide.js'
import Backgrounds from './controllers/backgrounds.js'
import AutoAnimate from './controllers/autoanimate.js'
import Fragments from './controllers/fragments.js'
import Overview from './controllers/overview.js'
import Keyboard from './controllers/keyboard.js'
import Location from './controllers/location.js'
import Controls from './controllers/controls.js'
import Progress from './controllers/progress.js'
import Pointer from './controllers/pointer.js'
import Plugins from './controllers/plugins.js'
import Print from './controllers/print.js'
import Touch from './controllers/touch.js'
import Focus from './controllers/focus.js'
import Notes from './controllers/notes.js'
import Playback from './components/playback.js'
import defaultConfig from './config.js'
import * as Util from './utils/util.js'
import * as Device from './utils/device.js'
import {
	SLIDES_SELECTOR,
	HORIZONTAL_SLIDES_SELECTOR,
	VERTICAL_SLIDES_SELECTOR,
	POST_MESSAGE_METHOD_BLACKLIST
} from './utils/constants.js'

// The reveal.js version
export const VERSION = '4.6.0';

/**
 * reveal.js
 * https://revealjs.com
 * MIT licensed
 *
 * Copyright (C) 2011-2022 Hakim El Hattab, https://hakim.se
 */
export default function( revealElement, options ) {

	// Support initialization with no args, one arg
	// [options] or two args [revealElement, options]
	if( arguments.length < 2 ) {
		options = arguments[0];
		revealElement = document.querySelector( '.reveal' );
	}

	const Reveal = {};

	// Configuration defaults, can be overridden at initialization time
	let config = {},

		// Flags if reveal.js is loaded (has dispatched the 'ready' event)
		ready = false,

		// The horizontal and vertical index of the currently active slide
		indexh,
		indexv,

		// The previous and current slide HTML elements
		previousSlide,
		currentSlide,

		// Remember which directions that the user has navigated towards
		navigationHistory = {
			hasNavigatedHorizontally: false,
			hasNavigatedVertically: false
		},

		// Slides may have a data-state attribute which we pick up and apply
		// as a class to the body. This list contains the combined state of
		// all current slides.
		state = [],

		// The current scale of the presentation (see width/height config)
		scale = 1,

		// CSS transform that is currently applied to the slides container,
		// split into two groups
		slidesTransform = { layout: '', overview: '' },

		// Cached references to DOM elements
		dom = {},

		// Flags if the interaction event listeners are bound
		eventsAreBound = false,

		// The current slide transition state; idle or running
		transition = 'idle',

		// The current auto-slide duration
		autoSlide = 0,

		// Auto slide properties
		autoSlidePlayer,
		autoSlideTimeout = 0,
		autoSlideStartTime = -1,
		autoSlidePaused = false,

		// Controllers for different aspects of our presentation. They're
		// all given direct references to this Reveal instance since there
		// may be multiple presentations running in parallel.
		slideContent = new SlideContent( Reveal ),
		slideNumber = new SlideNumber( Reveal ),
		jumpToSlide = new JumpToSlide( Reveal ),
		autoAnimate = new AutoAnimate( Reveal ),
		backgrounds = new Backgrounds( Reveal ),
		fragments = new Fragments( Reveal ),
		overview = new Overview( Reveal ),
		keyboard = new Keyboard( Reveal ),
		location = new Location( Reveal ),
		controls = new Controls( Reveal ),
		progress = new Progress( Reveal ),
		pointer = new Pointer( Reveal ),
		plugins = new Plugins( Reveal ),
		print = new Print( Reveal ),
		focus = new Focus( Reveal ),
		touch = new Touch( Reveal ),
		notes = new Notes( Reveal );

	/**
	 * Starts up the presentation.
	 */
	function initialize( initOptions ) {

		if( !revealElement ) throw 'Unable to find presentation root (<div class="reveal">).';

		// Cache references to key DOM elements
		dom.wrapper = revealElement;
		dom.slides = revealElement.querySelector( '.slides' );

		if( !dom.slides ) throw 'Unable to find slides container (<div class="slides">).';

		// Compose our config object in order of increasing precedence:
		// 1. Default reveal.js options
		// 2. Options provided via Reveal.configure() prior to
		//    initialization
		// 3. Options passed to the Reveal constructor
		// 4. Options passed to Reveal.initialize
		// 5. Query params
		config = { ...defaultConfig, ...config, ...options, ...initOptions, ...Util.getQueryHash() };

		setViewport();

		// Force a layout when the whole page, incl fonts, has loaded
		window.addEventListener( 'load', layout, false );

		// Register plugins and load dependencies, then move on to #start()
		plugins.load( config.plugins, config.dependencies ).then( start );

		return new Promise( resolve => Reveal.on( 'ready', resolve ) );

	}

	/**
	 * Encase the presentation in a reveal.js viewport. The
	 * extent of the viewport differs based on configuration.
	 */
	function setViewport() {

		// Embedded decks use the reveal element as their viewport
		if( config.embedded === true ) {
			dom.viewport = Util.closest( revealElement, '.reveal-viewport' ) || revealElement;
		}
		// Full-page decks use the body as their viewport
		else {
			dom.viewport = document.body;
			document.documentElement.classList.add( 'reveal-full-page' );
		}

		dom.viewport.classList.add( 'reveal-viewport' );

	}

	/**
	 * Starts up reveal.js by binding input events and navigating
	 * to the current URL deeplink if there is one.
	 */
	function start() {

		ready = true;

		// Remove slides hidden with data-visibility
		removeHiddenSlides();

		// Make sure we've got all the DOM elements we need
		setupDOM();

		// Listen to messages posted to this window
		setupPostMessage();

		// Prevent the slides from being scrolled out of view
		setupScrollPrevention();

		// Adds bindings for fullscreen mode
		setupFullscreen();

		// Resets all vertical slides so that only the first is visible
		resetVerticalSlides();

		// Updates the presentation to match the current configuration values
		configure();

		// Read the initial hash
		location.readURL();

		// Create slide backgrounds
		backgrounds.update( true );

		// Notify listeners that the presentation is ready but use a 1ms
		// timeout to ensure it's not fired synchronously after #initialize()
		setTimeout( () => {
			// Enable transitions now that we're loaded
			dom.slides.classList.remove( 'no-transition' );

			dom.wrapper.classList.add( 'ready' );

			dispatchEvent({
				type: 'ready',
				data: {
					indexh,
					indexv,
					currentSlide
				}
			});
		}, 1 );

		// Special setup and config is required when printing to PDF
		if( print.isPrintingPDF() ) {
			removeEventListeners();

			// The document needs to have loaded for the PDF layout
			// measurements to be accurate
			if( document.readyState === 'complete' ) {
				print.setupPDF();
			}
			else {
				window.addEventListener( 'load', () => {
					print.setupPDF();
				} );
			}
		}

	}

	/**
	 * Removes all slides with data-visibility="hidden". This
	 * is done right before the rest of the presentation is
	 * initialized.
	 *
	 * If you want to show all hidden slides, initialize
	 * reveal.js with showHiddenSlides set to true.
	 */
	function removeHiddenSlides() {

		if( !config.showHiddenSlides ) {
			Util.queryAll( dom.wrapper, 'section[data-visibility="hidden"]' ).forEach( slide => {
				slide.parentNode.removeChild( slide );
			} );
		}

	}

	/**
	 * Finds and stores references to DOM elements which are
	 * required by the presentation. If a required element is
	 * not found, it is created.
	 */
	function setupDOM() {

		// Prevent transitions while we're loading
		dom.slides.classList.add( 'no-transition' );

		if( Device.isMobile ) {
			dom.wrapper.classList.add( 'no-hover' );
		}
		else {
			dom.wrapper.classList.remove( 'no-hover' );
		}

		backgrounds.render();
		slideNumber.render();
		jumpToSlide.render();
		controls.render();
		progress.render();
		notes.render();

		// Overlay graphic which is displayed during the paused mode
		dom.pauseOverlay = Util.createSingletonNode( dom.wrapper, 'div', 'pause-overlay', config.controls ? '<button class="resume-button">Resume presentation</button>' : null );

		dom.statusElement = createStatusElement();

		dom.wrapper.setAttribute( 'role', 'application' );
	}

	/**
	 * Creates a hidden div with role aria-live to announce the
	 * current slide content. Hide the div off-screen to make it
	 * available only to Assistive Technologies.
	 *
	 * @return {HTMLElement}
	 */
	function createStatusElement() {

		let statusElement = dom.wrapper.querySelector( '.aria-status' );
		if( !statusElement ) {
			statusElement = document.createElement( 'div' );
			statusElement.style.position = 'absolute';
			statusElement.style.height = '1px';
			statusElement.style.width = '1px';
			statusElement.style.overflow = 'hidden';
			statusElement.style.clip = 'rect( 1px, 1px, 1px, 1px )';
			statusElement.classList.add( 'aria-status' );
			statusElement.setAttribute( 'aria-live', 'polite' );
			statusElement.setAttribute( 'aria-atomic','true' );
			dom.wrapper.appendChild( statusElement );
		}
		return statusElement;

	}

	/**
	 * Announces the given text to screen readers.
	 */
	function announceStatus( value ) {

		dom.statusElement.textContent = value;

	}

	/**
	 * Converts the given HTML element into a string of text
	 * that can be announced to a screen reader. Hidden
	 * elements are excluded.
	 */
	function getStatusText( node ) {

		let text = '';

		// Text node
		if( node.nodeType === 3 ) {
			text += node.textContent;
		}
		// Element node
		else if( node.nodeType === 1 ) {

			let isAriaHidden = node.getAttribute( 'aria-hidden' );
			let isDisplayHidden = window.getComputedStyle( node )['display'] === 'none';
			if( isAriaHidden !== 'true' && !isDisplayHidden ) {

				Array.from( node.childNodes ).forEach( child => {
					text += getStatusText( child );
				} );

			}

		}

		text = text.trim();

		return text === '' ? '' : text + ' ';

	}

	/**
	 * This is an unfortunate necessity. Some actions – such as
	 * an input field being focused in an iframe or using the
	 * keyboard to expand text selection beyond the bounds of
	 * a slide – can trigger our content to be pushed out of view.
	 * This scrolling can not be prevented by hiding overflow in
	 * CSS (we already do) so we have to resort to repeatedly
	 * checking if the slides have been offset :(
	 */
	function setupScrollPrevention() {

		setInterval( () => {
			if( dom.wrapper.scrollTop !== 0 || dom.wrapper.scrollLeft !== 0 ) {
				dom.wrapper.scrollTop = 0;
				dom.wrapper.scrollLeft = 0;
			}
		}, 1000 );

	}

	/**
	 * After entering fullscreen we need to force a layout to
	 * get our presentations to scale correctly. This behavior
	 * is inconsistent across browsers but a force layout seems
	 * to normalize it.
	 */
	function setupFullscreen() {

		document.addEventListener( 'fullscreenchange', onFullscreenChange );
		document.addEventListener( 'webkitfullscreenchange', onFullscreenChange );

	}

	/**
	 * Registers a listener to postMessage events, this makes it
	 * possible to call all reveal.js API methods from another
	 * window. For example:
	 *
	 * revealWindow.postMessage( JSON.stringify({
	 *   method: 'slide',
	 *   args: [ 2 ]
	 * }), '*' );
	 */
	function setupPostMessage() {

		if( config.postMessage ) {
			window.addEventListener( 'message', onPostMessage, false );
		}

	}

	/**
	 * Applies the configuration settings from the config
	 * object. May be called multiple times.
	 *
	 * @param {object} options
	 */
	function configure( options ) {

		const oldConfig = { ...config }

		// New config options may be passed when this method
		// is invoked through the API after initialization
		if( typeof options === 'object' ) Util.extend( config, options );

		// Abort if reveal.js hasn't finished loading, config
		// changes will be applied automatically once ready
		if( Reveal.isReady() ===  false ) return;

		const numberOfSlides = dom.wrapper.querySelectorAll( SLIDES_SELECTOR ).length;

		// The transition is added as a class on the .reveal element
		dom.wrapper.classList.remove( oldConfig.transition );
		dom.wrapper.classList.add( config.transition );

		dom.wrapper.setAttribute( 'data-transition-speed', config.transitionSpeed );
		dom.wrapper.setAttribute( 'data-background-transition', config.backgroundTransition );

		// Expose our configured slide dimensions as custom props
		dom.viewport.style.setProperty( '--slide-width', config.width + 'px' );
		dom.viewport.style.setProperty( '--slide-height', config.height + 'px' );

		if( config.shuffle ) {
			shuffle();
		}

		Util.toggleClass( dom.wrapper, 'embedded', config.embedded );
		Util.toggleClass( dom.wrapper, 'rtl', config.rtl );
		Util.toggleClass( dom.wrapper, 'center', config.center );

		// Exit the paused mode if it was configured off
		if( config.pause === false ) {
			resume();
		}

		// Iframe link previews
		if( config.previewLinks ) {
			enablePreviewLinks();
			disablePreviewLinks( '[data-preview-link=false]' );
		}
		else {
			disablePreviewLinks();
			enablePreviewLinks( '[data-preview-link]:not([data-preview-link=false])' );
		}

		// Reset all changes made by auto-animations
		autoAnimate.reset();

		// Remove existing auto-slide controls
		if( autoSlidePlayer ) {
			autoSlidePlayer.destroy();
			autoSlidePlayer = null;
		}

		// Generate auto-slide controls if needed
		if( numberOfSlides > 1 && config.autoSlide && config.autoSlideStoppable ) {
			autoSlidePlayer = new Playback( dom.wrapper, () => {
				return Math.min( Math.max( ( Date.now() - autoSlideStartTime ) / autoSlide, 0 ), 1 );
			} );

			autoSlidePlayer.on( 'click', onAutoSlidePlayerClick );
			autoSlidePaused = false;
		}

		// Add the navigation mode to the DOM so we can adjust styling
		if( config.navigationMode !== 'default' ) {
			dom.wrapper.setAttribute( 'data-navigation-mode', config.navigationMode );
		}
		else {
			dom.wrapper.removeAttribute( 'data-navigation-mode' );
		}

		notes.configure( config, oldConfig );
		focus.configure( config, oldConfig );
		pointer.configure( config, oldConfig );
		controls.configure( config, oldConfig );
		progress.configure( config, oldConfig );
		keyboard.configure( config, oldConfig );
		fragments.configure( config, oldConfig );
		slideNumber.configure( config, oldConfig );

		sync();

	}

	/**
	 * Binds all event listeners.
	 */
	function addEventListeners() {

		eventsAreBound = true;

		window.addEventListener( 'resize', onWindowResize, false );

		if( config.touch ) touch.bind();
		if( config.keyboard ) keyboard.bind();
		if( config.progress ) progress.bind();
		if( config.respondToHashChanges ) location.bind();
		controls.bind();
		focus.bind();

		dom.slides.addEventListener( 'click', onSlidesClicked, false );
		dom.slides.addEventListener( 'transitionend', onTransitionEnd, false );
		dom.pauseOverlay.addEventListener( 'click', resume, false );

		if( config.focusBodyOnPageVisibilityChange ) {
			document.addEventListener( 'visibilitychange', onPageVisibilityChange, false );
		}

	}

	/**
	 * Unbinds all event listeners.
	 */
	function removeEventListeners() {

		eventsAreBound = false;

		touch.unbind();
		focus.unbind();
		keyboard.unbind();
		controls.unbind();
		progress.unbind();
		location.unbind();

		window.removeEventListener( 'resize', onWindowResize, false );

		dom.slides.removeEventListener( 'click', onSlidesClicked, false );
		dom.slides.removeEventListener( 'transitionend', onTransitionEnd, false );
		dom.pauseOverlay.removeEventListener( 'click', resume, false );

	}

	/**
	 * Uninitializes reveal.js by undoing changes made to the
	 * DOM and removing all event listeners.
	 */
	function destroy() {

		removeEventListeners();
		cancelAutoSlide();
		disablePreviewLinks();

		// Destroy controllers
		notes.destroy();
		focus.destroy();
		plugins.destroy();
		pointer.destroy();
		controls.destroy();
		progress.destroy();
		backgrounds.destroy();
		slideNumber.destroy();
		jumpToSlide.destroy();

		// Remove event listeners
		document.removeEventListener( 'fullscreenchange', onFullscreenChange );
		document.removeEventListener( 'webkitfullscreenchange', onFullscreenChange );
		document.removeEventListener( 'visibilitychange', onPageVisibilityChange, false );
		window.removeEventListener( 'message', onPostMessage, false );
		window.removeEventListener( 'load', layout, false );

		// Undo DOM changes
		if( dom.pauseOverlay ) dom.pauseOverlay.remove();
		if( dom.statusElement ) dom.statusElement.remove();

		document.documentElement.classList.remove( 'reveal-full-page' );

		dom.wrapper.classList.remove( 'ready', 'center', 'has-horizontal-slides', 'has-vertical-slides' );
		dom.wrapper.removeAttribute( 'data-transition-speed' );
		dom.wrapper.removeAttribute( 'data-background-transition' );

		dom.viewport.classList.remove( 'reveal-viewport' );
		dom.viewport.style.removeProperty( '--slide-width' );
		dom.viewport.style.removeProperty( '--slide-height' );

		dom.slides.style.removeProperty( 'width' );
		dom.slides.style.removeProperty( 'height' );
		dom.slides.style.removeProperty( 'zoom' );
		dom.slides.style.removeProperty( 'left' );
		dom.slides.style.removeProperty( 'top' );
		dom.slides.style.removeProperty( 'bottom' );
		dom.slides.style.removeProperty( 'right' );
		dom.slides.style.removeProperty( 'transform' );

		Array.from( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ).forEach( slide => {
			slide.style.removeProperty( 'display' );
			slide.style.removeProperty( 'top' );
			slide.removeAttribute( 'hidden' );
			slide.removeAttribute( 'aria-hidden' );
		} );

	}

	/**
	 * Adds a listener to one of our custom reveal.js events,
	 * like slidechanged.
	 */
	function on( type, listener, useCapture ) {

		revealElement.addEventListener( type, listener, useCapture );

	}

	/**
	 * Unsubscribes from a reveal.js event.
	 */
	function off( type, listener, useCapture ) {

		revealElement.removeEventListener( type, listener, useCapture );

	}

	/**
	 * Applies CSS transforms to the slides container. The container
	 * is transformed from two separate sources: layout and the overview
	 * mode.
	 *
	 * @param {object} transforms
	 */
	function transformSlides( transforms ) {

		// Pick up new transforms from arguments
		if( typeof transforms.layout === 'string' ) slidesTransform.layout = transforms.layout;
		if( typeof transforms.overview === 'string' ) slidesTransform.overview = transforms.overview;

		// Apply the transforms to the slides container
		if( slidesTransform.layout ) {
			Util.transformElement( dom.slides, slidesTransform.layout + ' ' + slidesTransform.overview );
		}
		else {
			Util.transformElement( dom.slides, slidesTransform.overview );
		}

	}

	/**
	 * Dispatches an event of the specified type from the
	 * reveal DOM element.
	 */
	function dispatchEvent({ target=dom.wrapper, type, data, bubbles=true }) {

		let event = document.createEvent( 'HTMLEvents', 1, 2 );
		event.initEvent( type, bubbles, true );
		Util.extend( event, data );
		target.dispatchEvent( event );

		if( target === dom.wrapper ) {
			// If we're in an iframe, post each reveal.js event to the
			// parent window. Used by the notes plugin
			dispatchPostMessage( type );
		}

		return event;

	}

	/**
	 * Dispatched a postMessage of the given type from our window.
	 */
	function dispatchPostMessage( type, data ) {

		if( config.postMessageEvents && window.parent !== window.self ) {
			let message = {
				namespace: 'reveal',
				eventName: type,
				state: getState()
			};

			Util.extend( message, data );

			window.parent.postMessage( JSON.stringify( message ), '*' );
		}

	}

	/**
	 * Bind preview frame links.
	 *
	 * @param {string} [selector=a] - selector for anchors
	 */
	function enablePreviewLinks( selector = 'a' ) {

		Array.from( dom.wrapper.querySelectorAll( selector ) ).forEach( element => {
			if( /^(http|www)/gi.test( element.getAttribute( 'href' ) ) ) {
				element.addEventListener( 'click', onPreviewLinkClicked, false );
			}
		} );

	}

	/**
	 * Unbind preview frame links.
	 */
	function disablePreviewLinks( selector = 'a' ) {

		Array.from( dom.wrapper.querySelectorAll( selector ) ).forEach( element => {
			if( /^(http|www)/gi.test( element.getAttribute( 'href' ) ) ) {
				element.removeEventListener( 'click', onPreviewLinkClicked, false );
			}
		} );

	}

	/**
	 * Opens a preview window for the target URL.
	 *
	 * @param {string} url - url for preview iframe src
	 */
	function showPreview( url ) {

		closeOverlay();

		dom.overlay = document.createElement( 'div' );
		dom.overlay.classList.add( 'overlay' );
		dom.overlay.classList.add( 'overlay-preview' );
		dom.wrapper.appendChild( dom.overlay );

		dom.overlay.innerHTML =
			`<header>
				<a class="close" href="#"><span class="icon"></span></a>
				<a class="external" href="${url}" target="_blank"><span class="icon"></span></a>
			</header>
			<div class="spinner"></div>
			<div class="viewport">
				<iframe src="${url}"></iframe>
				<small class="viewport-inner">
					<span class="x-frame-error">Unable to load iframe. This is likely due to the site's policy (x-frame-options).</span>
				</small>
			</div>`;

		dom.overlay.querySelector( 'iframe' ).addEventListener( 'load', event => {
			dom.overlay.classList.add( 'loaded' );
		}, false );

		dom.overlay.querySelector( '.close' ).addEventListener( 'click', event => {
			closeOverlay();
			event.preventDefault();
		}, false );

		dom.overlay.querySelector( '.external' ).addEventListener( 'click', event => {
			closeOverlay();
		}, false );

	}

	/**
	 * Open or close help overlay window.
	 *
	 * @param {Boolean} [override] Flag which overrides the
	 * toggle logic and forcibly sets the desired state. True means
	 * help is open, false means it's closed.
	 */
	function toggleHelp( override ){

		if( typeof override === 'boolean' ) {
			override ? showHelp() : closeOverlay();
		}
		else {
			if( dom.overlay ) {
				closeOverlay();
			}
			else {
				showHelp();
			}
		}
	}

	/**
	 * Opens an overlay window with help material.
	 */
	function showHelp() {

		if( config.help ) {

			closeOverlay();

			dom.overlay = document.createElement( 'div' );
			dom.overlay.classList.add( 'overlay' );
			dom.overlay.classList.add( 'overlay-help' );
			dom.wrapper.appendChild( dom.overlay );

			let html = '<p class="title">Keyboard Shortcuts</p><br/>';

			let shortcuts = keyboard.getShortcuts(),
				bindings = keyboard.getBindings();

			html += '<table><th>KEY</th><th>ACTION</th>';
			for( let key in shortcuts ) {
				html += `<tr><td>${key}</td><td>${shortcuts[ key ]}</td></tr>`;
			}

			// Add custom key bindings that have associated descriptions
			for( let binding in bindings ) {
				if( bindings[binding].key && bindings[binding].description ) {
					html += `<tr><td>${bindings[binding].key}</td><td>${bindings[binding].description}</td></tr>`;
				}
			}

			html += '</table>';

			dom.overlay.innerHTML = `
				<header>
					<a class="close" href="#"><span class="icon"></span></a>
				</header>
				<div class="viewport">
					<div class="viewport-inner">${html}</div>
				</div>
			`;

			dom.overlay.querySelector( '.close' ).addEventListener( 'click', event => {
				closeOverlay();
				event.preventDefault();
			}, false );

		}

	}

	/**
	 * Closes any currently open overlay.
	 */
	function closeOverlay() {

		if( dom.overlay ) {
			dom.overlay.parentNode.removeChild( dom.overlay );
			dom.overlay = null;
			return true;
		}

		return false;

	}

	/**
	 * Applies JavaScript-controlled layout rules to the
	 * presentation.
	 */
	function layout() {

		if( dom.wrapper && !print.isPrintingPDF() ) {

			if( !config.disableLayout ) {

				// On some mobile devices '100vh' is taller than the visible
				// viewport which leads to part of the presentation being
				// cut off. To work around this we define our own '--vh' custom
				// property where 100x adds up to the correct height.
				//
				// https://css-tricks.com/the-trick-to-viewport-units-on-mobile/
				if( Device.isMobile && !config.embedded ) {
					document.documentElement.style.setProperty( '--vh', ( window.innerHeight * 0.01 ) + 'px' );
				}

				const size = getComputedSlideSize();

				const oldScale = scale;

				// Layout the contents of the slides
				layoutSlideContents( config.width, config.height );

				dom.slides.style.width = size.width + 'px';
				dom.slides.style.height = size.height + 'px';

				// Determine scale of content to fit within available space
				scale = Math.min( size.presentationWidth / size.width, size.presentationHeight / size.height );

				// Respect max/min scale settings
				scale = Math.max( scale, config.minScale );
				scale = Math.min( scale, config.maxScale );

				// Don't apply any scaling styles if scale is 1
				if( scale === 1 ) {
					dom.slides.style.zoom = '';
					dom.slides.style.left = '';
					dom.slides.style.top = '';
					dom.slides.style.bottom = '';
					dom.slides.style.right = '';
					transformSlides( { layout: '' } );
				}
				else {
					dom.slides.style.zoom = '';
					dom.slides.style.left = '50%';
					dom.slides.style.top = '50%';
					dom.slides.style.bottom = 'auto';
					dom.slides.style.right = 'auto';
					transformSlides( { layout: 'translate(-50%, -50%) scale('+ scale +')' } );
				}

				// Select all slides, vertical and horizontal
				const slides = Array.from( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) );

				for( let i = 0, len = slides.length; i < len; i++ ) {
					const slide = slides[ i ];

					// Don't bother updating invisible slides
					if( slide.style.display === 'none' ) {
						continue;
					}

					if( config.center || slide.classList.contains( 'center' ) ) {
						// Vertical stacks are not centred since their section
						// children will be
						if( slide.classList.contains( 'stack' ) ) {
							slide.style.top = 0;
						}
						else {
							slide.style.top = Math.max( ( size.height - slide.scrollHeight ) / 2, 0 ) + 'px';
						}
					}
					else {
						slide.style.top = '';
					}

				}

				if( oldScale !== scale ) {
					dispatchEvent({
						type: 'resize',
						data: {
							oldScale,
							scale,
							size
						}
					});
				}
			}

			dom.viewport.style.setProperty( '--slide-scale', scale );

			progress.update();
			backgrounds.updateParallax();

			if( overview.isActive() ) {
				overview.update();
			}

		}

	}

	/**
	 * Applies layout logic to the contents of all slides in
	 * the presentation.
	 *
	 * @param {string|number} width
	 * @param {string|number} height
	 */
	function layoutSlideContents( width, height ) {

		// Handle sizing of elements with the 'r-stretch' class
		Util.queryAll( dom.slides, 'section > .stretch, section > .r-stretch' ).forEach( element => {

			// Determine how much vertical space we can use
			let remainingHeight = Util.getRemainingHeight( element, height );

			// Consider the aspect ratio of media elements
			if( /(img|video)/gi.test( element.nodeName ) ) {
				const nw = element.naturalWidth || element.videoWidth,
					  nh = element.naturalHeight || element.videoHeight;

				const es = Math.min( width / nw, remainingHeight / nh );

				element.style.width = ( nw * es ) + 'px';
				element.style.height = ( nh * es ) + 'px';

			}
			else {
				element.style.width = width + 'px';
				element.style.height = remainingHeight + 'px';
			}

		} );

	}

	/**
	 * Calculates the computed pixel size of our slides. These
	 * values are based on the width and height configuration
	 * options.
	 *
	 * @param {number} [presentationWidth=dom.wrapper.offsetWidth]
	 * @param {number} [presentationHeight=dom.wrapper.offsetHeight]
	 */
	function getComputedSlideSize( presentationWidth, presentationHeight ) {
		let width = config.width;
		let height = config.height;

		if( config.disableLayout ) {
			width = dom.slides.offsetWidth;
			height = dom.slides.offsetHeight;
		}

		const size = {
			// Slide size
			width: width,
			height: height,

			// Presentation size
			presentationWidth: presentationWidth || dom.wrapper.offsetWidth,
			presentationHeight: presentationHeight || dom.wrapper.offsetHeight
		};

		// Reduce available space by margin
		size.presentationWidth -= ( size.presentationWidth * config.margin );
		size.presentationHeight -= ( size.presentationHeight * config.margin );

		// Slide width may be a percentage of available width
		if( typeof size.width === 'string' && /%$/.test( size.width ) ) {
			size.width = parseInt( size.width, 10 ) / 100 * size.presentationWidth;
		}

		// Slide height may be a percentage of available height
		if( typeof size.height === 'string' && /%$/.test( size.height ) ) {
			size.height = parseInt( size.height, 10 ) / 100 * size.presentationHeight;
		}

		return size;

	}

	/**
	 * Stores the vertical index of a stack so that the same
	 * vertical slide can be selected when navigating to and
	 * from the stack.
	 *
	 * @param {HTMLElement} stack The vertical stack element
	 * @param {string|number} [v=0] Index to memorize
	 */
	function setPreviousVerticalIndex( stack, v ) {

		if( typeof stack === 'object' && typeof stack.setAttribute === 'function' ) {
			stack.setAttribute( 'data-previous-indexv', v || 0 );
		}

	}

	/**
	 * Retrieves the vertical index which was stored using
	 * #setPreviousVerticalIndex() or 0 if no previous index
	 * exists.
	 *
	 * @param {HTMLElement} stack The vertical stack element
	 */
	function getPreviousVerticalIndex( stack ) {

		if( typeof stack === 'object' && typeof stack.setAttribute === 'function' && stack.classList.contains( 'stack' ) ) {
			// Prefer manually defined start-indexv
			const attributeName = stack.hasAttribute( 'data-start-indexv' ) ? 'data-start-indexv' : 'data-previous-indexv';

			return parseInt( stack.getAttribute( attributeName ) || 0, 10 );
		}

		return 0;

	}

	/**
	 * Checks if the current or specified slide is vertical
	 * (nested within another slide).
	 *
	 * @param {HTMLElement} [slide=currentSlide] The slide to check
	 * orientation of
	 * @return {Boolean}
	 */
	function isVerticalSlide( slide = currentSlide ) {

		return slide && slide.parentNode && !!slide.parentNode.nodeName.match( /section/i );

	}

	/**
	 * Returns true if we're on the last slide in the current
	 * vertical stack.
	 */
	function isLastVerticalSlide() {

		if( currentSlide && isVerticalSlide( currentSlide ) ) {
			// Does this slide have a next sibling?
			if( currentSlide.nextElementSibling ) return false;

			return true;
		}

		return false;

	}

	/**
	 * Returns true if we're currently on the first slide in
	 * the presentation.
	 */
	function isFirstSlide() {

		return indexh === 0 && indexv === 0;

	}

	/**
	 * Returns true if we're currently on the last slide in
	 * the presenation. If the last slide is a stack, we only
	 * consider this the last slide if it's at the end of the
	 * stack.
	 */
	function isLastSlide() {

		if( currentSlide ) {
			// Does this slide have a next sibling?
			if( currentSlide.nextElementSibling ) return false;

			// If it's vertical, does its parent have a next sibling?
			if( isVerticalSlide( currentSlide ) && currentSlide.parentNode.nextElementSibling ) return false;

			return true;
		}

		return false;

	}

	/**
	 * Enters the paused mode which fades everything on screen to
	 * black.
	 */
	function pause() {

		if( config.pause ) {
			const wasPaused = dom.wrapper.classList.contains( 'paused' );

			cancelAutoSlide();
			dom.wrapper.classList.add( 'paused' );

			if( wasPaused === false ) {
				dispatchEvent({ type: 'paused' });
			}
		}

	}

	/**
	 * Exits from the paused mode.
	 */
	function resume() {

		const wasPaused = dom.wrapper.classList.contains( 'paused' );
		dom.wrapper.classList.remove( 'paused' );

		cueAutoSlide();

		if( wasPaused ) {
			dispatchEvent({ type: 'resumed' });
		}

	}

	/**
	 * Toggles the paused mode on and off.
	 */
	function togglePause( override ) {

		if( typeof override === 'boolean' ) {
			override ? pause() : resume();
		}
		else {
			isPaused() ? resume() : pause();
		}

	}

	/**
	 * Checks if we are currently in the paused mode.
	 *
	 * @return {Boolean}
	 */
	function isPaused() {

		return dom.wrapper.classList.contains( 'paused' );

	}

	/**
	 * Toggles visibility of the jump-to-slide UI.
	 */
	function toggleJumpToSlide( override ) {

		if( typeof override === 'boolean' ) {
			override ? jumpToSlide.show() : jumpToSlide.hide();
		}
		else {
			jumpToSlide.isVisible() ? jumpToSlide.hide() : jumpToSlide.show();
		}

	}

	/**
	 * Toggles the auto slide mode on and off.
	 *
	 * @param {Boolean} [override] Flag which sets the desired state.
	 * True means autoplay starts, false means it stops.
	 */

	function toggleAutoSlide( override ) {

		if( typeof override === 'boolean' ) {
			override ? resumeAutoSlide() : pauseAutoSlide();
		}

		else {
			autoSlidePaused ? resumeAutoSlide() : pauseAutoSlide();
		}

	}

	/**
	 * Checks if the auto slide mode is currently on.
	 *
	 * @return {Boolean}
	 */
	function isAutoSliding() {

		return !!( autoSlide && !autoSlidePaused );

	}

	/**
	 * Steps from the current point in the presentation to the
	 * slide which matches the specified horizontal and vertical
	 * indices.
	 *
	 * @param {number} [h=indexh] Horizontal index of the target slide
	 * @param {number} [v=indexv] Vertical index of the target slide
	 * @param {number} [f] Index of a fragment within the
	 * target slide to activate
	 * @param {number} [origin] Origin for use in multimaster environments
	 */
	function slide( h, v, f, origin ) {

		// Dispatch an event before the slide
		const slidechange = dispatchEvent({
			type: 'beforeslidechange',
			data: {
				indexh: h === undefined ? indexh : h,
				indexv: v === undefined ? indexv : v,
				origin
			}
		});

		// Abort if this slide change was prevented by an event listener
		if( slidechange.defaultPrevented ) return;

		// Remember where we were at before
		previousSlide = currentSlide;

		// Query all horizontal slides in the deck
		const horizontalSlides = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR );

		// Abort if there are no slides
		if( horizontalSlides.length === 0 ) return;

		// If no vertical index is specified and the upcoming slide is a
		// stack, resume at its previous vertical index
		if( v === undefined && !overview.isActive() ) {
			v = getPreviousVerticalIndex( horizontalSlides[ h ] );
		}

		// If we were on a vertical stack, remember what vertical index
		// it was on so we can resume at the same position when returning
		if( previousSlide && previousSlide.parentNode && previousSlide.parentNode.classList.contains( 'stack' ) ) {
			setPreviousVerticalIndex( previousSlide.parentNode, indexv );
		}

		// Remember the state before this slide
		const stateBefore = state.concat();

		// Reset the state array
		state.length = 0;

		let indexhBefore = indexh || 0,
			indexvBefore = indexv || 0;

		// Activate and transition to the new slide
		indexh = updateSlides( HORIZONTAL_SLIDES_SELECTOR, h === undefined ? indexh : h );
		indexv = updateSlides( VERTICAL_SLIDES_SELECTOR, v === undefined ? indexv : v );

		// Dispatch an event if the slide changed
		let slideChanged = ( indexh !== indexhBefore || indexv !== indexvBefore );

		// Ensure that the previous slide is never the same as the current
		if( !slideChanged ) previousSlide = null;

		// Find the current horizontal slide and any possible vertical slides
		// within it
		let currentHorizontalSlide = horizontalSlides[ indexh ],
			currentVerticalSlides = currentHorizontalSlide.querySelectorAll( 'section' );

		// Store references to the previous and current slides
		currentSlide = currentVerticalSlides[ indexv ] || currentHorizontalSlide;

		let autoAnimateTransition = false;

		// Detect if we're moving between two auto-animated slides
		if( slideChanged && previousSlide && currentSlide && !overview.isActive() ) {

			// If this is an auto-animated transition, we disable the
			// regular slide transition
			//
			// Note 20-03-2020:
			// This needs to happen before we update slide visibility,
			// otherwise transitions will still run in Safari.
			if( previousSlide.hasAttribute( 'data-auto-animate' ) && currentSlide.hasAttribute( 'data-auto-animate' )
					&& previousSlide.getAttribute( 'data-auto-animate-id' ) === currentSlide.getAttribute( 'data-auto-animate-id' )
					&& !( ( indexh > indexhBefore || indexv > indexvBefore ) ? currentSlide : previousSlide ).hasAttribute( 'data-auto-animate-restart' ) ) {

				autoAnimateTransition = true;
				dom.slides.classList.add( 'disable-slide-transitions' );
			}

			transition = 'running';

		}

		// Update the visibility of slides now that the indices have changed
		updateSlidesVisibility();

		layout();

		// Update the overview if it's currently active
		if( overview.isActive() ) {
			overview.update();
		}

		// Show fragment, if specified
		if( typeof f !== 'undefined' ) {
			fragments.goto( f );
		}

		// Solves an edge case where the previous slide maintains the
		// 'present' class when navigating between adjacent vertical
		// stacks
		if( previousSlide && previousSlide !== currentSlide ) {
			previousSlide.classList.remove( 'present' );
			previousSlide.setAttribute( 'aria-hidden', 'true' );

			// Reset all slides upon navigate to home
			if( isFirstSlide() ) {
				// Launch async task
				setTimeout( () => {
					getVerticalStacks().forEach( slide => {
						setPreviousVerticalIndex( slide, 0 );
					} );
				}, 0 );
			}
		}

		// Apply the new state
		stateLoop: for( let i = 0, len = state.length; i < len; i++ ) {
			// Check if this state existed on the previous slide. If it
			// did, we will avoid adding it repeatedly
			for( let j = 0; j < stateBefore.length; j++ ) {
				if( stateBefore[j] === state[i] ) {
					stateBefore.splice( j, 1 );
					continue stateLoop;
				}
			}

			dom.viewport.classList.add( state[i] );

			// Dispatch custom event matching the state's name
			dispatchEvent({ type: state[i] });
		}

		// Clean up the remains of the previous state
		while( stateBefore.length ) {
			dom.viewport.classList.remove( stateBefore.pop() );
		}

		if( slideChanged ) {
			dispatchEvent({
				type: 'slidechanged',
				data: {
					indexh,
					indexv,
					previousSlide,
					currentSlide,
					origin
				}
			});
		}

		// Handle embedded content
		if( slideChanged || !previousSlide ) {
			slideContent.stopEmbeddedContent( previousSlide );
			slideContent.startEmbeddedContent( currentSlide );
		}

		// Announce the current slide contents to screen readers
		// Use animation frame to prevent getComputedStyle in getStatusText
		// from triggering layout mid-frame
		requestAnimationFrame( () => {
			announceStatus( getStatusText( currentSlide ) );
		});

		progress.update();
		controls.update();
		notes.update();
		backgrounds.update();
		backgrounds.updateParallax();
		slideNumber.update();
		fragments.update();

		// Update the URL hash
		location.writeURL();

		cueAutoSlide();

		// Auto-animation
		if( autoAnimateTransition ) {

			setTimeout( () => {
				dom.slides.classList.remove( 'disable-slide-transitions' );
			}, 0 );

			if( config.autoAnimate ) {
				// Run the auto-animation between our slides
				autoAnimate.run( previousSlide, currentSlide );
			}

		}

	}

	/**
	 * Syncs the presentation with the current DOM. Useful
	 * when new slides or control elements are added or when
	 * the configuration has changed.
	 */
	function sync() {

		// Subscribe to input
		removeEventListeners();
		addEventListeners();

		// Force a layout to make sure the current config is accounted for
		layout();

		// Reflect the current autoSlide value
		autoSlide = config.autoSlide;

		// Start auto-sliding if it's enabled
		cueAutoSlide();

		// Re-create all slide backgrounds
		backgrounds.create();

		// Write the current hash to the URL
		location.writeURL();

		if( config.sortFragmentsOnSync === true ) {
			fragments.sortAll();
		}

		controls.update();
		progress.update();

		updateSlidesVisibility();

		notes.update();
		notes.updateVisibility();
		backgrounds.update( true );
		slideNumber.update();
		slideContent.formatEmbeddedContent();

		// Start or stop embedded content depending on global config
		if( config.autoPlayMedia === false ) {
			slideContent.stopEmbeddedContent( currentSlide, { unloadIframes: false } );
		}
		else {
			slideContent.startEmbeddedContent( currentSlide );
		}

		if( overview.isActive() ) {
			overview.layout();
		}

	}

	/**
	 * Updates reveal.js to keep in sync with new slide attributes. For
	 * example, if you add a new `data-background-image` you can call
	 * this to have reveal.js render the new background image.
	 *
	 * Similar to #sync() but more efficient when you only need to
	 * refresh a specific slide.
	 *
	 * @param {HTMLElement} slide
	 */
	function syncSlide( slide = currentSlide ) {

		backgrounds.sync( slide );
		fragments.sync( slide );

		slideContent.load( slide );

		backgrounds.update();
		notes.update();

	}

	/**
	 * Resets all vertical slides so that only the first
	 * is visible.
	 */
	function resetVerticalSlides() {

		getHorizontalSlides().forEach( horizontalSlide => {

			Util.queryAll( horizontalSlide, 'section' ).forEach( ( verticalSlide, y ) => {

				if( y > 0 ) {
					verticalSlide.classList.remove( 'present' );
					verticalSlide.classList.remove( 'past' );
					verticalSlide.classList.add( 'future' );
					verticalSlide.setAttribute( 'aria-hidden', 'true' );
				}

			} );

		} );

	}

	/**
	 * Randomly shuffles all slides in the deck.
	 */
	function shuffle( slides = getHorizontalSlides() ) {

		slides.forEach( ( slide, i ) => {

			// Insert the slide next to a randomly picked sibling slide
			// slide. This may cause the slide to insert before itself,
			// but that's not an issue.
			let beforeSlide = slides[ Math.floor( Math.random() * slides.length ) ];
			if( beforeSlide.parentNode === slide.parentNode ) {
				slide.parentNode.insertBefore( slide, beforeSlide );
			}

			// Randomize the order of vertical slides (if there are any)
			let verticalSlides = slide.querySelectorAll( 'section' );
			if( verticalSlides.length ) {
				shuffle( verticalSlides );
			}

		} );

	}

	/**
	 * Updates one dimension of slides by showing the slide
	 * with the specified index.
	 *
	 * @param {string} selector A CSS selector that will fetch
	 * the group of slides we are working with
	 * @param {number} index The index of the slide that should be
	 * shown
	 *
	 * @return {number} The index of the slide that is now shown,
	 * might differ from the passed in index if it was out of
	 * bounds.
	 */
	function updateSlides( selector, index ) {

		// Select all slides and convert the NodeList result to
		// an array
		let slides = Util.queryAll( dom.wrapper, selector ),
			slidesLength = slides.length;

		let printMode = print.isPrintingPDF();
		let loopedForwards = false;
		let loopedBackwards = false;

		if( slidesLength ) {

			// Should the index loop?
			if( config.loop ) {
				if( index >= slidesLength ) loopedForwards = true;

				index %= slidesLength;

				if( index < 0 ) {
					index = slidesLength + index;
					loopedBackwards = true;
				}
			}

			// Enforce max and minimum index bounds
			index = Math.max( Math.min( index, slidesLength - 1 ), 0 );

			for( let i = 0; i < slidesLength; i++ ) {
				let element = slides[i];

				let reverse = config.rtl && !isVerticalSlide( element );

				// Avoid .remove() with multiple args for IE11 support
				element.classList.remove( 'past' );
				element.classList.remove( 'present' );
				element.classList.remove( 'future' );

				// http://www.w3.org/html/wg/drafts/html/master/editing.html#the-hidden-attribute
				element.setAttribute( 'hidden', '' );
				element.setAttribute( 'aria-hidden', 'true' );

				// If this element contains vertical slides
				if( element.querySelector( 'section' ) ) {
					element.classList.add( 'stack' );
				}

				// If we're printing static slides, all slides are "present"
				if( printMode ) {
					element.classList.add( 'present' );
					continue;
				}

				if( i < index ) {
					// Any element previous to index is given the 'past' class
					element.classList.add( reverse ? 'future' : 'past' );

					if( config.fragments ) {
						// Show all fragments in prior slides
						showFragmentsIn( element );
					}
				}
				else if( i > index ) {
					// Any element subsequent to index is given the 'future' class
					element.classList.add( reverse ? 'past' : 'future' );

					if( config.fragments ) {
						// Hide all fragments in future slides
						hideFragmentsIn( element );
					}
				}
				// Update the visibility of fragments when a presentation loops
				// in either direction
				else if( i === index && config.fragments ) {
					if( loopedForwards ) {
						hideFragmentsIn( element );
					}
					else if( loopedBackwards ) {
						showFragmentsIn( element );
					}
				}
			}

			let slide = slides[index];
			let wasPresent = slide.classList.contains( 'present' );

			// Mark the current slide as present
			slide.classList.add( 'present' );
			slide.removeAttribute( 'hidden' );
			slide.removeAttribute( 'aria-hidden' );

			if( !wasPresent ) {
				// Dispatch an event indicating the slide is now visible
				dispatchEvent({
					target: slide,
					type: 'visible',
					bubbles: false
				});
			}

			// If this slide has a state associated with it, add it
			// onto the current state of the deck
			let slideState = slide.getAttribute( 'data-state' );
			if( slideState ) {
				state = state.concat( slideState.split( ' ' ) );
			}

		}
		else {
			// Since there are no slides we can't be anywhere beyond the
			// zeroth index
			index = 0;
		}

		return index;

	}

	/**
	 * Shows all fragment elements within the given contaienr.
	 */
	function showFragmentsIn( container ) {

		Util.queryAll( container, '.fragment' ).forEach( fragment => {
			fragment.classList.add( 'visible' );
			fragment.classList.remove( 'current-fragment' );
		} );

	}

	/**
	 * Hides all fragment elements within the given contaienr.
	 */
	function hideFragmentsIn( container ) {

		Util.queryAll( container, '.fragment.visible' ).forEach( fragment => {
			fragment.classList.remove( 'visible', 'current-fragment' );
		} );

	}

	/**
	 * Optimization method; hide all slides that are far away
	 * from the present slide.
	 */
	function updateSlidesVisibility() {

		// Select all slides and convert the NodeList result to
		// an array
		let horizontalSlides = getHorizontalSlides(),
			horizontalSlidesLength = horizontalSlides.length,
			distanceX,
			distanceY;

		if( horizontalSlidesLength && typeof indexh !== 'undefined' ) {

			// The number of steps away from the present slide that will
			// be visible
			let viewDistance = overview.isActive() ? 10 : config.viewDistance;

			// Shorten the view distance on devices that typically have
			// less resources
			if( Device.isMobile ) {
				viewDistance = overview.isActive() ? 6 : config.mobileViewDistance;
			}

			// All slides need to be visible when exporting to PDF
			if( print.isPrintingPDF() ) {
				viewDistance = Number.MAX_VALUE;
			}

			for( let x = 0; x < horizontalSlidesLength; x++ ) {
				let horizontalSlide = horizontalSlides[x];

				let verticalSlides = Util.queryAll( horizontalSlide, 'section' ),
					verticalSlidesLength = verticalSlides.length;

				// Determine how far away this slide is from the present
				distanceX = Math.abs( ( indexh || 0 ) - x ) || 0;

				// If the presentation is looped, distance should measure
				// 1 between the first and last slides
				if( config.loop ) {
					distanceX = Math.abs( ( ( indexh || 0 ) - x ) % ( horizontalSlidesLength - viewDistance ) ) || 0;
				}

				// Show the horizontal slide if it's within the view distance
				if( distanceX < viewDistance ) {
					slideContent.load( horizontalSlide );
				}
				else {
					slideContent.unload( horizontalSlide );
				}

				if( verticalSlidesLength ) {

					let oy = getPreviousVerticalIndex( horizontalSlide );

					for( let y = 0; y < verticalSlidesLength; y++ ) {
						let verticalSlide = verticalSlides[y];

						distanceY = x === ( indexh || 0 ) ? Math.abs( ( indexv || 0 ) - y ) : Math.abs( y - oy );

						if( distanceX + distanceY < viewDistance ) {
							slideContent.load( verticalSlide );
						}
						else {
							slideContent.unload( verticalSlide );
						}
					}

				}
			}

			// Flag if there are ANY vertical slides, anywhere in the deck
			if( hasVerticalSlides() ) {
				dom.wrapper.classList.add( 'has-vertical-slides' );
			}
			else {
				dom.wrapper.classList.remove( 'has-vertical-slides' );
			}

			// Flag if there are ANY horizontal slides, anywhere in the deck
			if( hasHorizontalSlides() ) {
				dom.wrapper.classList.add( 'has-horizontal-slides' );
			}
			else {
				dom.wrapper.classList.remove( 'has-horizontal-slides' );
			}

		}

	}

	/**
	 * Determine what available routes there are for navigation.
	 *
	 * @return {{left: boolean, right: boolean, up: boolean, down: boolean}}
	 */
	function availableRoutes({ includeFragments = false } = {}) {

		let horizontalSlides = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ),
			verticalSlides = dom.wrapper.querySelectorAll( VERTICAL_SLIDES_SELECTOR );

		let routes = {
			left: indexh > 0,
			right: indexh < horizontalSlides.length - 1,
			up: indexv > 0,
			down: indexv < verticalSlides.length - 1
		};

		// Looped presentations can always be navigated as long as
		// there are slides available
		if( config.loop ) {
			if( horizontalSlides.length > 1 ) {
				routes.left = true;
				routes.right = true;
			}

			if( verticalSlides.length > 1 ) {
				routes.up = true;
				routes.down = true;
			}
		}

		if ( horizontalSlides.length > 1 && config.navigationMode === 'linear' ) {
			routes.right = routes.right || routes.down;
			routes.left = routes.left || routes.up;
		}

		// If includeFragments is set, a route will be considered
		// available if either a slid OR fragment is available in
		// the given direction
		if( includeFragments === true ) {
			let fragmentRoutes = fragments.availableRoutes();
			routes.left = routes.left || fragmentRoutes.prev;
			routes.up = routes.up || fragmentRoutes.prev;
			routes.down = routes.down || fragmentRoutes.next;
			routes.right = routes.right || fragmentRoutes.next;
		}

		// Reverse horizontal controls for rtl
		if( config.rtl ) {
			let left = routes.left;
			routes.left = routes.right;
			routes.right = left;
		}

		return routes;

	}

	/**
	 * Returns the number of past slides. This can be used as a global
	 * flattened index for slides.
	 *
	 * @param {HTMLElement} [slide=currentSlide] The slide we're counting before
	 *
	 * @return {number} Past slide count
	 */
	function getSlidePastCount( slide = currentSlide ) {

		let horizontalSlides = getHorizontalSlides();

		// The number of past slides
		let pastCount = 0;

		// Step through all slides and count the past ones
		mainLoop: for( let i = 0; i < horizontalSlides.length; i++ ) {

			let horizontalSlide = horizontalSlides[i];
			let verticalSlides = horizontalSlide.querySelectorAll( 'section' );

			for( let j = 0; j < verticalSlides.length; j++ ) {

				// Stop as soon as we arrive at the present
				if( verticalSlides[j] === slide ) {
					break mainLoop;
				}

				// Don't count slides with the "uncounted" class
				if( verticalSlides[j].dataset.visibility !== 'uncounted' ) {
					pastCount++;
				}

			}

			// Stop as soon as we arrive at the present
			if( horizontalSlide === slide ) {
				break;
			}

			// Don't count the wrapping section for vertical slides and
			// slides marked as uncounted
			if( horizontalSlide.classList.contains( 'stack' ) === false && horizontalSlide.dataset.visibility !== 'uncounted' ) {
				pastCount++;
			}

		}

		return pastCount;

	}

	/**
	 * Returns a value ranging from 0-1 that represents
	 * how far into the presentation we have navigated.
	 *
	 * @return {number}
	 */
	function getProgress() {

		// The number of past and total slides
		let totalCount = getTotalSlides();
		let pastCount = getSlidePastCount();

		if( currentSlide ) {

			let allFragments = currentSlide.querySelectorAll( '.fragment' );

			// If there are fragments in the current slide those should be
			// accounted for in the progress.
			if( allFragments.length > 0 ) {
				let visibleFragments = currentSlide.querySelectorAll( '.fragment.visible' );

				// This value represents how big a portion of the slide progress
				// that is made up by its fragments (0-1)
				let fragmentWeight = 0.9;

				// Add fragment progress to the past slide count
				pastCount += ( visibleFragments.length / allFragments.length ) * fragmentWeight;
			}

		}

		return Math.min( pastCount / ( totalCount - 1 ), 1 );

	}

	/**
	 * Retrieves the h/v location and fragment of the current,
	 * or specified, slide.
	 *
	 * @param {HTMLElement} [slide] If specified, the returned
	 * index will be for this slide rather than the currently
	 * active one
	 *
	 * @return {{h: number, v: number, f: number}}
	 */
	function getIndices( slide ) {

		// By default, return the current indices
		let h = indexh,
			v = indexv,
			f;

		// If a slide is specified, return the indices of that slide
		if( slide ) {
			let isVertical = isVerticalSlide( slide );
			let slideh = isVertical ? slide.parentNode : slide;

			// Select all horizontal slides
			let horizontalSlides = getHorizontalSlides();

			// Now that we know which the horizontal slide is, get its index
			h = Math.max( horizontalSlides.indexOf( slideh ), 0 );

			// Assume we're not vertical
			v = undefined;

			// If this is a vertical slide, grab the vertical index
			if( isVertical ) {
				v = Math.max( Util.queryAll( slide.parentNode, 'section' ).indexOf( slide ), 0 );
			}
		}

		if( !slide && currentSlide ) {
			let hasFragments = currentSlide.querySelectorAll( '.fragment' ).length > 0;
			if( hasFragments ) {
				let currentFragment = currentSlide.querySelector( '.current-fragment' );
				if( currentFragment && currentFragment.hasAttribute( 'data-fragment-index' ) ) {
					f = parseInt( currentFragment.getAttribute( 'data-fragment-index' ), 10 );
				}
				else {
					f = currentSlide.querySelectorAll( '.fragment.visible' ).length - 1;
				}
			}
		}

		return { h, v, f };

	}

	/**
	 * Retrieves all slides in this presentation.
	 */
	function getSlides() {

		return Util.queryAll( dom.wrapper, SLIDES_SELECTOR + ':not(.stack):not([data-visibility="uncounted"])' );

	}

	/**
	 * Returns a list of all horizontal slides in the deck. Each
	 * vertical stack is included as one horizontal slide in the
	 * resulting array.
	 */
	function getHorizontalSlides() {

		return Util.queryAll( dom.wrapper, HORIZONTAL_SLIDES_SELECTOR );

	}

	/**
	 * Returns all vertical slides that exist within this deck.
	 */
	function getVerticalSlides() {

		return Util.queryAll( dom.wrapper, '.slides>section>section' );

	}

	/**
	 * Returns all vertical stacks (each stack can contain multiple slides).
	 */
	function getVerticalStacks() {

		return Util.queryAll( dom.wrapper, HORIZONTAL_SLIDES_SELECTOR + '.stack');

	}

	/**
	 * Returns true if there are at least two horizontal slides.
	 */
	function hasHorizontalSlides() {

		return getHorizontalSlides().length > 1;
	}

	/**
	 * Returns true if there are at least two vertical slides.
	 */
	function hasVerticalSlides() {

		return getVerticalSlides().length > 1;

	}

	/**
	 * Returns an array of objects where each object represents the
	 * attributes on its respective slide.
	 */
	function getSlidesAttributes() {

		return getSlides().map( slide => {

			let attributes = {};
			for( let i = 0; i < slide.attributes.length; i++ ) {
				let attribute = slide.attributes[ i ];
				attributes[ attribute.name ] = attribute.value;
			}
			return attributes;

		} );

	}

	/**
	 * Retrieves the total number of slides in this presentation.
	 *
	 * @return {number}
	 */
	function getTotalSlides() {

		return getSlides().length;

	}

	/**
	 * Returns the slide element matching the specified index.
	 *
	 * @return {HTMLElement}
	 */
	function getSlide( x, y ) {

		let horizontalSlide = getHorizontalSlides()[ x ];
		let verticalSlides = horizontalSlide && horizontalSlide.querySelectorAll( 'section' );

		if( verticalSlides && verticalSlides.length && typeof y === 'number' ) {
			return verticalSlides ? verticalSlides[ y ] : undefined;
		}

		return horizontalSlide;

	}

	/**
	 * Returns the background element for the given slide.
	 * All slides, even the ones with no background properties
	 * defined, have a background element so as long as the
	 * index is valid an element will be returned.
	 *
	 * @param {mixed} x Horizontal background index OR a slide
	 * HTML element
	 * @param {number} y Vertical background index
	 * @return {(HTMLElement[]|*)}
	 */
	function getSlideBackground( x, y ) {

		let slide = typeof x === 'number' ? getSlide( x, y ) : x;
		if( slide ) {
			return slide.slideBackgroundElement;
		}

		return undefined;

	}

	/**
	 * Retrieves the current state of the presentation as
	 * an object. This state can then be restored at any
	 * time.
	 *
	 * @return {{indexh: number, indexv: number, indexf: number, paused: boolean, overview: boolean}}
	 */
	function getState() {

		let indices = getIndices();

		return {
			indexh: indices.h,
			indexv: indices.v,
			indexf: indices.f,
			paused: isPaused(),
			overview: overview.isActive()
		};

	}

	/**
	 * Restores the presentation to the given state.
	 *
	 * @param {object} state As generated by getState()
	 * @see {@link getState} generates the parameter `state`
	 */
	function setState( state ) {

		if( typeof state === 'object' ) {
			slide( Util.deserialize( state.indexh ), Util.deserialize( state.indexv ), Util.deserialize( state.indexf ) );

			let pausedFlag = Util.deserialize( state.paused ),
				overviewFlag = Util.deserialize( state.overview );

			if( typeof pausedFlag === 'boolean' && pausedFlag !== isPaused() ) {
				togglePause( pausedFlag );
			}

			if( typeof overviewFlag === 'boolean' && overviewFlag !== overview.isActive() ) {
				overview.toggle( overviewFlag );
			}
		}

	}

	/**
	 * Cues a new automated slide if enabled in the config.
	 */
	function cueAutoSlide() {

		cancelAutoSlide();

		if( currentSlide && config.autoSlide !== false ) {

			let fragment = currentSlide.querySelector( '.current-fragment[data-autoslide]' );

			let fragmentAutoSlide = fragment ? fragment.getAttribute( 'data-autoslide' ) : null;
			let parentAutoSlide = currentSlide.parentNode ? currentSlide.parentNode.getAttribute( 'data-autoslide' ) : null;
			let slideAutoSlide = currentSlide.getAttribute( 'data-autoslide' );

			// Pick value in the following priority order:
			// 1. Current fragment's data-autoslide
			// 2. Current slide's data-autoslide
			// 3. Parent slide's data-autoslide
			// 4. Global autoSlide setting
			if( fragmentAutoSlide ) {
				autoSlide = parseInt( fragmentAutoSlide, 10 );
			}
			else if( slideAutoSlide ) {
				autoSlide = parseInt( slideAutoSlide, 10 );
			}
			else if( parentAutoSlide ) {
				autoSlide = parseInt( parentAutoSlide, 10 );
			}
			else {
				autoSlide = config.autoSlide;

				// If there are media elements with data-autoplay,
				// automatically set the autoSlide duration to the
				// length of that media. Not applicable if the slide
				// is divided up into fragments.
				// playbackRate is accounted for in the duration.
				if( currentSlide.querySelectorAll( '.fragment' ).length === 0 ) {
					Util.queryAll( currentSlide, 'video, audio' ).forEach( el => {
						if( el.hasAttribute( 'data-autoplay' ) ) {
							if( autoSlide && (el.duration * 1000 / el.playbackRate ) > autoSlide ) {
								autoSlide = ( el.duration * 1000 / el.playbackRate ) + 1000;
							}
						}
					} );
				}
			}

			// Cue the next auto-slide if:
			// - There is an autoSlide value
			// - Auto-sliding isn't paused by the user
			// - The presentation isn't paused
			// - The overview isn't active
			// - The presentation isn't over
			if( autoSlide && !autoSlidePaused && !isPaused() && !overview.isActive() && ( !isLastSlide() || fragments.availableRoutes().next || config.loop === true ) ) {
				autoSlideTimeout = setTimeout( () => {
					if( typeof config.autoSlideMethod === 'function' ) {
						config.autoSlideMethod()
					}
					else {
						navigateNext();
					}
					cueAutoSlide();
				}, autoSlide );
				autoSlideStartTime = Date.now();
			}

			if( autoSlidePlayer ) {
				autoSlidePlayer.setPlaying( autoSlideTimeout !== -1 );
			}

		}

	}

	/**
	 * Cancels any ongoing request to auto-slide.
	 */
	function cancelAutoSlide() {

		clearTimeout( autoSlideTimeout );
		autoSlideTimeout = -1;

	}

	function pauseAutoSlide() {

		if( autoSlide && !autoSlidePaused ) {
			autoSlidePaused = true;
			dispatchEvent({ type: 'autoslidepaused' });
			clearTimeout( autoSlideTimeout );

			if( autoSlidePlayer ) {
				autoSlidePlayer.setPlaying( false );
			}
		}

	}

	function resumeAutoSlide() {

		if( autoSlide && autoSlidePaused ) {
			autoSlidePaused = false;
			dispatchEvent({ type: 'autoslideresumed' });
			cueAutoSlide();
		}

	}

	function navigateLeft({skipFragments=false}={}) {

		navigationHistory.hasNavigatedHorizontally = true;

		// Reverse for RTL
		if( config.rtl ) {
			if( ( overview.isActive() || skipFragments || fragments.next() === false ) && availableRoutes().left ) {
				slide( indexh + 1, config.navigationMode === 'grid' ? indexv : undefined );
			}
		}
		// Normal navigation
		else if( ( overview.isActive() || skipFragments || fragments.prev() === false ) && availableRoutes().left ) {
			slide( indexh - 1, config.navigationMode === 'grid' ? indexv : undefined );
		}

	}

	function navigateRight({skipFragments=false}={}) {

		navigationHistory.hasNavigatedHorizontally = true;

		// Reverse for RTL
		if( config.rtl ) {
			if( ( overview.isActive() || skipFragments || fragments.prev() === false ) && availableRoutes().right ) {
				slide( indexh - 1, config.navigationMode === 'grid' ? indexv : undefined );
			}
		}
		// Normal navigation
		else if( ( overview.isActive() || skipFragments || fragments.next() === false ) && availableRoutes().right ) {
			slide( indexh + 1, config.navigationMode === 'grid' ? indexv : undefined );
		}

	}

	function navigateUp({skipFragments=false}={}) {

		// Prioritize hiding fragments
		if( ( overview.isActive() || skipFragments || fragments.prev() === false ) && availableRoutes().up ) {
			slide( indexh, indexv - 1 );
		}

	}

	function navigateDown({skipFragments=false}={}) {

		navigationHistory.hasNavigatedVertically = true;

		// Prioritize revealing fragments
		if( ( overview.isActive() || skipFragments || fragments.next() === false ) && availableRoutes().down ) {
			slide( indexh, indexv + 1 );
		}

	}

	/**
	 * Navigates backwards, prioritized in the following order:
	 * 1) Previous fragment
	 * 2) Previous vertical slide
	 * 3) Previous horizontal slide
	 */
	function navigatePrev({skipFragments=false}={}) {

		// Prioritize revealing fragments
		if( skipFragments || fragments.prev() === false ) {
			if( availableRoutes().up ) {
				navigateUp({skipFragments});
			}
			else {
				// Fetch the previous horizontal slide, if there is one
				let previousSlide;

				if( config.rtl ) {
					previousSlide = Util.queryAll( dom.wrapper, HORIZONTAL_SLIDES_SELECTOR + '.future' ).pop();
				}
				else {
					previousSlide = Util.queryAll( dom.wrapper, HORIZONTAL_SLIDES_SELECTOR + '.past' ).pop();
				}

				// When going backwards and arriving on a stack we start
				// at the bottom of the stack
				if( previousSlide && previousSlide.classList.contains( 'stack' ) ) {
					let v = ( previousSlide.querySelectorAll( 'section' ).length - 1 ) || undefined;
					let h = indexh - 1;
					slide( h, v );
				}
				else {
					navigateLeft({skipFragments});
				}
			}
		}

	}

	/**
	 * The reverse of #navigatePrev().
	 */
	function navigateNext({skipFragments=false}={}) {

		navigationHistory.hasNavigatedHorizontally = true;
		navigationHistory.hasNavigatedVertically = true;

		// Prioritize revealing fragments
		if( skipFragments || fragments.next() === false ) {

			let routes = availableRoutes();

			// When looping is enabled `routes.down` is always available
			// so we need a separate check for when we've reached the
			// end of a stack and should move horizontally
			if( routes.down && routes.right && config.loop && isLastVerticalSlide() ) {
				routes.down = false;
			}

			if( routes.down ) {
				navigateDown({skipFragments});
			}
			else if( config.rtl ) {
				navigateLeft({skipFragments});
			}
			else {
				navigateRight({skipFragments});
			}
		}

	}


	// --------------------------------------------------------------------//
	// ----------------------------- EVENTS -------------------------------//
	// --------------------------------------------------------------------//

	/**
	 * Called by all event handlers that are based on user
	 * input.
	 *
	 * @param {object} [event]
	 */
	function onUserInput( event ) {

		if( config.autoSlideStoppable ) {
			pauseAutoSlide();
		}

	}

	/**
	* Listener for post message events posted to this window.
	*/
	function onPostMessage( event ) {

		let data = event.data;

		// Make sure we're dealing with JSON
		if( typeof data === 'string' && data.charAt( 0 ) === '{' && data.charAt( data.length - 1 ) === '}' ) {
			data = JSON.parse( data );

			// Check if the requested method can be found
			if( data.method && typeof Reveal[data.method] === 'function' ) {

				if( POST_MESSAGE_METHOD_BLACKLIST.test( data.method ) === false ) {

					const result = Reveal[data.method].apply( Reveal, data.args );

					// Dispatch a postMessage event with the returned value from
					// our method invocation for getter functions
					dispatchPostMessage( 'callback', { method: data.method, result: result } );

				}
				else {
					console.warn( 'reveal.js: "'+ data.method +'" is is blacklisted from the postMessage API' );
				}

			}
		}

	}

	/**
	 * Event listener for transition end on the current slide.
	 *
	 * @param {object} [event]
	 */
	function onTransitionEnd( event ) {

		if( transition === 'running' && /section/gi.test( event.target.nodeName ) ) {
			transition = 'idle';
			dispatchEvent({
				type: 'slidetransitionend',
				data: { indexh, indexv, previousSlide, currentSlide }
			});
		}

	}

	/**
	 * A global listener for all click events inside of the
	 * .slides container.
	 *
	 * @param {object} [event]
	 */
	function onSlidesClicked( event ) {

		const anchor = Util.closest( event.target, 'a[href^="#"]' );

		// If a hash link is clicked, we find the target slide
		// and navigate to it. We previously relied on 'hashchange'
		// for links like these but that prevented media with
		// audio tracks from playing in mobile browsers since it
		// wasn't considered a direct interaction with the document.
		if( anchor ) {
			const hash = anchor.getAttribute( 'href' );
			const indices = location.getIndicesFromHash( hash );

			if( indices ) {
				Reveal.slide( indices.h, indices.v, indices.f );
				event.preventDefault();
			}
		}

	}

	/**
	 * Handler for the window level 'resize' event.
	 *
	 * @param {object} [event]
	 */
	function onWindowResize( event ) {

		layout();

	}

	/**
	 * Handle for the window level 'visibilitychange' event.
	 *
	 * @param {object} [event]
	 */
	function onPageVisibilityChange( event ) {

		// If, after clicking a link or similar and we're coming back,
		// focus the document.body to ensure we can use keyboard shortcuts
		if( document.hidden === false && document.activeElement !== document.body ) {
			// Not all elements support .blur() - SVGs among them.
			if( typeof document.activeElement.blur === 'function' ) {
				document.activeElement.blur();
			}
			document.body.focus();
		}

	}

	/**
	 * Handler for the document level 'fullscreenchange' event.
	 *
	 * @param {object} [event]
	 */
	function onFullscreenChange( event ) {

		let element = document.fullscreenElement || document.webkitFullscreenElement;
		if( element === dom.wrapper ) {
			event.stopImmediatePropagation();

			// Timeout to avoid layout shift in Safari
			setTimeout( () => {
				Reveal.layout();
				Reveal.focus.focus(); // focus.focus :'(
			}, 1 );
		}

	}

	/**
	 * Handles clicks on links that are set to preview in the
	 * iframe overlay.
	 *
	 * @param {object} event
	 */
	function onPreviewLinkClicked( event ) {

		if( event.currentTarget && event.currentTarget.hasAttribute( 'href' ) ) {
			let url = event.currentTarget.getAttribute( 'href' );
			if( url ) {
				showPreview( url );
				event.preventDefault();
			}
		}

	}

	/**
	 * Handles click on the auto-sliding controls element.
	 *
	 * @param {object} [event]
	 */
	function onAutoSlidePlayerClick( event ) {

		// Replay
		if( isLastSlide() && config.loop === false ) {
			slide( 0, 0 );
			resumeAutoSlide();
		}
		// Resume
		else if( autoSlidePaused ) {
			resumeAutoSlide();
		}
		// Pause
		else {
			pauseAutoSlide();
		}

	}


	// --------------------------------------------------------------------//
	// ------------------------------- API --------------------------------//
	// --------------------------------------------------------------------//

	// The public reveal.js API
	const API = {
		VERSION,

		initialize,
		configure,
		destroy,

		sync,
		syncSlide,
		syncFragments: fragments.sync.bind( fragments ),

		// Navigation methods
		slide,
		left: navigateLeft,
		right: navigateRight,
		up: navigateUp,
		down: navigateDown,
		prev: navigatePrev,
		next: navigateNext,

		// Navigation aliases
		navigateLeft, navigateRight, navigateUp, navigateDown, navigatePrev, navigateNext,

		// Fragment methods
		navigateFragment: fragments.goto.bind( fragments ),
		prevFragment: fragments.prev.bind( fragments ),
		nextFragment: fragments.next.bind( fragments ),

		// Event binding
		on,
		off,

		// Legacy event binding methods left in for backwards compatibility
		addEventListener: on,
		removeEventListener: off,

		// Forces an update in slide layout
		layout,

		// Randomizes the order of slides
		shuffle,

		// Returns an object with the available routes as booleans (left/right/top/bottom)
		availableRoutes,

		// Returns an object with the available fragments as booleans (prev/next)
		availableFragments: fragments.availableRoutes.bind( fragments ),

		// Toggles a help overlay with keyboard shortcuts
		toggleHelp,

		// Toggles the overview mode on/off
		toggleOverview: overview.toggle.bind( overview ),

		// Toggles the "black screen" mode on/off
		togglePause,

		// Toggles the auto slide mode on/off
		toggleAutoSlide,

		// Toggles visibility of the jump-to-slide UI
		toggleJumpToSlide,

		// Slide navigation checks
		isFirstSlide,
		isLastSlide,
		isLastVerticalSlide,
		isVerticalSlide,

		// State checks
		isPaused,
		isAutoSliding,
		isSpeakerNotes: notes.isSpeakerNotesWindow.bind( notes ),
		isOverview: overview.isActive.bind( overview ),
		isFocused: focus.isFocused.bind( focus ),
		isPrintingPDF: print.isPrintingPDF.bind( print ),

		// Checks if reveal.js has been loaded and is ready for use
		isReady: () => ready,

		// Slide preloading
		loadSlide: slideContent.load.bind( slideContent ),
		unloadSlide: slideContent.unload.bind( slideContent ),

		// Media playback
		startEmbeddedContent: () => slideContent.startEmbeddedContent( currentSlide ),
		stopEmbeddedContent: () => slideContent.stopEmbeddedContent( currentSlide, { unloadIframes: false } ),

		// Preview management
		showPreview,
		hidePreview: closeOverlay,

		// Adds or removes all internal event listeners
		addEventListeners,
		removeEventListeners,
		dispatchEvent,

		// Facility for persisting and restoring the presentation state
		getState,
		setState,

		// Presentation progress on range of 0-1
		getProgress,

		// Returns the indices of the current, or specified, slide
		getIndices,

		// Returns an Array of key:value maps of the attributes of each
		// slide in the deck
		getSlidesAttributes,

		// Returns the number of slides that we have passed
		getSlidePastCount,

		// Returns the total number of slides
		getTotalSlides,

		// Returns the slide element at the specified index
		getSlide,

		// Returns the previous slide element, may be null
		getPreviousSlide: () => previousSlide,

		// Returns the current slide element
		getCurrentSlide: () => currentSlide,

		// Returns the slide background element at the specified index
		getSlideBackground,

		// Returns the speaker notes string for a slide, or null
		getSlideNotes: notes.getSlideNotes.bind( notes ),

		// Returns an Array of all slides
		getSlides,

		// Returns an array with all horizontal/vertical slides in the deck
		getHorizontalSlides,
		getVerticalSlides,

		// Checks if the presentation contains two or more horizontal
		// and vertical slides
		hasHorizontalSlides,
		hasVerticalSlides,

		// Checks if the deck has navigated on either axis at least once
		hasNavigatedHorizontally: () => navigationHistory.hasNavigatedHorizontally,
		hasNavigatedVertically: () => navigationHistory.hasNavigatedVertically,

		// Adds/removes a custom key binding
		addKeyBinding: keyboard.addKeyBinding.bind( keyboard ),
		removeKeyBinding: keyboard.removeKeyBinding.bind( keyboard ),

		// Programmatically triggers a keyboard event
		triggerKey: keyboard.triggerKey.bind( keyboard ),

		// Registers a new shortcut to include in the help overlay
		registerKeyboardShortcut: keyboard.registerKeyboardShortcut.bind( keyboard ),

		getComputedSlideSize,

		// Returns the current scale of the presentation content
		getScale: () => scale,

		// Returns the current configuration object
		getConfig: () => config,

		// Helper method, retrieves query string as a key:value map
		getQueryHash: Util.getQueryHash,

		// Returns the path to the current slide as represented in the URL
		getSlidePath: location.getHash.bind( location ),

		// Returns reveal.js DOM elements
		getRevealElement: () => revealElement,
		getSlidesElement: () => dom.slides,
		getViewportElement: () => dom.viewport,
		getBackgroundsElement: () => backgrounds.element,

		// API for registering and retrieving plugins
		registerPlugin: plugins.registerPlugin.bind( plugins ),
		hasPlugin: plugins.hasPlugin.bind( plugins ),
		getPlugin: plugins.getPlugin.bind( plugins ),
		getPlugins: plugins.getRegisteredPlugins.bind( plugins )

	};

	// Our internal API which controllers have access to
	Util.extend( Reveal, {
		...API,

		// Methods for announcing content to screen readers
		announceStatus,
		getStatusText,

		// Controllers
		print,
		focus,
		progress,
		controls,
		location,
		overview,
		fragments,
		slideContent,
		slideNumber,

		onUserInput,
		closeOverlay,
		updateSlidesVisibility,
		layoutSlideContents,
		transformSlides,
		cueAutoSlide,
		cancelAutoSlide
	} );

	return API;

};
