PageSourceSearch

https://www.khruangbin.com/assets/7c4aa20d/javascripts/gsap-business-green/esm/ScrollTrigger.js

js khruangbin.com collected 2026-09-25 19:55:11 UTC 107,577 bytes, 2,606 lines download raw bytes

vendor: 4,325 bytes, lines 1-120
1/*!
2 * ScrollTrigger 3.12.2
3 * https://greensock.com
4 *
5 * @license Copyright 2008-2023, GreenSock. All rights reserved.
6 * Subject to the terms at https://greensock.com/standard-license or for
7 * Club GreenSock members, the agreement issued with that membership.
8 * @author: Jack Doyle, [email protected]
9*/
10
11/* eslint-disable */
12import { Observer, _getTarget, _vertical, _horizontal, _scrollers, _proxies, _getScrollFunc, _getProxyProp, _getVelocityProp } from "./Observer.js";
13
14var gsap,
15    _coreInitted,
16    _win,
17    _doc,
18    _docEl,
19    _body,
20    _root,
21    _resizeDelay,
22    _toArray,
23    _clamp,
24    _time2,
25    _syncInterval,
26    _refreshing,
27    _pointerIsDown,
28    _transformProp,
29    _i,
30    _prevWidth,
31    _prevHeight,
32    _autoRefresh,
33    _sort,
34    _suppressOverwrites,
35    _ignoreResize,
36    _normalizer,
37    _ignoreMobileResize,
38    _baseScreenHeight,
39    _baseScreenWidth,
40    _fixIOSBug,
41    _context,
42    _scrollRestoration,
43    _div100vh,
44    _100vh,
45    _limitCallbacks,
46    // if true, we'll only trigger callbacks if the active state toggles, so if you scroll immediately past both the start and end positions of a ScrollTrigger (thus inactive to inactive), neither its onEnter nor onLeave will be called. This is useful during startup.
47_startup = 1,
48    _getTime = Date.now,
49    _time1 = _getTime(),
50    _lastScrollTime = 0,
51    _enabled = 0,
52    _parseClamp = function _parseClamp(value, type, self) {
53  var clamp = _isString(value) && (value.substr(0, 6) === "clamp(" || value.indexOf("max") > -1);
54  self["_" + type + "Clamp"] = clamp;
55  return clamp ? value.substr(6, value.length - 7) : value;
56},
57    _keepClamp = function _keepClamp(value, clamp) {
58  return clamp && (!_isString(value) || value.substr(0, 6) !== "clamp(") ? "clamp(" + value + ")" : value;
59},
60    _rafBugFix = function _rafBugFix() {
61  return _enabled && requestAnimationFrame(_rafBugFix);
62},
63    // in some browsers (like Firefox), screen repaints weren't consistent unless we had SOMETHING queued up in requestAnimationFrame()! So this just creates a super simple loop to keep it alive and smooth out repaints.
64_pointerDownHandler = function _pointerDownHandler() {
65  return _pointerIsDown = 1;
66},
67    _pointerUpHandler = function _pointerUpHandler() {
68  return _pointerIsDown = 0;
69},
70    _passThrough = function _passThrough(v) {
71  return v;
72},
73    _round = function _round(value) {
74  return Math.round(value * 100000) / 100000 || 0;
75},
76    _windowExists = function _windowExists() {
77  return typeof window !== "undefined";
78},
79    _getGSAP = function _getGSAP() {
80  return gsap || _windowExists() && (gsap = window.gsap) && gsap.registerPlugin && gsap;
81},
82    _isViewport = function _isViewport(e) {
83  return !!~_root.indexOf(e);
84},
85    _getViewportDimension = function _getViewportDimension(dimensionProperty) {
86  return (dimensionProperty === "Height" ? _100vh : _win["inner" + dimensionProperty]) || _docEl["client" + dimensionProperty] || _body["client" + dimensionProperty];
87},
88    _getBoundsFunc = function _getBoundsFunc(element) {
89  return _getProxyProp(element, "getBoundingClientRect") || (_isViewport(element) ? function () {
90    _winOffsets.width = _win.innerWidth;
91    _winOffsets.height = _100vh;
92    return _winOffsets;
93  } : function () {
94    return _getBounds(element);
95  });
96},
97    _getSizeFunc = function _getSizeFunc(scroller, isViewport, _ref) {
98  var d = _ref.d,
99      d2 = _ref.d2,
100      a = _ref.a;
101  return (a = _getProxyProp(scroller, "getBoundingClientRect")) ? function () {
102    return a()[d];
103  } : function () {
104    return (isViewport ? _getViewportDimension(d2) : scroller["client" + d2]) || 0;
105  };
106},
107    _getOffsetsFunc = function _getOffsetsFunc(element, isViewport) {
108  return !isViewport || ~_proxies.indexOf(element) ? _getBoundsFunc(element) : function () {
109    return _winOffsets;
110  };
111},
112    _maxScroll = function _maxScroll(element, _ref2) {
113  var s = _ref2.s,
114      d2 = _ref2.d2,
115      d = _ref2.d,
116      a = _ref2.a;
117  return Math.max(0, (s = "scroll" + d2) && (a = _getProxyProp(element, s)) ? a() - _getBoundsFunc(element)()[d] : _isViewport(element) ? (_docEl[s] || _body[s]) - _getViewportDimension(d2) : element[s] - element["offset" + d2]);
118},
119    _iterateAutoRefresh = function _iterateAutoRefresh(func, events) {
120  for (var i = 0; i < _autoRefresh.length; i += 3) {
vendor: 13,579 bytes, lines 121-494
121    (!events || ~events.indexOf(_autoRefresh[i + 1])) && func(_autoRefresh[i], _autoRefresh[i + 1], _autoRefresh[i + 2]);
122  }
123},
124    _isString = function _isString(value) {
125  return typeof value === "string";
126},
127    _isFunction = function _isFunction(value) {
128  return typeof value === "function";
129},
130    _isNumber = function _isNumber(value) {
131  return typeof value === "number";
132},
133    _isObject = function _isObject(value) {
134  return typeof value === "object";
135},
136    _endAnimation = function _endAnimation(animation, reversed, pause) {
137  return animation && animation.progress(reversed ? 0 : 1) && pause && animation.pause();
138},
139    _callback = function _callback(self, func) {
140  if (self.enabled) {
141    var result = func(self);
142    result && result.totalTime && (self.callbackAnimation = result);
143  }
144},
145    _abs = Math.abs,
146    _left = "left",
147    _top = "top",
148    _right = "right",
149    _bottom = "bottom",
150    _width = "width",
151    _height = "height",
152    _Right = "Right",
153    _Left = "Left",
154    _Top = "Top",
155    _Bottom = "Bottom",
156    _padding = "padding",
157    _margin = "margin",
158    _Width = "Width",
159    _Height = "Height",
160    _px = "px",
161    _getComputedStyle = function _getComputedStyle(element) {
162  return _win.getComputedStyle(element);
163},
164    _makePositionable = function _makePositionable(element) {
165  // if the element already has position: absolute or fixed, leave that, otherwise make it position: relative
166  var position = _getComputedStyle(element).position;
167
168  element.style.position = position === "absolute" || position === "fixed" ? position : "relative";
169},
170    _setDefaults = function _setDefaults(obj, defaults) {
171  for (var p in defaults) {
172    p in obj || (obj[p] = defaults[p]);
173  }
174
175  return obj;
176},
177    _getBounds = function _getBounds(element, withoutTransforms) {
178  var tween = withoutTransforms && _getComputedStyle(element)[_transformProp] !== "matrix(1, 0, 0, 1, 0, 0)" && gsap.to(element, {
179    x: 0,
180    y: 0,
181    xPercent: 0,
182    yPercent: 0,
183    rotation: 0,
184    rotationX: 0,
185    rotationY: 0,
186    scale: 1,
187    skewX: 0,
188    skewY: 0
189  }).progress(1),
190      bounds = element.getBoundingClientRect();
191  tween && tween.progress(0).kill();
192  return bounds;
193},
194    _getSize = function _getSize(element, _ref3) {
195  var d2 = _ref3.d2;
196  return element["offset" + d2] || element["client" + d2] || 0;
197},
198    _getLabelRatioArray = function _getLabelRatioArray(timeline) {
199  var a = [],
200      labels = timeline.labels,
201      duration = timeline.duration(),
202      p;
203
204  for (p in labels) {
205    a.push(labels[p] / duration);
206  }
207
208  return a;
209},
210    _getClosestLabel = function _getClosestLabel(animation) {
211  return function (value) {
212    return gsap.utils.snap(_getLabelRatioArray(animation), value);
213  };
214},
215    _snapDirectional = function _snapDirectional(snapIncrementOrArray) {
216  var snap = gsap.utils.snap(snapIncrementOrArray),
217      a = Array.isArray(snapIncrementOrArray) && snapIncrementOrArray.slice(0).sort(function (a, b) {
218    return a - b;
219  });
220  return a ? function (value, direction, threshold) {
221    if (threshold === void 0) {
222      threshold = 1e-3;
223    }
224
225    var i;
226
227    if (!direction) {
228      return snap(value);
229    }
230
231    if (direction > 0) {
232      value -= threshold; // to avoid rounding errors. If we're too strict, it might snap forward, then immediately again, and again.
233
234      for (i = 0; i < a.length; i++) {
235        if (a[i] >= value) {
236          return a[i];
237        }
238      }
239
240      return a[i - 1];
241    } else {
242      i = a.length;
243      value += threshold;
244
245      while (i--) {
246        if (a[i] <= value) {
247          return a[i];
248        }
249      }
250    }
251
252    return a[0];
253  } : function (value, direction, threshold) {
254    if (threshold === void 0) {
255      threshold = 1e-3;
256    }
257
258    var snapped = snap(value);
259    return !direction || Math.abs(snapped - value) < threshold || snapped - value < 0 === direction < 0 ? snapped : snap(direction < 0 ? value - snapIncrementOrArray : value + snapIncrementOrArray);
260  };
261},
262    _getLabelAtDirection = function _getLabelAtDirection(timeline) {
263  return function (value, st) {
264    return _snapDirectional(_getLabelRatioArray(timeline))(value, st.direction);
265  };
266},
267    _multiListener = function _multiListener(func, element, types, callback) {
268  return types.split(",").forEach(function (type) {
269    return func(element, type, callback);
270  });
271},
272    _addListener = function _addListener(element, type, func, nonPassive, capture) {
273  return element.addEventListener(type, func, {
274    passive: !nonPassive,
275    capture: !!capture
276  });
277},
278    _removeListener = function _removeListener(element, type, func, capture) {
279  return element.removeEventListener(type, func, !!capture);
280},
281    _wheelListener = function _wheelListener(func, el, scrollFunc) {
282  scrollFunc = scrollFunc && scrollFunc.wheelHandler;
283
284  if (scrollFunc) {
285    func(el, "wheel", scrollFunc);
286    func(el, "touchmove", scrollFunc);
287  }
288},
289    _markerDefaults = {
290  startColor: "green",
291  endColor: "red",
292  indent: 0,
293  fontSize: "16px",
294  fontWeight: "normal"
295},
296    _defaults = {
297  toggleActions: "play",
298  anticipatePin: 0
299},
300    _keywords = {
301  top: 0,
302  left: 0,
303  center: 0.5,
304  bottom: 1,
305  right: 1
306},
307    _offsetToPx = function _offsetToPx(value, size) {
308  if (_isString(value)) {
309    var eqIndex = value.indexOf("="),
310        relative = ~eqIndex ? +(value.charAt(eqIndex - 1) + 1) * parseFloat(value.substr(eqIndex + 1)) : 0;
311
312    if (~eqIndex) {
313      value.indexOf("%") > eqIndex && (relative *= size / 100);
314      value = value.substr(0, eqIndex - 1);
315    }
316
317    value = relative + (value in _keywords ? _keywords[value] * size : ~value.indexOf("%") ? parseFloat(value) * size / 100 : parseFloat(value) || 0);
318  }
319
320  return value;
321},
322    _createMarker = function _createMarker(type, name, container, direction, _ref4, offset, matchWidthEl, containerAnimation) {
323  var startColor = _ref4.startColor,
324      endColor = _ref4.endColor,
325      fontSize = _ref4.fontSize,
326      indent = _ref4.indent,
327      fontWeight = _ref4.fontWeight;
328
329  var e = _doc.createElement("div"),
330      useFixedPosition = _isViewport(container) || _getProxyProp(container, "pinType") === "fixed",
331      isScroller = type.indexOf("scroller") !== -1,
332      parent = useFixedPosition ? _body : container,
333      isStart = type.indexOf("start") !== -1,
334      color = isStart ? startColor : endColor,
335      css = "border-color:" + color + ";font-size:" + fontSize + ";color:" + color + ";font-weight:" + fontWeight + ";pointer-events:none;white-space:nowrap;font-family:sans-serif,Arial;z-index:1000;padding:4px 8px;border-width:0;border-style:solid;";
336
337  css += "position:" + ((isScroller || containerAnimation) && useFixedPosition ? "fixed;" : "absolute;");
338  (isScroller || containerAnimation || !useFixedPosition) && (css += (direction === _vertical ? _right : _bottom) + ":" + (offset + parseFloat(indent)) + "px;");
339  matchWidthEl && (css += "box-sizing:border-box;text-align:left;width:" + matchWidthEl.offsetWidth + "px;");
340  e._isStart = isStart;
341  e.setAttribute("class", "gsap-marker-" + type + (name ? " marker-" + name : ""));
342  e.style.cssText = css;
343  e.innerText = name || name === 0 ? type + "-" + name : type;
344  parent.children[0] ? parent.insertBefore(e, parent.children[0]) : parent.appendChild(e);
345  e._offset = e["offset" + direction.op.d2];
346
347  _positionMarker(e, 0, direction, isStart);
348
349  return e;
350},
351    _positionMarker = function _positionMarker(marker, start, direction, flipped) {
352  var vars = {
353    display: "block"
354  },
355      side = direction[flipped ? "os2" : "p2"],
356      oppositeSide = direction[flipped ? "p2" : "os2"];
357  marker._isFlipped = flipped;
358  vars[direction.a + "Percent"] = flipped ? -100 : 0;
359  vars[direction.a] = flipped ? "1px" : 0;
360  vars["border" + side + _Width] = 1;
361  vars["border" + oppositeSide + _Width] = 0;
362  vars[direction.p] = start + "px";
363  gsap.set(marker, vars);
364},
365    _triggers = [],
366    _ids = {},
367    _rafID,
368    _sync = function _sync() {
369  return _getTime() - _lastScrollTime > 34 && (_rafID || (_rafID = requestAnimationFrame(_updateAll)));
370},
371    _onScroll = function _onScroll() {
372  // previously, we tried to optimize performance by batching/deferring to the next requestAnimationFrame(), but discovered that Safari has a few bugs that make this unworkable (especially on iOS). See https://codepen.io/GreenSock/pen/16c435b12ef09c38125204818e7b45fc?editors=0010 and https://codepen.io/GreenSock/pen/JjOxYpQ/3dd65ccec5a60f1d862c355d84d14562?editors=0010 and https://codepen.io/GreenSock/pen/ExbrPNa/087cef197dc35445a0951e8935c41503?editors=0010
373  if (!_normalizer || !_normalizer.isPressed || _normalizer.startX > _body.clientWidth) {
374    // if the user is dragging the scrollbar, allow it.
375    _scrollers.cache++;
376
377    if (_normalizer) {
378      _rafID || (_rafID = requestAnimationFrame(_updateAll));
379    } else {
380      _updateAll(); // Safari in particular (on desktop) NEEDS the immediate update rather than waiting for a requestAnimationFrame() whereas iOS seems to benefit from waiting for the requestAnimationFrame() tick, at least when normalizing. See https://codepen.io/GreenSock/pen/qBYozqO?editors=0110
381
382    }
383
384    _lastScrollTime || _dispatch("scrollStart");
385    _lastScrollTime = _getTime();
386  }
387},
388    _setBaseDimensions = function _setBaseDimensions() {
389  _baseScreenWidth = _win.innerWidth;
390  _baseScreenHeight = _win.innerHeight;
391},
392    _onResize = function _onResize() {
393  _scrollers.cache++;
394  !_refreshing && !_ignoreResize && !_doc.fullscreenElement && !_doc.webkitFullscreenElement && (!_ignoreMobileResize || _baseScreenWidth !== _win.innerWidth || Math.abs(_win.innerHeight - _baseScreenHeight) > _win.innerHeight * 0.25) && _resizeDelay.restart(true);
395},
396    // ignore resizes triggered by refresh()
397_listeners = {},
398    _emptyArray = [],
399    _softRefresh = function _softRefresh() {
400  return _removeListener(ScrollTrigger, "scrollEnd", _softRefresh) || _refreshAll(true);
401},
402    _dispatch = function _dispatch(type) {
403  return _listeners[type] && _listeners[type].map(function (f) {
404    return f();
405  }) || _emptyArray;
406},
407    _savedStyles = [],
408    // when ScrollTrigger.saveStyles() is called, the inline styles are recorded in this Array in a sequential format like [element, cssText, gsCache, media]. This keeps it very memory-efficient and fast to iterate through.
409_revertRecorded = function _revertRecorded(media) {
410  for (var i = 0; i < _savedStyles.length; i += 5) {
411    if (!media || _savedStyles[i + 4] && _savedStyles[i + 4].query === media) {
412      _savedStyles[i].style.cssText = _savedStyles[i + 1];
413      _savedStyles[i].getBBox && _savedStyles[i].setAttribute("transform", _savedStyles[i + 2] || "");
414      _savedStyles[i + 3].uncache = 1;
415    }
416  }
417},
418    _revertAll = function _revertAll(kill, media) {
419  var trigger;
420
421  for (_i = 0; _i < _triggers.length; _i++) {
422    trigger = _triggers[_i];
423
424    if (trigger && (!media || trigger._ctx === media)) {
425      if (kill) {
426        trigger.kill(1);
427      } else {
428        trigger.revert(true, true);
429      }
430    }
431  }
432
433  media && _revertRecorded(media);
434  media || _dispatch("revert");
435},
436    _clearScrollMemory = function _clearScrollMemory(scrollRestoration, force) {
437  // zero-out all the recorded scroll positions. Don't use _triggers because if, for example, .matchMedia() is used to create some ScrollTriggers and then the user resizes and it removes ALL ScrollTriggers, and then go back to a size where there are ScrollTriggers, it would have kept the position(s) saved from the initial state.
438  _scrollers.cache++;
439  (force || !_refreshingAll) && _scrollers.forEach(function (obj) {
440    return _isFunction(obj) && obj.cacheID++ && (obj.rec = 0);
441  });
442  _isString(scrollRestoration) && (_win.history.scrollRestoration = _scrollRestoration = scrollRestoration);
443},
444    _refreshingAll,
445    _refreshID = 0,
446    _queueRefreshID,
447    _queueRefreshAll = function _queueRefreshAll() {
448  // we don't want to call _refreshAll() every time we create a new ScrollTrigger (for performance reasons) - it's better to batch them. Some frameworks dynamically load content and we can't rely on the window's "load" or "DOMContentLoaded" events to trigger it.
449  if (_queueRefreshID !== _refreshID) {
450    var id = _queueRefreshID = _refreshID;
451    requestAnimationFrame(function () {
452      return id === _refreshID && _refreshAll(true);
453    });
454  }
455},
456    _refresh100vh = function _refresh100vh() {
457  _body.appendChild(_div100vh);
458
459  _100vh = _div100vh.offsetHeight || _win.innerHeight;
460
461  _body.removeChild(_div100vh);
462},
463    _refreshAll = function _refreshAll(force, skipRevert) {
464  if (_lastScrollTime && !force) {
465    _addListener(ScrollTrigger, "scrollEnd", _softRefresh);
466
467    return;
468  }
469
470  _refresh100vh();
471
472  _refreshingAll = ScrollTrigger.isRefreshing = true;
473
474  _scrollers.forEach(function (obj) {
475    return _isFunction(obj) && ++obj.cacheID && (obj.rec = obj());
476  }); // force the clearing of the cache because some browsers take a little while to dispatch the "scroll" event and the user may have changed the scroll position and then called ScrollTrigger.refresh() right away
477
478
479  var refreshInits = _dispatch("refreshInit");
480
481  _sort && ScrollTrigger.sort();
482  skipRevert || _revertAll();
483
484  _scrollers.forEach(function (obj) {
485    if (_isFunction(obj)) {
486      obj.smooth && (obj.target.style.scrollBehavior = "auto"); // smooth scrolling interferes
487
488      obj(0);
489    }
490  });
491
492  _triggers.slice(0).forEach(function (t) {
493    return t.refresh();
494  }); // don't loop with _i because during a refresh() someone could call ScrollTrigger.update(
vendor: 17,541 bytes, lines 494-951
494) which would iterate through _i resulting in a skip.
495
496
497  _triggers.forEach(function (t, i) {
498    // nested pins (pinnedContainer) with pinSpacing may expand the container, so we must accommodate that here.
499    if (t._subPinOffset && t.pin) {
500      var prop = t.vars.horizontal ? "offsetWidth" : "offsetHeight",
501          original = t.pin[prop];
502      t.revert(true, 1);
503      t.adjustPinSpacing(t.pin[prop] - original);
504      t.refresh();
505    }
506  });
507
508  _triggers.forEach(function (t) {
509    // the scroller's max scroll position may change after all the ScrollTriggers refreshed (like pinning could push it down), so we need to loop back and correct any with end: "max". Same for anything with a clamped end
510    var max = _maxScroll(t.scroller, t._dir);
511
512    (t.vars.end === "max" || t._endClamp && t.end > max) && t.setPositions(t.start, Math.max(t.start + 1, max), true);
513  });
514
515  refreshInits.forEach(function (result) {
516    return result && result.render && result.render(-1);
517  }); // if the onRefreshInit() returns an animation (typically a gsap.set()), revert it. This makes it easy to put things in a certain spot before refreshing for measurement purposes, and then put things back.
518
519  _scrollers.forEach(function (obj) {
520    if (_isFunction(obj)) {
521      obj.smooth && requestAnimationFrame(function () {
522        return obj.target.style.scrollBehavior = "smooth";
523      });
524      obj.rec && obj(obj.rec);
525    }
526  });
527
528  _clearScrollMemory(_scrollRestoration, 1);
529
530  _resizeDelay.pause();
531
532  _refreshID++;
533  _refreshingAll = 2;
534
535  _updateAll(2);
536
537  _triggers.forEach(function (t) {
538    return _isFunction(t.vars.onRefresh) && t.vars.onRefresh(t);
539  });
540
541  _refreshingAll = ScrollTrigger.isRefreshing = false;
542
543  _dispatch("refresh");
544},
545    _lastScroll = 0,
546    _direction = 1,
547    _primary,
548    _updateAll = function _updateAll(force) {
549  if (!_refreshingAll || force === 2) {
550    ScrollTrigger.isUpdating = true;
551    _primary && _primary.update(0); // ScrollSmoother uses refreshPriority -9999 to become the primary that gets updated before all others because it affects the scroll position.
552
553    var l = _triggers.length,
554        time = _getTime(),
555        recordVelocity = time - _time1 >= 50,
556        scroll = l && _triggers[0].scroll();
557
558    _direction = _lastScroll > scroll ? -1 : 1;
559    _refreshingAll || (_lastScroll = scroll);
560
561    if (recordVelocity) {
562      if (_lastScrollTime && !_pointerIsDown && time - _lastScrollTime > 200) {
563        _lastScrollTime = 0;
564
565        _dispatch("scrollEnd");
566      }
567
568      _time2 = _time1;
569      _time1 = time;
570    }
571
572    if (_direction < 0) {
573      _i = l;
574
575      while (_i-- > 0) {
576        _triggers[_i] && _triggers[_i].update(0, recordVelocity);
577      }
578
579      _direction = 1;
580    } else {
581      for (_i = 0; _i < l; _i++) {
582        _triggers[_i] && _triggers[_i].update(0, recordVelocity);
583      }
584    }
585
586    ScrollTrigger.isUpdating = false;
587  }
588
589  _rafID = 0;
590},
591    _propNamesToCopy = [_left, _top, _bottom, _right, _margin + _Bottom, _margin + _Right, _margin + _Top, _margin + _Left, "display", "flexShrink", "float", "zIndex", "gridColumnStart", "gridColumnEnd", "gridRowStart", "gridRowEnd", "gridArea", "justifySelf", "alignSelf", "placeSelf", "order"],
592    _stateProps = _propNamesToCopy.concat([_width, _height, "boxSizing", "max" + _Width, "max" + _Height, "position", _margin, _padding, _padding + _Top, _padding + _Right, _padding + _Bottom, _padding + _Left]),
593    _swapPinOut = function _swapPinOut(pin, spacer, state) {
594  _setState(state);
595
596  var cache = pin._gsap;
597
598  if (cache.spacerIsNative) {
599    _setState(cache.spacerState);
600  } else if (pin._gsap.swappedIn) {
601    var parent = spacer.parentNode;
602
603    if (parent) {
604      parent.insertBefore(pin, spacer);
605      parent.removeChild(spacer);
606    }
607  }
608
609  pin._gsap.swappedIn = false;
610},
611    _swapPinIn = function _swapPinIn(pin, spacer, cs, spacerState) {
612  if (!pin._gsap.swappedIn) {
613    var i = _propNamesToCopy.length,
614        spacerStyle = spacer.style,
615        pinStyle = pin.style,
616        p;
617
618    while (i--) {
619      p = _propNamesToCopy[i];
620      spacerStyle[p] = cs[p];
621    }
622
623    spacerStyle.position = cs.position === "absolute" ? "absolute" : "relative";
624    cs.display === "inline" && (spacerStyle.display = "inline-block");
625    pinStyle[_bottom] = pinStyle[_right] = "auto";
626    spacerStyle.flexBasis = cs.flexBasis || "auto";
627    spacerStyle.overflow = "visible";
628    spacerStyle.boxSizing = "border-box";
629    spacerStyle[_width] = _getSize(pin, _horizontal) + _px;
630    spacerStyle[_height] = _getSize(pin, _vertical) + _px;
631    spacerStyle[_padding] = pinStyle[_margin] = pinStyle[_top] = pinStyle[_left] = "0";
632
633    _setState(spacerState);
634
635    pinStyle[_width] = pinStyle["max" + _Width] = cs[_width];
636    pinStyle[_height] = pinStyle["max" + _Height] = cs[_height];
637    pinStyle[_padding] = cs[_padding];
638
639    if (pin.parentNode !== spacer) {
640      pin.parentNode.insertBefore(spacer, pin);
641      spacer.appendChild(pin);
642    }
643
644    pin._gsap.swappedIn = true;
645  }
646},
647    _capsExp = /([A-Z])/g,
648    _setState = function _setState(state) {
649  if (state) {
650    var style = state.t.style,
651        l = state.length,
652        i = 0,
653        p,
654        value;
655    (state.t._gsap || gsap.core.getCache(state.t)).uncache = 1; // otherwise transforms may be off
656
657    for (; i < l; i += 2) {
658      value = state[i + 1];
659      p = state[i];
660
661      if (value) {
662        style[p] = value;
663      } else if (style[p]) {
664        style.removeProperty(p.replace(_capsExp, "-$1").toLowerCase());
665      }
666    }
667  }
668},
669    _getState = function _getState(element) {
670  // returns an Array with alternating values like [property, value, property, value] and a "t" property pointing to the target (element). Makes it fast and cheap.
671  var l = _stateProps.length,
672      style = element.style,
673      state = [],
674      i = 0;
675
676  for (; i < l; i++) {
677    state.push(_stateProps[i], style[_stateProps[i]]);
678  }
679
680  state.t = element;
681  return state;
682},
683    _copyState = function _copyState(state, override, omitOffsets) {
684  var result = [],
685      l = state.length,
686      i = omitOffsets ? 8 : 0,
687      // skip top, left, right, bottom if omitOffsets is true
688  p;
689
690  for (; i < l; i += 2) {
691    p = state[i];
692    result.push(p, p in override ? override[p] : state[i + 1]);
693  }
694
695  result.t = state.t;
696  return result;
697},
698    _winOffsets = {
699  left: 0,
700  top: 0
701},
702    // // potential future feature (?) Allow users to calculate where a trigger hits (scroll position) like getScrollPosition("#id", "top bottom")
703// _getScrollPosition = (trigger, position, {scroller, containerAnimation, horizontal}) => {
704// 	scroller = _getTarget(scroller || _win);
705// 	let direction = horizontal ? _horizontal : _vertical,
706// 		isViewport = _isViewport(scroller);
707// 	_getSizeFunc(scroller, isViewport, direction);
708// 	return _parsePosition(position, _getTarget(trigger), _getSizeFunc(scroller, isViewport, direction)(), direction, _getScrollFunc(scroller, direction)(), 0, 0, 0, _getOffsetsFunc(scroller, isViewport)(), isViewport ? 0 : parseFloat(_getComputedStyle(scroller)["border" + direction.p2 + _Width]) || 0, 0, containerAnimation ? containerAnimation.duration() : _maxScroll(scroller), containerAnimation);
709// },
710_parsePosition = function _parsePosition(value, trigger, scrollerSize, direction, scroll, marker, markerScroller, self, scrollerBounds, borderWidth, useFixedPosition, scrollerMax, containerAnimation, clampZeroProp) {
711  _isFunction(value) && (value = value(self));
712
713  if (_isString(value) && value.substr(0, 3) === "max") {
714    value = scrollerMax + (value.charAt(4) === "=" ? _offsetToPx("0" + value.substr(3), scrollerSize) : 0);
715  }
716
717  var time = containerAnimation ? containerAnimation.time() : 0,
718      p1,
719      p2,
720      element;
721  containerAnimation && containerAnimation.seek(0);
722  isNaN(value) || (value = +value); // convert a string number like "45" to an actual number
723
724  if (!_isNumber(value)) {
725    _isFunction(trigger) && (trigger = trigger(self));
726    var offsets = (value || "0").split(" "),
727        bounds,
728        localOffset,
729        globalOffset,
730        display;
731    element = _getTarget(trigger, self) || _body;
732    bounds = _getBounds(element) || {};
733
734    if ((!bounds || !bounds.left && !bounds.top) && _getComputedStyle(element).display === "none") {
735      // if display is "none", it won't report getBoundingClientRect() properly
736      display = element.style.display;
737      element.style.display = "block";
738      bounds = _getBounds(element);
739      display ? element.style.display = display : element.style.removeProperty("display");
740    }
741
742    localOffset = _offsetToPx(offsets[0], bounds[direction.d]);
743    globalOffset = _offsetToPx(offsets[1] || "0", scrollerSize);
744    value = bounds[direction.p] - scrollerBounds[direction.p] - borderWidth + localOffset + scroll - globalOffset;
745    markerScroller && _positionMarker(markerScroller, globalOffset, direction, scrollerSize - globalOffset < 20 || markerScroller._isStart && globalOffset > 20);
746    scrollerSize -= scrollerSize - globalOffset; // adjust for the marker
747  } else {
748    containerAnimation && (value = gsap.utils.mapRange(containerAnimation.scrollTrigger.start, containerAnimation.scrollTrigger.end, 0, scrollerMax, value));
749    markerScroller && _positionMarker(markerScroller, scrollerSize, direction, true);
750  }
751
752  if (clampZeroProp) {
753    self[clampZeroProp] = value || -0.001;
754    value < 0 && (value = 0);
755  }
756
757  if (marker) {
758    var position = value + scrollerSize,
759        isStart = marker._isStart;
760    p1 = "scroll" + direction.d2;
761
762    _positionMarker(marker, position, direction, isStart && position > 20 || !isStart && (useFixedPosition ? Math.max(_body[p1], _docEl[p1]) : marker.parentNode[p1]) <= position + 1);
763
764    if (useFixedPosition) {
765      scrollerBounds = _getBounds(markerScroller);
766      useFixedPosition && (marker.style[direction.op.p] = scrollerBounds[direction.op.p] - direction.op.m - marker._offset + _px);
767    }
768  }
769
770  if (containerAnimation && element) {
771    p1 = _getBounds(element);
772    containerAnimation.seek(scrollerMax);
773    p2 = _getBounds(element);
774    containerAnimation._caScrollDist = p1[direction.p] - p2[direction.p];
775    value = value / containerAnimation._caScrollDist * scrollerMax;
776  }
777
778  containerAnimation && containerAnimation.seek(time);
779  return containerAnimation ? value : Math.round(value);
780},
781    _prefixExp = /(webkit|moz|length|cssText|inset)/i,
782    _reparent = function _reparent(element, parent, top, left) {
783  if (element.parentNode !== parent) {
784    var style = element.style,
785        p,
786        cs;
787
788    if (parent === _body) {
789      element._stOrig = style.cssText; // record original inline styles so we can revert them later
790
791      cs = _getComputedStyle(element);
792
793      for (p in cs) {
794        // must copy all relevant styles to ensure that nothing changes visually when we reparent to the <body>. Skip the vendor prefixed ones.
795        if (!+p && !_prefixExp.test(p) && cs[p] && typeof style[p] === "string" && p !== "0") {
796          style[p] = cs[p];
797        }
798      }
799
800      style.top = top;
801      style.left = left;
802    } else {
803      style.cssText = element._stOrig;
804    }
805
806    gsap.core.getCache(element).uncache = 1;
807    parent.appendChild(element);
808  }
809},
810    _interruptionTracker = function _interruptionTracker(getValueFunc, initialValue, onInterrupt) {
811  var last1 = initialValue,
812      last2 = last1;
813  return function (value) {
814    var current = Math.round(getValueFunc()); // round because in some [very uncommon] Windows environments, scroll can get reported with decimals even though it was set without.
815
816    if (current !== last1 && current !== last2 && Math.abs(current - last1) > 3 && Math.abs(current - last2) > 3) {
817      // if the user scrolls, kill the tween. iOS Safari intermittently misreports the scroll position, it may be the most recently-set one or the one before that! When Safari is zoomed (CMD-+), it often misreports as 1 pixel off too! So if we set the scroll position to 125, for example, it'll actually report it as 124.
818      value = current;
819      onInterrupt && onInterrupt();
820    }
821
822    last2 = last1;
823    last1 = value;
824    return value;
825  };
826},
827    _shiftMarker = function _shiftMarker(marker, direction, value) {
828  var vars = {};
829  vars[direction.p] = "+=" + value;
830  gsap.set(marker, vars);
831},
832    // _mergeAnimations = animations => {
833// 	let tl = gsap.timeline({smoothChildTiming: true}).startTime(Math.min(...animations.map(a => a.globalTime(0))));
834// 	animations.forEach(a => {let time = a.totalTime(); tl.add(a); a.totalTime(time); });
835// 	tl.smoothChildTiming = false;
836// 	return tl;
837// },
838// returns a function that can be used to tween the scroll position in the direction provided, and when doing so it'll add a .tween property to the FUNCTION itself, and remove it when the tween completes or gets killed. This gives us a way to have multiple ScrollTriggers use a central function for any given scroller and see if there's a scroll tween running (which would affect if/how things get updated)
839_getTweenCreator = function _getTweenCreator(scroller, direction) {
840  var getScroll = _getScrollFunc(scroller, direction),
841      prop = "_scroll" + direction.p2,
842      // add a tweenable property to the scroller that's a getter/setter function, like _scrollTop or _scrollLeft. This way, if someone does gsap.killTweensOf(scroller) it'll kill the scroll tween.
843  getTween = function getTween(scrollTo, vars, initialValue, change1, change2) {
844    var tween = getTween.tween,
845        onComplete = vars.onComplete,
846        modifiers = {};
847    initialValue = initialValue || getScroll();
848
849    var checkForInterruption = _interruptionTracker(getScroll, initialValue, function () {
850      tween.kill();
851      getTween.tween = 0;
852    });
853
854    change2 = change1 && change2 || 0; // if change1 is 0, we set that to the difference and ignore change2. Otherwise, there would be a compound effect.
855
856    change1 = change1 || scrollTo - initialValue;
857    tween && tween.kill();
858    vars[prop] = scrollTo;
859    vars.modifiers = modifiers;
860
861    modifiers[prop] = function () {
862      return checkForInterruption(initialValue + change1 * tween.ratio + change2 * tween.ratio * tween.ratio);
863    };
864
865    vars.onUpdate = function () {
866      _scrollers.cache++;
867
868      _updateAll();
869    };
870
871    vars.onComplete = function () {
872      getTween.tween = 0;
873      onComplete && onComplete.call(tween);
874    };
875
876    tween = getTween.tween = gsap.to(scroller, vars);
877    return tween;
878  };
879
880  scroller[prop] = getScroll;
881
882  getScroll.wheelHandler = function () {
883    return getTween.tween && getTween.tween.kill() && (getTween.tween = 0);
884  };
885
886  _addListener(scroller, "wheel", getScroll.wheelHandler); // Windows machines handle mousewheel scrolling in chunks (like "3 lines per scroll") meaning the typical strategy for cancelling the scroll isn't as sensitive. It's much more likely to match one of the previous 2 scroll event positions. So we kill any snapping as soon as there's a wheel event.
887
888
889  ScrollTrigger.isTouch && _addListener(scroller, "touchmove", getScroll.wheelHandler);
890  return getTween;
891};
892
893export var ScrollTrigger = /*#__PURE__*/function () {
894  function ScrollTrigger(vars, animation) {
895    _coreInitted || ScrollTrigger.register(gsap) || console.warn("Please gsap.registerPlugin(ScrollTrigger)");
896
897    _context(this);
898
899    this.init(vars, animation);
900  }
901
902  var _proto = ScrollTrigger.prototype;
903
904  _proto.init = function init(vars, animation) {
905    this.progress = this.start = 0;
906    this.vars && this.kill(true, true); // in case it's being initted again
907
908    if (!_enabled) {
909      this.update = this.refresh = this.kill = _passThrough;
910      return;
911    }
912
913    vars = _setDefaults(_isString(vars) || _isNumber(vars) || vars.nodeType ? {
914      trigger: vars
915    } : vars, _defaults);
916
917    var _vars = vars,
918        onUpdate = _vars.onUpdate,
919        toggleClass = _vars.toggleClass,
920        id = _vars.id,
921        onToggle = _vars.onToggle,
922        onRefresh = _vars.onRefresh,
923        scrub = _vars.scrub,
924        trigger = _vars.trigger,
925        pin = _vars.pin,
926        pinSpacing = _vars.pinSpacing,
927        invalidateOnRefresh = _vars.invalidateOnRefresh,
928        anticipatePin = _vars.anticipatePin,
929        onScrubComplete = _vars.onScrubComplete,
930        onSnapComplete = _vars.onSnapComplete,
931        once = _vars.once,
932        snap = _vars.snap,
933        pinReparent = _vars.pinReparent,
934        pinSpacer = _vars.pinSpacer,
935        containerAnimation = _vars.containerAnimation,
936        fastScrollEnd = _vars.fastScrollEnd,
937        preventOverlaps = _vars.preventOverlaps,
938        direction = vars.horizontal || vars.containerAnimation && vars.horizontal !== false ? _horizontal : _vertical,
939        isToggle = !scrub && scrub !== 0,
940        scroller = _getTarget(vars.scroller || _win),
941        scrollerCache = gsap.core.getCache(scroller),
942        isViewport = _isViewport(scroller),
943        useFixedPosition = ("pinType" in vars ? vars.pinType : _getProxyProp(scroller, "pinType") || isViewport && "fixed") === "fixed",
944        callbacks = [vars.onEnter, vars.onLeave, vars.onEnterBack, vars.onLeaveBack],
945        toggleActions = isToggle && vars.toggleActions.split(" "),
946        markers = "markers" in vars ? vars.markers : _defaults.markers,
947        borderWidth = isViewport ? 0 : parseFloat(_getComputedStyle(scroller)["border" + direction.p2 + _Width]) || 0,
948        self = this,
949        onRefreshInit = vars.onRefreshInit && function () {
950      return vars.onRefreshInit(self);
951    },
vendor: 4,094 bytes, lines 952-1060
952        getScrollerSize = _getSizeFunc(scroller, isViewport, direction),
953        getScrollerOffsets = _getOffsetsFunc(scroller, isViewport),
954        lastSnap = 0,
955        lastRefresh = 0,
956        prevProgress = 0,
957        scrollFunc = _getScrollFunc(scroller, direction),
958        tweenTo,
959        pinCache,
960        snapFunc,
961        scroll1,
962        scroll2,
963        start,
964        end,
965        markerStart,
966        markerEnd,
967        markerStartTrigger,
968        markerEndTrigger,
969        markerVars,
970        executingOnRefresh,
971        change,
972        pinOriginalState,
973        pinActiveState,
974        pinState,
975        spacer,
976        offset,
977        pinGetter,
978        pinSetter,
979        pinStart,
980        pinChange,
981        spacingStart,
982        spacerState,
983        markerStartSetter,
984        pinMoves,
985        markerEndSetter,
986        cs,
987        snap1,
988        snap2,
989        scrubTween,
990        scrubSmooth,
991        snapDurClamp,
992        snapDelayedCall,
993        prevScroll,
994        prevAnimProgress,
995        caMarkerSetter,
996        customRevertReturn; // for the sake of efficiency, _startClamp/_endClamp serve like a truthy value indicating that clamping was enabled on the start/end, and ALSO store the actual pre-clamped numeric value. We tap into that in ScrollSmoother for speed effects. So for example, if start="clamp(top bottom)" results in a start of -100 naturally, it would get clamped to 0 but -100 would be stored in _startClamp.
997
998
999    self._startClamp = self._endClamp = false;
1000    self._dir = direction;
1001    anticipatePin *= 45;
1002    self.scroller = scroller;
1003    self.scroll = containerAnimation ? containerAnimation.time.bind(containerAnimation) : scrollFunc;
1004    scroll1 = scrollFunc();
1005    self.vars = vars;
1006    animation = animation || vars.animation;
1007
1008    if ("refreshPriority" in vars) {
1009      _sort = 1;
1010      vars.refreshPriority === -9999 && (_primary = self); // used by ScrollSmoother
1011    }
1012
1013    scrollerCache.tweenScroll = scrollerCache.tweenScroll || {
1014      top: _getTweenCreator(scroller, _vertical),
1015      left: _getTweenCreator(scroller, _horizontal)
1016    };
1017    self.tweenTo = tweenTo = scrollerCache.tweenScroll[direction.p];
1018
1019    self.scrubDuration = function (value) {
1020      scrubSmooth = _isNumber(value) && value;
1021
1022      if (!scrubSmooth) {
1023        scrubTween && scrubTween.progress(1).kill();
1024        scrubTween = 0;
1025      } else {
1026        scrubTween ? scrubTween.duration(value) : scrubTween = gsap.to(animation, {
1027          ease: "expo",
1028          totalProgress: "+=0",
1029          duration: scrubSmooth,
1030          paused: true,
1031          onComplete: function onComplete() {
1032            return onScrubComplete && onScrubComplete(self);
1033          }
1034        });
1035      }
1036    };
1037
1038    if (animation) {
1039      animation.vars.lazy = false;
1040      animation._initted && !self.isReverted || animation.vars.immediateRender !== false && vars.immediateRender !== false && animation.duration() && animation.render(0, true, true); // special case: if this ScrollTrigger gets re-initted, a from() tween with a stagger could get initted initially and then reverted on the re-init which means it'll need to get rendered again here to properly display things. Otherwise, See https://greensock.com/forums/topic/36777-scrollsmoother-splittext-nextjs/ and https://codepen.io/GreenSock/pen/eYPyPpd?editors=0010
1041
1042      self.animation = animation.pause();
1043      animation.scrollTrigger = self;
1044      self.scrubDuration(scrub);
1045      snap1 = 0;
1046      id || (id = animation.vars.id);
1047    }
1048
1049    if (snap) {
1050      // TODO: potential idea: use legitimate CSS scroll snapping by pushing invisible elements into the DOM that serve as snap positions, and toggle the document.scrollingElement.style.scrollSnapType onToggle. See https://codepen.io/GreenSock/pen/JjLrgWM for a quick proof of concept.
1051      if (!_isObject(snap) || snap.push) {
1052        snap = {
1053          snapTo: snap
1054        };
1055      }
1056
1057      "scrollBehavior" in _body.style && gsap.set(isViewport ? [_body, _docEl] : scroller, {
1058        scrollBehavior: "auto"
1059      }); // smooth scrolling doesn't work with snap.
1060
vendor: 2,718 bytes, lines 1061-1106
1061      _scrollers.forEach(function (o) {
1062        return _isFunction(o) && o.target === (isViewport ? _doc.scrollingElement || _docEl : scroller) && (o.smooth = false);
1063      }); // note: set smooth to false on both the vertical and horizontal scroll getters/setters
1064
1065
1066      snapFunc = _isFunction(snap.snapTo) ? snap.snapTo : snap.snapTo === "labels" ? _getClosestLabel(animation) : snap.snapTo === "labelsDirectional" ? _getLabelAtDirection(animation) : snap.directional !== false ? function (value, st) {
1067        return _snapDirectional(snap.snapTo)(value, _getTime() - lastRefresh < 500 ? 0 : st.direction);
1068      } : gsap.utils.snap(snap.snapTo);
1069      snapDurClamp = snap.duration || {
1070        min: 0.1,
1071        max: 2
1072      };
1073      snapDurClamp = _isObject(snapDurClamp) ? _clamp(snapDurClamp.min, snapDurClamp.max) : _clamp(snapDurClamp, snapDurClamp);
1074      snapDelayedCall = gsap.delayedCall(snap.delay || scrubSmooth / 2 || 0.1, function () {
1075        var scroll = scrollFunc(),
1076            refreshedRecently = _getTime() - lastRefresh < 500,
1077            tween = tweenTo.tween;
1078
1079        if ((refreshedRecently || Math.abs(self.getVelocity()) < 10) && !tween && !_pointerIsDown && lastSnap !== scroll) {
1080          var progress = (scroll - start) / change,
1081              totalProgress = animation && !isToggle ? animation.totalProgress() : progress,
1082              velocity = refreshedRecently ? 0 : (totalProgress - snap2) / (_getTime() - _time2) * 1000 || 0,
1083              change1 = gsap.utils.clamp(-progress, 1 - progress, _abs(velocity / 2) * velocity / 0.185),
1084              naturalEnd = progress + (snap.inertia === false ? 0 : change1),
1085              endValue = _clamp(0, 1, snapFunc(naturalEnd, self)),
1086              endScroll = Math.round(start + endValue * change),
1087              _snap = snap,
1088              onStart = _snap.onStart,
1089              _onInterrupt = _snap.onInterrupt,
1090              _onComplete = _snap.onComplete;
1091
1092          if (scroll <= end && scroll >= start && endScroll !== scroll) {
1093            if (tween && !tween._initted && tween.data <= _abs(endScroll - scroll)) {
1094              // there's an overlapping snap! So we must figure out which one is closer and let that tween live.
1095              return;
1096            }
1097
1098            if (snap.inertia === false) {
1099              change1 = endValue - progress;
1100            }
1101
1102            tweenTo(endScroll, {
1103              duration: snapDurClamp(_abs(Math.max(_abs(naturalEnd - totalProgress), _abs(endValue - totalProgress)) * 0.185 / velocity / 0.05 || 0)),
1104              ease: snap.ease || "power3",
1105              data: _abs(endScroll - scroll),
1106              // record the distance so that if another snap tween occurs (conflict) we 
vendor: 5,075 bytes, lines 1106-1198
1106can prioritize the closest snap.
1107              onInterrupt: function onInterrupt() {
1108                return snapDelayedCall.restart(true) && _onInterrupt && _onInterrupt(self);
1109              },
1110              onComplete: function onComplete() {
1111                self.update();
1112                lastSnap = scrollFunc();
1113                snap1 = snap2 = animation && !isToggle ? animation.totalProgress() : self.progress;
1114                onSnapComplete && onSnapComplete(self);
1115                _onComplete && _onComplete(self);
1116              }
1117            }, scroll, change1 * change, endScroll - scroll - change1 * change);
1118            onStart && onStart(self, tweenTo.tween);
1119          }
1120        } else if (self.isActive && lastSnap !== scroll) {
1121          snapDelayedCall.restart(true);
1122        }
1123      }).pause();
1124    }
1125
1126    id && (_ids[id] = self);
1127    trigger = self.trigger = _getTarget(trigger || pin !== true && pin); // if a trigger has some kind of scroll-related effect applied that could contaminate the "y" or "x" position (like a ScrollSmoother effect), we needed a way to temporarily revert it, so we use the stRevert property of the gsCache. It can return another function that we'll call at the end so it can return to its normal state.
1128
1129    customRevertReturn = trigger && trigger._gsap && trigger._gsap.stRevert;
1130    customRevertReturn && (customRevertReturn = customRevertReturn(self));
1131    pin = pin === true ? trigger : _getTarget(pin);
1132    _isString(toggleClass) && (toggleClass = {
1133      targets: trigger,
1134      className: toggleClass
1135    });
1136
1137    if (pin) {
1138      pinSpacing === false || pinSpacing === _margin || (pinSpacing = !pinSpacing && pin.parentNode && pin.parentNode.style && _getComputedStyle(pin.parentNode).display === "flex" ? false : _padding); // if the parent is display: flex, don't apply pinSpacing by default. We should check that pin.parentNode is an element (not shadow dom window)
1139
1140      self.pin = pin;
1141      pinCache = gsap.core.getCache(pin);
1142
1143      if (!pinCache.spacer) {
1144        // record the spacer and pinOriginalState on the cache in case someone tries pinning the same element with MULTIPLE ScrollTriggers - we don't want to have multiple spacers or record the "original" pin state after it has already been affected by another ScrollTrigger.
1145        if (pinSpacer) {
1146          pinSpacer = _getTarget(pinSpacer);
1147          pinSpacer && !pinSpacer.nodeType && (pinSpacer = pinSpacer.current || pinSpacer.nativeElement); // for React & Angular
1148
1149          pinCache.spacerIsNative = !!pinSpacer;
1150          pinSpacer && (pinCache.spacerState = _getState(pinSpacer));
1151        }
1152
1153        pinCache.spacer = spacer = pinSpacer || _doc.createElement("div");
1154        spacer.classList.add("pin-spacer");
1155        id && spacer.classList.add("pin-spacer-" + id);
1156        pinCache.pinState = pinOriginalState = _getState(pin);
1157      } else {
1158        pinOriginalState = pinCache.pinState;
1159      }
1160
1161      vars.force3D !== false && gsap.set(pin, {
1162        force3D: true
1163      });
1164      self.spacer = spacer = pinCache.spacer;
1165      cs = _getComputedStyle(pin);
1166      spacingStart = cs[pinSpacing + direction.os2];
1167      pinGetter = gsap.getProperty(pin);
1168      pinSetter = gsap.quickSetter(pin, direction.a, _px); // pin.firstChild && !_maxScroll(pin, direction) && (pin.style.overflow = "hidden"); // protects from collapsing margins, but can have unintended consequences as demonstrated here: https://codepen.io/GreenSock/pen/1e42c7a73bfa409d2cf1e184e7a4248d so it was removed in favor of just telling people to set up their CSS to avoid the collapsing margins (overflow: hidden | auto is just one option. Another is border-top: 1px solid transparent).
1169
1170      _swapPinIn(pin, spacer, cs);
1171
1172      pinState = _getState(pin);
1173    }
1174
1175    if (markers) {
1176      markerVars = _isObject(markers) ? _setDefaults(markers, _markerDefaults) : _markerDefaults;
1177      markerStartTrigger = _createMarker("scroller-start", id, scroller, direction, markerVars, 0);
1178      markerEndTrigger = _createMarker("scroller-end", id, scroller, direction, markerVars, 0, markerStartTrigger);
1179      offset = markerStartTrigger["offset" + direction.op.d2];
1180
1181      var content = _getTarget(_getProxyProp(scroller, "content") || scroller);
1182
1183      markerStart = this.markerStart = _createMarker("start", id, content, direction, markerVars, offset, 0, containerAnimation);
1184      markerEnd = this.markerEnd = _createMarker("end", id, content, direction, markerVars, offset, 0, containerAnimation);
1185      containerAnimation && (caMarkerSetter = gsap.quickSetter([markerStart, markerEnd], direction.a, _px));
1186
1187      if (!useFixedPosition && !(_proxies.length && _getProxyProp(scroller, "fixedMarkers") === true)) {
1188        _makePositionable(isViewport ? _body : scroller);
1189
1190        gsap.set([markerStartTrigger, markerEndTrigger], {
1191          force3D: true
1192        });
1193        markerStartSetter = gsap.quickSetter(markerStartTrigger, direction.a, _px);
1194        markerEndSetter = gsap.quickSetter(markerEndTrigger, direction.a, _px);
1195      }
1196    }
1197
1198    if (containerAnimation) {
vendor: 7,204 bytes, lines 1199-1348
1199      var oldOnUpdate = containerAnimation.vars.onUpdate,
1200          oldParams = containerAnimation.vars.onUpdateParams;
1201      containerAnimation.eventCallback("onUpdate", function () {
1202        self.update(0, 0, 1);
1203        oldOnUpdate && oldOnUpdate.apply(containerAnimation, oldParams || []);
1204      });
1205    }
1206
1207    self.previous = function () {
1208      return _triggers[_triggers.indexOf(self) - 1];
1209    };
1210
1211    self.next = function () {
1212      return _triggers[_triggers.indexOf(self) + 1];
1213    };
1214
1215    self.revert = function (revert, temp) {
1216      if (!temp) {
1217        return self.kill(true);
1218      } // for compatibility with gsap.context() and gsap.matchMedia() which call revert()
1219
1220
1221      var r = revert !== false || !self.enabled,
1222          prevRefreshing = _refreshing;
1223
1224      if (r !== self.isReverted) {
1225        if (r) {
1226          prevScroll = Math.max(scrollFunc(), self.scroll.rec || 0); // record the scroll so we can revert later (repositioning/pinning things can affect scroll position). In the static refresh() method, we first record all the scroll positions as a reference.
1227
1228          prevProgress = self.progress;
1229          prevAnimProgress = animation && animation.progress();
1230        }
1231
1232        markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) {
1233          return m.style.display = r ? "none" : "block";
1234        });
1235
1236        if (r) {
1237          _refreshing = self;
1238          self.update(r); // make sure the pin is back in its original position so that all the measurements are correct. do this BEFORE swapping the pin out
1239        }
1240
1241        if (pin && (!pinReparent || !self.isActive)) {
1242          if (r) {
1243            _swapPinOut(pin, spacer, pinOriginalState);
1244          } else {
1245            _swapPinIn(pin, spacer, _getComputedStyle(pin), spacerState);
1246          }
1247        }
1248
1249        r || self.update(r); // when we're restoring, the update should run AFTER swapping the pin into its pin-spacer.
1250
1251        _refreshing = prevRefreshing; // restore. We set it to true during the update() so that things fire properly in there.
1252
1253        self.isReverted = r;
1254      }
1255    };
1256
1257    self.refresh = function (soft, force, position, pinOffset) {
1258      // position is typically only defined if it's coming from setPositions() - it's a way to skip the normal parsing. pinOffset is also only from setPositions() and is mostly related to fancy stuff we need to do in ScrollSmoother with effects
1259      if ((_refreshing || !self.enabled) && !force) {
1260        return;
1261      }
1262
1263      if (pin && soft && _lastScrollTime) {
1264        _addListener(ScrollTrigger, "scrollEnd", _softRefresh);
1265
1266        return;
1267      }
1268
1269      !_refreshingAll && onRefreshInit && onRefreshInit(self);
1270      _refreshing = self;
1271
1272      if (tweenTo.tween && !position) {
1273        // we skip this if a position is passed in because typically that's from .setPositions() and it's best to allow in-progress snapping to continue.
1274        tweenTo.tween.kill();
1275        tweenTo.tween = 0;
1276      }
1277
1278      scrubTween && scrubTween.pause();
1279      invalidateOnRefresh && animation && animation.revert({
1280        kill: false
1281      }).invalidate();
1282      self.isReverted || self.revert(true, true);
1283      self._subPinOffset = false; // we'll set this to true in the sub-pins if we find any
1284
1285      var size = getScrollerSize(),
1286          scrollerBounds = getScrollerOffsets(),
1287          max = containerAnimation ? containerAnimation.duration() : _maxScroll(scroller, direction),
1288          isFirstRefresh = change <= 0.01,
1289          offset = 0,
1290          otherPinOffset = pinOffset || 0,
1291          parsedEnd = _isObject(position) ? position.end : vars.end,
1292          parsedEndTrigger = vars.endTrigger || trigger,
1293          parsedStart = _isObject(position) ? position.start : vars.start || (vars.start === 0 || !trigger ? 0 : pin ? "0 0" : "0 100%"),
1294          pinnedContainer = self.pinnedContainer = vars.pinnedContainer && _getTarget(vars.pinnedContainer, self),
1295          triggerIndex = trigger && Math.max(0, _triggers.indexOf(self)) || 0,
1296          i = triggerIndex,
1297          cs,
1298          bounds,
1299          scroll,
1300          isVertical,
1301          override,
1302          curTrigger,
1303          curPin,
1304          oppositeScroll,
1305          initted,
1306          revertedPins,
1307          forcedOverflow,
1308          markerStartOffset,
1309          markerEndOffset;
1310
1311      if (markers && _isObject(position)) {
1312        // if we alter the start/end positions with .setPositions(), it generally feeds in absolute NUMBERS which don't convey information about where to line up the markers, so to keep it intuitive, we record how far the trigger positions shift after applying the new numbers and then offset by that much in the opposite direction. We do the same to the associated trigger markers too of course.
1313        markerStartOffset = gsap.getProperty(markerStartTrigger, direction.p);
1314        markerEndOffset = gsap.getProperty(markerEndTrigger, direction.p);
1315      }
1316
1317      while (i--) {
1318        // user might try to pin the same element more than once, so we must find any prior triggers with the same pin, revert them, and determine how long they're pinning so that we can offset things appropriately. Make sure we revert from last to first so that things "rewind" properly.
1319        curTrigger = _triggers[i];
1320        curTrigger.end || curTrigger.refresh(0, 1) || (_refreshing = self); // if it's a timeline-based trigger that hasn't been fully initialized yet because it's waiting for 1 tick, just force the refresh() here, otherwise if it contains a pin that's supposed to affect other ScrollTriggers further down the page, they won't be adjusted properly.
1321
1322        curPin = curTrigger.pin;
1323
1324        if (curPin && (curPin === trigger || curPin === pin || curPin === pinnedContainer) && !curTrigger.isReverted) {
1325          revertedPins || (revertedPins = []);
1326          revertedPins.unshift(curTrigger); // we'll revert from first to last to make sure things reach their end state properly
1327
1328          curTrigger.revert(true, true);
1329        }
1330
1331        if (curTrigger !== _triggers[i]) {
1332          // in case it got removed.
1333          triggerIndex--;
1334          i--;
1335        }
1336      }
1337
1338      _isFunction(parsedStart) && (parsedStart = parsedStart(self));
1339      parsedStart = _parseClamp(parsedStart, "start", self);
1340      start = _parsePosition(parsedStart, trigger, size, direction, scrollFunc(), markerStart, markerStartTrigger, self, scrollerBounds, borderWidth, useFixedPosition, max, containerAnimation, self._startClamp && "_startClamp") || (pin ? -0.001 : 0);
1341      _isFunction(parsedEnd) && (parsedEnd = parsedEnd(self));
1342
1343      if (_isString(parsedEnd) && !parsedEnd.indexOf("+=")) {
1344        if (~parsedEnd.indexOf(" ")) {
1345          parsedEnd = (_isString(parsedStart) ? parsedStart.split(" ")[0] : "") + parsedEnd;
1346        } else {
1347          offset = _offsetToPx(parsedEnd.substr(2), size);
1348          parsedEnd = _isString(parsedStart) ? parsedStart : (containerAnimation ? gsap.utils.mapRange(0, containerAnimation.duration(), containerAnimation.scrollTrigger.start, containerAnimation.scrollTrigger.end, start) : start) + offset; // _parsePosition won't factor in the offset if the start is a 
vendor: 4,317 bytes, lines 1348-1438
1348number, so do it here.
1349
1350          parsedEndTrigger = trigger;
1351        }
1352      }
1353
1354      parsedEnd = _parseClamp(parsedEnd, "end", self);
1355      end = Math.max(start, _parsePosition(parsedEnd || (parsedEndTrigger ? "100% 0" : max), parsedEndTrigger, size, direction, scrollFunc() + offset, markerEnd, markerEndTrigger, self, scrollerBounds, borderWidth, useFixedPosition, max, containerAnimation, self._endClamp && "_endClamp")) || -0.001;
1356      offset = 0;
1357      i = triggerIndex;
1358
1359      while (i--) {
1360        curTrigger = _triggers[i];
1361        curPin = curTrigger.pin;
1362
1363        if (curPin && curTrigger.start - curTrigger._pinPush <= start && !containerAnimation && curTrigger.end > 0) {
1364          cs = curTrigger.end - (self._startClamp ? Math.max(0, curTrigger.start) : curTrigger.start);
1365
1366          if ((curPin === trigger && curTrigger.start - curTrigger._pinPush < start || curPin === pinnedContainer) && isNaN(parsedStart)) {
1367            // numeric start values shouldn't be offset at all - treat them as absolute
1368            offset += cs * (1 - curTrigger.progress);
1369          }
1370
1371          curPin === pin && (otherPinOffset += cs);
1372        }
1373      }
1374
1375      start += offset;
1376      end += offset;
1377      self._startClamp && (self._startClamp += offset);
1378
1379      if (self._endClamp && !_refreshingAll) {
1380        self._endClamp = end || -0.001;
1381        end = Math.min(end, _maxScroll(scroller, direction));
1382      }
1383
1384      change = end - start || (start -= 0.01) && 0.001;
1385
1386      if (isFirstRefresh) {
1387        // on the very first refresh(), the prevProgress couldn't have been accurate yet because the start/end were never calculated, so we set it here. Before 3.11.5, it could lead to an inaccurate scroll position restoration with snapping.
1388        prevProgress = gsap.utils.clamp(0, 1, gsap.utils.normalize(start, end, prevScroll));
1389      }
1390
1391      self._pinPush = otherPinOffset;
1392
1393      if (markerStart && offset) {
1394        // offset the markers if necessary
1395        cs = {};
1396        cs[direction.a] = "+=" + offset;
1397        pinnedContainer && (cs[direction.p] = "-=" + scrollFunc());
1398        gsap.set([markerStart, markerEnd], cs);
1399      }
1400
1401      if (pin) {
1402        cs = _getComputedStyle(pin);
1403        isVertical = direction === _vertical;
1404        scroll = scrollFunc(); // recalculate because the triggers can affect the scroll
1405
1406        pinStart = parseFloat(pinGetter(direction.a)) + otherPinOffset;
1407
1408        if (!max && end > 1) {
1409          // makes sure the scroller has a scrollbar, otherwise if something has width: 100%, for example, it would be too big (exclude the scrollbar). See https://greensock.com/forums/topic/25182-scrolltrigger-width-of-page-increase-where-markers-are-set-to-false/
1410          forcedOverflow = (isViewport ? _doc.scrollingElement || _docEl : scroller).style;
1411          forcedOverflow = {
1412            style: forcedOverflow,
1413            value: forcedOverflow["overflow" + direction.a.toUpperCase()]
1414          };
1415
1416          if (isViewport && _getComputedStyle(_body)["overflow" + direction.a.toUpperCase()] !== "scroll") {
1417            // avoid an extra scrollbar if BOTH <html> and <body> have overflow set to "scroll"
1418            forcedOverflow.style["overflow" + direction.a.toUpperCase()] = "scroll";
1419          }
1420        }
1421
1422        _swapPinIn(pin, spacer, cs);
1423
1424        pinState = _getState(pin); // transforms will interfere with the top/left/right/bottom placement, so remove them temporarily. getBoundingClientRect() factors in transforms.
1425
1426        bounds = _getBounds(pin, true);
1427        oppositeScroll = useFixedPosition && _getScrollFunc(scroller, isVertical ? _horizontal : _vertical)();
1428
1429        if (pinSpacing) {
1430          spacerState = [pinSpacing + direction.os2, change + otherPinOffset + _px];
1431          spacerState.t = spacer;
1432          i = pinSpacing === _padding ? _getSize(pin, direction) + change + otherPinOffset : 0;
1433          i && spacerState.push(direction.d, i + _px); // for box-sizing: border-box (must include padding).
1434
1435          _setState(spacerState);
1436
1437          if (pinnedContainer) {
1438            // in ScrollTrigger.refresh(), we need to re-evaluate the pinContainer's size because this pinSpacing may stretch it out, but we can't just add the exact distance because depending on layout, it may not push things down or it may only do so partially.
vendor: 5,553 bytes, lines 1439-1537
1439            _triggers.forEach(function (t) {
1440              if (t.pin === pinnedContainer && t.vars.pinSpacing !== false) {
1441                t._subPinOffset = true;
1442              }
1443            });
1444          }
1445
1446          useFixedPosition && scrollFunc(prevScroll);
1447        }
1448
1449        if (useFixedPosition) {
1450          override = {
1451            top: bounds.top + (isVertical ? scroll - start : oppositeScroll) + _px,
1452            left: bounds.left + (isVertical ? oppositeScroll : scroll - start) + _px,
1453            boxSizing: "border-box",
1454            position: "fixed"
1455          };
1456          override[_width] = override["max" + _Width] = Math.ceil(bounds.width) + _px;
1457          override[_height] = override["max" + _Height] = Math.ceil(bounds.height) + _px;
1458          override[_margin] = override[_margin + _Top] = override[_margin + _Right] = override[_margin + _Bottom] = override[_margin + _Left] = "0";
1459          override[_padding] = cs[_padding];
1460          override[_padding + _Top] = cs[_padding + _Top];
1461          override[_padding + _Right] = cs[_padding + _Right];
1462          override[_padding + _Bottom] = cs[_padding + _Bottom];
1463          override[_padding + _Left] = cs[_padding + _Left];
1464          pinActiveState = _copyState(pinOriginalState, override, pinReparent);
1465          _refreshingAll && scrollFunc(0);
1466        }
1467
1468        if (animation) {
1469          // the animation might be affecting the transform, so we must jump to the end, check the value, and compensate accordingly. Otherwise, when it becomes unpinned, the pinSetter() will get set to a value that doesn't include whatever the animation did.
1470          initted = animation._initted; // if not, we must invalidate() after this step, otherwise it could lock in starting values prematurely.
1471
1472          _suppressOverwrites(1);
1473
1474          animation.render(animation.duration(), true, true);
1475          pinChange = pinGetter(direction.a) - pinStart + change + otherPinOffset;
1476          pinMoves = Math.abs(change - pinChange) > 1;
1477          useFixedPosition && pinMoves && pinActiveState.splice(pinActiveState.length - 2, 2); // transform is the last property/value set in the state Array. Since the animation is controlling that, we should omit it.
1478
1479          animation.render(0, true, true);
1480          initted || animation.invalidate(true);
1481          animation.parent || animation.totalTime(animation.totalTime()); // if, for example, a toggleAction called play() and then refresh() happens and when we render(1) above, it would cause the animation to complete and get removed from its parent, so this makes sure it gets put back in.
1482
1483          _suppressOverwrites(0);
1484        } else {
1485          pinChange = change;
1486        }
1487
1488        forcedOverflow && (forcedOverflow.value ? forcedOverflow.style["overflow" + direction.a.toUpperCase()] = forcedOverflow.value : forcedOverflow.style.removeProperty("overflow-" + direction.a));
1489      } else if (trigger && scrollFunc() && !containerAnimation) {
1490        // it may be INSIDE a pinned element, so walk up the tree and look for any elements with _pinOffset to compensate because anything with pinSpacing that's already scrolled would throw off the measurements in getBoundingClientRect()
1491        bounds = trigger.parentNode;
1492
1493        while (bounds && bounds !== _body) {
1494          if (bounds._pinOffset) {
1495            start -= bounds._pinOffset;
1496            end -= bounds._pinOffset;
1497          }
1498
1499          bounds = bounds.parentNode;
1500        }
1501      }
1502
1503      revertedPins && revertedPins.forEach(function (t) {
1504        return t.revert(false, true);
1505      });
1506      self.start = start;
1507      self.end = end;
1508      scroll1 = scroll2 = _refreshingAll ? prevScroll : scrollFunc(); // reset velocity
1509
1510      if (!containerAnimation && !_refreshingAll) {
1511        scroll1 < prevScroll && scrollFunc(prevScroll);
1512        self.scroll.rec = 0;
1513      }
1514
1515      self.revert(false, true);
1516      lastRefresh = _getTime();
1517
1518      if (snapDelayedCall) {
1519        lastSnap = -1; // just so snapping gets re-enabled, clear out any recorded last value
1520        // self.isActive && scrollFunc(start + change * prevProgress); // previously this line was here to ensure that when snapping kicks in, it's from the previous progress but in some cases that's not desirable, like an all-page ScrollTrigger when new content gets added to the page, that'd totally change the progress.
1521
1522        snapDelayedCall.restart(true);
1523      }
1524
1525      _refreshing = 0;
1526      animation && isToggle && (animation._initted || prevAnimProgress) && animation.progress() !== prevAnimProgress && animation.progress(prevAnimProgress || 0, true).render(animation.time(), true, true); // must force a re-render because if saveStyles() was used on the target(s), the styles could have been wiped out during the refresh().
1527
1528      if (isFirstRefresh || prevProgress !== self.progress || containerAnimation) {
1529        // ensures that the direction is set properly (when refreshing, progress is set back to 0 initially, then back again to wherever it needs to be) and that callbacks are triggered.
1530        animation && !isToggle && animation.totalProgress(containerAnimation && start < -0.001 && !prevProgress ? gsap.utils.normalize(start, end, 0) : prevProgress, true); // to avoid issues where animation callbacks like onStart aren't triggered.
1531
1532        self.progress = isFirstRefresh || (scroll1 - start) / change === prevProgress ? 0 : prevProgress;
1533      }
1534
1535      pin && pinSpacing && (spacer._pinOffset = Math.round(self.progress * pinChange));
1536      scrubTween && scrubTween.invalidate();
1537
vendor: 4,238 bytes, lines 1538-1623
1538      if (!isNaN(markerStartOffset)) {
1539        // numbers were passed in for the position which are absolute, so instead of just putting the markers at the very bottom of the viewport, we figure out how far they shifted down (it's safe to assume they were originally positioned in closer relation to the trigger element with values like "top", "center", a percentage or whatever, so we offset that much in the opposite direction to basically revert them to the relative position thy were at previously.
1540        markerStartOffset -= gsap.getProperty(markerStartTrigger, direction.p);
1541        markerEndOffset -= gsap.getProperty(markerEndTrigger, direction.p);
1542
1543        _shiftMarker(markerStartTrigger, direction, markerStartOffset);
1544
1545        _shiftMarker(markerStart, direction, markerStartOffset - (pinOffset || 0));
1546
1547        _shiftMarker(markerEndTrigger, direction, markerEndOffset);
1548
1549        _shiftMarker(markerEnd, direction, markerEndOffset - (pinOffset || 0));
1550      }
1551
1552      isFirstRefresh && !_refreshingAll && self.update(); // edge case - when you reload a page when it's already scrolled down, some browsers fire a "scroll" event before DOMContentLoaded, triggering an updateAll(). If we don't update the self.progress as part of refresh(), then when it happens next, it may record prevProgress as 0 when it really shouldn't, potentially causing a callback in an animation to fire again.
1553
1554      if (onRefresh && !_refreshingAll && !executingOnRefresh) {
1555        // when refreshing all, we do extra work to correct pinnedContainer sizes and ensure things don't exceed the maxScroll, so we should do all the refreshes at the end after all that work so that the start/end values are corrected.
1556        executingOnRefresh = true;
1557        onRefresh(self);
1558        executingOnRefresh = false;
1559      }
1560    };
1561
1562    self.getVelocity = function () {
1563      return (scrollFunc() - scroll2) / (_getTime() - _time2) * 1000 || 0;
1564    };
1565
1566    self.endAnimation = function () {
1567      _endAnimation(self.callbackAnimation);
1568
1569      if (animation) {
1570        scrubTween ? scrubTween.progress(1) : !animation.paused() ? _endAnimation(animation, animation.reversed()) : isToggle || _endAnimation(animation, self.direction < 0, 1);
1571      }
1572    };
1573
1574    self.labelToScroll = function (label) {
1575      return animation && animation.labels && (start || self.refresh() || start) + animation.labels[label] / animation.duration() * change || 0;
1576    };
1577
1578    self.getTrailing = function (name) {
1579      var i = _triggers.indexOf(self),
1580          a = self.direction > 0 ? _triggers.slice(0, i).reverse() : _triggers.slice(i + 1);
1581
1582      return (_isString(name) ? a.filter(function (t) {
1583        return t.vars.preventOverlaps === name;
1584      }) : a).filter(function (t) {
1585        return self.direction > 0 ? t.end <= start : t.start >= end;
1586      });
1587    };
1588
1589    self.update = function (reset, recordVelocity, forceFake) {
1590      if (containerAnimation && !forceFake && !reset) {
1591        return;
1592      }
1593
1594      var scroll = _refreshingAll === true ? prevScroll : self.scroll(),
1595          p = reset ? 0 : (scroll - start) / change,
1596          clipped = p < 0 ? 0 : p > 1 ? 1 : p || 0,
1597          prevProgress = self.progress,
1598          isActive,
1599          wasActive,
1600          toggleState,
1601          action,
1602          stateChanged,
1603          toggled,
1604          isAtMax,
1605          isTakingAction;
1606
1607      if (recordVelocity) {
1608        scroll2 = scroll1;
1609        scroll1 = containerAnimation ? scrollFunc() : scroll;
1610
1611        if (snap) {
1612          snap2 = snap1;
1613          snap1 = animation && !isToggle ? animation.totalProgress() : clipped;
1614        }
1615      } // anticipate the pinning a few ticks ahead of time based on velocity to avoid a visual glitch due to the fact that most browsers do scrolling on a separate thread (not synced with requestAnimationFrame).
1616
1617
1618      anticipatePin && !clipped && pin && !_refreshing && !_startup && _lastScrollTime && start < scroll + (scroll - scroll2) / (_getTime() - _time2) * anticipatePin && (clipped = 0.0001);
1619
1620      if (clipped !== prevProgress && self.enabled) {
1621        isActive = self.isActive = !!clipped && clipped < 1;
1622        wasActive = !!prevProgress && prevProgress < 1;
1623        toggled = isActive !== wasActive;
vendor: 5,594 bytes, lines 1624-1721
1624        stateChanged = toggled || !!clipped !== !!prevProgress; // could go from start all the way to end, thus it didn't toggle but it did change state in a sense (may need to fire a callback)
1625
1626        self.direction = clipped > prevProgress ? 1 : -1;
1627        self.progress = clipped;
1628
1629        if (stateChanged && !_refreshing) {
1630          toggleState = clipped && !prevProgress ? 0 : clipped === 1 ? 1 : prevProgress === 1 ? 2 : 3; // 0 = enter, 1 = leave, 2 = enterBack, 3 = leaveBack (we prioritize the FIRST encounter, thus if you scroll really fast past the onEnter and onLeave in one tick, it'd prioritize onEnter.
1631
1632          if (isToggle) {
1633            action = !toggled && toggleActions[toggleState + 1] !== "none" && toggleActions[toggleState + 1] || toggleActions[toggleState]; // if it didn't toggle, that means it shot right past and since we prioritize the "enter" action, we should switch to the "leave" in this case (but only if one is defined)
1634
1635            isTakingAction = animation && (action === "complete" || action === "reset" || action in animation);
1636          }
1637        }
1638
1639        preventOverlaps && (toggled || isTakingAction) && (isTakingAction || scrub || !animation) && (_isFunction(preventOverlaps) ? preventOverlaps(self) : self.getTrailing(preventOverlaps).forEach(function (t) {
1640          return t.endAnimation();
1641        }));
1642
1643        if (!isToggle) {
1644          if (scrubTween && !_refreshing && !_startup) {
1645            scrubTween._dp._time - scrubTween._start !== scrubTween._time && scrubTween.render(scrubTween._dp._time - scrubTween._start); // if there's a scrub on both the container animation and this one (or a ScrollSmoother), the update order would cause this one not to have rendered yet, so it wouldn't make any progress before we .restart() it heading toward the new progress so it'd appear stuck thus we force a render here.
1646
1647            if (scrubTween.resetTo) {
1648              scrubTween.resetTo("totalProgress", clipped, animation._tTime / animation._tDur);
1649            } else {
1650              // legacy support (courtesy), before 3.10.0
1651              scrubTween.vars.totalProgress = clipped;
1652              scrubTween.invalidate().restart();
1653            }
1654          } else if (animation) {
1655            animation.totalProgress(clipped, !!(_refreshing && (lastRefresh || reset)));
1656          }
1657        }
1658
1659        if (pin) {
1660          reset && pinSpacing && (spacer.style[pinSpacing + direction.os2] = spacingStart);
1661
1662          if (!useFixedPosition) {
1663            pinSetter(_round(pinStart + pinChange * clipped));
1664          } else if (stateChanged) {
1665            isAtMax = !reset && clipped > prevProgress && end + 1 > scroll && scroll + 1 >= _maxScroll(scroller, direction); // if it's at the VERY end of the page, don't switch away from position: fixed because it's pointless and it could cause a brief flash when the user scrolls back up (when it gets pinned again)
1666
1667            if (pinReparent) {
1668              if (!reset && (isActive || isAtMax)) {
1669                var bounds = _getBounds(pin, true),
1670                    _offset = scroll - start;
1671
1672                _reparent(pin, _body, bounds.top + (direction === _vertical ? _offset : 0) + _px, bounds.left + (direction === _vertical ? 0 : _offset) + _px);
1673              } else {
1674                _reparent(pin, spacer);
1675              }
1676            }
1677
1678            _setState(isActive || isAtMax ? pinActiveState : pinState);
1679
1680            pinMoves && clipped < 1 && isActive || pinSetter(pinStart + (clipped === 1 && !isAtMax ? pinChange : 0));
1681          }
1682        }
1683
1684        snap && !tweenTo.tween && !_refreshing && !_startup && snapDelayedCall.restart(true);
1685        toggleClass && (toggled || once && clipped && (clipped < 1 || !_limitCallbacks)) && _toArray(toggleClass.targets).forEach(function (el) {
1686          return el.classList[isActive || once ? "add" : "remove"](toggleClass.className);
1687        }); // classes could affect positioning, so do it even if reset or refreshing is true.
1688
1689        onUpdate && !isToggle && !reset && onUpdate(self);
1690
1691        if (stateChanged && !_refreshing) {
1692          if (isToggle) {
1693            if (isTakingAction) {
1694              if (action === "complete") {
1695                animation.pause().totalProgress(1);
1696              } else if (action === "reset") {
1697                animation.restart(true).pause();
1698              } else if (action === "restart") {
1699                animation.restart(true);
1700              } else {
1701                animation[action]();
1702              }
1703            }
1704
1705            onUpdate && onUpdate(self);
1706          }
1707
1708          if (toggled || !_limitCallbacks) {
1709            // on startup, the page could be scrolled and we don't want to fire callbacks that didn't toggle. For example onEnter shouldn't fire if the ScrollTrigger isn't actually entered.
1710            onToggle && toggled && _callback(self, onToggle);
1711            callbacks[toggleState] && _callback(self, callbacks[toggleState]);
1712            once && (clipped === 1 ? self.kill(false, 1) : callbacks[toggleState] = 0); // a callback shouldn't be called again if once is true.
1713
1714            if (!toggled) {
1715              // it's possible to go completely past, like from before the start to after the end (or vice-versa) in which case BOTH callbacks should be fired in that order
1716              toggleState = clipped === 1 ? 1 : 3;
1717              callbacks[toggleState] && _callback(self, callbacks[toggleState]);
1718            }
1719          }
1720
1721          if (fastScrollEnd && !isActive && Math.abs(self.getVelocity()) > (_isNumber(fastScrollEnd) ? fastScrollEnd : 2500)) {
vendor: 4,133 bytes, lines 1722-1831
1722            _endAnimation(self.callbackAnimation);
1723
1724            scrubTween ? scrubTween.progress(1) : _endAnimation(animation, action === "reverse" ? 1 : !clipped, 1);
1725          }
1726        } else if (isToggle && onUpdate && !_refreshing) {
1727          onUpdate(self);
1728        }
1729      } // update absolutely-positioned markers (only if the scroller isn't the viewport)
1730
1731
1732      if (markerEndSetter) {
1733        var n = containerAnimation ? scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0) : scroll;
1734        markerStartSetter(n + (markerStartTrigger._isFlipped ? 1 : 0));
1735        markerEndSetter(n);
1736      }
1737
1738      caMarkerSetter && caMarkerSetter(-scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0));
1739    };
1740
1741    self.enable = function (reset, refresh) {
1742      if (!self.enabled) {
1743        self.enabled = true;
1744
1745        _addListener(scroller, "resize", _onResize);
1746
1747        isViewport || _addListener(scroller, "scroll", _onScroll);
1748        onRefreshInit && _addListener(ScrollTrigger, "refreshInit", onRefreshInit);
1749
1750        if (reset !== false) {
1751          self.progress = prevProgress = 0;
1752          scroll1 = scroll2 = lastSnap = scrollFunc();
1753        }
1754
1755        refresh !== false && self.refresh();
1756      }
1757    };
1758
1759    self.getTween = function (snap) {
1760      return snap && tweenTo ? tweenTo.tween : scrubTween;
1761    };
1762
1763    self.setPositions = function (newStart, newEnd, keepClamp, pinOffset) {
1764      // doesn't persist after refresh()! Intended to be a way to override values that were set during refresh(), like you could set it in onRefresh()
1765      if (containerAnimation) {
1766        // convert ratios into scroll positions. Remember, start/end values on ScrollTriggers that have a containerAnimation refer to the time (in seconds), NOT scroll positions.
1767        var st = containerAnimation.scrollTrigger,
1768            duration = containerAnimation.duration(),
1769            _change = st.end - st.start;
1770
1771        newStart = st.start + _change * newStart / duration;
1772        newEnd = st.start + _change * newEnd / duration;
1773      }
1774
1775      self.refresh(false, false, {
1776        start: _keepClamp(newStart, keepClamp && !!self._startClamp),
1777        end: _keepClamp(newEnd, keepClamp && !!self._endClamp)
1778      }, pinOffset);
1779      self.update();
1780    };
1781
1782    self.adjustPinSpacing = function (amount) {
1783      if (spacerState && amount) {
1784        var i = spacerState.indexOf(direction.d) + 1;
1785        spacerState[i] = parseFloat(spacerState[i]) + amount + _px;
1786        spacerState[1] = parseFloat(spacerState[1]) + amount + _px;
1787
1788        _setState(spacerState);
1789      }
1790    };
1791
1792    self.disable = function (reset, allowAnimation) {
1793      if (self.enabled) {
1794        reset !== false && self.revert(true, true);
1795        self.enabled = self.isActive = false;
1796        allowAnimation || scrubTween && scrubTween.pause();
1797        prevScroll = 0;
1798        pinCache && (pinCache.uncache = 1);
1799        onRefreshInit && _removeListener(ScrollTrigger, "refreshInit", onRefreshInit);
1800
1801        if (snapDelayedCall) {
1802          snapDelayedCall.pause();
1803          tweenTo.tween && tweenTo.tween.kill() && (tweenTo.tween = 0);
1804        }
1805
1806        if (!isViewport) {
1807          var i = _triggers.length;
1808
1809          while (i--) {
1810            if (_triggers[i].scroller === scroller && _triggers[i] !== self) {
1811              return; //don't remove the listeners if there are still other triggers referencing it.
1812            }
1813          }
1814
1815          _removeListener(scroller, "resize", _onResize);
1816
1817          isViewport || _removeListener(scroller, "scroll", _onScroll);
1818        }
1819      }
1820    };
1821
1822    self.kill = function (revert, allowAnimation) {
1823      self.disable(revert, allowAnimation);
1824      scrubTween && !allowAnimation && scrubTween.kill();
1825      id && delete _ids[id];
1826
1827      var i = _triggers.indexOf(self);
1828
1829      i >= 0 && _triggers.splice(i, 1);
1830      i === _i && _direction > 0 && _i--; // if we're in the middle of a refresh() or update(), splicing would cause skips in the index, so adjust...
1831      // if no other ScrollTrigger instances of the same scroller are found, wipe out any re
vendor: 4,816 bytes, lines 1831-1961
1831corded scroll position. Otherwise, in a single page application, for example, it could maintain scroll position when it really shouldn't.
1832
1833      i = 0;
1834
1835      _triggers.forEach(function (t) {
1836        return t.scroller === self.scroller && (i = 1);
1837      });
1838
1839      i || _refreshingAll || (self.scroll.rec = 0);
1840
1841      if (animation) {
1842        animation.scrollTrigger = null;
1843        revert && animation.revert({
1844          kill: false
1845        });
1846        allowAnimation || animation.kill();
1847      }
1848
1849      markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) {
1850        return m.parentNode && m.parentNode.removeChild(m);
1851      });
1852      _primary === self && (_primary = 0);
1853
1854      if (pin) {
1855        pinCache && (pinCache.uncache = 1);
1856        i = 0;
1857
1858        _triggers.forEach(function (t) {
1859          return t.pin === pin && i++;
1860        });
1861
1862        i || (pinCache.spacer = 0); // if there aren't any more ScrollTriggers with the same pin, remove the spacer, otherwise it could be contaminated with old/stale values if the user re-creates a ScrollTrigger for the same element.
1863      }
1864
1865      vars.onKill && vars.onKill(self);
1866    };
1867
1868    _triggers.push(self);
1869
1870    self.enable(false, false);
1871    customRevertReturn && customRevertReturn(self);
1872
1873    if (animation && animation.add && !change) {
1874      // if the animation is a timeline, it may not have been populated yet, so it wouldn't render at the proper place on the first refresh(), thus we should schedule one for the next tick. If "change" is defined, we know it must be re-enabling, thus we can refresh() right away.
1875      var updateFunc = self.update; // some browsers may fire a scroll event BEFORE a tick elapses and/or the DOMContentLoaded fires. So there's a chance update() will be called BEFORE a refresh() has happened on a Timeline-attached ScrollTrigger which means the start/end won't be calculated yet. We don't want to add conditional logic inside the update() method (like check to see if end is defined and if not, force a refresh()) because that's a function that gets hit a LOT (performance). So we swap out the real update() method for this one that'll re-attach it the first time it gets called and of course forces a refresh().
1876
1877      self.update = function () {
1878        self.update = updateFunc;
1879        start || end || self.refresh();
1880      };
1881
1882      gsap.delayedCall(0.01, self.update);
1883      change = 0.01;
1884      start = end = 0;
1885    } else {
1886      self.refresh();
1887    }
1888
1889    pin && _queueRefreshAll(); // pinning could affect the positions of other things, so make sure we queue a full refresh()
1890  };
1891
1892  ScrollTrigger.register = function register(core) {
1893    if (!_coreInitted) {
1894      gsap = core || _getGSAP();
1895      _windowExists() && window.document && ScrollTrigger.enable();
1896      _coreInitted = _enabled;
1897    }
1898
1899    return _coreInitted;
1900  };
1901
1902  ScrollTrigger.defaults = function defaults(config) {
1903    if (config) {
1904      for (var p in config) {
1905        _defaults[p] = config[p];
1906      }
1907    }
1908
1909    return _defaults;
1910  };
1911
1912  ScrollTrigger.disable = function disable(reset, kill) {
1913    _enabled = 0;
1914
1915    _triggers.forEach(function (trigger) {
1916      return trigger[kill ? "kill" : "disable"](reset);
1917    });
1918
1919    _removeListener(_win, "wheel", _onScroll);
1920
1921    _removeListener(_doc, "scroll", _onScroll);
1922
1923    clearInterval(_syncInterval);
1924
1925    _removeListener(_doc, "touchcancel", _passThrough);
1926
1927    _removeListener(_body, "touchstart", _passThrough);
1928
1929    _multiListener(_removeListener, _doc, "pointerdown,touchstart,mousedown", _pointerDownHandler);
1930
1931    _multiListener(_removeListener, _doc, "pointerup,touchend,mouseup", _pointerUpHandler);
1932
1933    _resizeDelay.kill();
1934
1935    _iterateAutoRefresh(_removeListener);
1936
1937    for (var i = 0; i < _scrollers.length; i += 3) {
1938      _wheelListener(_removeListener, _scrollers[i], _scrollers[i + 1]);
1939
1940      _wheelListener(_removeListener, _scrollers[i], _scrollers[i + 2]);
1941    }
1942  };
1943
1944  ScrollTrigger.enable = function enable() {
1945    _win = window;
1946    _doc = document;
1947    _docEl = _doc.documentElement;
1948    _body = _doc.body;
1949
1950    if (gsap) {
1951      _toArray = gsap.utils.toArray;
1952      _clamp = gsap.utils.clamp;
1953      _context = gsap.core.context || _passThrough;
1954      _suppressOverwrites = gsap.core.suppressOverwrites || _passThrough;
1955      _scrollRestoration = _win.history.scrollRestoration || "auto";
1956      _lastScroll = _win.pageYOffset;
1957      gsap.core.globals("ScrollTrigger", ScrollTrigger); // must register the global manually because in Internet Explorer, functions (classes) don't have a "name" property.
1958
1959      if (_body) {
1960        _enabled = 1;
1961        _div100vh = document.createElement("div"); // to solve mobile browser address bar show/hide resizing, we shouldn't rely on window.innerHeight. Instead, use a <div>
vendor: 4,791 bytes, lines 1961-2071
1961 with its height set to 100vh and measure that since that's what the scrolling is based on anyway and it's not affected by address bar showing/hiding.
1962
1963        _div100vh.style.height = "100vh";
1964        _div100vh.style.position = "absolute";
1965
1966        _refresh100vh();
1967
1968        _rafBugFix();
1969
1970        Observer.register(gsap); // isTouch is 0 if no touch, 1 if ONLY touch, and 2 if it can accommodate touch but also other types like mouse/pointer.
1971
1972        ScrollTrigger.isTouch = Observer.isTouch;
1973        _fixIOSBug = Observer.isTouch && /(iPad|iPhone|iPod|Mac)/g.test(navigator.userAgent); // since 2017, iOS has had a bug that causes event.clientX/Y to be inaccurate when a scroll occurs, thus we must alternate ignoring every other touchmove event to work around it. See https://bugs.webkit.org/show_bug.cgi?id=181954 and https://codepen.io/GreenSock/pen/ExbrPNa/087cef197dc35445a0951e8935c41503
1974
1975        _addListener(_win, "wheel", _onScroll); // mostly for 3rd party smooth scrolling libraries.
1976
1977
1978        _root = [_win, _doc, _docEl, _body];
1979
1980        if (gsap.matchMedia) {
1981          ScrollTrigger.matchMedia = function (vars) {
1982            var mm = gsap.matchMedia(),
1983                p;
1984
1985            for (p in vars) {
1986              mm.add(p, vars[p]);
1987            }
1988
1989            return mm;
1990          };
1991
1992          gsap.addEventListener("matchMediaInit", function () {
1993            return _revertAll();
1994          });
1995          gsap.addEventListener("matchMediaRevert", function () {
1996            return _revertRecorded();
1997          });
1998          gsap.addEventListener("matchMedia", function () {
1999            _refreshAll(0, 1);
2000
2001            _dispatch("matchMedia");
2002          });
2003          gsap.matchMedia("(orientation: portrait)", function () {
2004            // when orientation changes, we should take new base measurements for the ignoreMobileResize feature.
2005            _setBaseDimensions();
2006
2007            return _setBaseDimensions;
2008          });
2009        } else {
2010          console.warn("Requires GSAP 3.11.0 or later");
2011        }
2012
2013        _setBaseDimensions();
2014
2015        _addListener(_doc, "scroll", _onScroll); // some browsers (like Chrome), the window stops dispatching scroll events on the window if you scroll really fast, but it's consistent on the document!
2016
2017
2018        var bodyStyle = _body.style,
2019            border = bodyStyle.borderTopStyle,
2020            AnimationProto = gsap.core.Animation.prototype,
2021            bounds,
2022            i;
2023        AnimationProto.revert || Object.defineProperty(AnimationProto, "revert", {
2024          value: function value() {
2025            return this.time(-0.01, true);
2026          }
2027        }); // only for backwards compatibility (Animation.revert() was added after 3.10.4)
2028
2029        bodyStyle.borderTopStyle = "solid"; // works around an issue where a margin of a child element could throw off the bounds of the _body, making it seem like there's a margin when there actually isn't. The border ensures that the bounds are accurate.
2030
2031        bounds = _getBounds(_body);
2032        _vertical.m = Math.round(bounds.top + _vertical.sc()) || 0; // accommodate the offset of the <body> caused by margins and/or padding
2033
2034        _horizontal.m = Math.round(bounds.left + _horizontal.sc()) || 0;
2035        border ? bodyStyle.borderTopStyle = border : bodyStyle.removeProperty("border-top-style"); // TODO: (?) maybe move to leveraging the velocity mechanism in Observer and skip intervals.
2036
2037        _syncInterval = setInterval(_sync, 250);
2038        gsap.delayedCall(0.5, function () {
2039          return _startup = 0;
2040        });
2041
2042        _addListener(_doc, "touchcancel", _passThrough); // some older Android devices intermittently stop dispatching "touchmove" events if we don't listen for "touchcancel" on the document.
2043
2044
2045        _addListener(_body, "touchstart", _passThrough); //works around Safari bug: https://greensock.com/forums/topic/21450-draggable-in-iframe-on-mobile-is-buggy/
2046
2047
2048        _multiListener(_addListener, _doc, "pointerdown,touchstart,mousedown", _pointerDownHandler);
2049
2050        _multiListener(_addListener, _doc, "pointerup,touchend,mouseup", _pointerUpHandler);
2051
2052        _transformProp = gsap.utils.checkPrefix("transform");
2053
2054        _stateProps.push(_transformProp);
2055
2056        _coreInitted = _getTime();
2057        _resizeDelay = gsap.delayedCall(0.2, _refreshAll).pause();
2058        _autoRefresh = [_doc, "visibilitychange", function () {
2059          var w = _win.innerWidth,
2060              h = _win.innerHeight;
2061
2062          if (_doc.hidden) {
2063            _prevWidth = w;
2064            _prevHeight = h;
2065          } else if (_prevWidth !== w || _prevHeight !== h) {
2066            _onResize();
2067          }
2068        }, _doc, "DOMContentLoaded", _refreshAll, _win, "load", _refreshAll, _win, "resize", _onResize];
2069
2070        _iterateAutoRefresh(_addListener);
2071
vendor: 3,769 bytes, lines 2072-2171
2072        _triggers.forEach(function (trigger) {
2073          return trigger.enable(0, 1);
2074        });
2075
2076        for (i = 0; i < _scrollers.length; i += 3) {
2077          _wheelListener(_removeListener, _scrollers[i], _scrollers[i + 1]);
2078
2079          _wheelListener(_removeListener, _scrollers[i], _scrollers[i + 2]);
2080        }
2081      }
2082    }
2083  };
2084
2085  ScrollTrigger.config = function config(vars) {
2086    "limitCallbacks" in vars && (_limitCallbacks = !!vars.limitCallbacks);
2087    var ms = vars.syncInterval;
2088    ms && clearInterval(_syncInterval) || (_syncInterval = ms) && setInterval(_sync, ms);
2089    "ignoreMobileResize" in vars && (_ignoreMobileResize = ScrollTrigger.isTouch === 1 && vars.ignoreMobileResize);
2090
2091    if ("autoRefreshEvents" in vars) {
2092      _iterateAutoRefresh(_removeListener) || _iterateAutoRefresh(_addListener, vars.autoRefreshEvents || "none");
2093      _ignoreResize = (vars.autoRefreshEvents + "").indexOf("resize") === -1;
2094    }
2095  };
2096
2097  ScrollTrigger.scrollerProxy = function scrollerProxy(target, vars) {
2098    var t = _getTarget(target),
2099        i = _scrollers.indexOf(t),
2100        isViewport = _isViewport(t);
2101
2102    if (~i) {
2103      _scrollers.splice(i, isViewport ? 6 : 2);
2104    }
2105
2106    if (vars) {
2107      isViewport ? _proxies.unshift(_win, vars, _body, vars, _docEl, vars) : _proxies.unshift(t, vars);
2108    }
2109  };
2110
2111  ScrollTrigger.clearMatchMedia = function clearMatchMedia(query) {
2112    _triggers.forEach(function (t) {
2113      return t._ctx && t._ctx.query === query && t._ctx.kill(true, true);
2114    });
2115  };
2116
2117  ScrollTrigger.isInViewport = function isInViewport(element, ratio, horizontal) {
2118    var bounds = (_isString(element) ? _getTarget(element) : element).getBoundingClientRect(),
2119        offset = bounds[horizontal ? _width : _height] * ratio || 0;
2120    return horizontal ? bounds.right - offset > 0 && bounds.left + offset < _win.innerWidth : bounds.bottom - offset > 0 && bounds.top + offset < _win.innerHeight;
2121  };
2122
2123  ScrollTrigger.positionInViewport = function positionInViewport(element, referencePoint, horizontal) {
2124    _isString(element) && (element = _getTarget(element));
2125    var bounds = element.getBoundingClientRect(),
2126        size = bounds[horizontal ? _width : _height],
2127        offset = referencePoint == null ? size / 2 : referencePoint in _keywords ? _keywords[referencePoint] * size : ~referencePoint.indexOf("%") ? parseFloat(referencePoint) * size / 100 : parseFloat(referencePoint) || 0;
2128    return horizontal ? (bounds.left + offset) / _win.innerWidth : (bounds.top + offset) / _win.innerHeight;
2129  };
2130
2131  ScrollTrigger.killAll = function killAll(allowListeners) {
2132    _triggers.slice(0).forEach(function (t) {
2133      return t.vars.id !== "ScrollSmoother" && t.kill();
2134    });
2135
2136    if (allowListeners !== true) {
2137      var listeners = _listeners.killAll || [];
2138      _listeners = {};
2139      listeners.forEach(function (f) {
2140        return f();
2141      });
2142    }
2143  };
2144
2145  return ScrollTrigger;
2146}();
2147ScrollTrigger.version = "3.12.2";
2148
2149ScrollTrigger.saveStyles = function (targets) {
2150  return targets ? _toArray(targets).forEach(function (target) {
2151    // saved styles are recorded in a consecutive alternating Array, like [element, cssText, transform attribute, cache, matchMedia, ...]
2152    if (target && target.style) {
2153      var i = _savedStyles.indexOf(target);
2154
2155      i >= 0 && _savedStyles.splice(i, 5);
2156
2157      _savedStyles.push(target, target.style.cssText, target.getBBox && target.getAttribute("transform"), gsap.core.getCache(target), _context());
2158    }
2159  }) : _savedStyles;
2160};
2161
2162ScrollTrigger.revert = function (soft, media) {
2163  return _revertAll(!soft, media);
2164};
2165
2166ScrollTrigger.create = function (vars, animation) {
2167  return new ScrollTrigger(vars, animation);
2168};
2169
2170ScrollTrigger.refresh = function (safe) {
2171  return safe ? _onResize(
vendor: 13,931 bytes, lines 2171-2544
2171) : (_coreInitted || ScrollTrigger.register()) && _refreshAll(true);
2172};
2173
2174ScrollTrigger.update = function (force) {
2175  return ++_scrollers.cache && _updateAll(force === true ? 2 : 0);
2176};
2177
2178ScrollTrigger.clearScrollMemory = _clearScrollMemory;
2179
2180ScrollTrigger.maxScroll = function (element, horizontal) {
2181  return _maxScroll(element, horizontal ? _horizontal : _vertical);
2182};
2183
2184ScrollTrigger.getScrollFunc = function (element, horizontal) {
2185  return _getScrollFunc(_getTarget(element), horizontal ? _horizontal : _vertical);
2186};
2187
2188ScrollTrigger.getById = function (id) {
2189  return _ids[id];
2190};
2191
2192ScrollTrigger.getAll = function () {
2193  return _triggers.filter(function (t) {
2194    return t.vars.id !== "ScrollSmoother";
2195  });
2196}; // it's common for people to ScrollTrigger.getAll(t => t.kill()) on page routes, for example, and we don't want it to ruin smooth scrolling by killing the main ScrollSmoother one.
2197
2198
2199ScrollTrigger.isScrolling = function () {
2200  return !!_lastScrollTime;
2201};
2202
2203ScrollTrigger.snapDirectional = _snapDirectional;
2204
2205ScrollTrigger.addEventListener = function (type, callback) {
2206  var a = _listeners[type] || (_listeners[type] = []);
2207  ~a.indexOf(callback) || a.push(callback);
2208};
2209
2210ScrollTrigger.removeEventListener = function (type, callback) {
2211  var a = _listeners[type],
2212      i = a && a.indexOf(callback);
2213  i >= 0 && a.splice(i, 1);
2214};
2215
2216ScrollTrigger.batch = function (targets, vars) {
2217  var result = [],
2218      varsCopy = {},
2219      interval = vars.interval || 0.016,
2220      batchMax = vars.batchMax || 1e9,
2221      proxyCallback = function proxyCallback(type, callback) {
2222    var elements = [],
2223        triggers = [],
2224        delay = gsap.delayedCall(interval, function () {
2225      callback(elements, triggers);
2226      elements = [];
2227      triggers = [];
2228    }).pause();
2229    return function (self) {
2230      elements.length || delay.restart(true);
2231      elements.push(self.trigger);
2232      triggers.push(self);
2233      batchMax <= elements.length && delay.progress(1);
2234    };
2235  },
2236      p;
2237
2238  for (p in vars) {
2239    varsCopy[p] = p.substr(0, 2) === "on" && _isFunction(vars[p]) && p !== "onRefreshInit" ? proxyCallback(p, vars[p]) : vars[p];
2240  }
2241
2242  if (_isFunction(batchMax)) {
2243    batchMax = batchMax();
2244
2245    _addListener(ScrollTrigger, "refresh", function () {
2246      return batchMax = vars.batchMax();
2247    });
2248  }
2249
2250  _toArray(targets).forEach(function (target) {
2251    var config = {};
2252
2253    for (p in varsCopy) {
2254      config[p] = varsCopy[p];
2255    }
2256
2257    config.trigger = target;
2258    result.push(ScrollTrigger.create(config));
2259  });
2260
2261  return result;
2262}; // to reduce file size. clamps the scroll and also returns a duration multiplier so that if the scroll gets chopped shorter, the duration gets curtailed as well (otherwise if you're very close to the top of the page, for example, and swipe up really fast, it'll suddenly slow down and take a long time to reach the top).
2263
2264
2265var _clampScrollAndGetDurationMultiplier = function _clampScrollAndGetDurationMultiplier(scrollFunc, current, end, max) {
2266  current > max ? scrollFunc(max) : current < 0 && scrollFunc(0);
2267  return end > max ? (max - current) / (end - current) : end < 0 ? current / (current - end) : 1;
2268},
2269    _allowNativePanning = function _allowNativePanning(target, direction) {
2270  if (direction === true) {
2271    target.style.removeProperty("touch-action");
2272  } else {
2273    target.style.touchAction = direction === true ? "auto" : direction ? "pan-" + direction + (Observer.isTouch ? " pinch-zoom" : "") : "none"; // note: Firefox doesn't support it pinch-zoom properly, at least in addition to a pan-x or pan-y.
2274  }
2275
2276  target === _docEl && _allowNativePanning(_body, direction);
2277},
2278    _overflow = {
2279  auto: 1,
2280  scroll: 1
2281},
2282    _nestedScroll = function _nestedScroll(_ref5) {
2283  var event = _ref5.event,
2284      target = _ref5.target,
2285      axis = _ref5.axis;
2286
2287  var node = (event.changedTouches ? event.changedTouches[0] : event).target,
2288      cache = node._gsap || gsap.core.getCache(node),
2289      time = _getTime(),
2290      cs;
2291
2292  if (!cache._isScrollT || time - cache._isScrollT > 2000) {
2293    // cache for 2 seconds to improve performance.
2294    while (node && node !== _body && (node.scrollHeight <= node.clientHeight && node.scrollWidth <= node.clientWidth || !(_overflow[(cs = _getComputedStyle(node)).overflowY] || _overflow[cs.overflowX]))) {
2295      node = node.parentNode;
2296    }
2297
2298    cache._isScroll = node && node !== target && !_isViewport(node) && (_overflow[(cs = _getComputedStyle(node)).overflowY] || _overflow[cs.overflowX]);
2299    cache._isScrollT = time;
2300  }
2301
2302  if (cache._isScroll || axis === "x") {
2303    event.stopPropagation();
2304    event._gsapAllow = true;
2305  }
2306},
2307    // capture events on scrollable elements INSIDE the <body> and allow those by calling stopPropagation() when we find a scrollable ancestor
2308_inputObserver = function _inputObserver(target, type, inputs, nested) {
2309  return Observer.create({
2310    target: target,
2311    capture: true,
2312    debounce: false,
2313    lockAxis: true,
2314    type: type,
2315    onWheel: nested = nested && _nestedScroll,
2316    onPress: nested,
2317    onDrag: nested,
2318    onScroll: nested,
2319    onEnable: function onEnable() {
2320      return inputs && _addListener(_doc, Observer.eventTypes[0], _captureInputs, false, true);
2321    },
2322    onDisable: function onDisable() {
2323      return _removeListener(_doc, Observer.eventTypes[0], _captureInputs, true);
2324    }
2325  });
2326},
2327    _inputExp = /(input|label|select|textarea)/i,
2328    _inputIsFocused,
2329    _captureInputs = function _captureInputs(e) {
2330  var isInput = _inputExp.test(e.target.tagName);
2331
2332  if (isInput || _inputIsFocused) {
2333    e._gsapAllow = true;
2334    _inputIsFocused = isInput;
2335  }
2336},
2337    _getScrollNormalizer = function _getScrollNormalizer(vars) {
2338  _isObject(vars) || (vars = {});
2339  vars.preventDefault = vars.isNormalizer = vars.allowClicks = true;
2340  vars.type || (vars.type = "wheel,touch");
2341  vars.debounce = !!vars.debounce;
2342  vars.id = vars.id || "normalizer";
2343
2344  var _vars2 = vars,
2345      normalizeScrollX = _vars2.normalizeScrollX,
2346      momentum = _vars2.momentum,
2347      allowNestedScroll = _vars2.allowNestedScroll,
2348      onRelease = _vars2.onRelease,
2349      self,
2350      maxY,
2351      target = _getTarget(vars.target) || _docEl,
2352      smoother = gsap.core.globals().ScrollSmoother,
2353      smootherInstance = smoother && smoother.get(),
2354      content = _fixIOSBug && (vars.content && _getTarget(vars.content) || smootherInstance && vars.content !== false && !smootherInstance.smooth() && smootherInstance.content()),
2355      scrollFuncY = _getScrollFunc(target, _vertical),
2356      scrollFuncX = _getScrollFunc(target, _horizontal),
2357      scale = 1,
2358      initialScale = (Observer.isTouch && _win.visualViewport ? _win.visualViewport.scale * _win.visualViewport.width : _win.outerWidth) / _win.innerWidth,
2359      wheelRefresh = 0,
2360      resolveMomentumDuration = _isFunction(momentum) ? function () {
2361    return momentum(self);
2362  } : function () {
2363    return momentum || 2.8;
2364  },
2365      lastRefreshID,
2366      skipTouchMove,
2367      inputObserver = _inputObserver(target, vars.type, true, allowNestedScroll),
2368      resumeTouchMove = function resumeTouchMove() {
2369    return skipTouchMove = false;
2370  },
2371      scrollClampX = _passThrough,
2372      scrollClampY = _passThrough,
2373      updateClamps = function updateClamps() {
2374    maxY = _maxScroll(target, _vertical);
2375    scrollClampY = _clamp(_fixIOSBug ? 1 : 0, maxY);
2376    normalizeScrollX && (scrollClampX = _clamp(0, _maxScroll(target, _horizontal)));
2377    lastRefreshID = _refreshID;
2378  },
2379      removeContentOffset = function removeContentOffset() {
2380    content._gsap.y = _round(parseFloat(content._gsap.y) + scrollFuncY.offset) + "px";
2381    content.style.transform = "matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, " + parseFloat(content._gsap.y) + ", 0, 1)";
2382    scrollFuncY.offset = scrollFuncY.cacheID = 0;
2383  },
2384      ignoreDrag = function ignoreDrag() {
2385    if (skipTouchMove) {
2386      requestAnimationFrame(resumeTouchMove);
2387
2388      var offset = _round(self.deltaY / 2),
2389          scroll = scrollClampY(scrollFuncY.v - offset);
2390
2391      if (content && scroll !== scrollFuncY.v + scrollFuncY.offset) {
2392        scrollFuncY.offset = scroll - scrollFuncY.v;
2393
2394        var y = _round((parseFloat(content && content._gsap.y) || 0) - scrollFuncY.offset);
2395
2396        content.style.transform = "matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, " + y + ", 0, 1)";
2397        content._gsap.y = y + "px";
2398        scrollFuncY.cacheID = _scrollers.cache;
2399
2400        _updateAll();
2401      }
2402
2403      return true;
2404    }
2405
2406    scrollFuncY.offset && removeContentOffset();
2407    skipTouchMove = true;
2408  },
2409      tween,
2410      startScrollX,
2411      startScrollY,
2412      onStopDelayedCall,
2413      onResize = function onResize() {
2414    // if the window resizes, like on an iPhone which Apple FORCES the address bar to show/hide even if we event.preventDefault(), it may be scrolling too far now that the address bar is showing, so we must dynamically adjust the momentum tween.
2415    updateClamps();
2416
2417    if (tween.isActive() && tween.vars.scrollY > maxY) {
2418      scrollFuncY() > maxY ? tween.progress(1) && scrollFuncY(maxY) : tween.resetTo("scrollY", maxY);
2419    }
2420  };
2421
2422  content && gsap.set(content, {
2423    y: "+=0"
2424  }); // to ensure there's a cache (element._gsap)
2425
2426  vars.ignoreCheck = function (e) {
2427    return _fixIOSBug && e.type === "touchmove" && ignoreDrag(e) || scale > 1.05 && e.type !== "touchstart" || self.isGesturing || e.touches && e.touches.length > 1;
2428  };
2429
2430  vars.onPress = function () {
2431    skipTouchMove = false;
2432    var prevScale = scale;
2433    scale = _round((_win.visualViewport && _win.visualViewport.scale || 1) / initialScale);
2434    tween.pause();
2435    prevScale !== scale && _allowNativePanning(target, scale > 1.01 ? true : normalizeScrollX ? false : "x");
2436    startScrollX = scrollFuncX();
2437    startScrollY = scrollFuncY();
2438    updateClamps();
2439    lastRefreshID = _refreshID;
2440  };
2441
2442  vars.onRelease = vars.onGestureStart = function (self, wasDragging) {
2443    scrollFuncY.offset && removeContentOffset();
2444
2445    if (!wasDragging) {
2446      onStopDelayedCall.restart(true);
2447    } else {
2448      _scrollers.cache++; // make sure we're pulling the non-cached value
2449      // alternate algorithm: durX = Math.min(6, Math.abs(self.velocityX / 800)),	dur = Math.max(durX, Math.min(6, Math.abs(self.velocityY / 800))); dur = dur * (0.4 + (1 - _power4In(dur / 6)) * 0.6)) * (momentumSpeed || 1)
2450
2451      var dur = resolveMomentumDuration(),
2452          currentScroll,
2453          endScroll;
2454
2455      if (normalizeScrollX) {
2456        currentScroll = scrollFuncX();
2457        endScroll = currentScroll + dur * 0.05 * -self.velocityX / 0.227; // the constant .227 is from power4(0.05). velocity is inverted because scrolling goes in the opposite direction.
2458
2459        dur *= _clampScrollAndGetDurationMultiplier(scrollFuncX, currentScroll, endScroll, _maxScroll(target, _horizontal));
2460        tween.vars.scrollX = scrollClampX(endScroll);
2461      }
2462
2463      currentScroll = scrollFuncY();
2464      endScroll = currentScroll + dur * 0.05 * -self.velocityY / 0.227; // the constant .227 is from power4(0.05)
2465
2466      dur *= _clampScrollAndGetDurationMultiplier(scrollFuncY, currentScroll, endScroll, _maxScroll(target, _vertical));
2467      tween.vars.scrollY = scrollClampY(endScroll);
2468      tween.invalidate().duration(dur).play(0.01);
2469
2470      if (_fixIOSBug && tween.vars.scrollY >= maxY || currentScroll >= maxY - 1) {
2471        // iOS bug: it'll show the address bar but NOT fire the window "resize" event until the animation is done but we must protect against overshoot so we leverage an onUpdate to do so.
2472        gsap.to({}, {
2473          onUpdate: onResize,
2474          duration: dur
2475        });
2476      }
2477    }
2478
2479    onRelease && onRelease(self);
2480  };
2481
2482  vars.onWheel = function () {
2483    tween._ts && tween.pause();
2484
2485    if (_getTime() - wheelRefresh > 1000) {
2486      // after 1 second, refresh the clamps otherwise that'll only happen when ScrollTrigger.refresh() is called or for touch-scrolling.
2487      lastRefreshID = 0;
2488      wheelRefresh = _getTime();
2489    }
2490  };
2491
2492  vars.onChange = function (self, dx, dy, xArray, yArray) {
2493    _refreshID !== lastRefreshID && updateClamps();
2494    dx && normalizeScrollX && scrollFuncX(scrollClampX(xArray[2] === dx ? startScrollX + (self.startX - self.x) : scrollFuncX() + dx - xArray[1])); // for more precision, we track pointer/touch movement from the start, otherwise it'll drift.
2495
2496    if (dy) {
2497      scrollFuncY.offset && removeContentOffset();
2498      var isTouch = yArray[2] === dy,
2499          y = isTouch ? startScrollY + self.startY - self.y : scrollFuncY() + dy - yArray[1],
2500          yClamped = scrollClampY(y);
2501      isTouch && y !== yClamped && (startScrollY += yClamped - y);
2502      scrollFuncY(yClamped);
2503    }
2504
2505    (dy || dx) && _updateAll();
2506  };
2507
2508  vars.onEnable = function () {
2509    _allowNativePanning(target, normalizeScrollX ? false : "x");
2510
2511    ScrollTrigger.addEventListener("refresh", onResize);
2512
2513    _addListener(_win, "resize", onResize);
2514
2515    if (scrollFuncY.smooth) {
2516      scrollFuncY.target.style.scrollBehavior = "auto";
2517      scrollFuncY.smooth = scrollFuncX.smooth = false;
2518    }
2519
2520    inputObserver.enable();
2521  };
2522
2523  vars.onDisable = function () {
2524    _allowNativePanning(target, true);
2525
2526    _removeListener(_win, "resize", onResize);
2527
2528    ScrollTrigger.removeEventListener("refresh", onResize);
2529    inputObserver.kill();
2530  };
2531
2532  vars.lockAxis = vars.lockAxis !== false;
2533  self = new Observer(vars);
2534  self.iOS = _fixIOSBug; // used in the Observer getCachedScroll() function to work around an iOS bug that wreaks havoc with TouchEvent.clientY if we allow scroll to go all the way back to 0.
2535
2536  _fixIOSBug && !scrollFuncY() && scrollFuncY(1); // iOS bug causes event.clientY values to freak out (wildly inaccurate) if the scroll position is exactly 0.
2537
2538  _fixIOSBug && gsap.ticker.add(_passThrough); // prevent the ticker from sleeping
2539
2540  onStopDelayedCall = self._dc;
2541  tween = gsap.to(self, {
2542    ease: "power4",
2543    paused: true,
2544    
2544scrollX: normalizeScrollX ? "+=0.1" : "+=0",
2545    scrollY: "+=0.1",
2546    modifiers: {
2547      scrollY: _interruptionTracker(scrollFuncY, scrollFuncY(), function () {
2548        return tween.pause();
2549      })
2550    },
2551    onUpdate: _updateAll,
2552    onComplete: onStopDelayedCall.vars.onComplete
2553  }); // we need the modifier to sense if the scroll position is altered outside of the momentum tween (like with a scrollTo tween) so we can pause() it to prevent conflicts.
2554
2555  return self;
2556};
2557
2558ScrollTrigger.sort = function (func) {
2559  return _triggers.sort(func || function (a, b) {
2560    return (a.vars.refreshPriority || 0) * -1e6 + a.start - (b.start + (b.vars.refreshPriority || 0) * -1e6);
2561  });
2562};
2563
2564ScrollTrigger.observe = function (vars) {
2565  return new Observer(vars);
2566};
2567
2568ScrollTrigger.normalizeScroll = function (vars) {
2569  if (typeof vars === "undefined") {
2570    return _normalizer;
2571  }
2572
2573  if (vars === true && _normalizer) {
2574    return _normalizer.enable();
2575  }
2576
2577  if (vars === false) {
2578    return _normalizer && _normalizer.kill();
2579  }
2580
2581  var normalizer = vars instanceof Observer ? vars : _getScrollNormalizer(vars);
2582  _normalizer && _normalizer.target === normalizer.target && _normalizer.kill();
2583  _isViewport(normalizer.target) && (_normalizer = normalizer);
2584  return normalizer;
2585};
2586
2587ScrollTrigger.core = {
2588  // smaller file size way to leverage in ScrollSmoother and Observer
2589  _getVelocityProp: _getVelocityProp,
2590  _inputObserver: _inputObserver,
2591  _scrollers: _scrollers,
2592  _proxies: _proxies,
2593  bridge: {
2594    // when normalizeScroll sets the scroll position (ss = setScroll)
2595    ss: function ss() {
2596      _lastScrollTime || _dispatch("scrollStart");
2597      _lastScrollTime = _getTime();
2598    },
2599    // a way to get the _refreshing value in Observer
2600    ref: function ref() {
2601      return _refreshing;
2602    }
2603  }
2604};
2605_getGSAP() && gsap.registerPlugin(ScrollTrigger);
2606export { ScrollTrigger as default };

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.