{"version":3,"file":"GSDevTools.min.js","sources":["../src/utils/matrix.js","../src/Draggable.js","../src/GSDevTools.js"],"sourcesContent":["/*!\n * matrix 3.11.0\n * https://greensock.com\n *\n * Copyright 2008-2022, GreenSock. All rights reserved.\n * Subject to the terms at https://greensock.com/standard-license or for\n * Club GreenSock members, the agreement issued with that membership.\n * @author: Jack Doyle, jack@greensock.com\n*/\n/* eslint-disable */\n\nlet _doc, _win, _docElement, _body,\t_divContainer, _svgContainer, _identityMatrix, _gEl,\n\t_transformProp = \"transform\",\n\t_transformOriginProp = _transformProp + \"Origin\",\n\t_hasOffsetBug,\n\t_setDoc = element => {\n\t\tlet doc = element.ownerDocument || element;\n\t\tif (!(_transformProp in element.style) && \"msTransform\" in element.style) { //to improve compatibility with old Microsoft browsers\n\t\t\t_transformProp = \"msTransform\";\n\t\t\t_transformOriginProp = _transformProp + \"Origin\";\n\t\t}\n\t\twhile (doc.parentNode && (doc = doc.parentNode)) {\t}\n\t\t_win = window;\n\t\t_identityMatrix = new Matrix2D();\n\t\tif (doc) {\n\t\t\t_doc = doc;\n\t\t\t_docElement = doc.documentElement;\n\t\t\t_body = doc.body;\n\t\t\t_gEl = _doc.createElementNS(\"http://www.w3.org/2000/svg\", \"g\");\n\t\t\t// prevent any existing CSS from transforming it\n\t\t\t_gEl.style.transform = \"none\";\n\t\t\t// now test for the offset reporting bug. Use feature detection instead of browser sniffing to make things more bulletproof and future-proof. Hopefully Safari will fix their bug soon but it's 2020 and it's still not fixed.\n\t\t\tlet d1 = doc.createElement(\"div\"),\n\t\t\t\td2 = doc.createElement(\"div\");\n\t\t\t_body.appendChild(d1);\n\t\t\td1.appendChild(d2);\n\t\t\td1.style.position = \"static\";\n\t\t\td1.style[_transformProp] = \"translate3d(0,0,1px)\";\n\t\t\t_hasOffsetBug = (d2.offsetParent !== d1);\n\t\t\t_body.removeChild(d1);\n\t\t}\n\t\treturn doc;\n\t},\n\t_forceNonZeroScale = e => { // walks up the element's ancestors and finds any that had their scale set to 0 via GSAP, and changes them to 0.0001 to ensure that measurements work. Firefox has a bug that causes it to incorrectly report getBoundingClientRect() when scale is 0.\n\t\tlet a, cache;\n\t\twhile (e && e !== _body) {\n\t\t\tcache = e._gsap;\n\t\t\tcache && cache.uncache && cache.get(e, \"x\"); // force re-parsing of transforms if necessary\n\t\t\tif (cache && !cache.scaleX && !cache.scaleY && cache.renderTransform) {\n\t\t\t\tcache.scaleX = cache.scaleY = 1e-4;\n\t\t\t\tcache.renderTransform(1, cache);\n\t\t\t\ta ? a.push(cache) : (a = [cache]);\n\t\t\t}\n\t\t\te = e.parentNode;\n\t\t}\n\t\treturn a;\n\t},\n\t// possible future addition: pass an element to _forceDisplay() and it'll walk up all its ancestors and make sure anything with display: none is set to display: block, and if there's no parentNode, it'll add it to the body. It returns an Array that you can then feed to _revertDisplay() to have it revert all the changes it made.\n\t// _forceDisplay = e => {\n\t// \tlet a = [],\n\t// \t\tparent;\n\t// \twhile (e && e !== _body) {\n\t// \t\tparent = e.parentNode;\n\t// \t\t(_win.getComputedStyle(e).display === \"none\" || !parent) && a.push(e, e.style.display, parent) && (e.style.display = \"block\");\n\t// \t\tparent || _body.appendChild(e);\n\t// \t\te = parent;\n\t// \t}\n\t// \treturn a;\n\t// },\n\t// _revertDisplay = a => {\n\t// \tfor (let i = 0; i < a.length; i+=3) {\n\t// \t\ta[i+1] ? (a[i].style.display = a[i+1]) : a[i].style.removeProperty(\"display\");\n\t// \t\ta[i+2] || a[i].parentNode.removeChild(a[i]);\n\t// \t}\n\t// },\n\t_svgTemps = [], //we create 3 elements for SVG, and 3 for other DOM elements and cache them for performance reasons. They get nested in _divContainer and _svgContainer so that just one element is added to the DOM on each successive attempt. Again, performance is key.\n\t_divTemps = [],\n\t_getDocScrollTop = () => _win.pageYOffset || _doc.scrollTop || _docElement.scrollTop || _body.scrollTop || 0,\n\t_getDocScrollLeft = () => _win.pageXOffset || _doc.scrollLeft || _docElement.scrollLeft || _body.scrollLeft || 0,\n\t_svgOwner = element => element.ownerSVGElement || ((element.tagName + \"\").toLowerCase() === \"svg\" ? element : null),\n\t_isFixed = element => {\n\t\tif (_win.getComputedStyle(element).position === \"fixed\") {\n\t\t\treturn true;\n\t\t}\n\t\telement = element.parentNode;\n\t\tif (element && element.nodeType === 1) { // avoid document fragments which will throw an error.\n\t\t\treturn _isFixed(element);\n\t\t}\n\t},\n\t_createSibling = (element, i) => {\n\t\tif (element.parentNode && (_doc || _setDoc(element))) {\n\t\t\tlet svg = _svgOwner(element),\n\t\t\t\tns = svg ? (svg.getAttribute(\"xmlns\") || \"http://www.w3.org/2000/svg\") : \"http://www.w3.org/1999/xhtml\",\n\t\t\t\ttype = svg ? (i ? \"rect\" : \"g\") : \"div\",\n\t\t\t\tx = i !== 2 ? 0 : 100,\n\t\t\t\ty = i === 3 ? 100 : 0,\n\t\t\t\tcss = \"position:absolute;display:block;pointer-events:none;margin:0;padding:0;\",\n\t\t\t\te = _doc.createElementNS ? _doc.createElementNS(ns.replace(/^https/, \"http\"), type) : _doc.createElement(type);\n\t\t\tif (i) {\n\t\t\t\tif (!svg) {\n\t\t\t\t\tif (!_divContainer) {\n\t\t\t\t\t\t_divContainer = _createSibling(element);\n\t\t\t\t\t\t_divContainer.style.cssText = css;\n\t\t\t\t\t}\n\t\t\t\t\te.style.cssText = css + \"width:0.1px;height:0.1px;top:\" + y + \"px;left:\" + x + \"px\";\n\t\t\t\t\t_divContainer.appendChild(e);\n\n\t\t\t\t} else {\n\t\t\t\t\t_svgContainer || (_svgContainer = _createSibling(element));\n\t\t\t\t\te.setAttribute(\"width\", 0.01);\n\t\t\t\t\te.setAttribute(\"height\", 0.01);\n\t\t\t\t\te.setAttribute(\"transform\", \"translate(\" + x + \",\" + y + \")\");\n\t\t\t\t\t_svgContainer.appendChild(e);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn e;\n\t\t}\n\t\tthrow \"Need document and parent.\";\n\t},\n\t_consolidate = m => { // replaces SVGTransformList.consolidate() because a bug in Firefox causes it to break pointer events. See https://greensock.com/forums/topic/23248-touch-is-not-working-on-draggable-in-firefox-windows-v324/?tab=comments#comment-109800\n\t\tlet c = new Matrix2D(),\n\t\t\ti = 0;\n\t\tfor (; i < m.numberOfItems; i++) {\n\t\t\tc.multiply(m.getItem(i).matrix);\n\t\t}\n\t\treturn c;\n\t},\n\t_getCTM = svg => {\n\t\tlet m = svg.getCTM(),\n\t\t\ttransform;\n\t\tif (!m) { // Firefox returns null for getCTM() on root elements, so this is a workaround using a that we temporarily append.\n\t\t\ttransform = svg.style[_transformProp];\n\t\t\tsvg.style[_transformProp] = \"none\"; // a bug in Firefox causes css transforms to contaminate the getCTM()\n\t\t\tsvg.appendChild(_gEl);\n\t\t\tm = _gEl.getCTM();\n\t\t\tsvg.removeChild(_gEl);\n\t\t\ttransform ? (svg.style[_transformProp] = transform) : svg.style.removeProperty(_transformProp.replace(/([A-Z])/g, \"-$1\").toLowerCase());\n\t\t}\n\t\treturn m || _identityMatrix.clone(); // Firefox will still return null if the has a width/height of 0 in the browser.\n\t},\n\t_placeSiblings = (element, adjustGOffset) => {\n\t\tlet svg = _svgOwner(element),\n\t\t\tisRootSVG = element === svg,\n\t\t\tsiblings = svg ? _svgTemps : _divTemps,\n\t\t\tparent = element.parentNode,\n\t\t\tcontainer, m, b, x, y, cs;\n\t\tif (element === _win) {\n\t\t\treturn element;\n\t\t}\n\t\tsiblings.length || siblings.push(_createSibling(element, 1), _createSibling(element, 2), _createSibling(element, 3));\n\t\tcontainer = svg ? _svgContainer : _divContainer;\n\t\tif (svg) {\n\t\t\tif (isRootSVG) {\n\t\t\t\tb = _getCTM(element);\n\t\t\t\tx = -b.e / b.a;\n\t\t\t\ty = -b.f / b.d;\n\t\t\t\tm = _identityMatrix;\n\t\t\t} else if (element.getBBox) {\n\t\t\t\tb = element.getBBox();\n\t\t\t\tm = element.transform ? element.transform.baseVal : {}; // IE11 doesn't follow the spec.\n\t\t\t\tm = !m.numberOfItems ? _identityMatrix : m.numberOfItems > 1 ? _consolidate(m) : m.getItem(0).matrix; // don't call m.consolidate().matrix because a bug in Firefox makes pointer events not work when consolidate() is called on the same tick as getBoundingClientRect()! See https://greensock.com/forums/topic/23248-touch-is-not-working-on-draggable-in-firefox-windows-v324/?tab=comments#comment-109800\n\t\t\t\tx = m.a * b.x + m.c * b.y;\n\t\t\t\ty = m.b * b.x + m.d * b.y;\n\t\t\t} else { // may be a which has no getBBox() so just use defaults instead of throwing errors.\n\t\t\t\tm = new Matrix2D();\n\t\t\t\tx = y = 0;\n\t\t\t}\n\t\t\tif (adjustGOffset && element.tagName.toLowerCase() === \"g\") {\n\t\t\t\tx = y = 0;\n\t\t\t}\n\t\t\t(isRootSVG ? svg : parent).appendChild(container);\n\t\t\tcontainer.setAttribute(\"transform\", \"matrix(\" + m.a + \",\" + m.b + \",\" + m.c + \",\" + m.d + \",\" + (m.e + x) + \",\" + (m.f + y) + \")\");\n\t\t} else {\n\t\t\tx = y = 0;\n\t\t\tif (_hasOffsetBug) { // some browsers (like Safari) have a bug that causes them to misreport offset values. When an ancestor element has a transform applied, it's supposed to treat it as if it's position: relative (new context). Safari botches this, so we need to find the closest ancestor (between the element and its offsetParent) that has a transform applied and if one is found, grab its offsetTop/Left and subtract them to compensate.\n\t\t\t\tm = element.offsetParent;\n\t\t\t\tb = element;\n\t\t\t\twhile (b && (b = b.parentNode) && b !== m && b.parentNode) {\n\t\t\t\t\tif ((_win.getComputedStyle(b)[_transformProp] + \"\").length > 4) {\n\t\t\t\t\t\tx = b.offsetLeft;\n\t\t\t\t\t\ty = b.offsetTop;\n\t\t\t\t\t\tb = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcs = _win.getComputedStyle(element);\n\t\t\tif (cs.position !== \"absolute\" && cs.position !== \"fixed\") {\n\t\t\t\tm = element.offsetParent;\n\t\t\t\twhile (parent && parent !== m) { // if there's an ancestor element between the element and its offsetParent that's scrolled, we must factor that in.\n\t\t\t\t\tx += parent.scrollLeft || 0;\n\t\t\t\t\ty += parent.scrollTop || 0;\n\t\t\t\t\tparent = parent.parentNode;\n\t\t\t\t}\n\t\t\t}\n\t\t\tb = container.style;\n\t\t\tb.top = (element.offsetTop - y) + \"px\";\n\t\t\tb.left = (element.offsetLeft - x) + \"px\";\n\t\t\tb[_transformProp] = cs[_transformProp];\n\t\t\tb[_transformOriginProp] = cs[_transformOriginProp];\n\t\t\t// b.border = m.border;\n\t\t\t// b.borderLeftStyle = m.borderLeftStyle;\n\t\t\t// b.borderTopStyle = m.borderTopStyle;\n\t\t\t// b.borderLeftWidth = m.borderLeftWidth;\n\t\t\t// b.borderTopWidth = m.borderTopWidth;\n\t\t\tb.position = cs.position === \"fixed\" ? \"fixed\" : \"absolute\";\n\t\t\telement.parentNode.appendChild(container);\n\t\t}\n\t\treturn container;\n\t},\n\t_setMatrix = (m, a, b, c, d, e, f) => {\n\t\tm.a = a;\n\t\tm.b = b;\n\t\tm.c = c;\n\t\tm.d = d;\n\t\tm.e = e;\n\t\tm.f = f;\n\t\treturn m;\n\t};\n\nexport class Matrix2D {\n\tconstructor(a=1, b=0, c=0, d=1, e=0, f=0) {\n\t\t_setMatrix(this, a, b, c, d, e, f);\n\t}\n\n\tinverse() {\n\t\tlet {a, b, c, d, e, f} = this,\n\t\t\tdeterminant = (a * d - b * c) || 1e-10;\n\t\treturn _setMatrix(\n\t\t\tthis,\n\t\t\td / determinant,\n\t\t\t-b / determinant,\n\t\t\t-c / determinant,\n\t\t\ta / determinant,\n\t\t\t(c * f - d * e) / determinant,\n\t\t\t-(a * f - b * e) / determinant\n\t\t);\n\t}\n\n\tmultiply(matrix) {\n\t\tlet {a, b, c, d, e, f} = this,\n\t\t\ta2 = matrix.a,\n\t\t\tb2 = matrix.c,\n\t\t\tc2 = matrix.b,\n\t\t\td2 = matrix.d,\n\t\t\te2 = matrix.e,\n\t\t\tf2 = matrix.f;\n\t\treturn _setMatrix(this,\n\t\t\ta2 * a + c2 * c,\n\t\t\ta2 * b + c2 * d,\n\t\t\tb2 * a + d2 * c,\n\t\t\tb2 * b + d2 * d,\n\t\t\te + e2 * a + f2 * c,\n\t\t\tf + e2 * b + f2 * d);\n\t}\n\n\tclone() {\n\t\treturn new Matrix2D(this.a, this.b, this.c, this.d, this.e, this.f);\n\t}\n\n\tequals(matrix) {\n\t\tlet {a, b, c, d, e, f} = this;\n\t\treturn (a === matrix.a && b === matrix.b && c === matrix.c && d === matrix.d && e === matrix.e && f === matrix.f);\n\t}\n\n\tapply(point, decoratee={}) {\n\t\tlet {x, y} = point,\n\t\t\t{a, b, c, d, e, f} = this;\n\t\tdecoratee.x = (x * a + y * c + e) || 0;\n\t\tdecoratee.y = (x * b + y * d + f) || 0;\n\t\treturn decoratee;\n\t}\n\n}\n\n// Feed in an element and it'll return a 2D matrix (optionally inverted) so that you can translate between coordinate spaces.\n// Inverting lets you translate a global point into a local coordinate space. No inverting lets you go the other way.\n// We needed this to work around various browser bugs, like Firefox doesn't accurately report getScreenCTM() when there\n// are transforms applied to ancestor elements.\n// The matrix math to convert any x/y coordinate is as follows, which is wrapped in a convenient apply() method of Matrix2D above:\n// tx = m.a * x + m.c * y + m.e\n// ty = m.b * x + m.d * y + m.f\nexport function getGlobalMatrix(element, inverse, adjustGOffset, includeScrollInFixed) { // adjustGOffset is typically used only when grabbing an element's PARENT's global matrix, and it ignores the x/y offset of any SVG elements because they behave in a special way.\n\tif (!element || !element.parentNode || (_doc || _setDoc(element)).documentElement === element) {\n\t\treturn new Matrix2D();\n\t}\n\tlet zeroScales = _forceNonZeroScale(element),\n\t\tsvg = _svgOwner(element),\n\t\ttemps = svg ? _svgTemps : _divTemps,\n\t\tcontainer = _placeSiblings(element, adjustGOffset),\n\t\tb1 = temps[0].getBoundingClientRect(),\n\t\tb2 = temps[1].getBoundingClientRect(),\n\t\tb3 = temps[2].getBoundingClientRect(),\n\t\tparent = container.parentNode,\n\t\tisFixed = !includeScrollInFixed && _isFixed(element),\n\t\tm = new Matrix2D(\n\t\t\t(b2.left - b1.left) / 100,\n\t\t\t(b2.top - b1.top) / 100,\n\t\t\t(b3.left - b1.left) / 100,\n\t\t\t(b3.top - b1.top) / 100,\n\t\t\tb1.left + (isFixed ? 0 : _getDocScrollLeft()),\n\t\t\tb1.top + (isFixed ? 0 : _getDocScrollTop())\n\t\t);\n\tparent.removeChild(container);\n\tif (zeroScales) {\n\t\tb1 = zeroScales.length;\n\t\twhile (b1--) {\n\t\t\tb2 = zeroScales[b1];\n\t\t\tb2.scaleX = b2.scaleY = 0;\n\t\t\tb2.renderTransform(1, b2);\n\t\t}\n\t}\n\treturn inverse ? m.inverse() : m;\n}\n\nexport { _getDocScrollTop, _getDocScrollLeft, _setDoc, _isFixed, _getCTM };\n\n// export function getMatrix(element) {\n// \t_doc || _setDoc(element);\n// \tlet m = (_win.getComputedStyle(element)[_transformProp] + \"\").substr(7).match(/[-.]*\\d+[.e\\-+]*\\d*[e\\-\\+]*\\d*/g),\n// \t\tis2D = m && m.length === 6;\n// \treturn !m || m.length < 6 ? new Matrix2D() : new Matrix2D(+m[0], +m[1], +m[is2D ? 2 : 4], +m[is2D ? 3 : 5], +m[is2D ? 4 : 12], +m[is2D ? 5 : 13]);\n// }","/*!\n * Draggable 3.11.0\n * https://greensock.com\n *\n * @license Copyright 2008-2022, GreenSock. All rights reserved.\n * Subject to the terms at https://greensock.com/standard-license or for\n * Club GreenSock members, the agreement issued with that membership.\n * @author: Jack Doyle, jack@greensock.com\n */\n/* eslint-disable */\n\nimport { getGlobalMatrix, Matrix2D } from \"./utils/matrix.js\";\n\nlet gsap, _win, _doc, _docElement, _body, _tempDiv, _placeholderDiv, _coreInitted, _checkPrefix, _toArray, _supportsPassive, _isTouchDevice, _touchEventLookup, _dragCount, _isMultiTouching, _isAndroid, InertiaPlugin, _defaultCursor, _supportsPointer,\n\t_windowExists = () => typeof(window) !== \"undefined\",\n\t_getGSAP = () => gsap || (_windowExists() && (gsap = window.gsap) && gsap.registerPlugin && gsap),\n\t_isFunction = value => typeof(value) === \"function\",\n\t_isObject = value => typeof(value) === \"object\",\n\t_isUndefined = value => typeof(value) === \"undefined\",\n\t_emptyFunc = () => false,\n\t_transformProp = \"transform\",\n\t_transformOriginProp = \"transformOrigin\",\n\t_round = value => Math.round(value * 10000) / 10000,\n\t_isArray = Array.isArray,\n\t_createElement = (type, ns) => {\n\t\tlet e = _doc.createElementNS ? _doc.createElementNS((ns || \"http://www.w3.org/1999/xhtml\").replace(/^https/, \"http\"), type) : _doc.createElement(type); //some servers swap in https for http in the namespace which can break things, making \"style\" inaccessible.\n\t\treturn e.style ? e : _doc.createElement(type); //some environments won't allow access to the element's style when created with a namespace in which case we default to the standard createElement() to work around the issue. Also note that when GSAP is embedded directly inside an SVG file, createElement() won't allow access to the style object in Firefox (see https://greensock.com/forums/topic/20215-problem-using-tweenmax-in-standalone-self-containing-svg-file-err-cannot-set-property-csstext-of-undefined/).\n\t},\n\t_RAD2DEG = 180 / Math.PI,\n\t_bigNum = 1e20,\n\t_identityMatrix = new Matrix2D(),\n\t_getTime = Date.now || (() => new Date().getTime()),\n\t_renderQueue = [],\n\t_lookup = {}, //when a Draggable is created, the target gets a unique _gsDragID property that allows gets associated with the Draggable instance for quick lookups in Draggable.get(). This avoids circular references that could cause gc problems.\n\t_lookupCount = 0,\n\t_clickableTagExp = /^(?:a|input|textarea|button|select)$/i,\n\t_lastDragTime = 0,\n\t_temp1 = {}, // a simple object we reuse and populate (usually x/y properties) to conserve memory and improve performance.\n\t_windowProxy = {}, //memory/performance optimization - we reuse this object during autoScroll to store window-related bounds/offsets.\n\t_copy = (obj, factor) => {\n\t\tlet copy = {}, p;\n\t\tfor (p in obj) {\n\t\t\tcopy[p] = factor ? obj[p] * factor : obj[p];\n\t\t}\n\t\treturn copy;\n\t},\n\t_extend = (obj, defaults) => {\n\t\tfor (let p in defaults) {\n\t\t\tif (!(p in obj)) {\n\t\t\t\tobj[p] = defaults[p];\n\t\t\t}\n\t\t}\n\t\treturn obj;\n\t},\n\t_setTouchActionForAllDescendants = (elements, value) => {\n\t\tlet i = elements.length,\n\t\t\tchildren;\n\t\twhile (i--) {\n\t\t\tvalue ? (elements[i].style.touchAction = value) : elements[i].style.removeProperty(\"touch-action\");\n\t\t\tchildren = elements[i].children;\n\t\t\tchildren && children.length && _setTouchActionForAllDescendants(children, value);\n\t\t}\n\t},\n\t_renderQueueTick = () => _renderQueue.forEach(func => func()),\n\t_addToRenderQueue = func => {\n\t\t_renderQueue.push(func);\n\t\tif (_renderQueue.length === 1) {\n\t\t\tgsap.ticker.add(_renderQueueTick);\n\t\t}\n\t},\n\t_renderQueueTimeout = () => !_renderQueue.length && gsap.ticker.remove(_renderQueueTick),\n\t_removeFromRenderQueue = func => {\n\t\tlet i = _renderQueue.length;\n\t\twhile (i--) {\n\t\t\tif (_renderQueue[i] === func) {\n\t\t\t\t_renderQueue.splice(i, 1);\n\t\t\t}\n\t\t}\n\t\tgsap.to(_renderQueueTimeout, {overwrite:true, delay:15, duration:0, onComplete:_renderQueueTimeout, data:\"_draggable\"}); //remove the \"tick\" listener only after the render queue is empty for 15 seconds (to improve performance). Adding/removing it constantly for every click/touch wouldn't deliver optimal speed, and we also don't want the ticker to keep calling the render method when things are idle for long periods of time (we want to improve battery life on mobile devices).\n\t},\n\t_setDefaults = (obj, defaults) => {\n\t\tfor (let p in defaults) {\n\t\t\tif (!(p in obj)) {\n\t\t\t\tobj[p] = defaults[p];\n\t\t\t}\n\t\t}\n\t\treturn obj;\n\t},\n\t_addListener = (element, type, func, capture) => {\n\t\tif (element.addEventListener) {\n\t\t\tlet touchType = _touchEventLookup[type];\n\t\t\tcapture = capture || (_supportsPassive ? {passive: false} : null);\n\t\t\telement.addEventListener(touchType || type, func, capture);\n\t\t\t(touchType && type !== touchType) && element.addEventListener(type, func, capture);//some browsers actually support both, so must we. But pointer events cover all.\n\t\t}\n\t},\n\t_removeListener = (element, type, func) => {\n\t\tif (element.removeEventListener) {\n\t\t\tlet touchType = _touchEventLookup[type];\n\t\t\telement.removeEventListener(touchType || type, func);\n\t\t\t(touchType && type !== touchType) && element.removeEventListener(type, func);\n\t\t}\n\t},\n\t_preventDefault = event => {\n\t\tevent.preventDefault && event.preventDefault();\n\t\tevent.preventManipulation && event.preventManipulation(); //for some Microsoft browsers\n\t},\n\t_hasTouchID = (list, ID) => {\n\t\tlet i = list.length;\n\t\twhile (i--) {\n\t\t\tif (list[i].identifier === ID) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t},\n\t_onMultiTouchDocumentEnd = event => {\n\t\t_isMultiTouching = (event.touches && _dragCount < event.touches.length);\n\t\t_removeListener(event.target, \"touchend\", _onMultiTouchDocumentEnd);\n\t},\n\n\t_onMultiTouchDocument = event => {\n\t\t_isMultiTouching = (event.touches && _dragCount < event.touches.length);\n\t\t_addListener(event.target, \"touchend\", _onMultiTouchDocumentEnd);\n\t},\n\t_getDocScrollTop = doc => _win.pageYOffset || doc.scrollTop || doc.documentElement.scrollTop || doc.body.scrollTop || 0,\n\t_getDocScrollLeft = doc => _win.pageXOffset || doc.scrollLeft || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0,\n\t_addScrollListener = (e, callback) => {\n\t\t_addListener(e, \"scroll\", callback);\n\t\tif (!_isRoot(e.parentNode)) {\n\t\t\t_addScrollListener(e.parentNode, callback);\n\t\t}\n\t},\n\t_removeScrollListener = (e, callback) => {\n\t\t_removeListener(e, \"scroll\", callback);\n\t\tif (!_isRoot(e.parentNode)) {\n\t\t\t_removeScrollListener(e.parentNode, callback);\n\t\t}\n\t},\n\t_isRoot = e => !!(!e || e === _docElement || e.nodeType === 9 || e === _doc.body || e === _win || !e.nodeType || !e.parentNode),\n\t_getMaxScroll = (element, axis) => {\n\t\tlet dim = (axis === \"x\") ? \"Width\" : \"Height\",\n\t\t\tscroll = \"scroll\" + dim,\n\t\t\tclient = \"client\" + dim;\n\t\treturn Math.max(0, _isRoot(element) ? Math.max(_docElement[scroll], _body[scroll]) - (_win[\"inner\" + dim] || _docElement[client] || _body[client]) : element[scroll] - element[client]);\n\t},\n\t_recordMaxScrolls = (e, skipCurrent) => { //records _gsMaxScrollX and _gsMaxScrollY properties for the element and all ancestors up the chain so that we can cap it, otherwise dragging beyond the edges with autoScroll on can endlessly scroll.\n\t\tlet x = _getMaxScroll(e, \"x\"),\n\t\t\ty = _getMaxScroll(e, \"y\");\n\t\tif (_isRoot(e)) {\n\t\t\te = _windowProxy;\n\t\t} else {\n\t\t\t_recordMaxScrolls(e.parentNode, skipCurrent);\n\t\t}\n\t\te._gsMaxScrollX = x;\n\t\te._gsMaxScrollY = y;\n\t\tif (!skipCurrent) {\n\t\t\te._gsScrollX = e.scrollLeft || 0;\n\t\t\te._gsScrollY = e.scrollTop || 0;\n\t\t}\n\t},\n\t_setStyle = (element, property, value) => {\n\t\tlet style = element.style;\n\t\tif (!style) {\n\t\t\treturn;\n\t\t}\n\t\tif (_isUndefined(style[property])) {\n\t\t\tproperty = _checkPrefix(property, element) || property;\n\t\t}\n\t\tif (value == null) {\n\t\t\tstyle.removeProperty && style.removeProperty(property.replace(/([A-Z])/g, \"-$1\").toLowerCase());\n\t\t} else {\n\t\t\tstyle[property] = value;\n\t\t}\n\t},\n\t_getComputedStyle = element => _win.getComputedStyle((element instanceof Element) ? element : element.host || (element.parentNode || {}).host || element), //the \"host\" stuff helps to accommodate ShadowDom objects.\n\n\t_tempRect = {}, //reuse to reduce garbage collection tasks\n\t_parseRect = e => { //accepts a DOM element, a mouse event, or a rectangle object and returns the corresponding rectangle with left, right, width, height, top, and bottom properties\n\t\tif (e === _win) {\n\t\t\t_tempRect.left = _tempRect.top = 0;\n\t\t\t_tempRect.width = _tempRect.right = _docElement.clientWidth || e.innerWidth || _body.clientWidth || 0;\n\t\t\t_tempRect.height = _tempRect.bottom = ((e.innerHeight || 0) - 20 < _docElement.clientHeight) ? _docElement.clientHeight : e.innerHeight || _body.clientHeight || 0;\n\t\t\treturn _tempRect;\n\t\t}\n\t\tlet doc = e.ownerDocument || _doc,\n\t\t\tr = !_isUndefined(e.pageX) ? {left: e.pageX - _getDocScrollLeft(doc), top: e.pageY - _getDocScrollTop(doc), right: e.pageX - _getDocScrollLeft(doc) + 1, bottom: e.pageY - _getDocScrollTop(doc) + 1} : (!e.nodeType && !_isUndefined(e.left) && !_isUndefined(e.top)) ? e : _toArray(e)[0].getBoundingClientRect();\n\t\tif (_isUndefined(r.right) && !_isUndefined(r.width)) {\n\t\t\tr.right = r.left + r.width;\n\t\t\tr.bottom = r.top + r.height;\n\t\t} else if (_isUndefined(r.width)) { //some browsers don't include width and height properties. We can't just set them directly on r because some browsers throw errors, so create a new generic object.\n\t\t\tr = {width: r.right - r.left, height: r.bottom - r.top, right: r.right, left: r.left, bottom: r.bottom, top: r.top};\n\t\t}\n\t\treturn r;\n\t},\n\n\t_dispatchEvent = (target, type, callbackName) => {\n\t\tlet vars = target.vars,\n\t\t\tcallback = vars[callbackName],\n\t\t\tlisteners = target._listeners[type],\n\t\t\tresult;\n\t\tif (_isFunction(callback)) {\n\t\t\tresult = callback.apply(vars.callbackScope || target, vars[callbackName + \"Params\"] || [target.pointerEvent]);\n\t\t}\n\t\tif (listeners && target.dispatchEvent(type) === false) {\n\t\t\tresult = false;\n\t\t}\n\t\treturn result;\n\t},\n\t_getBounds = (target, context) => { //accepts any of the following: a DOM element, jQuery object, selector text, or an object defining bounds as {top, left, width, height} or {minX, maxX, minY, maxY}. Returns an object with left, top, width, and height properties.\n\t\tlet e = _toArray(target)[0],\n\t\t\ttop, left, offset;\n\t\tif (!e.nodeType && e !== _win) {\n\t\t\tif (!_isUndefined(target.left)) {\n\t\t\t\toffset = {x:0, y:0}; //_getOffsetTransformOrigin(context); //the bounds should be relative to the origin\n\t\t\t\treturn {left: target.left - offset.x, top: target.top - offset.y, width: target.width, height: target.height};\n\t\t\t}\n\t\t\tleft = target.min || target.minX || target.minRotation || 0;\n\t\t\ttop = target.min || target.minY || 0;\n\t\t\treturn {left:left, top:top, width:(target.max || target.maxX || target.maxRotation || 0) - left, height:(target.max || target.maxY || 0) - top};\n\t\t}\n\t\treturn _getElementBounds(e, context);\n\t},\n\t_point1 = {}, //we reuse to minimize garbage collection tasks.\n\t_getElementBounds = (element, context) => {\n\t\tcontext = _toArray(context)[0];\n\t\tlet isSVG = (element.getBBox && element.ownerSVGElement),\n\t\t\tdoc = element.ownerDocument || _doc,\n\t\t\tleft, right, top, bottom, matrix, p1, p2, p3, p4, bbox, width, height, cs;\n\t\tif (element === _win) {\n\t\t\ttop = _getDocScrollTop(doc);\n\t\t\tleft = _getDocScrollLeft(doc);\n\t\t\tright = left + (doc.documentElement.clientWidth || element.innerWidth || doc.body.clientWidth || 0);\n\t\t\tbottom = top + (((element.innerHeight || 0) - 20 < doc.documentElement.clientHeight) ? doc.documentElement.clientHeight : element.innerHeight || doc.body.clientHeight || 0); //some browsers (like Firefox) ignore absolutely positioned elements, and collapse the height of the documentElement, so it could be 8px, for example, if you have just an absolutely positioned div. In that case, we use the innerHeight to resolve this.\n\t\t} else if (context === _win || _isUndefined(context)) {\n\t\t\treturn element.getBoundingClientRect();\n\t\t} else {\n\t\t\tleft = top = 0;\n\t\t\tif (isSVG) {\n\t\t\t\tbbox = element.getBBox();\n\t\t\t\twidth = bbox.width;\n\t\t\t\theight = bbox.height;\n\t\t\t} else {\n\t\t\t\tif (element.viewBox && (bbox = element.viewBox.baseVal)) {\n\t\t\t\t\tleft = bbox.x || 0;\n\t\t\t\t\ttop = bbox.y || 0;\n\t\t\t\t\twidth = bbox.width;\n\t\t\t\t\theight = bbox.height;\n\t\t\t\t}\n\t\t\t\tif (!width) {\n\t\t\t\t\tcs = _getComputedStyle(element);\n\t\t\t\t\tbbox = cs.boxSizing === \"border-box\";\n\t\t\t\t\twidth = (parseFloat(cs.width) || element.clientWidth || 0) + (bbox ? 0 : parseFloat(cs.borderLeftWidth) + parseFloat(cs.borderRightWidth));\n\t\t\t\t\theight = (parseFloat(cs.height) || element.clientHeight || 0) + (bbox ? 0 : parseFloat(cs.borderTopWidth) + parseFloat(cs.borderBottomWidth));\n\t\t\t\t}\n\t\t\t}\n\t\t\tright = width;\n\t\t\tbottom = height;\n\t\t}\n\t\tif (element === context) {\n\t\t\treturn {left:left, top:top, width: right - left, height: bottom - top};\n\t\t}\n\t\tmatrix = getGlobalMatrix(context, true).multiply(getGlobalMatrix(element));\n\t\tp1 = matrix.apply({x:left, y:top});\n\t\tp2 = matrix.apply({x:right, y:top});\n\t\tp3 = matrix.apply({x:right, y:bottom});\n\t\tp4 = matrix.apply({x:left, y:bottom});\n\t\tleft = Math.min(p1.x, p2.x, p3.x, p4.x);\n\t\ttop = Math.min(p1.y, p2.y, p3.y, p4.y);\n\t\treturn {left: left, top: top, width: Math.max(p1.x, p2.x, p3.x, p4.x) - left, height: Math.max(p1.y, p2.y, p3.y, p4.y) - top};\n\t},\n\t_parseInertia = (draggable, snap, max, min, factor, forceZeroVelocity) => {\n\t\tlet vars = {},\n\t\t\ta, i, l;\n\t\tif (snap) {\n\t\t\tif (factor !== 1 && snap instanceof Array) { //some data must be altered to make sense, like if the user passes in an array of rotational values in degrees, we must convert it to radians. Or for scrollLeft and scrollTop, we invert the values.\n\t\t\t\tvars.end = a = [];\n\t\t\t\tl = snap.length;\n\t\t\t\tif (_isObject(snap[0])) { //if the array is populated with objects, like points ({x:100, y:200}), make copies before multiplying by the factor, otherwise we'll mess up the originals and the user may reuse it elsewhere.\n\t\t\t\t\tfor (i = 0; i < l; i++) {\n\t\t\t\t\t\ta[i] = _copy(snap[i], factor);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfor (i = 0; i < l; i++) {\n\t\t\t\t\t\ta[i] = snap[i] * factor;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tmax += 1.1; //allow 1.1 pixels of wiggle room when snapping in order to work around some browser inconsistencies in the way bounds are reported which can make them roughly a pixel off. For example, if \"snap:[-$('#menu').width(), 0]\" was defined and #menu had a wrapper that was used as the bounds, some browsers would be one pixel off, making the minimum -752 for example when snap was [-753,0], thus instead of snapping to -753, it would snap to 0 since -753 was below the minimum.\n\t\t\t\tmin -= 1.1;\n\t\t\t} else if (_isFunction(snap)) {\n\t\t\t\tvars.end = value => {\n\t\t\t\t\tlet result = snap.call(draggable, value),\n\t\t\t\t\t\tcopy, p;\n\t\t\t\t\tif (factor !== 1) {\n\t\t\t\t\t\tif (_isObject(result)) {\n\t\t\t\t\t\t\tcopy = {};\n\t\t\t\t\t\t\tfor (p in result) {\n\t\t\t\t\t\t\t\tcopy[p] = result[p] * factor;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tresult = copy;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresult *= factor;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn result; //we need to ensure that we can scope the function call to the Draggable instance itself so that users can access important values like maxX, minX, maxY, minY, x, and y from within that function.\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\tvars.end = snap;\n\t\t\t}\n\t\t}\n\t\tif (max || max === 0) {\n\t\t\tvars.max = max;\n\t\t}\n\t\tif (min || min === 0) {\n\t\t\tvars.min = min;\n\t\t}\n\t\tif (forceZeroVelocity) {\n\t\t\tvars.velocity = 0;\n\t\t}\n\t\treturn vars;\n\t},\n\t_isClickable = element => { //sometimes it's convenient to mark an element as clickable by adding a data-clickable=\"true\" attribute (in which case we won't preventDefault() the mouse/touch event). This method checks if the element is an ,
0.00 / 0.00
';\n\t\tif (element) {\n\t\t\troot.style.position = \"absolute\";\n\t\t\troot.style.top = minimal ? \"calc(100% - 42px)\" : \"calc(100% - 51px)\";\n\t\t}\n\t\tif (css) {\n\t\t\tif (_isString(css)) {\n\t\t\t\troot.style.cssText = css;\n\t\t\t} else if (_isObject(css)) {\n\t\t\t\tcss.data = \"root\";\n\t\t\t\tgsap.set(root, css).kill();\n\t\t\t}\n\t\t\tif (root.style.top) {\n\t\t\t\troot.style.bottom = \"auto\";\n\t\t\t}\n\t\t\tif (root.style.width) {\n\t\t\t\tgsap.set(root, {xPercent: -50, left: \"50%\", right: \"auto\", data:\"root\"}).kill();\n\t\t\t}\n\t\t}\n\t\tif (!minimal && root.offsetWidth < 600) {\n\t\t\troot.setAttribute(\"class\", \"gs-dev-tools minimal\");\n\t\t\tif (element) {\n\t\t\t\troot.style.top = \"calc(100% - 42px)\";\n\t\t\t}\n\t\t}\n\t\treturn root;\n\t},\n\t_clickedOnce = true, //perhaps we shouldn't preventDefault() on the first mousedown/touchstart/pointerdown so that iframes get focus properly. Did that previously, but now it seems to prevent interaction on the first click (annoying).\n\t_addListener = (e, type, callback, capture) => {\n\t\tlet handler, altType;\n\t\tif (type === \"mousedown\" || type === \"mouseup\") {\n\t\t\te.style.cursor = \"pointer\";\n\t\t}\n\t\tif (type === \"mousedown\") {\n\t\t\t//some browsers call BOTH mousedown AND touchstart, for example, on a single interaction so we need to skip one of them if both are called within 100ms.\n\t\t\taltType = !_isUndefined(e.onpointerdown) ? \"pointerdown\" : !_isUndefined(e.ontouchstart) ? \"touchstart\" : null;\n\t\t\tif (altType) {\n\t\t\t\thandler = event => {\n\t\t\t\t\tif (event.target.nodeName.toLowerCase() !== \"select\" && event.type === altType) { //don't preventDefault() on a up or down by a certain amount.\n\t_shiftSelectedValue = (element, amount, label) => {\n\t\tlet options = element.options,\n\t\t\ti = Math.min(options.length - 1, Math.max(0, element.selectedIndex + amount));\n\t\telement.selectedIndex = i;\n\t\tif (label) {\n\t\t\tlabel.innerHTML = options[i].innerHTML;\n\t\t}\n\t\treturn options[i].value;\n\t},\n\t//moves everything from _globalTimeline into _recordedRoot and updates the _rootTween if it is currently controlling the Global timeline (_recordedRoot). _recordedTemp is just a temporary recording area for anything that happens while _recordedRoot is paused. Returns true if the _recordedRoot's duration changed due to the merge.\n\t_merge = () => {\n\t\tlet t = _globalTimeline._first,\n\t\t\tduration, next, target;\n\t\tif (_rootInstance) {\n\t\t\tduration = _recordedRoot._dur;\n\t\t\twhile (t) {\n\t\t\t\tnext = t._next;\n\t\t\t\ttarget = t._targets && t._targets[0];\n\t\t\t\tif (!(_isFunction(target) && target === t.vars.onComplete && !t._dur) && !(target && target._gsIgnore)) { //typically, delayedCalls aren't included in the _recordedTemp, but since the hijacked add() below fires BEFORE TweenLite's constructor sets the target, we couldn't check that target === vars.onComplete there. And Draggable creates a tween with just an onComplete (no onReverseComplete), thus it fails that test. Therefore, we test again here to avoid merging that in.\n\t\t\t\t\t_recordedRoot.add(t, t._start - t._delay);\n\t\t\t\t}\n\t\t\t\tt = next;\n\t\t\t}\n\t\t\treturn (duration !== _recordedRoot.duration());\n\t\t}\n\t},\n\t_updateRootDuration = () => {\n\t\tif (_rootInstance) {\n\t\t\t_rootInstance.update();\n\t\t\t_rootIsDirty = false;\n\t\t}\n\t\tgsap.ticker.remove(_updateRootDuration);\n\t},\n\n\t_buildPlayPauseMorph = svg => {\n\t\tlet tl = gsap.timeline({data:\"root\", parent:_independentRoot, onComplete:() => tl.kill() }, _independentRoot._time);\n\t\ttl.to(svg.querySelector(\".play-1\"), {duration:0.4, attr:{d:\"M5.75,3.13 C5.75,9.79 5.75,16.46 5.75,23.13 4.08,23.13 2.41,23.13 0.75,23.13 0.75,16.46 0.75,9.79 0.75,3.12 2.41,3.12 4.08,3.12 5.75,3.12\"}, ease:\"power2.inOut\", rotation:360, transformOrigin:\"50% 50%\"})\n\t\t .to(svg.querySelector(\".play-2\"), {duration:0.4, attr:{d:\"M16.38,3.13 C16.38,9.79 16.38,16.46 16.38,23.13 14.71,23.13 13.04,23.13 11.38,23.13 11.38,16.46 11.38,9.79 11.38,3.12 13.04,3.12 14.71,3.12 16.38,3.12\"}, ease:\"power2.inOut\", rotation:360, transformOrigin:\"50% 50%\"}, 0.05);\n\t\treturn tl;\n\t},\n\n\t_buildLoopAnimation = svg => {\n\t\tlet tl = gsap.timeline({data:\"root\", id:\"loop\", parent:_independentRoot, paused:true, onComplete:() => tl.kill() }, _independentRoot._time);\n\t\ttl.to(svg, {duration: 0.5, rotation:360, ease:\"power3.inOut\", transformOrigin:\"50% 50%\"})\n\t\t .to(svg.querySelectorAll(\".loop-path\"), {duration:0.5, fill:\"#91e600\", ease:\"none\"}, 0);\n\t\treturn tl;\n\t},\n\n\t_getAnimationById = id => gsap.getById(id) || _independentRoot.getById(id) || (id === _recordedRoot.vars.id && _recordedRoot),\n\n\n\n\t_initCore = core => {\n\t\tgsap = core || _getGSAP();\n\t\tif (!_coreInitted) {\n\t\t\tif (gsap && _windowExists()) {\n\t\t\t\t_doc = document;\n\t\t\t\t_docEl = _doc.documentElement;\n\t\t\t\t_win = window;\n\t\t\t\tgsap.registerPlugin(Draggable);\n\t\t\t\t_globalTimeline = gsap.globalTimeline;\n\t\t\t\t_globalTimeline._sort = true;\n\t\t\t\t_globalTimeline.autoRemoveChildren = false;\n\t\t\t\tAnimation = gsap.core.Animation;\n\t\t\t\t_independentRoot = gsap.timeline({data:\"indy\", autoRemoveChildren:true, smoothChildTiming:true});\n\t\t\t\t_independentRoot.kill();\n\t\t\t\t_independentRoot._dp = 0; //don't let it revert to the global timeline as its parent.\n\t\t\t\t_independentRoot.to({}, {duration:1e12});\n\t\t\t\t_recordedRoot = gsap.timeline({data:\"root\", id:\"Global Timeline\", autoRemoveChildren:false, smoothChildTiming:true, parent:_independentRoot}, 0);\n\t\t\t\t_rootTween = gsap.to(_recordedRoot, {duration:1, time:1, ease:\"none\", data:\"root\", id:\"_rootTween\", paused:true, immediateRender:false, parent:_independentRoot}, 0);\n\t\t\t\t// so that auto-overwriting works. Initially we transferred the tweens to the _recordedRoot.\n\t\t\t\t_globalTimeline.killTweensOf = function(targets, props, onlyActive) {\n\t\t\t\t\t_recordedRoot.killTweensOf(targets, props, onlyActive);\n\t\t\t\t\t_recordedRoot.killTweensOf.call(_globalTimeline, targets, props, onlyActive);\n\t\t\t\t}\n\t\t\t\t_independentRoot._start = gsap.ticker.time;\n\t\t\t\tgsap.ticker.add(time => _independentRoot.render(time - _independentRoot._start));\n\t\t\t\t// before 3.7.0, the listener below was necessary (in place of the line above)\n\t\t\t\t// gsap.ticker.add(time => {\n\t\t\t\t// \t_independentRoot._initted || _independentRoot.render(0.001, true); // to prevent callbacks from being fired on the first tick, like onComplete would fire immediately and then again at the correct time.\n\t\t\t\t// \t_independentRoot.render(time - _independentRoot._start);\n\t\t\t\t// });\n\n\t\t\t\t//align the all of the playheads so they're starting at 0 now.\n\t\t\t\t_globalTimeline._start += _globalTimeline._time;\n\t\t\t\t_recordedRoot._start = _globalTimeline._time = _globalTimeline._tTime = 0;\n\t\t\t\t_delayedCall = (delay, callback, params, scope) => gsap.to(callback, {delay:delay, duration:0, onComplete:callback, onReverseComplete:callback, onCompleteParams:params, onReverseCompleteParams:params, callbackScope:scope, parent:_independentRoot}, _independentRoot._time);\n\n\t\t\t\t//in case GSDevTools.create() is called before anything is actually on the global timeline, we've gotta update it or else the duration will be 0 and it'll be stuck.\n\t\t\t\t_delayedCall(0.01, () => _rootInstance ? _rootInstance.update() : _merge());\n\n\t\t\t\t//initially we record everything into the _recordedRoot Timeline because developers might call GSDevTools.create() AFTER some of their code executes, but after 2 seconds if there aren't any GSDevTool instances that have globalSync enabled, we should dump all the stuff from _recordedRoot into the global timeline to improve performance and avoid issues where _recordedRoot is paused and reaches its end and wants to stop the playhead.\n\t\t\t\t_delayedCall(2, () => {\n\t\t\t\t\tlet t, next, offset;\n\t\t\t\t\tif (!_rootInstance) {\n\t\t\t\t\t\t_merge();\n\t\t\t\t\t\tt = _recordedRoot._first;\n\t\t\t\t\t\toffset = _recordedRoot._start;\n\t\t\t\t\t\twhile (t) {\n\t\t\t\t\t\t\tnext = t._next;\n\t\t\t\t\t\t\t//any animations that aren't finished should be dumped into the root timeline. If they're done, just kill them.\n\t\t\t\t\t\t\tif (t._tDur !== t._tTime || (!t._dur && t.progress() !== 1)) {\n\t\t\t\t\t\t\t\t_globalTimeline.add(t, t._start - t._delay + offset);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tt.kill();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tt = next;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (GSDevTools.globalRecordingTime > 2) {\n\t\t\t\t\t\t_delayedCall(GSDevTools.globalRecordingTime - 2, () => {\n\t\t\t\t\t\t\t_rootInstance && _rootInstance.update();\n\t\t\t\t\t\t\t_recording = false;\n\t\t\t\t\t\t\t_globalTimeline.autoRemoveChildren = true;\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\t_recording = false;\n\t\t\t\t\t\t_globalTimeline.autoRemoveChildren = true;\n\t\t\t\t\t}\n\t\t\t\t\t_startupPhase = false;\n\t\t\t\t});\n\t\t\t\t_coreInitted = 1;\n\t\t\t}\n\t\t}\n\t},\n\t_checkIndependence = (animation, vars) => {\n\t\tif (!vars.globalSync && animation.parent !== _globalTimeline) { //in case it's nested in a timeline (playing it won't help if the parent timeline isn't playing).\n\t\t\t_globalTimeline.add(animation, _globalTimeline.time());\n\t\t}\n\t},\n\n\n\n\n\n\n\n\tGSDevTools = function(vars) {\n\t\tif (!_coreInitted) {\n\t\t\t_initCore();\n\t\t\tgsap || console.warn(\"Please gsap.registerPlugin(GSDevTools)\");\n\t\t}\n\n\t\tthis.vars = vars = vars || {};\n\t\tif (vars.animation) {\n\t\t\t(GSDevTools.getByAnimation(vars.animation) || {kill:() => 0}).kill();\n\t\t}\n\t\tvars.id = vars.id || (_isString(vars.animation) ? vars.animation : _idSeed++); //try to find a unique ID so that sessionStorage can be mapped to it (otherwise, for example, all the embedded codepens on a page would share the same settings). So if no id is defined, see if there's a string-based \"animation\" defined. Last of all, we default to a numeric counter that we increment.\n\t\t_lookup[vars.id + \"\"] = this;\n\n\t\t(\"globalSync\" in vars) || (vars.globalSync = !vars.animation); //if the user calls create() and passes in an animation AFTER the initial recording time has elapsed, there's a good chance the animation won't be in the recordedRoot, so we change the default globalSync to false because that's the most intuitive behavior.\n\n\t\t//GENERAL/UTILITY\n\t\tlet _self = this,\n\t\t\troot = _createRootElement(vars.container, vars.minimal, vars.css),\n\t\t\tfind = s => root.querySelector(s),\n\t\t\trecord = (key, value) => {\n\t\t\t\tif (vars.persist !== false && _supportsStorage) {\n\t\t\t\t\tsessionStorage.setItem(\"gs-dev-\" + key + vars.id, value);\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t},\n\t\t\trecall = key => {\n\t\t\t\tlet value;\n\t\t\t\tif (vars.persist !== false && _supportsStorage) {\n\t\t\t\t\tvalue = sessionStorage.getItem(\"gs-dev-\" + key + vars.id);\n\t\t\t\t\treturn (key === \"animation\") ? value : (key === \"loop\") ? (value === \"true\") : parseFloat(value); // handle data typing too.\n\t\t\t\t}\n\t\t\t},\n\n\n\t\t\t//SCRUBBER/PROGRESS\n\t\t\tplayhead = find(\".playhead\"),\n\t\t\ttimelineTrack = find(\".timeline-track\"),\n\t\t\tprogressBar = find(\".progress-bar\"),\n\t\t\ttimeLabel = find(\".time\"),\n\t\t\tdurationLabel = find(\".duration\"),\n\t\t\tpixelToTimeRatio, timeAtDragStart, dragged, skipDragUpdates,\n\t\t\tprogress = 0,\n\t\t\tinPoint = find(\".in-point\"),\n\t\t\toutPoint = find(\".out-point\"),\n\t\t\tinProgress = 0,\n\t\t\toutProgress = 100,\n\t\t\tpausedWhenDragStarted,\n\t\t\tlist = find(\".animation-list\"),\n\t\t\tanimationLabel = find(\".animation-label\"),\n\t\t\tselectedAnimation, //the currently selected animation\n\t\t\tlinkedAnimation, //the animation that's linked to all the controls and scrubber. This is always _rootTween if globalSync is true, so it can be different than the selectedAnimation!\n\t\t\tdeclaredAnimation, //whatever the user defines in the config object initially (often this will be null). If the user defines a string, it'll be resolved to a real Animation instance for this variable.\n\t\t\tstartTime, endTime,\n\t\t\t_fullyInitialized, //we call initialize() initially, and then again on the very next tick just in case someone called GSDevTools.create() BEFORE they create their animations. This variable tracks that state. Note: we don't record sessionStorage.setItem() until we're fully initialized, otherwise we may inadvertently set in/out points to the defaults just because the animation couldn't be found (yet).\n\t\t\tkeyboardHandler,\n\t\t\tplayPauseButton = find(\".play-pause\"),\n\t\t\tplayPauseMorph = _buildPlayPauseMorph(playPauseButton),\n\t\t\tpaused = false,\n\t\t\tloopButton = find(\".loop\"),\n\t\t\tloopAnimation = _buildLoopAnimation(loopButton),\n\t\t\tloopEnabled,\n\t\t\ttimeScale = find(\".time-scale select\"),\n\t\t\ttimeScaleLabel = find(\".time-scale-label\"),\n\t\t\t//spits back a common onPress function for anything that's dragged along the timeline (playhead, inPoint, outPoint). The originRatio is a value from 0-1 indicating how far along the x-axis the origin is located (0.5 is in the center, 0 is left, 1 is on right side). limitElement is optional, and sets the bounds such that the element can't be dragged past the limitElement.\n\t\t\tonPressTimeline = (element, originRatio, limitToInOut) => {\n\t\t\t\treturn function(e) {\n\t\t\t\t\tlet trackBounds = timelineTrack.getBoundingClientRect(),\n\t\t\t\t\t\telementBounds = element.getBoundingClientRect(),\n\t\t\t\t\t\tleft = elementBounds.width * originRatio,\n\t\t\t\t\t\tx = gsap.getProperty(element, \"x\"),\n\t\t\t\t\t\tminX = trackBounds.left - elementBounds.left - left + x,\n\t\t\t\t\t\tmaxX = trackBounds.right - elementBounds.right + (elementBounds.width - left) + x,\n\t\t\t\t\t\tunlimitedMinX = minX,\n\t\t\t\t\t\tlimitBounds;\n\t\t\t\t\tif (limitToInOut) {\n\t\t\t\t\t\tif (element !== inPoint) {\n\t\t\t\t\t\t\tlimitBounds = inPoint.getBoundingClientRect();\n\t\t\t\t\t\t\tif (limitBounds.left) { //if inPoint is hidden (like display:none), ignore.\n\t\t\t\t\t\t\t\tminX += (limitBounds.left + limitBounds.width) - trackBounds.left;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (element !== outPoint) {\n\t\t\t\t\t\t\tlimitBounds = outPoint.getBoundingClientRect();\n\t\t\t\t\t\t\tif (limitBounds.left) { //if outPoint is hidden (like display:none), ignore.\n\t\t\t\t\t\t\t\tmaxX -= (trackBounds.left + trackBounds.width) - limitBounds.left;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpausedWhenDragStarted = paused;\n\t\t\t\t\tthis.applyBounds({minX:minX, maxX:maxX});\n\t\t\t\t\tpixelToTimeRatio = linkedAnimation.duration() / trackBounds.width;\n\t\t\t\t\ttimeAtDragStart = -unlimitedMinX * pixelToTimeRatio;\n\t\t\t\t\tif (!skipDragUpdates) {\n\t\t\t\t\t\tlinkedAnimation.pause(timeAtDragStart + pixelToTimeRatio * this.x);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlinkedAnimation.pause();\n\t\t\t\t\t}\n\t\t\t\t\tif (this.target === playhead) {\n\t\t\t\t\t\tif (this.activated) {\n\t\t\t\t\t\t\tthis.allowEventDefault = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.activated = true;\n\t\t\t\t\t}\n\t\t\t\t\tdragged = true;\n\t\t\t\t};\n\t\t\t},\n\t\t\tprogressDrag = Draggable.create(playhead, {\n\t\t\t\ttype:\"x\",\n\t\t\t\tcursor: \"ew-resize\",\n\t\t\t\tallowNativeTouchScrolling: false,\n\t\t\t\tallowEventDefault: true, //otherwise, when dragged outside an iframe, the mouseup doesn't bubble up so it could seem \"stuck\" to the mouse.\n\t\t\t\tonPress: onPressTimeline(playhead, 0.5, true),\n\t\t\t\tonDrag: function() {\n\t\t\t\t\tlet time = timeAtDragStart + pixelToTimeRatio * this.x;\n\t\t\t\t\tif (time < 0) {\n\t\t\t\t\t\ttime = 0;\n\t\t\t\t\t} else if (time > linkedAnimation._dur) {\n\t\t\t\t\t\ttime = linkedAnimation._dur;\n\t\t\t\t\t}\n\t\t\t\t\tif (!skipDragUpdates) {\n\t\t\t\t\t\tlinkedAnimation.time(time);\n\t\t\t\t\t}\n\t\t\t\t\tprogressBar.style.width = Math.min(outProgress - inProgress, Math.max(0, (time / linkedAnimation._dur) * 100 - inProgress)) + \"%\";\n\t\t\t\t\ttimeLabel.innerHTML = time.toFixed(2);\n\t\t\t\t},\n\t\t\t\tonRelease: function() {\n\t\t\t\t\tpaused || linkedAnimation.resume();\n\t\t\t\t}\n\t\t\t})[0],\n\t\t\tresetInOut = () => {\n\t\t\t\tinProgress = 0;\n\t\t\t\toutProgress = 100;\n\t\t\t\tinPoint.style.left = \"0%\";\n\t\t\t\toutPoint.style.left = \"100%\";\n\t\t\t\trecord(\"in\", inProgress);\n\t\t\t\trecord(\"out\", outProgress);\n\t\t\t\tupdateProgress(true);\n\t\t\t},\n\t\t\tinDrag = Draggable.create(inPoint, {\n\t\t\t\ttype: \"x\",\n\t\t\t\tcursor: \"ew-resize\",\n\t\t\t\tzIndexBoost: false,\n\t\t\t\tallowNativeTouchScrolling: false,\n\t\t\t\tallowEventDefault: true, //otherwise, when dragged outside an iframe, the mouseup doesn't bubble up so it could seem \"stuck\" to the mouse.\n\t\t\t\tonPress: onPressTimeline(inPoint, 1, true),\n\t\t\t\tonDoubleClick: resetInOut,\n\t\t\t\tonDrag: function() {\n\t\t\t\t\tinProgress = (timeAtDragStart + pixelToTimeRatio * this.x) / linkedAnimation.duration() * 100;\n\t\t\t\t\tlinkedAnimation.progress(inProgress / 100);\n\t\t\t\t\tupdateProgress(true);\n\t\t\t\t},\n\t\t\t\tonRelease: function() {\n\t\t\t\t\tif (inProgress < 0) {\n\t\t\t\t\t\tinProgress = 0;\n\t\t\t\t\t}\n\t\t\t\t\t_clearSelection();\n\t\t\t\t\t//for responsiveness, convert the px-based transform into %-based left position.\n\t\t\t\t\tinPoint.style.left = inProgress + \"%\";\n\t\t\t\t\trecord(\"in\", inProgress);\n\t\t\t\t\tgsap.set(inPoint, {x:0, data:\"root\", display:\"block\"}); //set display:block so that it remains visible even when the minimal skin is enabled.\n\t\t\t\t\tif (!paused) {\n\t\t\t\t\t\tlinkedAnimation.resume();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})[0],\n\t\t\toutDrag = Draggable.create(outPoint, {\n\t\t\t\ttype: \"x\",\n\t\t\t\tcursor: \"ew-resize\",\n\t\t\t\tallowNativeTouchScrolling: false,\n\t\t\t\tallowEventDefault: true, //otherwise, when dragged outside an iframe, the mouseup doesn't bubble up so it could seem \"stuck\" to the mouse.\n\t\t\t\tzIndexBoost: false,\n\t\t\t\tonPress: onPressTimeline(outPoint, 0, true),\n\t\t\t\tonDoubleClick: resetInOut,\n\t\t\t\tonDrag: function() {\n\t\t\t\t\toutProgress = (timeAtDragStart + pixelToTimeRatio * this.x) / linkedAnimation.duration() * 100;\n\t\t\t\t\tlinkedAnimation.progress(outProgress / 100);\n\t\t\t\t\tupdateProgress(true);\n\t\t\t\t},\n\t\t\t\tonRelease: function() {\n\t\t\t\t\tif (outProgress > 100) {\n\t\t\t\t\t\toutProgress = 100;\n\t\t\t\t\t}\n\t\t\t\t\t_clearSelection();\n\t\t\t\t\t//for responsiveness, convert the px-based transform into %-based left position.\n\t\t\t\t\toutPoint.style.left = outProgress + \"%\";\n\t\t\t\t\trecord(\"out\", outProgress);\n\t\t\t\t\tgsap.set(outPoint, {x:0, data:\"root\", display:\"block\"}); //set display:block so that it remains visible even when the minimal skin is enabled.\n\t\t\t\t\tif (!pausedWhenDragStarted) {\n\t\t\t\t\t\tplay();\n\t\t\t\t\t\tlinkedAnimation.resume();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})[0],\n\t\t\tupdateProgress = function(force) { // NOTE: \"force\" is actually the \"time\" when this method gets called by the gsap.ticker!\n\t\t\t\tif (progressDrag.isPressed && force !== true) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlet p = (!loopEnabled && selectedAnimation._repeat === -1) ? selectedAnimation.totalTime() / selectedAnimation.duration() * 100 : (linkedAnimation.progress() * 100) || 0,\n\t\t\t\t\trepeatDelayPhase = (selectedAnimation._repeat && selectedAnimation._rDelay && selectedAnimation.totalTime() % (selectedAnimation.duration() + selectedAnimation._rDelay) > selectedAnimation.duration()),\n\t\t\t\t\ttarget;\n\t\t\t\tif (p > 100) {\n\t\t\t\t\tp = 100;\n\t\t\t\t}\n\t\t\t\tif (p >= outProgress) {\n\t\t\t\t\tif (loopEnabled && !linkedAnimation.paused() && !progressDrag.isDragging) {\n\t\t\t\t\t\tif (!repeatDelayPhase) {\n\t\t\t\t\t\t\tp = inProgress;\n\t\t\t\t\t\t\ttarget = linkedAnimation._targets && linkedAnimation._targets[0];\n\t\t\t\t\t\t\tif (target === selectedAnimation) { //in case there are callbacks on the timeline, when we jump back to the start we should seek() so that the playhead doesn't drag [backward] past those and trigger them.\n\t\t\t\t\t\t\t\ttarget.seek(startTime + ((endTime - startTime) * inProgress / 100));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (selectedAnimation._repeat > 0 && !inProgress && outProgress === 100) {\n\t\t\t\t\t\t\t\tif (selectedAnimation.totalProgress() === 1) {\n\t\t\t\t\t\t\t\t\tlinkedAnimation.totalProgress(0, true).resume();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tlinkedAnimation.progress(p / 100, true).resume();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (p !== outProgress || selectedAnimation._repeat === -1) {\n\t\t\t\t\t\t\tp = outProgress;\n\t\t\t\t\t\t\tlinkedAnimation.progress(p / 100);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!paused && (outProgress < 100 || selectedAnimation.totalProgress() === 1 || selectedAnimation._repeat === -1)) {\n\t\t\t\t\t\t\tpause();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t} else if (p < inProgress) {\n\t\t\t\t\tp = inProgress;\n\t\t\t\t\tlinkedAnimation.progress(p / 100, true);\n\t\t\t\t}\n\t\t\t\tif (p !== progress || force === true) {\n\t\t\t\t\tprogressBar.style.left = inProgress + \"%\";\n\t\t\t\t\tprogressBar.style.width = Math.max(0, p - inProgress) + \"%\";\n\t\t\t\t\tplayhead.style.left = p + \"%\";\n\t\t\t\t\ttimeLabel.innerHTML = linkedAnimation._time.toFixed(2);\n\t\t\t\t\tdurationLabel.innerHTML = linkedAnimation._dur.toFixed(2);\n\t\t\t\t\tif (dragged) {\n\t\t\t\t\t\tplayhead.style.transform = \"translate(-50%,0)\";\n\t\t\t\t\t\tplayhead._gsap.x = \"0px\";\n\t\t\t\t\t\tplayhead._gsap.xPercent = -50;\n\t\t\t\t\t\tdragged = false;\n\t\t\t\t\t}\n\t\t\t\t\tprogress = p;\n\t\t\t\t}\n\t\t\t\tlinkedAnimation.paused() !== paused && togglePlayPause(); // if the user has an addPause() in the middle of the animation.\n\t\t\t},\n\t\t\tonPressSeekBar = function(e) {\n\t\t\t\tif (progressDrag.isPressed) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlet bounds = e.target.getBoundingClientRect(),\n\t\t\t\t\tx = (e.changedTouches ? e.changedTouches[0] : e).clientX,\n\t\t\t\t\tp = ((x - bounds.left) / bounds.width) * 100;\n\t\t\t\tif (p < inProgress) {\n\t\t\t\t\tinProgress = p = Math.max(0, p);\n\t\t\t\t\tinPoint.style.left = inProgress + \"%\";\n\t\t\t\t\tinDrag.startDrag(e);\n\t\t\t\t\treturn;\n\t\t\t\t} else if (p > outProgress) {\n\t\t\t\t\toutProgress = p = Math.min(100, p);\n\t\t\t\t\toutPoint.style.left = outProgress + \"%\";\n\t\t\t\t\toutDrag.startDrag(e);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlinkedAnimation.progress(p / 100).pause();\n\t\t\t\tupdateProgress(true);\n\t\t\t\tprogressDrag.startDrag(e);\n\t\t\t},\n\n\n\n\t\t\t//PLAY/PAUSE button\n\t\t\tplay = () => {\n\t\t\t\tif (linkedAnimation.progress() >= outProgress / 100) {\n\t\t\t\t\t_checkIndependence(linkedAnimation, vars);\n\t\t\t\t\tlet target = linkedAnimation._targets && linkedAnimation._targets[0];\n\t\t\t\t\tif (target === selectedAnimation) { //in case there are callbacks on the timeline, when we jump back to the start we should seek() so that the playhead doesn't drag [backward] past those and trigger them.\n\t\t\t\t\t\ttarget.seek(startTime + ((endTime - startTime) * inProgress / 100));\n\t\t\t\t\t}\n\t\t\t\t\tif (linkedAnimation._repeat && !inProgress) {\n\t\t\t\t\t\tlinkedAnimation.totalProgress(0, true); //for repeating animations, don't get stuck in the last iteration - jump all the way back to the start.\n\t\t\t\t\t} else if (!linkedAnimation.reversed()) {\n\t\t\t\t\t\tlinkedAnimation.progress(inProgress / 100, true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tplayPauseMorph.play();\n\t\t\t\tlinkedAnimation.resume();\n\t\t\t\tif (paused) {\n\t\t\t\t\t_self.update();\n\t\t\t\t}\n\t\t\t\tpaused = false;\n\t\t\t},\n\t\t\tpause = () => {\n\t\t\t\tplayPauseMorph.reverse();\n\t\t\t\tif (linkedAnimation) {\n\t\t\t\t\tlinkedAnimation.pause();\n\t\t\t\t}\n\t\t\t\tpaused = true;\n\t\t\t},\n\t\t\ttogglePlayPause = () => {\n\t\t\t\tif (paused) {\n\t\t\t\t\tplay();\n\t\t\t\t} else {\n\t\t\t\t\tpause();\n\t\t\t\t}\n\t\t\t},\n\n\n\n\t\t\t//REWIND button\n\t\t\tonPressRewind = e => {\n\t\t\t\tif (progressDrag.isPressed) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t//_self.update();\n\t\t\t\t_checkIndependence(linkedAnimation, vars);\n\t\t\t\tlet target = linkedAnimation._targets && linkedAnimation._targets[0];\n\t\t\t\tif (target === selectedAnimation) { //in case there are callbacks on the timeline, when we jump back to the start we should seek() so that the playhead doesn't drag [backward] past those and trigger them.\n\t\t\t\t\ttarget.seek(startTime + ((endTime - startTime) * inProgress / 100));\n\t\t\t\t}\n\t\t\t\tlinkedAnimation.progress(inProgress / 100, true);\n\t\t\t\tif (!paused) {\n\t\t\t\t\tlinkedAnimation.resume();\n\t\t\t\t}\n\t\t\t},\n\n\n\n\t\t\t//LOOP button\n\t\t\tloop = value => {\n\t\t\t\tloopEnabled = value;\n\t\t\t\trecord(\"loop\", loopEnabled);\n\t\t\t\tif (loopEnabled) {\n\t\t\t\t\tloopAnimation.play();\n\t\t\t\t\tif (linkedAnimation.progress() >= outProgress / 100) {\n\t\t\t\t\t\tlet target = linkedAnimation._targets && linkedAnimation._targets[0];\n\t\t\t\t\t\tif (target === selectedAnimation) { //in case there are callbacks on the timeline, when we jump back to the start we should seek() so that the playhead doesn't drag [backward] past those and trigger them.\n\t\t\t\t\t\t\ttarget.seek(startTime + ((endTime - startTime) * inProgress / 100));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (selectedAnimation._repeat && !inProgress && outProgress === 100) {\n\t\t\t\t\t\t\tlinkedAnimation.totalProgress(0, true);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlinkedAnimation.progress(inProgress / 100, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tplay();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tloopAnimation.reverse();\n\t\t\t\t}\n\t\t\t},\n\n\t\t\ttoggleLoop = () => loop(!loopEnabled),\n\n\n\n\t\t\t//ANIMATIONS list\n\t\t\tupdateList = () => {\n\t\t\t\tlet animations = _getChildrenOf((declaredAnimation && !vars.globalSync) ? declaredAnimation : _recordedRoot, true),\n\t\t\t\t\toptions = list.children,\n\t\t\t\t\tmatches = 0,\n\t\t\t\t\toption,\ti;\n\t\t\t\tif (declaredAnimation && !vars.globalSync) {\n\t\t\t\t\tanimations.unshift(declaredAnimation);\n\t\t\t\t} else if (!vars.hideGlobalTimeline) {\n\t\t\t\t\tanimations.unshift(_recordedRoot);\n\t\t\t\t}\n\t\t\t\tfor (i = 0; i < animations.length; i++) {\n\t\t\t\t\toption = options[i] || _createElement(\"option\", list);\n\t\t\t\t\toption.animation = animations[i];\n\t\t\t\t\tmatches = (i && animations[i].vars.id === animations[i-1].vars.id) ? matches + 1 : 0;\n\t\t\t\t\toption.setAttribute(\"value\", (option.innerHTML = animations[i].vars.id + (matches ? \" [\" + matches + \"]\" : (animations[i+1] && animations[i+1].vars.id === animations[i].vars.id) ? \" [0]\" : \"\")));\n\t\t\t\t}\n\t\t\t\tfor (; i < options.length; i++) {\n\t\t\t\t\tlist.removeChild(options[i]);\n\t\t\t\t}\n\t\t\t},\n\t\t\tanimation = function(anim) {\n\t\t\t\tlet ts = parseFloat(timeScale.options[timeScale.selectedIndex].value) || 1,\n\t\t\t\t\ttl, maxDuration;\n\t\t\t\tif (!arguments.length) {\n\t\t\t\t\treturn selectedAnimation;\n\t\t\t\t}\n\t\t\t\tif (_isString(anim)) {\n\t\t\t\t\tanim = _getAnimationById(anim);\n\t\t\t\t}\n\t\t\t\t//console.log(\"animation() \", anim.vars.id);\n\t\t\t\tif (!(anim instanceof Animation)) {\n\t\t\t\t\tconsole.warn(\"GSDevTools error: invalid animation.\");\n\t\t\t\t}\n\t\t\t\tif (anim.scrollTrigger) {\n\t\t\t\t\tconsole.warn(\"GSDevTools can't work with ScrollTrigger-based animations; either the scrollbar -OR- the GSDevTools scrubber can control the animation.\");\n\t\t\t\t}\n\t\t\t\tif (anim === selectedAnimation) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (selectedAnimation) {\n\t\t\t\t\tselectedAnimation._inProgress = inProgress;\n\t\t\t\t\tselectedAnimation._outProgress = outProgress;\n\t\t\t\t}\n\t\t\t\tselectedAnimation = anim;\n\t\t\t\tif (linkedAnimation) {\n\t\t\t\t\tts = linkedAnimation.timeScale();\n\t\t\t\t\tif (linkedAnimation._targets && linkedAnimation._targets[0] === declaredAnimation) {\n\t\t\t\t\t\tdeclaredAnimation.resume();\n\t\t\t\t\t\tlinkedAnimation.kill();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tinProgress = selectedAnimation._inProgress || 0;\n\t\t\t\toutProgress = selectedAnimation._outProgress || 100;\n\t\t\t\tinPoint.style.left = inProgress + \"%\";\n\t\t\t\toutPoint.style.left = outProgress + \"%\";\n\t\t\t\tif (_fullyInitialized) { //don't record inProgress/outProgress unless we're fully instantiated because people may call GSDevTools.create() before creating/defining their animations, thus the inTime/outTime may not exist yet.\n\t\t\t\t\trecord(\"animation\", selectedAnimation.vars.id);\n\t\t\t\t\trecord(\"in\", inProgress);\n\t\t\t\t\trecord(\"out\", outProgress);\n\t\t\t\t}\n\t\t\t\tstartTime = 0;\n\t\t\t\tmaxDuration = vars.maxDuration || Math.min(1000, _getClippedDuration(selectedAnimation));\n\t\t\t\tif (selectedAnimation === _recordedRoot || vars.globalSync) {\n\t\t\t\t\t_merge();\n\t\t\t\t\tlinkedAnimation = _rootTween;\n\t\t\t\t\t_rootInstance && _rootInstance !== _self && console.warn(\"Error: GSDevTools can only have one instance that's globally synchronized.\");\n\t\t\t\t\t_rootInstance = _self;\n\t\t\t\t\tif (selectedAnimation !== _recordedRoot) {\n\t\t\t\t\t\ttl = selectedAnimation;\n\t\t\t\t\t\tendTime = tl.totalDuration();\n\t\t\t\t\t\tif (endTime > 99999999) { //in the case of an infinitely repeating animation, just use a single iteration's duration instead.\n\t\t\t\t\t\t\tendTime = tl.duration();\n\t\t\t\t\t\t}\n\t\t\t\t\t\twhile (tl.parent) {\n\t\t\t\t\t\t\tstartTime = (startTime / tl._ts) + tl._start;\n\t\t\t\t\t\t\tendTime = (endTime / tl._ts) + tl._start;\n\t\t\t\t\t\t\ttl = tl.parent;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tendTime = _recordedRoot.duration();\n\t\t\t\t\t}\n\t\t\t\t\tif (endTime - startTime > maxDuration) { //cap end time at 1000 because it doesn't seem reasonable to accommodate super long stuff.\n\t\t\t\t\t\tendTime = startTime + maxDuration;\n\t\t\t\t\t}\n\t\t\t\t\t_recordedRoot.pause(startTime);\n\t\t\t\t\t_rootTween.vars.time = endTime;\n\t\t\t\t\t_rootTween.invalidate();\n\t\t\t\t\t_rootTween.duration(endTime - startTime).timeScale(ts);\n\t\t\t\t\t//wait for a tick before starting because some browsers freeze things immediately following a .\n\t\t\t\t\te.target.blur();\n\t\t\t\t}\n\t\t\t\tpaused && play();\n\t\t\t},\n\n\n\n\t\t\t//TIMESCALE button\n\t\t\tonChangeTimeScale = e => {\n\t\t\t\tlet ts = parseFloat(timeScale.options[timeScale.selectedIndex].value) || 1,\n\t\t\t\t\ttarget;\n\t\t\t\tlinkedAnimation.timeScale(ts);\n\t\t\t\trecord(\"timeScale\", ts);\n\t\t\t\tif (!paused) {\n\t\t\t\t\tif (linkedAnimation.progress() >= outProgress / 100) {\n\t\t\t\t\t\ttarget = linkedAnimation._targets && linkedAnimation._targets[0];\n\t\t\t\t\t\tif (target === selectedAnimation) { //in case there are callbacks on the timeline, when we jump back to the start we should seek() so that the playhead doesn't drag [backward] past those and trigger them.\n\t\t\t\t\t\t\ttarget.seek(startTime + ((endTime - startTime) * inProgress / 100));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlinkedAnimation.progress(inProgress / 100, true).pause();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlinkedAnimation.pause();\n\t\t\t\t\t}\n\t\t\t\t\t_delayedCall(0.01, () => linkedAnimation.resume());\n\t\t\t\t}\n\t\t\t\ttimeScaleLabel.innerHTML = ts + \"x\";\n\t\t\t\tif (timeScale.blur) { //so that if an option is selected, and then the user tries to hit the up/down arrow, it doesn't just try selecting something else in the