├── .DS_Store ├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── css └── base.css ├── favicon.ico ├── img ├── .DS_Store ├── 1.jpg ├── 10.jpg ├── 11.jpg ├── 12.jpg ├── 13.jpg ├── 2.jpg ├── 3.jpg ├── 4.jpg ├── 5.jpg ├── 6.jpg ├── 7.jpg ├── 8.jpg ├── 9.jpg ├── main.jpg └── noise.png ├── index.html └── js ├── .DS_Store ├── Flip.min.js ├── ScrollTrigger.min.js ├── gsap.min.js ├── imagesloaded.pkgd.min.js ├── index.js ├── lenis.min.js ├── smoothscroll.js └── utils.js /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/OneElementScroll/feb7ad7fbc602b8cdbb5109da83442ff5995cdaf/.DS_Store -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .cache 3 | .parcel-cache 4 | package-lock.json -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2009 - 2024 [Codrops](https://tympanus.net/codrops) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Consecutive Scroll Animations with One Element 2 | 3 | A simple concept of animating one element across different waypoints on scroll using GSAP Flip and ScrollTrigger. 4 | 5 | ![Image Title](https://tympanus.net/codrops/wp-content/uploads/2024/11/OneElementScroll.jpg) 6 | 7 | [Article on Codrops](https://tympanus.net/codrops/?p=82884) 8 | 9 | [Demo](https://tympanus.net/Development/OneElementScroll/) 10 | 11 | ## Installation 12 | 13 | Run this demo on a [local server](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/Tools_and_setup/set_up_a_local_testing_server). 14 | 15 | ## Credits 16 | 17 | - Images generated with [Midjourney](https://midjourney.com) 18 | 19 | ## Misc 20 | 21 | Follow Codrops: [Bluesky](https://bsky.app/profile/codrops.bsky.social), [Facebook](http://www.facebook.com/codrops), [GitHub](https://github.com/codrops), [Instagram](https://www.instagram.com/codropsss/), [X](http://www.x.com/codrops) 22 | 23 | ## License 24 | [MIT](LICENSE) 25 | 26 | Made with :blue_heart: by [Codrops](http://www.codrops.com) 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /css/base.css: -------------------------------------------------------------------------------- 1 | *, 2 | *::after, 3 | *::before { 4 | box-sizing: border-box; 5 | } 6 | 7 | :root { 8 | font-size: 16px; 9 | --color-text: #503717; 10 | --color-bg: rgb(234 234 234); 11 | --color-link: #b19162; 12 | --color-link-hover: #e1c093; 13 | --color-title: #000; 14 | --page-padding: 2rem; 15 | --gradient-1: rgb(234 234 234 / 80%); 16 | --gradient-2: rgb(229 134 27 / 30%); 17 | } 18 | 19 | body { 20 | margin: 0; 21 | color: var(--color-text); 22 | background-color: var(--color-bg); 23 | font-family: "capitana", sans-serif; 24 | -webkit-font-smoothing: antialiased; 25 | -moz-osx-font-smoothing: grayscale; 26 | width: 100vw; 27 | overflow-x: hidden; 28 | background-image: url(../img/noise.png), radial-gradient(ellipse at top, var(--gradient-1), transparent), radial-gradient(ellipse at bottom, var(--gradient-2), transparent); 29 | background-size: 180px, 100%, 200%; 30 | background-attachment: fixed; 31 | } 32 | 33 | .font-alt { 34 | font-family: "harpagan", sans-serif; 35 | font-weight: 500; 36 | } 37 | 38 | .outro__title, 39 | .credits { 40 | font-size: clamp(1rem,5vw,3rem); 41 | text-transform: uppercase; 42 | text-align: center; 43 | margin: 50vh auto 0; 44 | padding-bottom: 10vh; 45 | } 46 | 47 | .js .loading:before,.js .loading:after { 48 | content: ""; 49 | position: fixed; 50 | z-index: 10000 51 | } 52 | 53 | .js .loading:before { 54 | top: 0; 55 | left: 0; 56 | width: 100%; 57 | height: 100%; 58 | background: var(--color-bg) 59 | } 60 | 61 | .js .loading:after { 62 | top: 50%; 63 | left: 50%; 64 | width: 100px; 65 | height: 1px; 66 | margin: 0 0 0 -50px; 67 | background: var(--color-link); 68 | animation: loaderAnim 1.5s ease-in-out infinite alternate forwards 69 | } 70 | 71 | @keyframes loaderAnim { 72 | 0% { 73 | transform: scaleX(0); 74 | transform-origin: 0% 50% 75 | } 76 | 77 | 50% { 78 | transform: scaleX(1); 79 | transform-origin: 0% 50% 80 | } 81 | 82 | 50.1% { 83 | transform: scaleX(1); 84 | transform-origin: 100% 50% 85 | } 86 | 87 | to { 88 | transform: scaleX(0); 89 | transform-origin: 100% 50% 90 | } 91 | } 92 | 93 | a { 94 | text-decoration: none; 95 | color: var(--color-link); 96 | outline: none; 97 | cursor: pointer; 98 | } 99 | 100 | a:hover { 101 | color: var(--color-link-hover); 102 | outline: none; 103 | } 104 | 105 | /* Better focus styles from https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible */ 106 | a:focus { 107 | /* Provide a fallback style for browsers 108 | that don't support :focus-visible */ 109 | outline: none; 110 | background: lightgrey; 111 | } 112 | 113 | a:focus:not(:focus-visible) { 114 | /* Remove the focus indicator on mouse-focus for browsers 115 | that do support :focus-visible */ 116 | background: transparent; 117 | } 118 | 119 | a:focus-visible { 120 | /* Draw a very noticeable focus style for 121 | keyboard-focus on browsers that do support 122 | :focus-visible */ 123 | outline: 2px solid red; 124 | background: transparent; 125 | } 126 | 127 | main { 128 | position: relative; 129 | overflow: hidden; 130 | width: 100vw; 131 | } 132 | 133 | .unbutton { 134 | background: none; 135 | border: 0; 136 | padding: 0; 137 | margin: 0; 138 | font: inherit; 139 | cursor: pointer; 140 | } 141 | 142 | .unbutton:focus { 143 | outline: none; 144 | } 145 | 146 | .frame { 147 | position: fixed; 148 | margin: 10px; 149 | top: 0; 150 | left: 0; 151 | right: 0; 152 | display: grid; 153 | z-index: 6000; 154 | grid-template-columns: 100%; 155 | grid-template-areas: 'title' 'wrap' 'sponsor'; 156 | justify-items: start; 157 | align-items: start; 158 | } 159 | 160 | .font-cap { 161 | text-transform: uppercase; 162 | font-size: 10px; 163 | } 164 | 165 | .frame__title { 166 | grid-area: title; 167 | font-size: inherit; 168 | margin: 0; 169 | font-weight: inherit; 170 | padding: 5px 0; 171 | } 172 | 173 | .frame-wrap { 174 | max-width: 22rem; 175 | grid-area: wrap; 176 | justify-self: start; 177 | display: flex; 178 | flex-wrap: wrap; 179 | column-gap: 1rem; 180 | padding: 5px 13px; 181 | border-radius: 2rem; 182 | background: #000; 183 | } 184 | 185 | .frame #cdawrap { 186 | opacity: 1; 187 | padding: 5px 0; 188 | transition: opacity 0.3s 1s linear; 189 | max-width: 300px; 190 | } 191 | 192 | .frame #cdawrap a { 193 | color: var(--color-text) !important; 194 | } 195 | 196 | .loading .frame #cdawrap { 197 | opacity: 0; 198 | } 199 | 200 | .tags { 201 | display: flex; 202 | flex-wrap: wrap; 203 | gap: 1rem; 204 | align-self: start; 205 | } 206 | 207 | .content { 208 | display: grid; 209 | align-items: center; 210 | justify-content: center; 211 | width: 100%; 212 | height: 100vh; 213 | grid-template-columns: 1fr; 214 | grid-template-rows: auto; 215 | grid-template-areas: 'content'; 216 | position: relative; 217 | z-index: 90; 218 | } 219 | 220 | .content--blend { 221 | mix-blend-mode: overlay; 222 | } 223 | 224 | .content--center { 225 | height: 100vh; 226 | text-align: center; 227 | justify-items: center; 228 | display: grid; 229 | gap: 1.5rem; 230 | align-content: center; 231 | position: relative; 232 | } 233 | 234 | .content--column { 235 | grid-template-columns: repeat(5,1fr); 236 | grid-template-areas: unset; 237 | gap: 2rem; 238 | max-width: 1400px; 239 | margin: 0 auto 20vh; 240 | z-index: 80; 241 | justify-items: center; 242 | } 243 | 244 | .content--grid { 245 | grid-template-columns: repeat(3,1fr); 246 | grid-template-rows: repeat(3,1fr); 247 | grid-template-areas: unset; 248 | width: 120%; 249 | height: 100vh; 250 | left: -10%; 251 | gap: 1rem; 252 | margin: 0 auto; 253 | } 254 | 255 | .content--grid .content__img { 256 | width: 100%; 257 | height: 100%; 258 | } 259 | 260 | .content__title { 261 | grid-area: content; 262 | margin: 0; 263 | line-height: .9; 264 | margin: 0; 265 | text-transform: uppercase; 266 | font-size: clamp(3rem,19vw,8rem); 267 | max-width: 1000px; 268 | color: var(--color-title); 269 | } 270 | 271 | .content__title span { 272 | display: inline-block; 273 | } 274 | 275 | .content__title--medium { 276 | line-height: 1.1; 277 | max-width: none; 278 | font-size: clamp(2rem,12vw,6rem); 279 | } 280 | 281 | .content__text { 282 | grid-area: content; 283 | padding: var(--page-padding); 284 | margin: 0 auto; 285 | font-size: 1rem; 286 | font-weight: 400; 287 | position: relative; 288 | max-width: 500px; 289 | } 290 | 291 | .content__text--large { 292 | font-size: clamp(1rem,4vw,2rem); 293 | max-width: none; 294 | } 295 | 296 | .one { 297 | width: 100%; 298 | height: 100%; 299 | position: relative; 300 | z-index: 10; 301 | background-size: cover; 302 | background-position: 50% 50%; 303 | will-change: transform, width, height, filter; 304 | } 305 | 306 | .content__img { 307 | background-size: cover; 308 | background-position: 50% 50%; 309 | will-change: transform, filter, opacity; 310 | } 311 | 312 | .content--sides { 313 | display: grid; 314 | grid-template-columns: 1fr; 315 | grid-template-areas: 'img' 'content'; 316 | } 317 | 318 | .content--sides .content__img { 319 | grid-area: img; 320 | height: 50vh; 321 | } 322 | 323 | .content--center .content__img { 324 | height: 38vh; 325 | width: auto; 326 | aspect-ratio: 0.8; 327 | grid-area: 1 / 1 / -1 / -1; 328 | } 329 | 330 | .content--center-tall { 331 | padding-top: 20vh; 332 | margin-bottom: 30vh; 333 | } 334 | 335 | .content--center-tall .content__img { 336 | height: 30vh; 337 | width: auto; 338 | aspect-ratio: 0.8; 339 | } 340 | 341 | .content--column .content__img { 342 | height: auto; 343 | width: 100%; 344 | max-width: 150px; 345 | aspect-ratio: 0.8; 346 | background-size: cover; 347 | background-position: 50% 50%; 348 | } 349 | 350 | .content--lines { 351 | display: flex; 352 | flex-direction: column; 353 | } 354 | 355 | .content--lines .content__title { 356 | display: flex; 357 | flex-wrap: wrap; 358 | align-self: center; 359 | gap: 10px; 360 | } 361 | 362 | .content--lines .content__img { 363 | height: 0.725em; 364 | width: auto; 365 | aspect-ratio: 16/9; 366 | background-size: cover; 367 | align-self: center; 368 | flex: none; 369 | } 370 | 371 | .outro { 372 | display: grid; 373 | place-items: center; 374 | margin: 40vh 0; 375 | padding: 0 10vw; 376 | } 377 | 378 | .outro__title { 379 | font-weight: 300; 380 | margin-bottom: 3rem; 381 | } 382 | 383 | .card-wrap { 384 | width: 100%; 385 | display: grid; 386 | grid-gap: 2rem; 387 | grid-auto-flow: row; 388 | grid-auto-columns: 1fr; 389 | justify-items: center; 390 | justify-content: center; 391 | } 392 | 393 | .card { 394 | width: 100%; 395 | max-width: 255px; 396 | min-width: 150px; 397 | gap: 1rem; 398 | display: flex; 399 | flex-direction: column; 400 | position: relative; 401 | } 402 | 403 | .card__img { 404 | background-size: cover; 405 | background-position: 50% 50%; 406 | aspect-ratio: 1; 407 | max-width: 100%; 408 | } 409 | 410 | .card__title a { 411 | color: var(--color-text); 412 | } 413 | 414 | @media screen and (min-width: 53em) { 415 | .frame { 416 | grid-template-columns: 25% 50% 25%; 417 | grid-template-areas: 'title wrap sponsor'; 418 | } 419 | .frame-wrap { 420 | justify-self: center; 421 | } 422 | .frame #cdawrap { 423 | max-width: 300px; 424 | text-align: right; 425 | justify-self: end; 426 | } 427 | .card-wrap { 428 | grid-auto-flow: column; 429 | } 430 | .content--sides { 431 | grid-template-columns: 40% 1fr; 432 | grid-template-areas: 'img content'; 433 | } 434 | .content--lines .content__title { 435 | white-space: nowrap; 436 | flex-wrap: nowrap; 437 | } 438 | .content--grid { 439 | height: 160vh; 440 | } 441 | } 442 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/OneElementScroll/feb7ad7fbc602b8cdbb5109da83442ff5995cdaf/favicon.ico -------------------------------------------------------------------------------- /img/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/OneElementScroll/feb7ad7fbc602b8cdbb5109da83442ff5995cdaf/img/.DS_Store -------------------------------------------------------------------------------- /img/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/OneElementScroll/feb7ad7fbc602b8cdbb5109da83442ff5995cdaf/img/1.jpg -------------------------------------------------------------------------------- /img/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/OneElementScroll/feb7ad7fbc602b8cdbb5109da83442ff5995cdaf/img/10.jpg -------------------------------------------------------------------------------- /img/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/OneElementScroll/feb7ad7fbc602b8cdbb5109da83442ff5995cdaf/img/11.jpg -------------------------------------------------------------------------------- /img/12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/OneElementScroll/feb7ad7fbc602b8cdbb5109da83442ff5995cdaf/img/12.jpg -------------------------------------------------------------------------------- /img/13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/OneElementScroll/feb7ad7fbc602b8cdbb5109da83442ff5995cdaf/img/13.jpg -------------------------------------------------------------------------------- /img/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/OneElementScroll/feb7ad7fbc602b8cdbb5109da83442ff5995cdaf/img/2.jpg -------------------------------------------------------------------------------- /img/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/OneElementScroll/feb7ad7fbc602b8cdbb5109da83442ff5995cdaf/img/3.jpg -------------------------------------------------------------------------------- /img/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/OneElementScroll/feb7ad7fbc602b8cdbb5109da83442ff5995cdaf/img/4.jpg -------------------------------------------------------------------------------- /img/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/OneElementScroll/feb7ad7fbc602b8cdbb5109da83442ff5995cdaf/img/5.jpg -------------------------------------------------------------------------------- /img/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/OneElementScroll/feb7ad7fbc602b8cdbb5109da83442ff5995cdaf/img/6.jpg -------------------------------------------------------------------------------- /img/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/OneElementScroll/feb7ad7fbc602b8cdbb5109da83442ff5995cdaf/img/7.jpg -------------------------------------------------------------------------------- /img/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/OneElementScroll/feb7ad7fbc602b8cdbb5109da83442ff5995cdaf/img/8.jpg -------------------------------------------------------------------------------- /img/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/OneElementScroll/feb7ad7fbc602b8cdbb5109da83442ff5995cdaf/img/9.jpg -------------------------------------------------------------------------------- /img/main.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/OneElementScroll/feb7ad7fbc602b8cdbb5109da83442ff5995cdaf/img/main.jpg -------------------------------------------------------------------------------- /img/noise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/OneElementScroll/feb7ad7fbc602b8cdbb5109da83442ff5995cdaf/img/noise.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | One Element Scroll | Codrops 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

One Element Scroll

18 |
19 | Article 20 | All demos 21 | GitHub 22 | 26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |

Seraph
Kamos

34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |

Natural
Garments

44 |

Crafted with
love

45 |

with
respect

46 |
47 |
48 |
49 |
50 |

Welcome to Seraph Kamos where time meets the eternal. 51 | We believe in crafting more than garments—we create connections. Connections to the earth, to human hands, and to the moments that matter. Our designs are born from natural fabrics, each fiber carrying the whispers of its origin: the rustle of flax in a summer breeze, the soft strength of organic cotton, the warmth of wool from sheep raised with care.

52 |
53 |
54 |
55 |
56 |
57 |

We honor the hands that touch every thread, partnering with artisans and communities to ensure fairness, respect, and dignity at every step. No shortcuts, no exploitation—just honest, thoughtful craftsmanship. Every piece you wear carries a story, one rooted in sustainability, transparency, and timeless design.

58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |

More you might like

73 |
74 | 80 | 86 | 92 | 100 |
101 | 104 | 105 | On-Scroll Sliced Text Animation 106 | 107 |
108 |
109 |
110 |

Browse all demos

111 |

Made by @codrops

112 |
113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /js/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/OneElementScroll/feb7ad7fbc602b8cdbb5109da83442ff5995cdaf/js/.DS_Store -------------------------------------------------------------------------------- /js/Flip.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Flip 3.11.4 3 | * https://greensock.com 4 | * 5 | * @license Copyright 2022, GreenSock. All rights reserved. 6 | * Subject to the terms at https://greensock.com/standard-license or for Club GreenSock members, the agreement issued with that membership. 7 | * @author: Jack Doyle, jack@greensock.com 8 | */ 9 | 10 | !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t=t||self).window=t.window||{})}(this,function(e){"use strict";function p(t){var e=t.ownerDocument||t;!(w in t.style)&&"msTransform"in t.style&&(S=(w="msTransform")+"Origin");for(;e.parentNode&&(e=e.parentNode););if(y=window,d=new _,e){r=(g=e).documentElement,b=e.body,(a=g.createElementNS("http://www.w3.org/2000/svg","g")).style.transform="none";var i=e.createElement("div"),n=e.createElement("div");b.appendChild(i),i.appendChild(n),i.style.position="static",i.style[w]="translate3d(0,0,1px)",m=n.offsetParent!==i,b.removeChild(i)}return e}function t(){return y.pageYOffset||g.scrollTop||r.scrollTop||b.scrollTop||0}function u(){return y.pageXOffset||g.scrollLeft||r.scrollLeft||b.scrollLeft||0}function v(t){return t.ownerSVGElement||("svg"===(t.tagName+"").toLowerCase()?t:null)}function x(t,e){if(t.parentNode&&(g||p(t))){var i=v(t),n=i?i.getAttribute("xmlns")||"http://www.w3.org/2000/svg":"http://www.w3.org/1999/xhtml",r=i?e?"rect":"g":"div",a=2!==e?0:100,s=3===e?100:0,o="position:absolute;display:block;pointer-events:none;margin:0;padding:0;",l=g.createElementNS?g.createElementNS(n.replace(/^https/,"http"),r):g.createElement(r);return e&&(i?(f=f||x(t),l.setAttribute("width",.01),l.setAttribute("height",.01),l.setAttribute("transform","translate("+a+","+s+")"),f.appendChild(l)):(c||((c=x(t)).style.cssText=o),l.style.cssText=o+"width:0.1px;height:0.1px;top:"+s+"px;left:"+a+"px",c.appendChild(l))),l}throw"Need document and parent."}function z(t){var e,i=t.getCTM();return i||(e=t.style[w],t.style[w]="none",t.appendChild(a),i=a.getCTM(),t.removeChild(a),e?t.style[w]=e:t.style.removeProperty(w.replace(/([A-Z])/g,"-$1").toLowerCase())),i||d.clone()}function A(t,e){var i,n,r,a,s,o,l=v(t),u=t===l,p=l?k:C,h=t.parentNode;if(t===y)return t;if(p.length||p.push(x(t,1),x(t,2),x(t,3)),i=l?f:c,l)u?(a=-(r=z(t)).e/r.a,s=-r.f/r.d,n=d):t.getBBox?(r=t.getBBox(),a=(n=(n=t.transform?t.transform.baseVal:{}).numberOfItems?1=o;t&&!n&&ga(G,!x),F&&W(e,F,t?"remove":"add")})},k&&(S=G.filter(function(t){return!t.sd&&!t.a.isVisible&&t.b.isVisible}).map(function(t){return t.a.element})),tt?(S&&(v=tt._abs).push.apply(v,ja(G,S)),tt._run.push(m)):(S&&ka(ja(G,S)),m());var J=tt?tt.timeline:D;return J.revert=function(){return lt(J,1)},J}function Ca(t){for(var e,i=t.idLookup={},n=t.alt={},r=t.elementStates,a=r.length;a--;)i[(e=r[a]).id]?n[e.id]=e:i[e.id]=e}var T,Q,tt,s,o,P,l,n,h=1,E={},O=180/Math.PI,N=Math.PI/180,M={},F={},et={},it=R("onStart,onUpdate,onComplete,onReverseComplete,onInterrupt"),nt=R("transform,transformOrigin,width,height,position,top,left,opacity,zIndex,maxWidth,maxHeight,minWidth,minHeight"),rt={zIndex:1,kill:1,simple:1,spin:1,clearProps:1,targets:1,toggleClass:1,onComplete:1,onUpdate:1,onInterrupt:1,onStart:1,delay:1,repeat:1,repeatDelay:1,yoyo:1,scale:1,fade:1,absolute:1,props:1,onEnter:1,onLeave:1,custom:1,paused:1,nested:1,prune:1,absoluteOnLeave:1},at={zIndex:1,simple:1,clearProps:1,scale:1,absolute:1,fitChild:1,getVars:1,props:1},st={},I="paddingTop,paddingRight,paddingBottom,paddingLeft,gridArea,transition".split(","),L=function _parseElementState(t,e,i,n){return t instanceof pt?t:t instanceof ut?function _findElStateInState(t,e){return e&&t.idLookup[L(e).id]||t.elementStates[0]}(t,n):new pt("string"==typeof t?U(t)||console.warn(t+" not found"):t,e,i)},ot=function _fit(t,e,i,n,r,a){var s,o,l,u,p,h,c,f=t.element,d=t.cache,m=t.parent,g=t.x,y=t.y,v=e.width,x=e.height,b=e.scaleX,w=e.scaleY,S=e.rotation,k=e.bounds,C=a&&f.style.cssText,_=a&&f.getBBox&&f.getAttribute("transform"),E=t,B=e.matrix,M=B.e,F=B.f,I=t.bounds.width!==k.width||t.bounds.height!==k.height||t.scaleX!==b||t.scaleY!==w||t.rotation!==S,L=!I&&t.simple&&e.simple&&!r;return L||!m?(b=w=1,S=s=0):(h=(p=function _getInverseGlobalMatrix(t){var e=t._gsap||Q.core.getCache(t);return e.gmCache===Q.ticker.frame?e.gMatrix:(e.gmCache=Q.ticker.frame,e.gMatrix=getGlobalMatrix(t,!0,!1,!0))}(m)).clone().multiply(e.ctm?e.matrix.clone().multiply(e.ctm):e.matrix),S=V(Math.atan2(h.b,h.a)*O),s=V(Math.atan2(h.c,h.d)*O+S)%360,b=Math.sqrt(Math.pow(h.a,2)+Math.pow(h.b,2)),w=Math.sqrt(Math.pow(h.c,2)+Math.pow(h.d,2))*Math.cos(s*N),r&&(r=T(r)[0],u=Q.getProperty(r),c=r.getBBox&&"function"==typeof r.getBBox&&r.getBBox(),E={scaleX:u("scaleX"),scaleY:u("scaleY"),width:c?c.width:Math.ceil(parseFloat(u("width","px"))),height:c?c.height:parseFloat(u("height","px"))}),d.rotation=S+"deg",d.skewX=s+"deg"),i?(b*=v!==E.width&&E.width?v/E.width:1,w*=x!==E.height&&E.height?x/E.height:1,d.scaleX=b,d.scaleY=w):(v=P(v*b/E.scaleX,0),x=P(x*w/E.scaleY,0),f.style.width=v+"px",f.style.height=x+"px"),n&&oa(f,e.props),L||!m?(g+=M-t.matrix.e,y+=F-t.matrix.f):I||m!==e.parent?(d.renderTransform(1,d),h=getGlobalMatrix(r||f,!1,!1,!0),o=p.apply({x:h.e,y:h.f}),g+=(l=p.apply({x:M,y:F})).x-o.x,y+=l.y-o.y):(p.e=p.f=0,g+=(l=p.apply({x:M-t.matrix.e,y:F-t.matrix.f})).x,y+=l.y),g=P(g,.02),y=P(y,.02),!a||a instanceof pt?(d.x=g+"px",d.y=y+"px",d.renderTransform(1,d)):(f.style.cssText=C,f.getBBox&&f.setAttribute("transform",_||""),d.uncache=1),a&&(a.x=g,a.y=y,a.rotation=S,a.skewX=s,i?(a.scaleX=b,a.scaleY=w):(a.width=v,a.height=x)),a||d},X=[],D="width,height,overflowX,overflowY".split(","),lt=function _killFlip(t,e){if(t&&t.progress()<1&&!t.paused())return e&&(function _interrupt(t){t.vars.onInterrupt&&t.vars.onInterrupt.apply(t,t.vars.onInterruptParams||[]),t.getChildren(!0,!1,!0).forEach(_interrupt)}(t),e<2&&t.progress(1),t.kill()),!0},ut=((n=FlipState.prototype).update=function update(t){var e=this;return this.elementStates=this.targets.map(function(t){return new pt(t,e.props,e.simple)}),Ca(this),this.interrupt(t),this.recordInlineStyles(),this},n.clear=function clear(){return this.targets.length=this.elementStates.length=0,Ca(this),this},n.fit=function fit(t,e,i){for(var n,r,a=da(this.elementStates.slice(0),!1,!0),s=(t||this).idLookup,o=0;o=Math.abs(r)?t:r}function O(){(Ae=Ce.core.globals().ScrollTrigger)&&Ae.core&&function _integrate(){var e=Ae.core,r=e.bridge||{},t=e._scrollers,n=e._proxies;t.push.apply(t,Ie),n.push.apply(n,Le),Ie=t,Le=n,i=function _bridge(e,t){return r[e](t)}}()}function P(e){return Ce=e||r(),!Te&&Ce&&"undefined"!=typeof document&&document.body&&(Se=window,Pe=(ke=document).documentElement,Me=ke.body,t=[Se,ke,Pe,Me],Ce.utils.clamp,Be=Ce.core.context||function(){},Oe="onpointerenter"in Me?"pointer":"mouse",Ee=k.isTouch=Se.matchMedia&&Se.matchMedia("(hover: none), (pointer: coarse)").matches?1:"ontouchstart"in Se||0=o,n=Math.abs(t)>=o;S&&(r||n)&&S(se,e,t,me,ye),r&&(m&&0Math.abs(t)?"x":"y",ie=!0),"y"!==ae&&(me[2]+=e,se._vx.update(e,!0)),"x"!==ae&&(ye[2]+=t,se._vy.update(t,!0)),n?ee=ee||requestAnimationFrame(ff):ff()}function jf(e){if(!df(e,1)){var t=(e=M(e,s)).clientX,r=e.clientY,n=t-se.x,o=r-se.y,i=se.isDragging;se.x=t,se.y=r,(i||Math.abs(se.startX-t)>=a||Math.abs(se.startY-r)>=a)&&(h&&(re=!0),i||(se.isDragging=!0),hf(n,o),i||p&&p(se))}}function mf(e){return e.touches&&1=e)return a[n];return a[n-1]}for(n=a.length,e+=r;n--;)if(a[n]<=e)return a[n];return a[0]}:function(e,t,r){void 0===r&&(r=.001);var n=i(e);return!t||Math.abs(n-e)r&&(n*=t/100),e=e.substr(0,r-1)),e=n+(e in H?H[e]*t:~e.indexOf("%")?parseFloat(e)*t/100:parseFloat(e)||0)}return e}function Db(e,t,r,n,o,i,a,s){var l=o.startColor,c=o.endColor,u=o.fontSize,f=o.indent,d=o.fontWeight,p=Xe.createElement("div"),g=La(r)||"fixed"===z(r,"pinType"),h=-1!==e.indexOf("scroller"),v=g?We:r,b=-1!==e.indexOf("start"),m=b?l:c,y="border-color:"+m+";font-size:"+u+";color:"+m+";font-weight:"+d+";pointer-events:none;white-space:nowrap;font-family:sans-serif,Arial;z-index:1000;padding:4px 8px;border-width:0;border-style:solid;";return y+="position:"+((h||s)&&g?"fixed;":"absolute;"),!h&&!s&&g||(y+=(n===Fe?q:I)+":"+(i+parseFloat(f))+"px;"),a&&(y+="box-sizing:border-box;text-align:left;width:"+a.offsetWidth+"px;"),p._isStart=b,p.setAttribute("class","gsap-marker-"+e+(t?" marker-"+t:"")),p.style.cssText=y,p.innerText=t||0===t?e+"-"+t:e,v.children[0]?v.insertBefore(p,v.children[0]):v.appendChild(p),p._offset=p["offset"+n.op.d2],X(p,0,n,b),p}function Ib(){return 34We.clientWidth)||(Ie.cache++,v?D=D||requestAnimationFrame(Z):Z(),st||U("scrollStart"),st=at())}function Kb(){y=Ne.innerWidth,m=Ne.innerHeight}function Lb(){Ie.cache++,je||h||Xe.fullscreenElement||Xe.webkitFullscreenElement||b&&y===Ne.innerWidth&&!(Math.abs(Ne.innerHeight-m)>.25*Ne.innerHeight)||c.restart(!0)}function Ob(){return xb(ne,"scrollEnd",Ob)||Pt(!0)}function Rb(e){for(var t=0;tt,n=e._startClamp&&e.start>=t;(r||n)&&e.setPositions(n?t-1:e.start,r?Math.max(n?t:e.start+1,t):e.end,!0)}),Zb(!1),et=0,r.forEach(function(e){return e&&e.render&&e.render(-1)}),Ie.forEach(function(e){Ta(e)&&(e.smooth&&requestAnimationFrame(function(){return e.target.style.scrollBehavior="smooth"}),e.rec&&e(e.rec))}),Tb(w,1),c.pause(),kt++,Z(rt=2),Tt.forEach(function(e){return Ta(e.vars.onRefresh)&&e.vars.onRefresh(e)}),rt=ne.isRefreshing=!1,U("refresh")}else wb(ne,"scrollEnd",Ob)},Q=0,Mt=1,Z=function _updateAll(e){if(2===e||!rt&&!S){ne.isUpdating=!0,ot&&ot.update(0);var t=Tt.length,r=at(),n=50<=r-R,o=t&&Tt[0].scroll();if(Mt=o=Qa(be,he)){if(ie&&Ae()&&!de)for(i=ie.parentNode;i&&i!==We;)i._pinOffset&&(B-=i._pinOffset,q-=i._pinOffset),i=i.parentNode}else o=mb(ae),s=he===Fe,a=Ae(),G=parseFloat(j(he.a))+_,!y&&1=q})},Te.update=function(e,t,r){if(!de||r||e){var n,o,i,a,s,l,c,u=!0===rt?re:Te.scroll(),f=e?0:(u-B)/N,d=f<0?0:1u+(u-R)/(at()-Ke)*M&&(d=.9999)),d!==p&&Te.enabled){if(a=(s=(n=Te.isActive=!!d&&d<1)!=(!!p&&p<1))||!!d!=!!p,Te.direction=p=Qa(be,he),fe)if(e||!n&&!l)oc(ae,U);else{var g=wt(ae,!0),h=u-B;oc(ae,We,g.top+(he===Fe?h:0)+xt,g.left+(he===Fe?0:h)+xt)}Et(n||l?W:V),$&&d<1&&n||b(G+(1!==d||l?0:Q))}}else b(Ia(G+Q*d));!ue||A.tween||je||it||te.restart(!0),S&&(s||ce&&d&&(d<1||!tt))&&Ve(S.targets).forEach(function(e){return e.classList[n||ce?"add":"remove"](S.className)}),!T||ve||e||T(Te),a&&!je?(ve&&(c&&("complete"===i?O.pause().totalProgress(1):"reset"===i?O.restart(!0).pause():"restart"===i?O.restart(!0):O[i]()),T&&T(Te)),!s&&tt||(k&&s&&Xa(Te,k),xe[o]&&Xa(Te,xe[o]),ce&&(1===d?Te.kill(!1,1):xe[o]=0),s||xe[o=1===d?1:3]&&Xa(Te,xe[o])),pe&&!n&&Math.abs(Te.getVelocity())>(Ua(pe)?pe:2500)&&(Wa(Te.callbackAnimation),ee?ee.progress(1):Wa(O,"reverse"===i?1:!d,1))):ve&&T&&!je&&T(Te)}if(x){var v=de?u/de.duration()*(de._caScrollDist||0):u;y(v+(Y._isFlipped?1:0)),x(v)}C&&C(-u/de.duration()*(de._caScrollDist||0))}},Te.enable=function(e,t){Te.enabled||(Te.enabled=!0,wb(be,"resize",Lb),me||wb(be,"scroll",Jb),Se&&wb(ScrollTrigger,"refreshInit",Se),!1!==e&&(Te.progress=Oe=0,D=R=Me=Ae()),!1!==t&&Te.refresh())},Te.getTween=function(e){return e&&A?A.tween:ee},Te.setPositions=function(e,t,r,n){if(de){var o=de.scrollTrigger,i=de.duration(),a=o.end-o.start;e=o.start+a*e/i,t=o.start+a*t/i}Te.refresh(!1,!1,{start:Da(e,r&&!!Te._startClamp),end:Da(t,r&&!!Te._endClamp)},n),Te.update()},Te.adjustPinSpacing=function(e){if(Z&&e){var t=Z.indexOf(he.d)+1;Z[t]=parseFloat(Z[t])+e+xt,Z[1]=parseFloat(Z[1])+e+xt,Et(Z)}},Te.disable=function(e,t){if(Te.enabled&&(!1!==e&&Te.revert(!0,!0),Te.enabled=Te.isActive=!1,t||ee&&ee.pause(),re=0,n&&(n.uncache=1),Se&&xb(ScrollTrigger,"refreshInit",Se),te&&(te.pause(),A.tween&&A.tween.kill()&&(A.tween=0)),!me)){for(var r=Tt.length;r--;)if(Tt[r].scroller===be&&Tt[r]!==Te)return;xb(be,"resize",Lb),me||xb(be,"scroll",Jb)}},Te.kill=function(e,t){Te.disable(e,t),ee&&!t&&ee.kill(),a&&delete St[a];var r=Tt.indexOf(Te);0<=r&&Tt.splice(r,1),r===Qe&&0i&&(b()>i?a.progress(1)&&b(i):a.resetTo("scrollY",i))}Va(e)||(e={}),e.preventDefault=e.isNormalizer=e.allowClicks=!0,e.type||(e.type="wheel,touch"),e.debounce=!!e.debounce,e.id=e.id||"normalizer";var n,i,l,o,a,c,u,s,f=e.normalizeScrollX,t=e.momentum,r=e.allowNestedScroll,d=e.onRelease,p=J(e.target)||Je,g=He.core.globals().ScrollSmoother,h=g&&g.get(),v=E&&(e.content&&J(e.content)||h&&!1!==e.content&&!h.smooth()&&h.content()),b=K(p,Fe),m=K(p,Ye),y=1,x=(k.isTouch&&Ne.visualViewport?Ne.visualViewport.scale*Ne.visualViewport.width:Ne.outerWidth)/Ne.innerWidth,w=0,_=Ta(t)?function(){return t(n)}:function(){return t||2.8},C=xc(p,e.type,!0,r),T=Ha,S=Ha;return v&&He.set(v,{y:"+=0"}),e.ignoreCheck=function(e){return E&&"touchmove"===e.type&&function ignoreDrag(){if(o){requestAnimationFrame(zq);var e=Ia(n.deltaY/2),t=S(b.v-e);if(v&&t!==b.v+b.offset){b.offset=t-b.v;var r=Ia((parseFloat(v&&v._gsap.y)||0)-b.offset);v.style.transform="matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, "+r+", 0, 1)",v._gsap.y=r+"px",b.cacheID=Ie.cache,Z()}return!0}b.offset&&Dq(),o=!0}()||1.05=i||i-1<=r)&&He.to({},{onUpdate:Jq,duration:o})}else s.restart(!0);d&&d(e)},e.onWheel=function(){a._ts&&a.pause(),1e3a;)s=s._prev;return s?(e._next=s._next,s._next=e):(e._next=t[r],t[r]=e),e._next?e._next._prev=e:t[i]=e,e._prev=s,e.parent=e._dp=t,e}function ya(t,e,r,i){void 0===r&&(r="_first"),void 0===i&&(i="_last");var n=e._prev,a=e._next;n?n._next=a:t[r]===e&&(t[r]=a),a?a._prev=n:t[i]===e&&(t[i]=n),e._next=e._prev=e.parent=null}function za(t,e){t.parent&&(!e||t.parent.autoRemoveChildren)&&t.parent.remove&&t.parent.remove(t),t._act=0}function Aa(t,e){if(t&&(!e||e._end>t._dur||e._start<0))for(var r=t;r;)r._dirty=1,r=r.parent;return t}function Ca(t,e,r,i){return t._startAt&&(L?t._startAt.revert(ht):t.vars.immediateRender&&!t.vars.autoRevert||t._startAt.render(e,!0,i))}function Ea(t){return t._repeat?Tt(t._tTime,t=t.duration()+t._rDelay)*t:0}function Ga(t,e){return(t-e._start)*e._ts+(0<=e._ts?0:e._dirty?e.totalDuration():e._tDur)}function Ha(t){return t._end=ja(t._start+(t._tDur/Math.abs(t._ts||t._rts||X)||0))}function Ia(t,e){var r=t._dp;return r&&r.smoothChildTiming&&t._ts&&(t._start=ja(r._time-(0X)&&e.render(r,!0)),Aa(t,e)._dp&&t._initted&&t._time>=t._dur&&t._ts){if(t._dur(n=Math.abs(n))&&(a=i,o=n);return a}function tb(t){return za(t),t.scrollTrigger&&t.scrollTrigger.kill(!!L),t.progress()<1&&Ct(t,"onInterrupt"),t}function wb(t){if(t)if(t=!t.name&&t.default||t,x()||t.headless){var e=t.name,r=s(t),i=e&&!r&&t.init?function(){this._props=[]}:t,n={init:T,render:he,add:Wt,kill:ce,modifier:fe,rawVars:0},a={targetTest:0,get:0,getSetter:ne,aliases:{},register:0};if(Ft(),t!==i){if(pt[e])return;qa(i,qa(ua(t,n),a)),yt(i.prototype,yt(n,ua(t,a))),pt[i.prop=e]=i,t.targetTest&&(gt.push(i),ft[e]=1),e=("css"===e?"CSS":e.charAt(0).toUpperCase()+e.substr(1))+"Plugin"}S(e,i),t.register&&t.register(ze,i,_e)}else At.push(t)}function zb(t,e,r){return(6*(t+=t<0?1:1>16,e>>8&St,e&St]:0:zt.black;if(!p){if(","===e.substr(-1)&&(e=e.substr(0,e.length-1)),zt[e])p=zt[e];else if("#"===e.charAt(0)){if(e.length<6&&(e="#"+(n=e.charAt(1))+n+(a=e.charAt(2))+a+(s=e.charAt(3))+s+(5===e.length?e.charAt(4)+e.charAt(4):"")),9===e.length)return[(p=parseInt(e.substr(1,6),16))>>16,p>>8&St,p&St,parseInt(e.substr(7),16)/255];p=[(e=parseInt(e.substr(1),16))>>16,e>>8&St,e&St]}else if("hsl"===e.substr(0,3))if(p=c=e.match(tt),r){if(~e.indexOf("="))return p=e.match(et),i&&p.length<4&&(p[3]=1),p}else o=+p[0]%360/360,u=p[1]/100,n=2*(h=p[2]/100)-(a=h<=.5?h*(u+1):h+u-h*u),3=U?u.endTime(!1):t._dur;return r(e)&&(isNaN(e)||e in o)?(a=e.charAt(0),s="%"===e.substr(-1),n=e.indexOf("="),"<"===a||">"===a?(0<=n&&(e=e.replace(/=/,"")),("<"===a?u._start:u.endTime(0<=u._repeat))+(parseFloat(e.substr(1))||0)*(s?(n<0?u:i).totalDuration()/100:1)):n<0?(e in o||(o[e]=h),o[e]):(a=parseFloat(e.charAt(n-1)+e.substr(n+1)),s&&i&&(a=a/100*(Z(i)?i[0]:i).totalDuration()),1=r&&te)return i;i=i._next}else for(i=t._last;i&&i._start>=r;){if("isPause"===i.data&&i._start=n._start)&&n._ts&&h!==n){if(n.parent!==this)return this.render(t,e,r);if(n.render(0=this.totalDuration()||!v&&_)&&(f!==this._start&&Math.abs(l)===Math.abs(this._ts)||this._lock||(!t&&g||!(v===m&&0=i&&(a instanceof $t?e&&n.push(a):(r&&n.push(a),t&&n.push.apply(n,a.getChildren(!0,e,r)))),a=a._next;return n},e.getById=function getById(t){for(var e=this.getChildren(1,1,1),r=e.length;r--;)if(e[r].vars.id===t)return e[r]},e.remove=function remove(t){return r(t)?this.removeLabel(t):s(t)?this.killTweensOf(t):(ya(this,t),t===this._recent&&(this._recent=this._last),Aa(this))},e.totalTime=function totalTime(t,e){return arguments.length?(this._forcing=1,!this._dp&&this._ts&&(this._start=ja(Rt.time-(0r:!r||s.isActive())&&n.push(s):(i=s.getTweensOf(a,r)).length&&n.push.apply(n,i),s=s._next;return n},e.tweenTo=function tweenTo(t,e){e=e||{};var r,i=this,n=xt(i,t),a=e.startAt,s=e.onStart,o=e.onStartParams,u=e.immediateRender,h=$t.to(i,qa({ease:e.ease||"none",lazy:!1,immediateRender:!1,time:n,overwrite:"auto",duration:e.duration||Math.abs((n-(a&&"time"in a?a.time:i._time))/i.timeScale())||X,onStart:function onStart(){if(i.pause(),!r){var t=e.duration||Math.abs((n-(a&&"time"in a?a.time:i._time))/i.timeScale());h._dur!==t&&Ra(h,t,0,1).render(h._time,!0,!0),r=1}s&&s.apply(h,o||[])}},e));return u?h.render(0):h},e.tweenFromTo=function tweenFromTo(t,e,r){return this.tweenTo(e,qa({startAt:{time:xt(this,t)}},r))},e.recent=function recent(){return this._recent},e.nextLabel=function nextLabel(t){return void 0===t&&(t=this._time),rb(this,xt(this,t))},e.previousLabel=function previousLabel(t){return void 0===t&&(t=this._time),rb(this,xt(this,t),1)},e.currentLabel=function currentLabel(t){return arguments.length?this.seek(t,!0):this.previousLabel(this._time+X)},e.shiftChildren=function shiftChildren(t,e,r){void 0===r&&(r=0);for(var i,n=this._first,a=this.labels;n;)n._start>=r&&(n._start+=t,n._end+=t),n=n._next;if(e)for(i in a)a[i]>=r&&(a[i]+=t);return Aa(this)},e.invalidate=function invalidate(t){var e=this._first;for(this._lock=0;e;)e.invalidate(t),e=e._next;return i.prototype.invalidate.call(this,t)},e.clear=function clear(t){void 0===t&&(t=!0);for(var e,r=this._first;r;)e=r._next,this.remove(r),r=e;return this._dp&&(this._time=this._tTime=this._pTime=0),t&&(this.labels={}),Aa(this)},e.totalDuration=function totalDuration(t){var e,r,i,n=0,a=this,s=a._last,o=U;if(arguments.length)return a.timeScale((a._repeat<0?a.duration():a.totalDuration())/(a.reversed()?-t:t));if(a._dirty){for(i=a.parent;s;)e=s._prev,s._dirty&&s.totalDuration(),o<(r=s._start)&&a._sort&&s._ts&&!a._lock?(a._lock=1,Ka(a,s,r-s._delay,1)._lock=0):o=r,r<0&&s._ts&&(n-=r,(!i&&!a._dp||i&&i.smoothChildTiming)&&(a._start+=r/a._ts,a._time-=r,a._tTime-=r),a.shiftChildren(-r,!1,-Infinity),o=0),s._end>n&&s._ts&&(n=s._end),s=e;Ra(a,a===I&&a._time>n?a._time:n,1,1),a._dirty=0}return a._tDur},Timeline.updateRoot=function updateRoot(t){if(I._ts&&(na(I,Ga(t,I)),f=Rt.frame),Rt.frame>=mt){mt+=q.autoSleep||120;var e=I._first;if((!e||!e._ts)&&q.autoSleep&&Rt._listeners.length<2){for(;e&&!e._ts;)e=e._next;e||Rt.sleep()}}},Timeline}(Ut);qa(Xt.prototype,{_lock:0,_hasPause:0,_forcing:0});function ac(t,e,i,n,a,o){var u,h,l,f;if(pt[t]&&!1!==(u=new pt[t]).init(a,u.rawVars?e[t]:function _processVars(t,e,i,n,a){if(s(t)&&(t=Kt(t,a,e,i,n)),!v(t)||t.style&&t.nodeType||Z(t)||$(t))return r(t)?Kt(t,a,e,i,n):t;var o,u={};for(o in t)u[o]=Kt(t[o],a,e,i,n);return u}(e[t],n,a,o,i),i,n,o)&&(i._pt=h=new _e(i._pt,a,t,0,1,u.render,u,0,u.priority),i!==d))for(l=i._ptLookup[i._targets.indexOf(a)],f=u._props.length;f--;)l[u._props[f]]=h;return u}function gc(t,r,e,i){var n,a,s=r.ease||i||"power1.inOut";if(Z(r))a=e[t]||(e[t]=[]),r.forEach(function(t,e){return a.push({t:e/(r.length-1)*100,v:t,e:s})});else for(n in r)a=e[n]||(e[n]=[]),"ease"===n||a.push({t:parseFloat(t),v:r[n],e:s})}var Nt,Gt,Wt=function _addPropTween(t,e,i,n,a,o,u,h,l,f){s(n)&&(n=n(a||0,t,o));var d,c=t[e],p="get"!==i?i:s(c)?l?t[e.indexOf("set")||!s(t["get"+e.substr(3)])?e:"get"+e.substr(3)](l):t[e]():c,_=s(c)?l?re:te:Zt;if(r(n)&&(~n.indexOf("random(")&&(n=ob(n)),"="===n.charAt(1)&&(!(d=ka(p,n)+(Ya(p)||0))&&0!==d||(n=d))),!f||p!==n||Gt)return isNaN(p*n)||""===n?(c||e in t||Q(e,n),function _addComplexStringPropTween(t,e,r,i,n,a,s){var o,u,h,l,f,d,c,p,_=new _e(this._pt,t,e,0,1,ue,null,n),m=0,g=0;for(_.b=r,_.e=i,r+="",(c=~(i+="").indexOf("random("))&&(i=ob(i)),a&&(a(p=[r,i],t,e),r=p[0],i=p[1]),u=r.match(it)||[];o=it.exec(i);)l=o[0],f=i.substring(m,o.index),h?h=(h+1)%5:"rgba("===f.substr(-5)&&(h=1),l!==u[g++]&&(d=parseFloat(u[g-1])||0,_._pt={_next:_._pt,p:f||1===g?f:",",s:d,c:"="===l.charAt(1)?ka(d,l)-d:parseFloat(l)-d,m:h&&h<4?Math.round:0},m=it.lastIndex);return _.c=m")}),s.duration();else{for(l in u={},x)"ease"===l||"easeEach"===l||gc(l,x[l],u,x.easeEach);for(l in u)for(A=u[l].sort(function(t,e){return t.t-e.t}),o=E=0;o=t._tDur||e<0)&&t.ratio===u&&(u&&za(t,1),r||L||(Ct(t,u?"onComplete":"onReverseComplete",!0),t._prom&&t._prom()))}else t._zTime||(t._zTime=e)}(this,t,e,r);return this},e.targets=function targets(){return this._targets},e.invalidate=function invalidate(t){return t&&this.vars.runBackwards||(this._startAt=0),this._pt=this._op=this._onUpdate=this._lazy=this.ratio=0,this._ptLookup=[],this.timeline&&this.timeline.invalidate(t),D.prototype.invalidate.call(this,t)},e.resetTo=function resetTo(t,e,r,i,n){c||Rt.wake(),this._ts||this.play();var a,s=Math.min(this._dur,(this._dp._time-this._start)*this._ts);return this._initted||Qt(this,s),a=this._ease(s/this._dur),function _updatePropTweens(t,e,r,i,n,a,s,o){var u,h,l,f,d=(t._pt&&t._ptCache||(t._ptCache={}))[e];if(!d)for(d=t._ptCache[e]=[],l=t._ptLookup,f=t._targets.length;f--;){if((u=l[f][e])&&u.d&&u.d._pt)for(u=u.d._pt;u&&u.p!==e&&u.fp!==e;)u=u._next;if(!u)return Gt=1,t.vars[e]="+=0",Qt(t,s),Gt=0,o?R(e+" not eligible for reset"):1;d.push(u)}for(f=d.length;f--;)(u=(h=d[f])._pt||h).s=!i&&0!==i||n?u.s+(i||0)+a*u.c:i,u.c=r-u.s,h.e&&(h.e=ia(r)+Ya(h.e)),h.b&&(h.b=u.s+Ya(h.b))}(this,t,e,r,i,a,s,n)?this.resetTo(t,e,r,i,1):(Ia(this,0),this.parent||xa(this._dp,this,"_first","_last",this._dp._sort?"_start":0),this.render(0))},e.kill=function kill(t,e){if(void 0===e&&(e="all"),!(t||e&&"all"!==e))return this._lazy=this._pt=0,this.parent?tb(this):this;if(this.timeline){var i=this.timeline.totalDuration();return this.timeline.killTweensOf(t,e,Nt&&!0!==Nt.vars.overwrite)._first||tb(this),this.parent&&i!==this.timeline.totalDuration()&&Ra(this,this._dur*this.timeline._tDur/i,0,1),this}var n,a,s,o,u,h,l,f=this._targets,d=t?Mt(t):f,c=this._ptLookup,p=this._pt;if((!e||"all"===e)&&function _arraysMatch(t,e){for(var r=t.length,i=r===e.length;i&&r--&&t[r]===e[r];);return r<0}(f,d))return"all"===e&&(this._pt=0),tb(this);for(n=this._op=this._op||[],"all"!==e&&(r(e)&&(u={},ha(e,function(t){return u[t]=1}),e=u),e=function _addAliasesToVars(t,e){var r,i,n,a,s=t[0]?fa(t[0]).harness:0,o=s&&s.aliases;if(!o)return e;for(i in r=yt({},e),o)if(i in r)for(n=(a=o[i].split(",")).length;n--;)r[a[n]]=r[i];return r}(f,e)),l=f.length;l--;)if(~d.indexOf(f[l]))for(u in a=c[l],"all"===e?(n[l]=e,o=a,s={}):(s=n[l]=n[l]||{},o=e),o)(h=a&&a[u])&&("kill"in h.d&&!0!==h.d.kill(u)||ya(this,h,"_pt"),delete a[u]),"all"!==s&&(s[u]=1);return this._initted&&!this._pt&&p&&tb(this),this},Tween.to=function to(t,e,r){return new Tween(t,e,r)},Tween.from=function from(t,e){return Va(1,arguments)},Tween.delayedCall=function delayedCall(t,e,r,i){return new Tween(e,0,{immediateRender:!1,lazy:!1,overwrite:!1,delay:t,onComplete:e,onReverseComplete:e,onCompleteParams:r,onReverseCompleteParams:r,callbackScope:i})},Tween.fromTo=function fromTo(t,e,r){return Va(2,arguments)},Tween.set=function set(t,e){return e.duration=0,e.repeatDelay||(e.repeat=0),new Tween(t,e)},Tween.killTweensOf=function killTweensOf(t,e,r){return I.killTweensOf(t,e,r)},Tween}(Ut);qa($t.prototype,{_targets:[],_lazy:0,_startAt:0,_op:0,_onInit:0}),ha("staggerTo,staggerFrom,staggerFromTo",function(r){$t[r]=function(){var t=new Xt,e=kt.call(arguments,0);return e.splice("staggerFromTo"===r?5:4,0,0),t[r].apply(t,e)}});function oc(t,e,r){return t.setAttribute(e,r)}function wc(t,e,r,i){i.mSet(t,e,i.m.call(i.tween,r,i.mt),i)}var Zt=function _setterPlain(t,e,r){return t[e]=r},te=function _setterFunc(t,e,r){return t[e](r)},re=function _setterFuncWithParam(t,e,r,i){return t[e](i.fp,r)},ne=function _getSetter(t,e){return s(t[e])?te:u(t[e])&&t.setAttribute?oc:Zt},ae=function _renderPlain(t,e){return e.set(e.t,e.p,Math.round(1e6*(e.s+e.c*t))/1e6,e)},se=function _renderBoolean(t,e){return e.set(e.t,e.p,!!(e.s+e.c*t),e)},ue=function _renderComplexString(t,e){var r=e._pt,i="";if(!t&&e.b)i=e.b;else if(1===t&&e.e)i=e.e;else{for(;r;)i=r.p+(r.m?r.m(r.s+r.c*t):Math.round(1e4*(r.s+r.c*t))/1e4)+i,r=r._next;i+=e.c}e.set(e.t,e.p,i,e)},he=function _renderPropTweens(t,e){for(var r=e._pt;r;)r.r(t,r.d),r=r._next},fe=function _addPluginModifier(t,e,r,i){for(var n,a=this._pt;a;)n=a._next,a.p===i&&a.modifier(t,e,r),a=n},ce=function _killPropTweensOf(t){for(var e,r,i=this._pt;i;)r=i._next,i.p===t&&!i.op||i.op===t?ya(this,i,"_pt"):i.dep||(e=1),i=r;return!e},pe=function _sortPropTweensByPriority(t){for(var e,r,i,n,a=t._pt;a;){for(e=a._next,r=i;r&&r.pr>a.pr;)r=r._next;(a._prev=r?r._prev:n)?a._prev._next=a:i=a,(a._next=r)?r._prev=a:n=a,a=e}t._pt=i},_e=(PropTween.prototype.modifier=function modifier(t,e,r){this.mSet=this.mSet||this.set,this.set=wc,this.m=t,this.mt=r,this.tween=e},PropTween);function PropTween(t,e,r,i,n,a,s,o,u){this.t=e,this.s=i,this.c=n,this.p=r,this.r=a||ae,this.d=s||this,this.set=o||Zt,this.pr=u||0,(this._next=t)&&(t._prev=this)}ha(vt+"parent,duration,ease,delay,overwrite,runBackwards,startAt,yoyo,immediateRender,repeat,repeatDelay,data,paused,reversed,lazy,callbackScope,stringFilter,id,yoyoEase,stagger,inherit,repeatRefresh,keyframes,autoRevert,scrollTrigger",function(t){return ft[t]=1}),ot.TweenMax=ot.TweenLite=$t,ot.TimelineLite=ot.TimelineMax=Xt,I=new Xt({sortChildren:!1,defaults:V,autoRemoveChildren:!0,id:"root",smoothChildTiming:!0}),q.stringFilter=Fb;function Ec(t){return(ye[t]||Te).map(function(t){return t()})}function Fc(){var t=Date.now(),o=[];2{setTimeout((()=>{this.progress(t,e,i)}))};this.images.forEach((function(e){e.once("progress",t),e.check()}))},n.prototype.progress=function(t,e,i){this.progressedCount++,this.hasAnyBroken=this.hasAnyBroken||!t.isLoaded,this.emitEvent("progress",[this,t,e]),this.jqDeferred&&this.jqDeferred.notify&&this.jqDeferred.notify(this,t),this.progressedCount===this.images.length&&this.complete(),this.options.debug&&s&&s.log(`progress: ${i}`,t,e)},n.prototype.complete=function(){let t=this.hasAnyBroken?"fail":"done";if(this.isComplete=!0,this.emitEvent(t,[this]),this.emitEvent("always",[this]),this.jqDeferred){let t=this.hasAnyBroken?"reject":"resolve";this.jqDeferred[t](this)}},h.prototype=Object.create(e.prototype),h.prototype.check=function(){this.getIsImageComplete()?this.confirm(0!==this.img.naturalWidth,"naturalWidth"):(this.proxyImage=new Image,this.img.crossOrigin&&(this.proxyImage.crossOrigin=this.img.crossOrigin),this.proxyImage.addEventListener("load",this),this.proxyImage.addEventListener("error",this),this.img.addEventListener("load",this),this.img.addEventListener("error",this),this.proxyImage.src=this.img.currentSrc||this.img.src)},h.prototype.getIsImageComplete=function(){return this.img.complete&&this.img.naturalWidth},h.prototype.confirm=function(t,e){this.isLoaded=t;let{parentNode:i}=this.img,s="PICTURE"===i.nodeName?i:this.img;this.emitEvent("progress",[this,s,e])},h.prototype.handleEvent=function(t){let e="on"+t.type;this[e]&&this[e](t)},h.prototype.onload=function(){this.confirm(!0,"onload"),this.unbindEvents()},h.prototype.onerror=function(){this.confirm(!1,"onerror"),this.unbindEvents()},h.prototype.unbindEvents=function(){this.proxyImage.removeEventListener("load",this),this.proxyImage.removeEventListener("error",this),this.img.removeEventListener("load",this),this.img.removeEventListener("error",this)},d.prototype=Object.create(h.prototype),d.prototype.check=function(){this.img.addEventListener("load",this),this.img.addEventListener("error",this),this.img.src=this.url,this.getIsImageComplete()&&(this.confirm(0!==this.img.naturalWidth,"naturalWidth"),this.unbindEvents())},d.prototype.unbindEvents=function(){this.img.removeEventListener("load",this),this.img.removeEventListener("error",this)},d.prototype.confirm=function(t,e){this.isLoaded=t,this.emitEvent("progress",[this,this.element,e])},n.makeJQueryPlugin=function(e){(e=e||t.jQuery)&&(i=e,i.fn.imagesLoaded=function(t,e){return new n(this,t,e).jqDeferred.promise(i(this))})},n.makeJQueryPlugin(),n})); -------------------------------------------------------------------------------- /js/index.js: -------------------------------------------------------------------------------- 1 | import { preloadImages } from './utils.js'; // Import utility function to preload images 2 | 3 | gsap.registerPlugin(ScrollTrigger, Flip); // Register GSAP's ScrollTrigger and Flip plugins 4 | 5 | // Select the element that will be animated with Flip and its parent 6 | const oneElement = document.querySelector('.one'); 7 | const parentElement = oneElement.parentNode; 8 | 9 | // Select all elements with a `data-step` attribute for the Flip animation steps 10 | const stepElements = [...document.querySelectorAll('[data-step]')]; 11 | 12 | let flipCtx; // Variable to store the Flip animation context 13 | 14 | // Function to create a Flip animation tied to scroll events 15 | const createFlipOnScrollAnimation = () => { 16 | // Revert any previous animation context 17 | flipCtx && flipCtx.revert(); 18 | 19 | flipCtx = gsap.context(() => { 20 | const flipConfig = { 21 | duration: 1, // Duration of each Flip animation 22 | ease: 'sine.inOut' // Easing for smooth transitions 23 | }; 24 | 25 | // Store Flip states for each step element 26 | const states = stepElements.map(stepElement => Flip.getState(stepElement)); 27 | 28 | // Create a GSAP timeline with ScrollTrigger for the Flip animation 29 | const tl = gsap.timeline({ 30 | scrollTrigger: { 31 | trigger: parentElement, // Trigger animation based on the parent element 32 | start: 'clamp(center center)', // Start animation when parent is in the center of the viewport 33 | endTrigger: stepElements[stepElements.length - 1], // End at the last step element 34 | end: 'clamp(center center)', // End animation when the last step is centered 35 | scrub: true, // Synchronize animation with scroll 36 | immediateRender: false 37 | } 38 | }); 39 | 40 | // Add Flip animations to the timeline for each state 41 | states.forEach((state, index) => { 42 | const customFlipConfig = { 43 | ...flipConfig, 44 | ease: index === 0 ? 'none' : flipConfig.ease // Use 'none' easing for the first step 45 | }; 46 | tl.add(Flip.fit(oneElement, state, customFlipConfig), index ? '+=0.5' : 0); 47 | }); 48 | }); 49 | }; 50 | 51 | // Animate spans within `.content__title` elements on scroll 52 | const animateSpansOnScroll = () => { 53 | const spans = document.querySelectorAll('.content__title > span'); // Select all spans 54 | 55 | spans.forEach((span, index) => { 56 | const direction = index % 2 === 0 ? -150 : 150; // Alternate direction for animation 57 | 58 | // Determine the scroll trigger dynamically based on the parent section 59 | const triggerElement = span.closest('.content--center') ? span.parentNode : span; 60 | 61 | gsap.from(span, { 62 | x: direction, // Animate from the left or right 63 | duration: 1, 64 | ease: 'sine', // Smooth easing 65 | scrollTrigger: { 66 | trigger: triggerElement, // Trigger element 67 | start: 'top bottom', // Start animation when element enters viewport 68 | end: '+=45%', // End animation after 45% of the viewport 69 | scrub: true, // Synchronize with scroll 70 | }, 71 | }); 72 | }); 73 | }; 74 | 75 | // Animate specific images on scroll 76 | const animateImagesOnScroll = () => { 77 | const images = document.querySelectorAll('.content--lines .content__img:not([data-step]), .content--grid .content__img:not([data-step])'); 78 | 79 | images.forEach((image) => { 80 | gsap.fromTo(image, { 81 | scale: 0, // Start small 82 | autoAlpha: 0, // Start transparent 83 | filter: 'brightness(180%) saturate(0%)' // Start desaturated and bright 84 | }, { 85 | scale: 1, // Scale to full size 86 | autoAlpha: 1, // Fade in 87 | filter: 'brightness(100%) saturate(100%)', // Restore normal brightness and saturation 88 | duration: 1, 89 | ease: 'sine', // Smooth easing 90 | scrollTrigger: { 91 | trigger: image, 92 | start: 'top bottom', // Start animation when element enters viewport 93 | end: '+=45%', // End animation after 45% of the viewport 94 | scrub: true, 95 | }, 96 | }); 97 | }); 98 | }; 99 | 100 | // Add a parallax effect to `.content__text` elements 101 | const addParallaxToText = () => { 102 | const firstTextElement = document.querySelector('.content__text'); // Select the first text element 103 | if (!firstTextElement) return; // Exit if no element is found 104 | 105 | gsap.fromTo( 106 | firstTextElement, { 107 | y: 250, // Start below its original position 108 | }, { 109 | y: -250, // Move above its original position 110 | ease: 'sine', // Smooth easing 111 | scrollTrigger: { 112 | trigger: firstTextElement, 113 | start: 'top bottom', // Start when top of element enters viewport 114 | end: 'top top', // End when top of element reaches top of viewport 115 | scrub: true, // Synchronize with scroll 116 | }, 117 | } 118 | ); 119 | }; 120 | 121 | // Animate the filter effect on the `.one` element during the first scroll 122 | const animateFilterOnFirstSwitch = () => { 123 | gsap.fromTo(oneElement, { 124 | filter: 'brightness(80%)' // Start with high brightness and reduced saturation 125 | }, { 126 | filter: 'brightness(100%)', // Transition to normal state 127 | ease: 'sine', // Smooth easing 128 | scrollTrigger: { 129 | trigger: parentElement, 130 | start: 'clamp(top bottom)', // Start when parent enters viewport 131 | end: 'clamp(bottom top)', // End when parent leaves viewport 132 | scrub: true, 133 | } 134 | }); 135 | }; 136 | 137 | // Add a parallax effect to images in the `.content--column` section 138 | const addParallaxToColumnImages = () => { 139 | const columnImages = [...document.querySelectorAll('.content--column .content__img:not([data-step])')]; 140 | const totalImages = columnImages.length; 141 | const middleIndex = (totalImages - 1) / 2; // Calculate the virtual center index for symmetry 142 | 143 | columnImages.forEach((image, index) => { 144 | const intensity = Math.abs(index - middleIndex) * 75; // Calculate intensity based on distance from center 145 | 146 | gsap.fromTo(image, { 147 | y: intensity // Start with offset based on intensity 148 | }, { 149 | y: -intensity, // Move in the opposite direction 150 | ease: 'sine', // Smooth easing 151 | scrollTrigger: { 152 | trigger: image, 153 | start: 'top bottom', // Start when top of element enters viewport 154 | end: 'bottom top', // End when bottom of element leaves viewport 155 | scrub: true, 156 | }, 157 | }); 158 | }); 159 | }; 160 | 161 | const animateRelatedDemos = () => { 162 | const relatedSection = document.querySelector('.card-wrap'); 163 | const relatedDemos = [...relatedSection.querySelectorAll('.card-wrap > .card')]; 164 | 165 | gsap.from(relatedDemos, { 166 | scale: 0, 167 | ease: 'sine', 168 | stagger: { 169 | each: 0.04, 170 | from: 'center' 171 | }, 172 | scrollTrigger: { 173 | trigger: relatedSection, 174 | start: 'top bottom', 175 | end: 'clamp(center center)', 176 | scrub: true, 177 | }, 178 | }); 179 | }; 180 | 181 | // Main initialization function 182 | const init = () => { 183 | createFlipOnScrollAnimation(); // Initialize Flip animations 184 | animateSpansOnScroll(); // Animate spans on scroll 185 | animateImagesOnScroll(); // Animate images on scroll 186 | addParallaxToText(); // Add parallax effect to text 187 | addParallaxToColumnImages(); // Add parallax effect to column images 188 | animateFilterOnFirstSwitch(); // Animate the filter on the `.one` element 189 | animateRelatedDemos(); // Animate the related demos section 190 | window.addEventListener('resize', createFlipOnScrollAnimation); // Reinitialize Flip animations on resize 191 | }; 192 | 193 | // Preload images and initialize animations after images have loaded 194 | preloadImages('.one__img').then(() => { 195 | document.body.classList.remove('loading'); // Remove the 'loading' class from the body 196 | init(); // Initialize animations 197 | }); 198 | -------------------------------------------------------------------------------- /js/lenis.min.js: -------------------------------------------------------------------------------- 1 | !function(t,i){"object"==typeof exports&&"undefined"!=typeof module?module.exports=i():"function"==typeof define&&define.amd?define(i):(t="undefined"!=typeof globalThis?globalThis:t||self).Lenis=i()}(this,(function(){"use strict";function clamp(t,i,e){return Math.max(t,Math.min(i,e))}class Animate{constructor(){this.isRunning=!1,this.value=0,this.from=0,this.to=0,this.duration=0,this.currentTime=0}advance(t){var i;if(!this.isRunning)return;let e=!1;if(this.duration&&this.easing){this.currentTime+=t;const i=clamp(0,this.currentTime/this.duration,1);e=i>=1;const s=e?1:this.easing(i);this.value=this.from+(this.to-this.from)*s}else this.lerp?(this.value=function damp(t,i,e,s){return function lerp(t,i,e){return(1-e)*t+e*i}(t,i,1-Math.exp(-e*s))}(this.value,this.to,60*this.lerp,t),Math.round(this.value)===this.to&&(this.value=this.to,e=!0)):(this.value=this.to,e=!0);e&&this.stop(),null===(i=this.onUpdate)||void 0===i||i.call(this,this.value,e)}stop(){this.isRunning=!1}fromTo(t,i,{lerp:e,duration:s,easing:o,onStart:n,onUpdate:l}){this.from=this.value=t,this.to=i,this.lerp=e,this.duration=s,this.easing=o,this.currentTime=0,this.isRunning=!0,null==n||n(),this.onUpdate=l}}class Dimensions{constructor({wrapper:t,content:i,autoResize:e=!0,debounce:s=250}={}){this.width=0,this.height=0,this.scrollWidth=0,this.scrollHeight=0,this.resize=()=>{this.onWrapperResize(),this.onContentResize()},this.onWrapperResize=()=>{this.wrapper===window?(this.width=window.innerWidth,this.height=window.innerHeight):this.wrapper instanceof HTMLElement&&(this.width=this.wrapper.clientWidth,this.height=this.wrapper.clientHeight)},this.onContentResize=()=>{this.wrapper===window?(this.scrollHeight=this.content.scrollHeight,this.scrollWidth=this.content.scrollWidth):this.wrapper instanceof HTMLElement&&(this.scrollHeight=this.wrapper.scrollHeight,this.scrollWidth=this.wrapper.scrollWidth)},this.wrapper=t,this.content=i,e&&(this.debouncedResize=function debounce(t,i){let e;return function(){let s=arguments,o=this;clearTimeout(e),e=setTimeout((function(){t.apply(o,s)}),i)}}(this.resize,s),this.wrapper===window?window.addEventListener("resize",this.debouncedResize,!1):(this.wrapperResizeObserver=new ResizeObserver(this.debouncedResize),this.wrapperResizeObserver.observe(this.wrapper)),this.contentResizeObserver=new ResizeObserver(this.debouncedResize),this.contentResizeObserver.observe(this.content)),this.resize()}destroy(){var t,i;null===(t=this.wrapperResizeObserver)||void 0===t||t.disconnect(),null===(i=this.contentResizeObserver)||void 0===i||i.disconnect(),window.removeEventListener("resize",this.debouncedResize,!1)}get limit(){return{x:this.scrollWidth-this.width,y:this.scrollHeight-this.height}}}class Emitter{constructor(){this.events={}}emit(t,...i){let e=this.events[t]||[];for(let t=0,s=e.length;t{var e;this.events[t]=null===(e=this.events[t])||void 0===e?void 0:e.filter((t=>i!==t))}}off(t,i){var e;this.events[t]=null===(e=this.events[t])||void 0===e?void 0:e.filter((t=>i!==t))}destroy(){this.events={}}}const t=100/6;class VirtualScroll{constructor(i,{wheelMultiplier:e=1,touchMultiplier:s=1}){this.lastDelta={x:0,y:0},this.windowWidth=0,this.windowHeight=0,this.onTouchStart=t=>{const{clientX:i,clientY:e}=t.targetTouches?t.targetTouches[0]:t;this.touchStart.x=i,this.touchStart.y=e,this.lastDelta={x:0,y:0},this.emitter.emit("scroll",{deltaX:0,deltaY:0,event:t})},this.onTouchMove=t=>{var i,e,s,o;const{clientX:n,clientY:l}=t.targetTouches?t.targetTouches[0]:t,r=-(n-(null!==(e=null===(i=this.touchStart)||void 0===i?void 0:i.x)&&void 0!==e?e:0))*this.touchMultiplier,h=-(l-(null!==(o=null===(s=this.touchStart)||void 0===s?void 0:s.y)&&void 0!==o?o:0))*this.touchMultiplier;this.touchStart.x=n,this.touchStart.y=l,this.lastDelta={x:r,y:h},this.emitter.emit("scroll",{deltaX:r,deltaY:h,event:t})},this.onTouchEnd=t=>{this.emitter.emit("scroll",{deltaX:this.lastDelta.x,deltaY:this.lastDelta.y,event:t})},this.onWheel=i=>{let{deltaX:e,deltaY:s,deltaMode:o}=i;e*=1===o?t:2===o?this.windowWidth:1,s*=1===o?t:2===o?this.windowHeight:1,e*=this.wheelMultiplier,s*=this.wheelMultiplier,this.emitter.emit("scroll",{deltaX:e,deltaY:s,event:i})},this.onWindowResize=()=>{this.windowWidth=window.innerWidth,this.windowHeight=window.innerHeight},this.element=i,this.wheelMultiplier=e,this.touchMultiplier=s,this.touchStart={x:null,y:null},this.emitter=new Emitter,window.addEventListener("resize",this.onWindowResize,!1),this.onWindowResize(),this.element.addEventListener("wheel",this.onWheel,{passive:!1}),this.element.addEventListener("touchstart",this.onTouchStart,{passive:!1}),this.element.addEventListener("touchmove",this.onTouchMove,{passive:!1}),this.element.addEventListener("touchend",this.onTouchEnd,{passive:!1})}on(t,i){return this.emitter.on(t,i)}destroy(){this.emitter.destroy(),window.removeEventListener("resize",this.onWindowResize,!1),this.element.removeEventListener("wheel",this.onWheel),this.element.removeEventListener("touchstart",this.onTouchStart),this.element.removeEventListener("touchmove",this.onTouchMove),this.element.removeEventListener("touchend",this.onTouchEnd)}}return class Lenis{constructor({wrapper:t=window,content:i=document.documentElement,wheelEventsTarget:e=t,eventsTarget:s=e,smoothWheel:o=!0,syncTouch:n=!1,syncTouchLerp:l=.075,touchInertiaMultiplier:r=35,duration:h,easing:a=(t=>Math.min(1,1.001-Math.pow(2,-10*t))),lerp:c=.1,infinite:d=!1,orientation:u="vertical",gestureOrientation:p="vertical",touchMultiplier:m=1,wheelMultiplier:v=1,autoResize:g=!0,prevent:w,virtualScroll:S,__experimental__naiveDimensions:f=!1}={}){this.__isScrolling=!1,this.__isStopped=!1,this.__isLocked=!1,this.userData={},this.lastVelocity=0,this.velocity=0,this.direction=0,this.onPointerDown=t=>{1===t.button&&this.reset()},this.onVirtualScroll=t=>{if("function"==typeof this.options.virtualScroll&&!1===this.options.virtualScroll(t))return;const{deltaX:i,deltaY:e,event:s}=t;if(this.emitter.emit("virtual-scroll",{deltaX:i,deltaY:e,event:s}),s.ctrlKey)return;const o=s.type.includes("touch"),n=s.type.includes("wheel");this.isTouching="touchstart"===s.type||"touchmove"===s.type;if(this.options.syncTouch&&o&&"touchstart"===s.type&&!this.isStopped&&!this.isLocked)return void this.reset();const l=0===i&&0===e,r="vertical"===this.options.gestureOrientation&&0===e||"horizontal"===this.options.gestureOrientation&&0===i;if(l||r)return;let h=s.composedPath();h=h.slice(0,h.indexOf(this.rootElement));const a=this.options.prevent;if(h.find((t=>{var i,e,s,l,r;return t instanceof Element&&("function"==typeof a&&(null==a?void 0:a(t))||(null===(i=t.hasAttribute)||void 0===i?void 0:i.call(t,"data-lenis-prevent"))||o&&(null===(e=t.hasAttribute)||void 0===e?void 0:e.call(t,"data-lenis-prevent-touch"))||n&&(null===(s=t.hasAttribute)||void 0===s?void 0:s.call(t,"data-lenis-prevent-wheel"))||(null===(l=t.classList)||void 0===l?void 0:l.contains("lenis"))&&!(null===(r=t.classList)||void 0===r?void 0:r.contains("lenis-stopped")))})))return;if(this.isStopped||this.isLocked)return void s.preventDefault();if(!(this.options.syncTouch&&o||this.options.smoothWheel&&n))return this.isScrolling="native",void this.animate.stop();s.preventDefault();let c=e;"both"===this.options.gestureOrientation?c=Math.abs(e)>Math.abs(i)?e:i:"horizontal"===this.options.gestureOrientation&&(c=i);const d=o&&this.options.syncTouch,u=o&&"touchend"===s.type&&Math.abs(c)>5;u&&(c=this.velocity*this.options.touchInertiaMultiplier),this.scrollTo(this.targetScroll+c,Object.assign({programmatic:!1},d?{lerp:u?this.options.syncTouchLerp:1}:{lerp:this.options.lerp,duration:this.options.duration,easing:this.options.easing}))},this.onNativeScroll=()=>{if(clearTimeout(this.__resetVelocityTimeout),delete this.__resetVelocityTimeout,this.__preventNextNativeScrollEvent)delete this.__preventNextNativeScrollEvent;else if(!1===this.isScrolling||"native"===this.isScrolling){const t=this.animatedScroll;this.animatedScroll=this.targetScroll=this.actualScroll,this.lastVelocity=this.velocity,this.velocity=this.animatedScroll-t,this.direction=Math.sign(this.animatedScroll-t),this.isScrolling="native",this.emit(),0!==this.velocity&&(this.__resetVelocityTimeout=setTimeout((()=>{this.lastVelocity=this.velocity,this.velocity=0,this.isScrolling=!1,this.emit()}),400))}},window.lenisVersion="1.1.9",t&&t!==document.documentElement&&t!==document.body||(t=window),this.options={wrapper:t,content:i,wheelEventsTarget:e,eventsTarget:s,smoothWheel:o,syncTouch:n,syncTouchLerp:l,touchInertiaMultiplier:r,duration:h,easing:a,lerp:c,infinite:d,gestureOrientation:p,orientation:u,touchMultiplier:m,wheelMultiplier:v,autoResize:g,prevent:w,virtualScroll:S,__experimental__naiveDimensions:f},this.animate=new Animate,this.emitter=new Emitter,this.dimensions=new Dimensions({wrapper:t,content:i,autoResize:g}),this.updateClassName(),this.userData={},this.time=0,this.velocity=this.lastVelocity=0,this.isLocked=!1,this.isStopped=!1,this.isScrolling=!1,this.targetScroll=this.animatedScroll=this.actualScroll,this.options.wrapper.addEventListener("scroll",this.onNativeScroll,!1),this.options.wrapper.addEventListener("pointerdown",this.onPointerDown,!1),this.virtualScroll=new VirtualScroll(s,{touchMultiplier:m,wheelMultiplier:v}),this.virtualScroll.on("scroll",this.onVirtualScroll)}destroy(){this.emitter.destroy(),this.options.wrapper.removeEventListener("scroll",this.onNativeScroll,!1),this.options.wrapper.removeEventListener("pointerdown",this.onPointerDown,!1),this.virtualScroll.destroy(),this.dimensions.destroy(),this.cleanUpClassName()}on(t,i){return this.emitter.on(t,i)}off(t,i){return this.emitter.off(t,i)}setScroll(t){this.isHorizontal?this.rootElement.scrollLeft=t:this.rootElement.scrollTop=t}resize(){this.dimensions.resize()}emit(){this.emitter.emit("scroll",this)}reset(){this.isLocked=!1,this.isScrolling=!1,this.animatedScroll=this.targetScroll=this.actualScroll,this.lastVelocity=this.velocity=0,this.animate.stop()}start(){this.isStopped&&(this.isStopped=!1,this.reset())}stop(){this.isStopped||(this.isStopped=!0,this.animate.stop(),this.reset())}raf(t){const i=t-(this.time||t);this.time=t,this.animate.advance(.001*i)}scrollTo(t,{offset:i=0,immediate:e=!1,lock:s=!1,duration:o=this.options.duration,easing:n=this.options.easing,lerp:l=this.options.lerp,onStart:r,onComplete:h,force:a=!1,programmatic:c=!0,userData:d={}}={}){if(!this.isStopped&&!this.isLocked||a){if("string"==typeof t&&["top","left","start"].includes(t))t=0;else if("string"==typeof t&&["bottom","right","end"].includes(t))t=this.limit;else{let e;if("string"==typeof t?e=document.querySelector(t):t instanceof HTMLElement&&(null==t?void 0:t.nodeType)&&(e=t),e){if(this.options.wrapper!==window){const t=this.rootElement.getBoundingClientRect();i-=this.isHorizontal?t.left:t.top}const s=e.getBoundingClientRect();t=(this.isHorizontal?s.left:s.top)+this.animatedScroll}}if("number"==typeof t&&(t+=i,t=Math.round(t),this.options.infinite?c&&(this.targetScroll=this.animatedScroll=this.scroll):t=clamp(0,t,this.limit),t!==this.targetScroll)){if(this.userData=d,e)return this.animatedScroll=this.targetScroll=t,this.setScroll(this.scroll),this.reset(),this.preventNextNativeScrollEvent(),this.emit(),null==h||h(this),void(this.userData={});c||(this.targetScroll=t),this.animate.fromTo(this.animatedScroll,t,{duration:o,easing:n,lerp:l,onStart:()=>{s&&(this.isLocked=!0),this.isScrolling="smooth",null==r||r(this)},onUpdate:(t,i)=>{this.isScrolling="smooth",this.lastVelocity=this.velocity,this.velocity=t-this.animatedScroll,this.direction=Math.sign(this.velocity),this.animatedScroll=t,this.setScroll(this.scroll),c&&(this.targetScroll=t),i||this.emit(),i&&(this.reset(),this.emit(),null==h||h(this),this.userData={},this.preventNextNativeScrollEvent())}})}}}preventNextNativeScrollEvent(){this.__preventNextNativeScrollEvent=!0,requestAnimationFrame((()=>{delete this.__preventNextNativeScrollEvent}))}get rootElement(){return this.options.wrapper===window?document.documentElement:this.options.wrapper}get limit(){return this.options.__experimental__naiveDimensions?this.isHorizontal?this.rootElement.scrollWidth-this.rootElement.clientWidth:this.rootElement.scrollHeight-this.rootElement.clientHeight:this.dimensions.limit[this.isHorizontal?"x":"y"]}get isHorizontal(){return"horizontal"===this.options.orientation}get actualScroll(){return this.isHorizontal?this.rootElement.scrollLeft:this.rootElement.scrollTop}get scroll(){return this.options.infinite?function modulo(t,i){return(t%i+i)%i}(this.animatedScroll,this.limit):this.animatedScroll}get progress(){return 0===this.limit?1:this.scroll/this.limit}get isScrolling(){return this.__isScrolling}set isScrolling(t){this.__isScrolling!==t&&(this.__isScrolling=t,this.updateClassName())}get isStopped(){return this.__isStopped}set isStopped(t){this.__isStopped!==t&&(this.__isStopped=t,this.updateClassName())}get isLocked(){return this.__isLocked}set isLocked(t){this.__isLocked!==t&&(this.__isLocked=t,this.updateClassName())}get isSmooth(){return"smooth"===this.isScrolling}get className(){let t="lenis";return this.isStopped&&(t+=" lenis-stopped"),this.isLocked&&(t+=" lenis-locked"),this.isScrolling&&(t+=" lenis-scrolling"),"smooth"===this.isScrolling&&(t+=" lenis-smooth"),t}updateClassName(){this.cleanUpClassName(),this.rootElement.className=`${this.rootElement.className} ${this.className}`.trim()}cleanUpClassName(){this.rootElement.className=this.rootElement.className.replace(/lenis(-\w+)?/g,"").trim()}}})); 2 | //# sourceMappingURL=lenis.min.js.map -------------------------------------------------------------------------------- /js/smoothscroll.js: -------------------------------------------------------------------------------- 1 | // Initializes smooth scrolling with Lenis and integrates it with GSAP's ScrollTrigger. 2 | // Function to set up smooth scrolling. 3 | const initSmoothScrolling = () => { 4 | // Initialize Lenis for smooth scroll effects. Lerp value controls the smoothness. 5 | const lenis = new Lenis({ lerp: 0.1 }); 6 | 7 | // Sync ScrollTrigger with Lenis' scroll updates. 8 | lenis.on('scroll', ScrollTrigger.update); 9 | 10 | // Ensure GSAP animations are in sync with Lenis' scroll frame updates. 11 | gsap.ticker.add(time => { 12 | lenis.raf(time * 1000); // Convert GSAP's time to milliseconds for Lenis. 13 | }); 14 | 15 | // Turn off GSAP's default lag smoothing to avoid conflicts with Lenis. 16 | gsap.ticker.lagSmoothing(0); 17 | }; 18 | 19 | // Activate the smooth scrolling feature. 20 | initSmoothScrolling(); 21 | -------------------------------------------------------------------------------- /js/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Preloads images specified by the CSS selector. 3 | * @function 4 | * @param {string} [selector='img'] - CSS selector for target images. 5 | * @returns {Promise} - Resolves when all specified images are loaded. 6 | */ 7 | const preloadImages = (selector = 'img') => { 8 | return new Promise((resolve) => { 9 | // The imagesLoaded library is used to ensure all images (including backgrounds) are fully loaded. 10 | imagesLoaded(document.querySelectorAll(selector), {background: true}, resolve); 11 | }); 12 | }; 13 | 14 | // Exporting utility functions for use in other modules. 15 | export { 16 | preloadImages 17 | }; --------------------------------------------------------------------------------