@widelab-nc/widelab 1.1.47 → 1.1.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.js CHANGED
@@ -116,25 +116,25 @@ function contactFormOpenAnimation() {
116
116
  }
117
117
 
118
118
  //Smooth scroll init
119
- const lenis = new Lenis({
120
- duration: 1.2,
121
- easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
122
- });
123
- function lenisScroll() {
124
- lenis.on('scroll', ScrollTrigger.update);
125
- gsap.ticker.add((time)=>{
126
- lenis.raf(time * 1000)
127
- })
128
- gsap.ticker.lagSmoothing(0)
129
- function raf(time) {
130
- lenis.raf(time);
131
- requestAnimationFrame(raf);
132
- }
119
+ const lenis = new Lenis({
120
+ duration: 1.2,
121
+ easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
122
+ });
123
+ function lenisScroll() {
124
+ lenis.on('scroll', ScrollTrigger.update);
125
+ gsap.ticker.add((time)=>{
126
+ lenis.raf(time * 1000)
127
+ })
128
+ gsap.ticker.lagSmoothing(0)
129
+ function raf(time) {
130
+ lenis.raf(time);
133
131
  requestAnimationFrame(raf);
134
132
  }
133
+ requestAnimationFrame(raf);
134
+ }
135
135
 
136
- // Lazy load videos
137
- function lazyLoadVideos() {
136
+ // Lazy load videos
137
+ function lazyLoadVideos() {
138
138
  let lazyVideos = [].slice.call(document.querySelectorAll("video.lazyload"));
139
139
  if ("IntersectionObserver" in window) {
140
140
  let lazyVideoObserver = new IntersectionObserver(function(entries, observer) {
@@ -155,54 +155,54 @@ function contactFormOpenAnimation() {
155
155
  }
156
156
  }
157
157
 
158
- // Reload page on browser back action
159
- function reloadOnBack() {
160
- window.addEventListener('pageshow', function (event) {
161
- if (event.persisted) {
162
- window.location.reload();
163
- }
164
- });
165
- }
158
+ // Reload page on browser back action
159
+ function reloadOnBack() {
160
+ window.addEventListener('pageshow', function (event) {
161
+ if (event.persisted) {
162
+ window.location.reload();
163
+ }
164
+ });
165
+ }
166
166
 
167
- // Scroll disable when mobile menu opened
168
- function disableScrollMenu() {
169
- function observeNavOverlay() {
170
- const target = document.querySelector('.w-nav-overlay');
171
- const config = { attributes: true, attributeFilter: ['style'] };
172
- const callback = function(mutationsList, observer) {
173
- for(const mutation of mutationsList) {
174
- if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
175
- const displayValue = target.style.display;
176
- if (displayValue === 'none') {
177
- document.body.classList.remove('is-scroll-off');
178
- lenis.start();
179
- } else {
180
- document.body.classList.add('is-scroll-off');
181
- lenis.stop();
182
- }
167
+ // Scroll disable when mobile menu opened
168
+ function disableScrollMenu() {
169
+ function observeNavOverlay() {
170
+ const target = document.querySelector('.w-nav-overlay');
171
+ const config = { attributes: true, attributeFilter: ['style'] };
172
+ const callback = function(mutationsList, observer) {
173
+ for(const mutation of mutationsList) {
174
+ if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
175
+ const displayValue = target.style.display;
176
+ if (displayValue === 'none') {
177
+ document.body.classList.remove('is-scroll-off');
178
+ lenis.start();
179
+ } else {
180
+ document.body.classList.add('is-scroll-off');
181
+ lenis.stop();
183
182
  }
184
183
  }
185
- };
186
- const observer = new MutationObserver(callback);
187
- observer.observe(target, config);
188
- }
189
- observeNavOverlay();
184
+ }
185
+ };
186
+ const observer = new MutationObserver(callback);
187
+ observer.observe(target, config);
190
188
  }
189
+ observeNavOverlay();
190
+ }
191
191
 
192
- // Hero move to reveal footer
193
- function revealFooter() {
194
- const footer = document.querySelector('.is-footer');
195
- if (footer) {
196
- gsap.to('#heroSection', {
197
- scrollTrigger: {
198
- trigger: '#bottomWrapper',
199
- start: 'top bottom',
200
- toggleActions: 'restart none none reverse',
201
- },
202
- autoAlpha: 0,
203
- });
204
- }
192
+ // Hero move to reveal footer
193
+ function revealFooter() {
194
+ const footer = document.querySelector('.is-footer');
195
+ if (footer) {
196
+ gsap.to('#heroSection', {
197
+ scrollTrigger: {
198
+ trigger: '#bottomWrapper',
199
+ start: 'top bottom',
200
+ toggleActions: 'restart none none reverse',
201
+ },
202
+ autoAlpha: 0,
203
+ });
205
204
  }
205
+ }
206
206
 
207
207
  // Page load animation (no-op below 992px)
208
208
  function pageLoadAnimation() {
@@ -273,9 +273,9 @@ function pageTransitionAnimation() {
273
273
  }
274
274
  });
275
275
  }
276
- // Header on scroll animation
276
+ // Header on scroll animation
277
277
  const infoBar = document.querySelector('.info-bar');
278
- const showHideHeader = gsap.timeline({ paused: true,})
278
+ const showHideHeader = gsap.timeline({ paused: true,})
279
279
  showHideHeader.to('.navbar', {
280
280
  y: '-100%',
281
281
  duration: 0.2,
@@ -288,19 +288,19 @@ if (infoBar) {
288
288
  ease: 'loader2',
289
289
  }, "<") }
290
290
 
291
- // Custom cursor on mousedown and mouseup
292
- function customCursorOnClick() {
293
- const cursorElements = document.querySelectorAll('[wide="customCursor"]');
294
- const customCursor = document.querySelector('.custom_cursor');
295
- cursorElements.forEach((element) => {
296
- element.addEventListener('mousedown', function () {
297
- customCursor.style.transform = 'scale3d(0.8, 0.8, 1)';
298
- });
299
- element.addEventListener('mouseup', function () {
300
- customCursor.style.transform = 'scale3d(1, 1, 1)';
301
- });
291
+ // Custom cursor on mousedown and mouseup
292
+ function customCursorOnClick() {
293
+ const cursorElements = document.querySelectorAll('[wide="customCursor"]');
294
+ const customCursor = document.querySelector('.custom_cursor');
295
+ cursorElements.forEach((element) => {
296
+ element.addEventListener('mousedown', function () {
297
+ customCursor.style.transform = 'scale3d(0.8, 0.8, 1)';
302
298
  });
303
- }
299
+ element.addEventListener('mouseup', function () {
300
+ customCursor.style.transform = 'scale3d(1, 1, 1)';
301
+ });
302
+ });
303
+ }
304
304
 
305
305
  // === SKILLS TRIGGER HARD-FIX (drop-in) ===
306
306
  (function () {
@@ -410,43 +410,43 @@ if (infoBar) {
410
410
  }
411
411
  })();
412
412
 
413
- // Header scroll trigger
414
- window.standardHeaderScrollAnimation = function() {
415
- ScrollTrigger.create({
416
- start: 'top top',
417
- endTrigger: '.bottom-wrapper',
418
- end: 'bottom bottom',
419
- onUpdate: (self) => {
420
- self.direction === 1 ? showHideHeader.play() : showHideHeader.reverse();
421
- },
422
- });
423
- }
413
+ // Header scroll trigger
414
+ window.standardHeaderScrollAnimation = function() {
415
+ ScrollTrigger.create({
416
+ start: 'top top',
417
+ endTrigger: '.bottom-wrapper',
418
+ end: 'bottom bottom',
419
+ onUpdate: (self) => {
420
+ self.direction === 1 ? showHideHeader.play() : showHideHeader.reverse();
421
+ },
422
+ });
423
+ }
424
424
 
425
- // Place video inside the text
426
- window.videoInsideText = function(e) {
425
+ // Place video inside the text
426
+ window.videoInsideText = function(e) {
427
427
  const headlineContent = e.querySelector('[class*="copy-this"]');
428
428
  const headlineSpan = e.querySelector('[class*="headline-span"]');
429
429
  headlineSpan.appendChild(headlineContent);
430
430
  }
431
431
 
432
- // Span video mask animation
433
- window.spanVideoMaskAnimation = function(e) {
434
- gsap.to(e, {
435
- scrollTrigger: { trigger: e, start: 'bottom bottom-=5%' },
436
- width: 0,
437
- ease: 'loader2',
438
- duration: 0.6,
439
- });
440
- }
432
+ // Span video mask animation
433
+ window.spanVideoMaskAnimation = function(e) {
434
+ gsap.to(e, {
435
+ scrollTrigger: { trigger: e, start: 'bottom bottom-=5%' },
436
+ width: 0,
437
+ ease: 'loader2',
438
+ duration: 0.6,
439
+ });
440
+ }
441
441
 
442
- // Custom cursor text change
443
- window.customCursorText = function(e) {
444
- e.addEventListener('mouseenter', () => {
445
- const wideCursorTextValue = e.getAttribute('wideCursorText');
446
- const customCursorTextElement = document.querySelector('.custom_cursor_text');
447
- customCursorTextElement.innerHTML = wideCursorTextValue;
448
- });
449
- }
442
+ // Custom cursor text change
443
+ window.customCursorText = function(e) {
444
+ e.addEventListener('mouseenter', () => {
445
+ const wideCursorTextValue = e.getAttribute('wideCursorText');
446
+ const customCursorTextElement = document.querySelector('.custom_cursor_text');
447
+ customCursorTextElement.innerHTML = wideCursorTextValue;
448
+ });
449
+ }
450
450
 
451
451
  let articleModalOpen;
452
452
  function articleModalOpenAnimation() {
@@ -594,14 +594,40 @@ window.expandableProcessSticky = function (e) {
594
594
  }
595
595
  }
596
596
 
597
+ // Click the row (number + title) to scroll to the trigger point that opens this item.
598
+ // Ignore clicks that originate inside the already-open .process-item panel (e.g. reading
599
+ // the description or clicking a link inside it shouldn't re-trigger a scroll).
600
+ function scrollToIndex(index) {
601
+ var rect = wrapper.getBoundingClientRect();
602
+ var absoluteTop = rect.top + window.pageYOffset;
603
+ var total = wrapper.offsetHeight - window.innerHeight;
604
+ if (total <= 0) return;
605
+ var progress = (index + 0.5) / (count + 1);
606
+ var targetY = absoluteTop + progress * total;
607
+
608
+ lenis.scrollTo(targetY, {
609
+ duration: 1.2,
610
+ easing: function (t) { return Math.min(1, 1.001 - Math.pow(2, -10 * t)); },
611
+ });
612
+ }
613
+
614
+ for (var i = 0; i < items.length; i++) {
615
+ (function (index) {
616
+ var tab = items[index].closest('.process-wrapper');
617
+ if (!tab) return;
618
+ tab.addEventListener('click', function (event) {
619
+ if (event.target.closest('.process-item')) return;
620
+ scrollToIndex(index);
621
+ });
622
+ })(i);
623
+ }
624
+
597
625
  window.addEventListener('scroll', onScrollOrResize, { passive: true });
598
626
  window.addEventListener('resize', onResize);
599
627
  update();
600
628
  };
601
629
 
602
630
 
603
-
604
-
605
631
  window.faqDropdowns = function (e) {
606
632
  var wrapper = e;
607
633
  if (!wrapper || wrapper.dataset.faqDropdownsInit === 'true') return;
@@ -651,9 +677,6 @@ window.faqDropdowns = function (e) {
651
677
  };
652
678
 
653
679
 
654
-
655
-
656
-
657
680
  window.navbarThemeWatcher = function () {
658
681
  function checkNavbarTheme() {
659
682
  var stack = document.elementsFromPoint(window.innerWidth / 2, 20);
@@ -680,10 +703,6 @@ window.navbarThemeWatcher = function () {
680
703
  };
681
704
 
682
705
 
683
-
684
-
685
-
686
-
687
706
  window.stickyServices = function (e) {
688
707
  var wrapper = e;
689
708
  if (!wrapper || wrapper.dataset.stickyServicesInit === 'true') return;
@@ -697,6 +716,7 @@ window.stickyServices = function (e) {
697
716
 
698
717
  var currentActive = -1;
699
718
  var displayedProgress = 0;
719
+ var pendingIndex = -1; // set while a click-triggered scroll is animating
700
720
 
701
721
  function setActive(index) {
702
722
  if (index === currentActive) return;
@@ -719,6 +739,21 @@ window.stickyServices = function (e) {
719
739
 
720
740
  function loop() {
721
741
  var target = getTargetProgress();
742
+
743
+ // While a click-triggered scroll is in flight, keep the clicked tab
744
+ // forced active instead of letting the lerp below pull it back to the
745
+ // tab that matches the not-yet-moved real scroll position.
746
+ if (pendingIndex !== -1) {
747
+ var pendingProgress = (pendingIndex + 0.5) / count;
748
+ if (Math.abs(target - pendingProgress) < 0.02) {
749
+ pendingIndex = -1; // real scroll has caught up, resume normal driving
750
+ } else {
751
+ setActive(pendingIndex);
752
+ requestAnimationFrame(loop);
753
+ return;
754
+ }
755
+ }
756
+
722
757
  displayedProgress += (target - displayedProgress) * 0.18;
723
758
  if (Math.abs(target - displayedProgress) < 0.001) {
724
759
  displayedProgress = target;
@@ -728,12 +763,36 @@ window.stickyServices = function (e) {
728
763
  requestAnimationFrame(loop);
729
764
  }
730
765
 
731
- loop();
732
- };
766
+ // Click a tab to scroll to the point where it becomes active, forcing it
767
+ // active immediately instead of waiting for the scroll animation to finish.
768
+ function scrollToIndex(index) {
769
+ var rect = wrapper.getBoundingClientRect();
770
+ var absoluteTop = rect.top + window.pageYOffset;
771
+ var total = wrapper.offsetHeight - window.innerHeight;
772
+ if (total <= 0) return;
773
+ var progress = (index + 0.5) / count;
774
+ var targetY = absoluteTop + progress * total;
733
775
 
776
+ pendingIndex = index;
777
+ displayedProgress = progress;
778
+ setActive(index);
734
779
 
780
+ lenis.scrollTo(targetY, {
781
+ duration: 1.2,
782
+ easing: function (t) { return Math.min(1, 1.001 - Math.pow(2, -10 * t)); },
783
+ });
784
+ }
735
785
 
786
+ for (var k = 0; k < navItems.length; k++) {
787
+ (function (index) {
788
+ navItems[index].addEventListener('click', function () {
789
+ scrollToIndex(index);
790
+ });
791
+ })(k);
792
+ }
736
793
 
794
+ loop();
795
+ };
737
796
 
738
797
 
739
798
  window.heroAnimationOnLoad = function(e) {
@@ -845,8 +904,6 @@ window.heroAnimationOnLoad = function(e) {
845
904
  };
846
905
 
847
906
 
848
-
849
-
850
907
  // Case study mask animation + pill fade-in (full, iOS-safe, L->R reveal)
851
908
  window.caseStudyInteraction = function (e) {
852
909
  const mask = e.querySelector('.portfolio_item_image-mask');
@@ -928,220 +985,219 @@ window.caseStudyInteraction = function (e) {
928
985
  };
929
986
 
930
987
 
988
+ // Reviews slider
989
+ window.reviewsSlider = function(e) {
990
+ // Put content of static slide into list
991
+ const staticContent = e.querySelector(
992
+ '.splide__slide.reviews_collection_item.is-static'
993
+ ).innerHTML;
994
+ const dynamicElement = e.querySelector('.reviews_collection_item');
995
+ dynamicElement.innerHTML = staticContent;
996
+ dynamicElement.classList.add('is-static');
931
997
 
932
- // Reviews slider
933
- window.reviewsSlider = function(e) {
934
- // Put content of static slide into list
935
- const staticContent = e.querySelector(
936
- '.splide__slide.reviews_collection_item.is-static'
937
- ).innerHTML;
938
- const dynamicElement = e.querySelector('.reviews_collection_item');
939
- dynamicElement.innerHTML = staticContent;
940
- dynamicElement.classList.add('is-static');
941
-
942
- // Init reviews splide
943
- const reviewsSplide = new Splide(e, {
944
- type: 'slide',
945
- fixedWidth: '24.5rem',
946
- rewind: true,
947
- focus: 0,
948
- padding: { left: '2.5rem', right: 0 },
949
- gap: 0,
950
- omitEnd: true,
951
- arrows: false,
952
- drag: false,
953
- easing: 'cubic-bezier(0.83, 0, 0.17, 1)',
954
- snap: true,
955
- classes: {
956
- pagination: 'splide__pagination reviews-pagination',
957
- page: 'splide__pagination__page reviews-page',
958
- },
959
- breakpoints: {
960
- 992: { fixedWidth: '17.438rem', padding: { left: '1.75rem' }, drag: 'free', snap: false },
961
- 480: { fixedWidth: '16.25rem', padding: { left: '1.375rem' }},
962
- },
963
- }).mount();
964
-
965
- // Next slide on click
966
- if (window.innerWidth > 992) {
967
- reviewsSplide.on('click', function () {
968
- reviewsSplide.go('+1');
969
- });
970
- }
998
+ // Init reviews splide
999
+ const reviewsSplide = new Splide(e, {
1000
+ type: 'slide',
1001
+ fixedWidth: '24.5rem',
1002
+ rewind: true,
1003
+ focus: 0,
1004
+ padding: { left: '2.5rem', right: 0 },
1005
+ gap: 0,
1006
+ omitEnd: true,
1007
+ arrows: false,
1008
+ drag: false,
1009
+ easing: 'cubic-bezier(0.83, 0, 0.17, 1)',
1010
+ snap: true,
1011
+ classes: {
1012
+ pagination: 'splide__pagination reviews-pagination',
1013
+ page: 'splide__pagination__page reviews-page',
1014
+ },
1015
+ breakpoints: {
1016
+ 992: { fixedWidth: '17.438rem', padding: { left: '1.75rem' }, drag: 'free', snap: false },
1017
+ 480: { fixedWidth: '16.25rem', padding: { left: '1.375rem' }},
1018
+ },
1019
+ }).mount();
971
1020
 
972
- // Animation in
973
- gsap.from(e, {
974
- scrollTrigger: {
975
- trigger: e,
976
- start: 'top bottom',
977
- end: 'bottom bottom-=15%',
978
- scrub: 1,
979
- once: true,
980
- },
981
- x: '10%',
982
- opacity: 0,
983
- ease: 'linear',
1021
+ // Next slide on click
1022
+ if (window.innerWidth > 992) {
1023
+ reviewsSplide.on('click', function () {
1024
+ reviewsSplide.go('+1');
984
1025
  });
985
1026
  }
986
1027
 
987
- // Facts slider
988
- window.factsSlider = function(e) {
989
- // Facts slider splide initialize
990
- const factsSplide = new Splide(e, {
991
- type: 'loop',
992
- perPage: 1,
993
- gap: 0,
994
- arrows: false,
995
- drag: false,
996
- duration: 0.15,
997
- easing: 'cubic-bezier(0.83, 0, 0.17, 1)',
998
- classes: {
999
- pagination: 'splide__pagination facts-pagination',
1000
- page: 'splide__pagination__page facts-page',
1001
- },
1002
- breakpoints: {
1003
- 992: { gap: '1.75rem', drag: true },
1004
- 480: { gap: '1.375rem' },
1005
- },
1006
- }).mount();
1007
- // Next on click
1008
- if (window.innerWidth > 992) {
1009
- factsSplide.on('click', function () {
1010
- factsSplide.go('+1');
1011
- });
1012
- }
1028
+ // Animation in
1029
+ gsap.from(e, {
1030
+ scrollTrigger: {
1031
+ trigger: e,
1032
+ start: 'top bottom',
1033
+ end: 'bottom bottom-=15%',
1034
+ scrub: 1,
1035
+ once: true,
1036
+ },
1037
+ x: '10%',
1038
+ opacity: 0,
1039
+ ease: 'linear',
1040
+ });
1041
+ }
1013
1042
 
1014
- // Click on external link
1015
- const externalLink = e.querySelectorAll('.external_link.is-cursor');
1016
- // Loop through each element and execute customCursorIn.reverse()
1017
- externalLink.forEach((link) => {
1018
- link.addEventListener('click', () => {
1019
- event.stopPropagation();
1020
- });
1043
+ // Facts slider
1044
+ window.factsSlider = function(e) {
1045
+ // Facts slider splide initialize
1046
+ const factsSplide = new Splide(e, {
1047
+ type: 'loop',
1048
+ perPage: 1,
1049
+ gap: 0,
1050
+ arrows: false,
1051
+ drag: false,
1052
+ duration: 0.15,
1053
+ easing: 'cubic-bezier(0.83, 0, 0.17, 1)',
1054
+ classes: {
1055
+ pagination: 'splide__pagination facts-pagination',
1056
+ page: 'splide__pagination__page facts-page',
1057
+ },
1058
+ breakpoints: {
1059
+ 992: { gap: '1.75rem', drag: true },
1060
+ 480: { gap: '1.375rem' },
1061
+ },
1062
+ }).mount();
1063
+ // Next on click
1064
+ if (window.innerWidth > 992) {
1065
+ factsSplide.on('click', function () {
1066
+ factsSplide.go('+1');
1021
1067
  });
1068
+ }
1022
1069
 
1023
- // Animations
1024
- // Function to play video on the active slide
1025
- function playActiveSlideVideo(newIndex) {
1026
- var activeSlide = factsSplide.Components.Elements.slides[newIndex];
1027
- var activeVideo = activeSlide.querySelector('video');
1028
- if (activeVideo) {
1029
- activeVideo.play();
1030
- }
1031
- }
1032
-
1033
- // Function to pause and rewind videos on inactive slides
1034
- function pauseAndRewindInactiveVideos(newIndex) {
1035
- var slides = factsSplide.Components.Elements.slides;
1036
- slides.forEach(function (slide, index) {
1037
- var video = slide.querySelector('video');
1038
- if (video && index !== newIndex) {
1039
- video.pause();
1040
- video.currentTime = 0; // rewind the video
1041
- }
1042
- });
1043
- }
1044
- // Function to animate elements on the active slide
1045
- function animateSlideElements(slide) {
1046
- gsap.fromTo(
1047
- [
1048
- slide.querySelector('.is-h4'),
1049
- slide.querySelector('.facts-slide_legend-wrapper'),
1050
- slide.querySelector('.facts-slide_diagram-wrapper'),
1051
- slide.querySelector('.facts-slide_source')
1052
- ],
1053
- {
1054
- x: '2rem',
1055
- opacity: 0
1056
- },
1057
- {
1058
- x: '0',
1059
- opacity: 1,
1060
- stagger: 0.2,
1061
- duration: 0.5,
1062
- easing: 'loader2'
1063
- }
1064
- );
1065
- }
1066
- // Function to reset animation for the elements in the slide
1067
- function resetSlideAnimation(slide) {
1068
- gsap.set(
1069
- [
1070
- slide.querySelector('.is-h4'),
1071
- slide.querySelector('.facts-slide_legend-wrapper'),
1072
- slide.querySelector('.facts-slide_diagram-wrapper'),
1073
- slide.querySelector('.facts-slide_source')
1074
- ],
1075
- {
1076
- x: '2rem',
1077
- opacity: 0
1078
- }
1079
- );
1080
- }
1081
- // Event listener for 'move' event
1082
- factsSplide.on('move', function (newIndex) {
1083
- playActiveSlideVideo(newIndex);
1084
- var activeSlide = factsSplide.Components.Elements.slides[newIndex];
1085
- animateSlideElements(activeSlide);
1086
- });
1087
- // Event listener for 'moved' event
1088
- factsSplide.on('moved', function (oldIndex) {
1089
- pauseAndRewindInactiveVideos(oldIndex);
1090
- var previousSlide = factsSplide.Components.Elements.slides[oldIndex];
1091
- resetSlideAnimation(previousSlide);
1070
+ // Click on external link
1071
+ const externalLink = e.querySelectorAll('.external_link.is-cursor');
1072
+ // Loop through each element and execute customCursorIn.reverse()
1073
+ externalLink.forEach((link) => {
1074
+ link.addEventListener('click', () => {
1075
+ event.stopPropagation();
1092
1076
  });
1077
+ });
1093
1078
 
1079
+ // Animations
1080
+ // Function to play video on the active slide
1081
+ function playActiveSlideVideo(newIndex) {
1082
+ var activeSlide = factsSplide.Components.Elements.slides[newIndex];
1083
+ var activeVideo = activeSlide.querySelector('video');
1084
+ if (activeVideo) {
1085
+ activeVideo.play();
1086
+ }
1094
1087
  }
1095
1088
 
1096
- // Team slider
1097
- window.teamSlider = function(e) {
1098
- // Randomize order of slides
1099
- const teamList = e.querySelector('.team_collection_list');
1100
- const teamItems = Array.from(teamList.children);
1101
- teamItems.sort(function () {
1102
- return 0.5 - Math.random();
1103
- });
1104
- teamItems.forEach(function (item) {
1105
- teamList.appendChild(item);
1089
+ // Function to pause and rewind videos on inactive slides
1090
+ function pauseAndRewindInactiveVideos(newIndex) {
1091
+ var slides = factsSplide.Components.Elements.slides;
1092
+ slides.forEach(function (slide, index) {
1093
+ var video = slide.querySelector('video');
1094
+ if (video && index !== newIndex) {
1095
+ video.pause();
1096
+ video.currentTime = 0; // rewind the video
1097
+ }
1106
1098
  });
1107
-
1108
- // Team slider splide initialize
1109
- new Splide(e, {
1110
- type: 'slide',
1111
- fixedWidth: '20%',
1112
- padding: { left: '2.5rem', right: 0 },
1113
- focus: 0,
1114
- gap: 0,
1115
- pagination: false,
1116
- omitEnd: true,
1117
- arrows: false,
1118
- drag: true,
1119
- easing: 'cubic-bezier(0.83, 0, 0.17, 1)',
1120
- snap: true,
1121
- classes: {
1122
- pagination: 'splide__pagination facts-pagination',
1123
- page: 'splide__pagination__page facts-page',
1124
- },
1125
- breakpoints: {
1126
- 992: { fixedWidth: '40%', padding: { left: '1.75rem' }, drag: 'free', snap: false },
1127
- 560: { fixedWidth: '75%', padding: { left: '1.375rem' }, drag: 'free', snap: false },
1128
- },
1129
- }).mount();
1130
-
1131
- // Animation in
1132
- gsap.from(e, {
1133
- scrollTrigger: {
1134
- trigger: e,
1135
- start: 'top bottom',
1136
- end: 'bottom bottom',
1137
- scrub: 1,
1138
- once: true,
1099
+ }
1100
+ // Function to animate elements on the active slide
1101
+ function animateSlideElements(slide) {
1102
+ gsap.fromTo(
1103
+ [
1104
+ slide.querySelector('.is-h4'),
1105
+ slide.querySelector('.facts-slide_legend-wrapper'),
1106
+ slide.querySelector('.facts-slide_diagram-wrapper'),
1107
+ slide.querySelector('.facts-slide_source')
1108
+ ],
1109
+ {
1110
+ x: '2rem',
1111
+ opacity: 0
1139
1112
  },
1140
- x: '10%',
1141
- opacity: 0,
1142
- ease: 'linear',
1143
- });
1113
+ {
1114
+ x: '0',
1115
+ opacity: 1,
1116
+ stagger: 0.2,
1117
+ duration: 0.5,
1118
+ easing: 'loader2'
1119
+ }
1120
+ );
1144
1121
  }
1122
+ // Function to reset animation for the elements in the slide
1123
+ function resetSlideAnimation(slide) {
1124
+ gsap.set(
1125
+ [
1126
+ slide.querySelector('.is-h4'),
1127
+ slide.querySelector('.facts-slide_legend-wrapper'),
1128
+ slide.querySelector('.facts-slide_diagram-wrapper'),
1129
+ slide.querySelector('.facts-slide_source')
1130
+ ],
1131
+ {
1132
+ x: '2rem',
1133
+ opacity: 0
1134
+ }
1135
+ );
1136
+ }
1137
+ // Event listener for 'move' event
1138
+ factsSplide.on('move', function (newIndex) {
1139
+ playActiveSlideVideo(newIndex);
1140
+ var activeSlide = factsSplide.Components.Elements.slides[newIndex];
1141
+ animateSlideElements(activeSlide);
1142
+ });
1143
+ // Event listener for 'moved' event
1144
+ factsSplide.on('moved', function (oldIndex) {
1145
+ pauseAndRewindInactiveVideos(oldIndex);
1146
+ var previousSlide = factsSplide.Components.Elements.slides[oldIndex];
1147
+ resetSlideAnimation(previousSlide);
1148
+ });
1149
+
1150
+ }
1151
+
1152
+ // Team slider
1153
+ window.teamSlider = function(e) {
1154
+ // Randomize order of slides
1155
+ const teamList = e.querySelector('.team_collection_list');
1156
+ const teamItems = Array.from(teamList.children);
1157
+ teamItems.sort(function () {
1158
+ return 0.5 - Math.random();
1159
+ });
1160
+ teamItems.forEach(function (item) {
1161
+ teamList.appendChild(item);
1162
+ });
1163
+
1164
+ // Team slider splide initialize
1165
+ new Splide(e, {
1166
+ type: 'slide',
1167
+ fixedWidth: '20%',
1168
+ padding: { left: '2.5rem', right: 0 },
1169
+ focus: 0,
1170
+ gap: 0,
1171
+ pagination: false,
1172
+ omitEnd: true,
1173
+ arrows: false,
1174
+ drag: true,
1175
+ easing: 'cubic-bezier(0.83, 0, 0.17, 1)',
1176
+ snap: true,
1177
+ classes: {
1178
+ pagination: 'splide__pagination facts-pagination',
1179
+ page: 'splide__pagination__page facts-page',
1180
+ },
1181
+ breakpoints: {
1182
+ 992: { fixedWidth: '40%', padding: { left: '1.75rem' }, drag: 'free', snap: false },
1183
+ 560: { fixedWidth: '75%', padding: { left: '1.375rem' }, drag: 'free', snap: false },
1184
+ },
1185
+ }).mount();
1186
+
1187
+ // Animation in
1188
+ gsap.from(e, {
1189
+ scrollTrigger: {
1190
+ trigger: e,
1191
+ start: 'top bottom',
1192
+ end: 'bottom bottom',
1193
+ scrub: 1,
1194
+ once: true,
1195
+ },
1196
+ x: '10%',
1197
+ opacity: 0,
1198
+ ease: 'linear',
1199
+ });
1200
+ }
1145
1201
 
1146
1202
  // Partner slider
1147
1203
  window.partnerSlider = function (e) {
@@ -1189,68 +1245,68 @@ window.partnerSlider = function (e) {
1189
1245
  ease: 'linear',
1190
1246
  });
1191
1247
  };
1192
- // Element padding change on scroll
1193
- window.elementPaddingChange = function(e) {
1194
- gsap.to(e, {
1195
- scrollTrigger: {
1196
- trigger: e,
1197
- start: 'top bottom',
1198
- end: 'top top',
1199
- toggleActions: 'restart none none reverse',
1200
- scrub: 1,
1248
+ // Element padding change on scroll
1249
+ window.elementPaddingChange = function(e) {
1250
+ gsap.to(e, {
1251
+ scrollTrigger: {
1252
+ trigger: e,
1253
+ start: 'top bottom',
1254
+ end: 'top top',
1255
+ toggleActions: 'restart none none reverse',
1256
+ scrub: 1,
1257
+ },
1258
+ paddingLeft: '0rem',
1259
+ paddingRight: '0rem',
1260
+ ease: 'linear',
1261
+ });
1262
+ }
1263
+
1264
+ // Section bg change
1265
+ window.sectionBgChange = function(e) {
1266
+ gsap.set(e, { backgroundColor: '#fff' });
1267
+ gsap.set('#heroNavbarLottie path', { fill: 'rgb(21, 21, 21)' });
1268
+ const sectionsBgChange = gsap.timeline({
1269
+ duration: 0.15,
1270
+ ease: 'loader2',
1271
+ scrollTrigger: {
1272
+ trigger: e,
1273
+ start: 'top center',
1274
+ end: 'bottom top',
1275
+ toggleActions: 'play reverse play reverse',
1276
+ },
1277
+ });
1278
+ sectionsBgChange.to(['#skills', '#portfolio'], {
1279
+ backgroundColor: '#151515',
1280
+ }, '<');
1281
+ sectionsBgChange.to(".info-bar_wrapper", {
1282
+ backgroundColor: '#2E2E2E',
1283
+ color: "#fff"
1284
+ }, '<');
1285
+ // Change navbar element on bg animation
1286
+ sectionsBgChange.to(
1287
+ [
1288
+ '.button_small',
1289
+ '.button_small_icon',
1290
+ '.navbar_brand_svg',
1291
+ '#heroNavbarLottie path ',
1292
+ ],
1293
+ {
1294
+ color: '#fff',
1295
+ fill: 'rgb(254, 254, 254)',
1296
+ },
1297
+ '<'
1298
+ );
1299
+ if (window.innerWidth > 992) {
1300
+ sectionsBgChange.to(
1301
+ '.navbar_menu_link',
1302
+ {
1303
+ color: '#fff',
1304
+ fill: 'rgb(254, 254, 254)',
1201
1305
  },
1202
- paddingLeft: '0rem',
1203
- paddingRight: '0rem',
1204
- ease: 'linear',
1205
- });
1306
+ '<'
1307
+ );
1206
1308
  }
1207
-
1208
- // Section bg change
1209
- window.sectionBgChange = function(e) {
1210
- gsap.set(e, { backgroundColor: '#fff' });
1211
- gsap.set('#heroNavbarLottie path', { fill: 'rgb(21, 21, 21)' });
1212
- const sectionsBgChange = gsap.timeline({
1213
- duration: 0.15,
1214
- ease: 'loader2',
1215
- scrollTrigger: {
1216
- trigger: e,
1217
- start: 'top center',
1218
- end: 'bottom top',
1219
- toggleActions: 'play reverse play reverse',
1220
- },
1221
- });
1222
- sectionsBgChange.to(['#skills', '#portfolio'], {
1223
- backgroundColor: '#151515',
1224
- }, '<');
1225
- sectionsBgChange.to(".info-bar_wrapper", {
1226
- backgroundColor: '#2E2E2E',
1227
- color: "#fff"
1228
- }, '<');
1229
- // Change navbar element on bg animation
1230
- sectionsBgChange.to(
1231
- [
1232
- '.button_small',
1233
- '.button_small_icon',
1234
- '.navbar_brand_svg',
1235
- '#heroNavbarLottie path ',
1236
- ],
1237
- {
1238
- color: '#fff',
1239
- fill: 'rgb(254, 254, 254)',
1240
- },
1241
- '<'
1242
- );
1243
- if (window.innerWidth > 992) {
1244
- sectionsBgChange.to(
1245
- '.navbar_menu_link',
1246
- {
1247
- color: '#fff',
1248
- fill: 'rgb(254, 254, 254)',
1249
- },
1250
- '<'
1251
- );
1252
- }
1253
- }
1309
+ }
1254
1310
 
1255
1311
  // Awwwards badge color change
1256
1312
  window.badgeColorChange = function(e) {
@@ -1272,262 +1328,261 @@ window.badgeColorChange = function(e) {
1272
1328
  }, '<');
1273
1329
  }
1274
1330
 
1275
- // Client logos animation
1276
- window.clientLogosAnimation = function(e) {
1277
- const logosStagger = 0.15;
1278
- const logoMask = e.querySelectorAll('[class*="item_mask"]');
1279
- const logoImg = e.querySelectorAll('[class*="image"]');
1280
- gsap.from(logoMask, {
1281
- scrollTrigger: {
1282
- trigger: logoMask,
1283
- start: 'top bottom-=25%',
1284
- },
1285
- width: '0%',
1286
- duration: 0.7,
1287
- ease: 'loader2',
1288
- stagger: logosStagger,
1331
+ // Client logos animation
1332
+ window.clientLogosAnimation = function(e) {
1333
+ const logosStagger = 0.15;
1334
+ const logoMask = e.querySelectorAll('[class*="item_mask"]');
1335
+ const logoImg = e.querySelectorAll('[class*="image"]');
1336
+ gsap.from(logoMask, {
1337
+ scrollTrigger: {
1338
+ trigger: logoMask,
1339
+ start: 'top bottom-=25%',
1340
+ },
1341
+ width: '0%',
1342
+ duration: 0.7,
1343
+ ease: 'loader2',
1344
+ stagger: logosStagger,
1345
+ });
1346
+ gsap.from(logoImg, {
1347
+ scrollTrigger: {
1348
+ trigger: logoMask,
1349
+ start: 'top bottom-=25%',
1350
+ },
1351
+ opacity: 0,
1352
+ delay: 0.4,
1353
+ duration: 0.45,
1354
+ ease: 'loader2',
1355
+ stagger: logosStagger,
1356
+ });
1357
+ }
1358
+
1359
+ // Hero span video on hover
1360
+ window.heroSpanVideoOnHover = function(e) {
1361
+ window.customCursorText(e);
1362
+ const heroSpanContentAnimation = gsap.timeline({ paused: true, ease: 'loader2' });
1363
+ heroSpanContentAnimation.to('.hero-line-mask', { clipPath: 'none', duration: 0.05 }, '>');
1364
+ heroSpanContentAnimation.to(e, { scale: 2, duration: 0.35 }, '>');
1365
+ if (window.innerWidth > 992) {
1366
+ e.addEventListener('mouseenter', () => {
1367
+ heroSpanContentAnimation.timeScale(1).play();
1289
1368
  });
1290
- gsap.from(logoImg, {
1291
- scrollTrigger: {
1292
- trigger: logoMask,
1293
- start: 'top bottom-=25%',
1294
- },
1295
- opacity: 0,
1296
- delay: 0.4,
1297
- duration: 0.45,
1298
- ease: 'loader2',
1299
- stagger: logosStagger,
1369
+ e.addEventListener('mouseleave', () => {
1370
+ heroSpanContentAnimation.timeScale(2).reverse();
1300
1371
  });
1301
1372
  }
1373
+ }
1302
1374
 
1303
- // Hero span video on hover
1304
- window.heroSpanVideoOnHover = function(e) {
1305
- window.customCursorText(e);
1306
- const heroSpanContentAnimation = gsap.timeline({ paused: true, ease: 'loader2' });
1307
- heroSpanContentAnimation.to('.hero-line-mask', { clipPath: 'none', duration: 0.05 }, '>');
1308
- heroSpanContentAnimation.to(e, { scale: 2, duration: 0.35 }, '>');
1309
- if (window.innerWidth > 992) {
1310
- e.addEventListener('mouseenter', () => {
1311
- heroSpanContentAnimation.timeScale(1).play();
1312
- });
1313
- e.addEventListener('mouseleave', () => {
1314
- heroSpanContentAnimation.timeScale(2).reverse();
1315
- });
1375
+ // Reel modal
1376
+ window.reelModal = function() {
1377
+ const reelTrigger = document.querySelectorAll('[wideClick="playReel"]');
1378
+ const reelModal = document.querySelector('.reel-modal');
1379
+ const reelModalPlayer = document.getElementById('fullReel');
1380
+ const reelPlayback = 0;
1381
+ const reelModalShow = gsap.timeline({ ease: 'loader2', paused: true });
1382
+ reelModalShow.to(reelModal, { display: 'flex', opacity: 0, duration: 0 });
1383
+ reelModalShow.to(reelModal, { opacity: 1, duration: 0.6 }, '>');
1384
+ if (window.innerWidth > 992) {
1385
+ reelTrigger.forEach((element) => {
1386
+ element.addEventListener('click', () => {
1387
+ lenis.stop();
1388
+ reelModalShow.timeScale(1).play();
1389
+ // Set the video source based on whether the player can handle WebM
1390
+ if (reelPlayback === 0) {
1391
+ if (reelModalPlayer.canPlayType('video/webm')) {
1392
+ reelModalPlayer.src =
1393
+ 'https://widelabco.sfo3.cdn.digitaloceanspaces.com/Widelab-reel.webm';
1394
+ } else {
1395
+ reelModalPlayer.src =
1396
+ 'https://widelabco.sfo3.cdn.digitaloceanspaces.com/Widelab-reel.mp4';
1397
+ }
1398
+ // Load the video
1399
+ reelModalPlayer.load();
1400
+ } else {
1401
+ return;
1402
+ }
1403
+
1404
+ reelModalPlayer.play();
1405
+ });
1406
+ });
1407
+ reelModal.addEventListener('click', () => {
1408
+ reelModalShow.timeScale(4).reverse();
1409
+ reelModalPlayer.pause();
1410
+ lenis.start();
1411
+ });
1412
+ window.addEventListener('keydown', function (event) {
1413
+ // The key code for the ESC key is 27
1414
+ if (event.keyCode === 27) {
1415
+ reelModalShow.timeScale(4).reverse();
1416
+ reelModalPlayer.pause();
1417
+ lenis.start();
1316
1418
  }
1317
- }
1419
+ });
1420
+ } else {
1421
+ reelTrigger.forEach((element) => {
1422
+ element.addEventListener('click', () => {
1423
+ // Set the video source based on whether the player can handle WebM
1424
+ if (reelModalPlayer.canPlayType('video/webm')) {
1425
+ reelModalPlayer.src = 'https://widelabco.sfo3.cdn.digitaloceanspaces.com/Widelab-reel.webm';
1426
+ } else {
1427
+ reelModalPlayer.src = 'https://widelabco.sfo3.cdn.digitaloceanspaces.com/Widelab-reel.mp4';
1428
+ }
1318
1429
 
1319
- // Reel modal
1320
- window.reelModal = function() {
1321
- const reelTrigger = document.querySelectorAll('[wideClick="playReel"]');
1322
- const reelModal = document.querySelector('.reel-modal');
1323
- const reelModalPlayer = document.getElementById('fullReel');
1324
- const reelPlayback = 0;
1325
- const reelModalShow = gsap.timeline({ ease: 'loader2', paused: true });
1326
- reelModalShow.to(reelModal, { display: 'flex', opacity: 0, duration: 0 });
1327
- reelModalShow.to(reelModal, { opacity: 1, duration: 0.6 }, '>');
1328
- if (window.innerWidth > 992) {
1329
- reelTrigger.forEach((element) => {
1330
- element.addEventListener('click', () => {
1331
- lenis.stop();
1332
- reelModalShow.timeScale(1).play();
1333
- // Set the video source based on whether the player can handle WebM
1334
- if (reelPlayback === 0) {
1335
- if (reelModalPlayer.canPlayType('video/webm')) {
1336
- reelModalPlayer.src =
1337
- 'https://widelabco.sfo3.cdn.digitaloceanspaces.com/Widelab-reel.webm';
1338
- } else {
1339
- reelModalPlayer.src =
1340
- 'https://widelabco.sfo3.cdn.digitaloceanspaces.com/Widelab-reel.mp4';
1341
- }
1342
- // Load the video
1343
- reelModalPlayer.load();
1344
- } else {
1345
- return;
1346
- }
1430
+ // Load the video
1431
+ reelModalPlayer.load();
1347
1432
 
1433
+ // Add a listener to the 'canplaythrough' event
1434
+ reelModalPlayer.addEventListener(
1435
+ 'canplaythrough',
1436
+ () => {
1437
+ // Once there's enough data loaded to play through, start playback
1348
1438
  reelModalPlayer.play();
1349
- });
1350
- });
1351
- reelModal.addEventListener('click', () => {
1352
- reelModalShow.timeScale(4).reverse();
1353
- reelModalPlayer.pause();
1354
- lenis.start();
1355
- });
1356
- window.addEventListener('keydown', function (event) {
1357
- // The key code for the ESC key is 27
1358
- if (event.keyCode === 27) {
1359
- reelModalShow.timeScale(4).reverse();
1360
- reelModalPlayer.pause();
1361
- lenis.start();
1362
- }
1363
- });
1364
- } else {
1365
- reelTrigger.forEach((element) => {
1366
- element.addEventListener('click', () => {
1367
- // Set the video source based on whether the player can handle WebM
1368
- if (reelModalPlayer.canPlayType('video/webm')) {
1369
- reelModalPlayer.src = 'https://widelabco.sfo3.cdn.digitaloceanspaces.com/Widelab-reel.webm';
1370
- } else {
1371
- reelModalPlayer.src = 'https://widelabco.sfo3.cdn.digitaloceanspaces.com/Widelab-reel.mp4';
1372
- }
1373
-
1374
- // Load the video
1375
- reelModalPlayer.load();
1376
-
1377
- // Add a listener to the 'canplaythrough' event
1378
- reelModalPlayer.addEventListener(
1379
- 'canplaythrough',
1380
- () => {
1381
- // Once there's enough data loaded to play through, start playback
1382
- reelModalPlayer.play();
1383
- },
1384
- { once: true }
1385
- ); // Ensure this event only fires once per click
1386
- });
1387
- });
1388
- reelModal.addEventListener('click', () => {
1389
- reelModalPlayer.pause();
1390
- });
1391
- }
1439
+ },
1440
+ { once: true }
1441
+ ); // Ensure this event only fires once per click
1442
+ });
1443
+ });
1444
+ reelModal.addEventListener('click', () => {
1445
+ reelModalPlayer.pause();
1446
+ });
1392
1447
  }
1448
+ }
1393
1449
 
1394
- // Founders tooltip
1395
- window.foundersTooltip = function(e) {
1396
- const line = e.querySelector('.line');
1397
- const arrow = e.querySelector('.arrow');
1398
- const foundersHover = gsap.timeline({ paused: true, ease: 'loader2' });
1399
- foundersHover.from(e, {
1400
- x: '5%',
1401
- opacity: 0,
1402
- duration: 0.4,
1403
- });
1404
- foundersHover.from(
1405
- line,
1406
- {
1407
- drawSVG: '0% 0%',
1408
- duration: 0.2,
1409
- },
1410
- '>-0.2'
1411
- );
1412
- foundersHover.from(arrow, {
1450
+ // Founders tooltip
1451
+ window.foundersTooltip = function(e) {
1452
+ const line = e.querySelector('.line');
1453
+ const arrow = e.querySelector('.arrow');
1454
+ const foundersHover = gsap.timeline({ paused: true, ease: 'loader2' });
1455
+ foundersHover.from(e, {
1456
+ x: '5%',
1457
+ opacity: 0,
1458
+ duration: 0.4,
1459
+ });
1460
+ foundersHover.from(
1461
+ line,
1462
+ {
1413
1463
  drawSVG: '0% 0%',
1414
- duration: 0.15,
1415
- }),
1416
- '>';
1417
- if (window.innerWidth > 992) {
1418
- e.addEventListener('mouseenter', () => {
1419
- foundersHover.timeScale(1).play();
1420
- });
1421
- e.addEventListener('mouseleave', () => {
1422
- foundersHover.timeScale(3).reverse();
1423
- });
1424
- }
1464
+ duration: 0.2,
1465
+ },
1466
+ '>-0.2'
1467
+ );
1468
+ foundersHover.from(arrow, {
1469
+ drawSVG: '0% 0%',
1470
+ duration: 0.15,
1471
+ }),
1472
+ '>';
1473
+ if (window.innerWidth > 992) {
1474
+ e.addEventListener('mouseenter', () => {
1475
+ foundersHover.timeScale(1).play();
1476
+ });
1477
+ e.addEventListener('mouseleave', () => {
1478
+ foundersHover.timeScale(3).reverse();
1479
+ });
1425
1480
  }
1481
+ }
1426
1482
 
1427
- // Clients map actions
1428
- window.clientsMapActions = function(e) {
1429
- // Map animation
1430
- const mapAnimation = gsap.timeline({
1431
- scrollTrigger: {
1432
- trigger: '.reviews_map_base',
1433
- start: 'bottom-=160px bottom',
1434
- },
1435
- });
1436
- mapAnimation.from('.map-point', {
1483
+ // Clients map actions
1484
+ window.clientsMapActions = function(e) {
1485
+ // Map animation
1486
+ const mapAnimation = gsap.timeline({
1487
+ scrollTrigger: {
1488
+ trigger: '.reviews_map_base',
1489
+ start: 'bottom-=160px bottom',
1490
+ },
1491
+ });
1492
+ mapAnimation.from('.map-point', {
1493
+ duration: 1,
1494
+ opacity: 0,
1495
+ stagger: 0.1,
1496
+ ease: 'loader2',
1497
+ });
1498
+ mapAnimation.from(
1499
+ '.map-pin_wrapper',
1500
+ {
1437
1501
  duration: 1,
1438
1502
  opacity: 0,
1439
1503
  stagger: 0.1,
1440
1504
  ease: 'loader2',
1441
- });
1442
- mapAnimation.from(
1443
- '.map-pin_wrapper',
1444
- {
1445
- duration: 1,
1505
+ },
1506
+ '0.3'
1507
+ );
1508
+
1509
+ // Map pins animation on hover
1510
+ const allMapPins = document.querySelectorAll('.map-pin_wrapper');
1511
+ allMapPins.forEach(function (element) {
1512
+ element.addEventListener('mouseenter', function () {
1513
+ const mapPin = this.getAttribute('w-map-pin');
1514
+ const oldPin = document.querySelectorAll('.map_info-collection-item');
1515
+ const infoElements = document.querySelectorAll(
1516
+ ".map_info-collection-item[w-map-info='" + mapPin + "']"
1517
+ );
1518
+ const infoElementsAppear = gsap.timeline({});
1519
+ infoElementsAppear.to(oldPin, {
1446
1520
  opacity: 0,
1447
- stagger: 0.1,
1448
1521
  ease: 'loader2',
1449
- },
1450
- '0.3'
1451
- );
1452
-
1453
- // Map pins animation on hover
1454
- const allMapPins = document.querySelectorAll('.map-pin_wrapper');
1455
- allMapPins.forEach(function (element) {
1456
- element.addEventListener('mouseenter', function () {
1457
- const mapPin = this.getAttribute('w-map-pin');
1458
- const oldPin = document.querySelectorAll('.map_info-collection-item');
1459
- const infoElements = document.querySelectorAll(
1460
- ".map_info-collection-item[w-map-info='" + mapPin + "']"
1461
- );
1462
- const infoElementsAppear = gsap.timeline({});
1463
- infoElementsAppear.to(oldPin, {
1464
- opacity: 0,
1465
- ease: 'loader2',
1466
- duration: 0.1,
1467
- });
1468
- infoElementsAppear.to(oldPin, {
1469
- display: 'none',
1470
- duration: 0.01,
1471
- });
1472
- infoElementsAppear.to(infoElements, {
1473
- display: 'block',
1474
- duration: 0.01,
1475
- });
1476
- infoElementsAppear.to(infoElements, {
1477
- opacity: 1,
1478
- ease: 'loader2',
1479
- duration: 0.2,
1480
- });
1522
+ duration: 0.1,
1523
+ });
1524
+ infoElementsAppear.to(oldPin, {
1525
+ display: 'none',
1526
+ duration: 0.01,
1527
+ });
1528
+ infoElementsAppear.to(infoElements, {
1529
+ display: 'block',
1530
+ duration: 0.01,
1531
+ });
1532
+ infoElementsAppear.to(infoElements, {
1533
+ opacity: 1,
1534
+ ease: 'loader2',
1535
+ duration: 0.2,
1481
1536
  });
1482
1537
  });
1483
- // Map boxes link special code
1484
- const elements = document.querySelectorAll('.map_info-wrapper');
1485
- for (let i = 0; i < elements.length; i++) {
1486
- const href = elements[i].getAttribute('href');
1487
- if (href && href.length > 3) {
1488
- elements[i].style.cursor = 'pointer';
1489
- }
1490
- }
1538
+ });
1539
+ // Map boxes link special code
1540
+ const elements = document.querySelectorAll('.map_info-wrapper');
1541
+ for (let i = 0; i < elements.length; i++) {
1542
+ const href = elements[i].getAttribute('href');
1543
+ if (href && href.length > 3) {
1544
+ elements[i].style.cursor = 'pointer';
1545
+ }
1491
1546
  }
1547
+ }
1492
1548
 
1493
1549
 
1494
-
1495
- // Stats section headline animation
1496
- window.statsHeadlineAnimation = function() {
1497
- const statsHeadlineAnimation = gsap.timeline({
1498
- scrollTrigger: {
1499
- trigger: '#statsKnow',
1500
- start: 'center center',
1501
- toggleActions: 'restart none none reverse',
1502
- end: '+=500',
1503
- },
1504
- pause: 'paused',
1505
- ease: 'defaultEase',
1506
- }),
1507
- homeStatsHeading = new SplitText('#statsDone', {
1508
- type: 'lines',
1509
- linesClass: 'stats-line',
1510
- }),
1511
- homeStatsHeadingMask = new SplitText('#statsDone', {
1512
- type: 'lines',
1513
- linesClass: 'stats-line-mask',
1514
- });
1515
- statsHeadlineAnimation.to(
1516
- '#statsKnow',
1517
- {
1518
- duration: 0.5,
1519
- opacity: 0,
1520
- display: 'none',
1550
+ // Stats section headline animation
1551
+ window.statsHeadlineAnimation = function() {
1552
+ const statsHeadlineAnimation = gsap.timeline({
1553
+ scrollTrigger: {
1554
+ trigger: '#statsKnow',
1555
+ start: 'center center',
1556
+ toggleActions: 'restart none none reverse',
1557
+ end: '+=500',
1521
1558
  },
1522
- '>'
1523
- );
1524
- statsHeadlineAnimation.from('.stats-line', {
1559
+ pause: 'paused',
1560
+ ease: 'defaultEase',
1561
+ }),
1562
+ homeStatsHeading = new SplitText('#statsDone', {
1563
+ type: 'lines',
1564
+ linesClass: 'stats-line',
1565
+ }),
1566
+ homeStatsHeadingMask = new SplitText('#statsDone', {
1567
+ type: 'lines',
1568
+ linesClass: 'stats-line-mask',
1569
+ });
1570
+ statsHeadlineAnimation.to(
1571
+ '#statsKnow',
1572
+ {
1525
1573
  duration: 0.5,
1526
1574
  opacity: 0,
1527
- y: '100%',
1528
- stagger: 0.25,
1529
- });
1530
- }
1575
+ display: 'none',
1576
+ },
1577
+ '>'
1578
+ );
1579
+ statsHeadlineAnimation.from('.stats-line', {
1580
+ duration: 0.5,
1581
+ opacity: 0,
1582
+ y: '100%',
1583
+ stagger: 0.25,
1584
+ });
1585
+ }
1531
1586
 
1532
1587
  // Single entry you call from x-init
1533
1588
  window.clientFilters = function () {
@@ -2151,7 +2206,7 @@ window.initBentoRevealScrub = function (container) {
2151
2206
  start: 'top 90%', // start easing in slightly later
2152
2207
  end: 'bottom 65%', // full reveal by near the end of container
2153
2208
  scrub: 0.5, // smoothing; use true for no smoothing
2154
- markers: false, // uncomment for debugging
2209
+ markers: false, // uncomment for debugging
2155
2210
  }
2156
2211
  });
2157
2212
 
@@ -2253,101 +2308,101 @@ window.initPartnerVideos = function (container) {
2253
2308
  };
2254
2309
 
2255
2310
 
2256
- // Case study - What's next interaction
2257
- window.whatsNext = function() {
2258
- const caseItem = document.querySelectorAll('.whats-next_links_item.is-case');
2259
- const allCases = document.querySelector('.whats-next_links_item.is-all');
2260
- caseItem.forEach((item) => {
2261
- const imageMask = item.querySelector('.whats-next_links_item_image_mask');
2262
- const imageWrapper = item.querySelector('.whats-next_links_item_image-wrapper');
2263
- const whatsNextHover = gsap.timeline({ paused: true, ease: 'loader2' });
2264
- whatsNextHover.to(imageWrapper, { opacity: 0.8, duration: 0.15 });
2265
- whatsNextHover.to(imageMask, { width: '0%', duration: 0.3 }, '>-0.');
2266
- item.addEventListener('mouseenter', () => {
2267
- whatsNextHover.timeScale(1).play();
2268
- caseItem.forEach((i) => {
2269
- if (i !== event.target) {
2270
- gsap.to(i, { color: '#7A7A7A', duration: 0.2, ease: 'loader2' });
2271
- }
2272
- });
2273
- });
2274
- item.addEventListener('mouseleave', () => {
2275
- whatsNextHover.timeScale(3).reverse();
2276
- caseItem.forEach((i) => {
2277
- if (i !== event.target) {
2278
- gsap.to(i, { color: '#fff', duration: 0.1, ease: 'loader2' });
2279
- }
2280
- });
2311
+ // Case study - What's next interaction
2312
+ window.whatsNext = function() {
2313
+ const caseItem = document.querySelectorAll('.whats-next_links_item.is-case');
2314
+ const allCases = document.querySelector('.whats-next_links_item.is-all');
2315
+ caseItem.forEach((item) => {
2316
+ const imageMask = item.querySelector('.whats-next_links_item_image_mask');
2317
+ const imageWrapper = item.querySelector('.whats-next_links_item_image-wrapper');
2318
+ const whatsNextHover = gsap.timeline({ paused: true, ease: 'loader2' });
2319
+ whatsNextHover.to(imageWrapper, { opacity: 0.8, duration: 0.15 });
2320
+ whatsNextHover.to(imageMask, { width: '0%', duration: 0.3 }, '>-0.');
2321
+ item.addEventListener('mouseenter', () => {
2322
+ whatsNextHover.timeScale(1).play();
2323
+ caseItem.forEach((i) => {
2324
+ if (i !== event.target) {
2325
+ gsap.to(i, { color: '#7A7A7A', duration: 0.2, ease: 'loader2' });
2326
+ }
2281
2327
  });
2282
2328
  });
2283
- allCases.addEventListener('mouseenter', () => {
2284
- gsap.to(allCases, { color: '#fff', duration: 0.2, ease: 'loader2' });
2285
- caseItem.forEach((item) => {
2286
- gsap.to(item, { color: '#7A7A7A', duration: 0.2, ease: 'loader2' });
2329
+ item.addEventListener('mouseleave', () => {
2330
+ whatsNextHover.timeScale(3).reverse();
2331
+ caseItem.forEach((i) => {
2332
+ if (i !== event.target) {
2333
+ gsap.to(i, { color: '#fff', duration: 0.1, ease: 'loader2' });
2334
+ }
2287
2335
  });
2288
2336
  });
2289
- allCases.addEventListener('mouseleave', () => {
2290
- gsap.to(allCases, { color: '#7A7A7A', duration: 0.2, ease: 'loader2' });
2291
- caseItem.forEach((item) => {
2292
- gsap.to(item, { color: '#fff', duration: 0.2, ease: 'loader2' });
2293
- });
2337
+ });
2338
+ allCases.addEventListener('mouseenter', () => {
2339
+ gsap.to(allCases, { color: '#fff', duration: 0.2, ease: 'loader2' });
2340
+ caseItem.forEach((item) => {
2341
+ gsap.to(item, { color: '#7A7A7A', duration: 0.2, ease: 'loader2' });
2294
2342
  });
2343
+ });
2344
+ allCases.addEventListener('mouseleave', () => {
2345
+ gsap.to(allCases, { color: '#7A7A7A', duration: 0.2, ease: 'loader2' });
2346
+ caseItem.forEach((item) => {
2347
+ gsap.to(item, { color: '#fff', duration: 0.2, ease: 'loader2' });
2348
+ });
2349
+ });
2295
2350
 
2296
- // Remove responsive image feature from CS pages
2297
- for (var i = 0; i < document.getElementsByTagName('img').length; i++) {
2298
- document.getElementsByTagName('img')[i].srcset = '';
2299
- }
2300
- for (var i = 0; i < document.getElementsByTagName('img').length; i++) {
2301
- document.getElementsByTagName('img')[i].sizes = '';
2302
- }
2351
+ // Remove responsive image feature from CS pages
2352
+ for (var i = 0; i < document.getElementsByTagName('img').length; i++) {
2353
+ document.getElementsByTagName('img')[i].srcset = '';
2354
+ }
2355
+ for (var i = 0; i < document.getElementsByTagName('img').length; i++) {
2356
+ document.getElementsByTagName('img')[i].sizes = '';
2303
2357
  }
2358
+ }
2304
2359
 
2305
- // Case study - images mask animation
2306
- window.csMaskAnimation = function() {
2307
- const csImageMasks = document.querySelectorAll('.portfolio_item_image-mask');
2308
- csImageMasks.forEach((mask, index) => {
2309
- if (index === 0) {
2310
- return;
2311
- }
2312
- const maskAnimation = gsap.from(mask, {
2313
- width: '100%',
2314
- duration: 0.7,
2315
- ease: 'loader2',
2316
- paused: true,
2317
- });
2318
- ScrollTrigger.create({
2319
- animation: maskAnimation,
2320
- trigger: mask,
2321
- start: 'top 80%',
2322
- onEnter: () => maskAnimation.play(),
2323
- });
2360
+ // Case study - images mask animation
2361
+ window.csMaskAnimation = function() {
2362
+ const csImageMasks = document.querySelectorAll('.portfolio_item_image-mask');
2363
+ csImageMasks.forEach((mask, index) => {
2364
+ if (index === 0) {
2365
+ return;
2366
+ }
2367
+ const maskAnimation = gsap.from(mask, {
2368
+ width: '100%',
2369
+ duration: 0.7,
2370
+ ease: 'loader2',
2371
+ paused: true,
2324
2372
  });
2325
- }
2373
+ ScrollTrigger.create({
2374
+ animation: maskAnimation,
2375
+ trigger: mask,
2376
+ start: 'top 80%',
2377
+ onEnter: () => maskAnimation.play(),
2378
+ });
2379
+ });
2380
+ }
2326
2381
 
2327
- // Update the scroll trigger on page load
2382
+ // Update the scroll trigger on page load
2328
2383
  window.updateScrollTrigger = function() {
2329
2384
  window.onload = function() {
2330
2385
  ScrollTrigger.update();
2331
2386
  };
2332
2387
  }
2333
2388
 
2334
- // Blog post main image mask animation
2335
- window.blogPostMaskAnimation = function(e) {
2336
- const blogHero = document.querySelector('#heroSection');
2337
- const blogMaskAnimation = gsap.from('.post_main-mask-ract', {
2338
- left: '0%',
2339
- ease: 'loader2',
2340
- });
2341
- ScrollTrigger.create({
2342
- animation: blogMaskAnimation,
2343
- trigger: blogHero,
2344
- start: 'top -5%',
2345
- end: 'bottom 50%',
2346
- scrub: 0.5,
2347
- });
2348
- }
2389
+ // Blog post main image mask animation
2390
+ window.blogPostMaskAnimation = function(e) {
2391
+ const blogHero = document.querySelector('#heroSection');
2392
+ const blogMaskAnimation = gsap.from('.post_main-mask-ract', {
2393
+ left: '0%',
2394
+ ease: 'loader2',
2395
+ });
2396
+ ScrollTrigger.create({
2397
+ animation: blogMaskAnimation,
2398
+ trigger: blogHero,
2399
+ start: 'top -5%',
2400
+ end: 'bottom 50%',
2401
+ scrub: 0.5,
2402
+ });
2403
+ }
2349
2404
 
2350
- // Custom checkboxes
2405
+ // Custom checkboxes
2351
2406
  window.changeCheckboxLabelColor = function() {
2352
2407
  let checkboxInputs = document.querySelectorAll('.w-checkbox-input');
2353
2408
 
@@ -2372,7 +2427,7 @@ window.changeCheckboxLabelColor = function() {
2372
2427
  });
2373
2428
  }
2374
2429
 
2375
- // Contact modal open animation
2430
+ // Contact modal open animation
2376
2431
  window.openContactModal = function() {
2377
2432
  contactFormOpen.play();
2378
2433
  document.body.classList.add('is-scroll-off');
@@ -2417,15 +2472,15 @@ window.successMsgAnimation = function(e) {
2417
2472
  ease: 'loader2',
2418
2473
  }
2419
2474
  );
2420
- successMsgAnim.to(
2421
- e,
2422
- {
2423
- width: '0%',
2424
- duration: 0.6,
2425
- ease: 'loader2',
2426
- },
2427
- '>-0.5'
2428
- );
2475
+ successMsgAnim.to(
2476
+ e,
2477
+ {
2478
+ width: '0%',
2479
+ duration: 0.6,
2480
+ ease: 'loader2',
2481
+ },
2482
+ '>-0.5'
2483
+ );
2429
2484
  successMsgAnim.from(
2430
2485
  '#successParagraph',
2431
2486
  {
@@ -2472,7 +2527,6 @@ window.contactUsHide = function(e) {
2472
2527
  }
2473
2528
 
2474
2529
 
2475
-
2476
2530
  window.expandablePadSticky = function (e) {
2477
2531
  var wrapper = e;
2478
2532
  if (!wrapper || wrapper.dataset.expandablePadStickyInit === 'true') return;
@@ -2517,13 +2571,38 @@ window.expandablePadSticky = function (e) {
2517
2571
  }
2518
2572
  }
2519
2573
 
2574
+ // Click a tab (the title row next to .service_expanded) to scroll to its trigger point
2575
+ function scrollToIndex(index) {
2576
+ var rect = wrapper.getBoundingClientRect();
2577
+ var absoluteTop = rect.top + window.pageYOffset;
2578
+ var total = wrapper.offsetHeight - window.innerHeight;
2579
+ if (total <= 0) return;
2580
+ var progress = (index + 0.5) / (count + 1);
2581
+ var targetY = absoluteTop + progress * total;
2582
+
2583
+ lenis.scrollTo(targetY, {
2584
+ duration: 1.2,
2585
+ easing: function (t) { return Math.min(1, 1.001 - Math.pow(2, -10 * t)); },
2586
+ });
2587
+ }
2588
+
2589
+ for (var i = 0; i < items.length; i++) {
2590
+ (function (index) {
2591
+ var parent = items[index].parentElement;
2592
+ var tab = parent ? parent.querySelector('.service_item-wrapper.is-p-l') : null;
2593
+ if (!tab) return;
2594
+ tab.addEventListener('click', function () {
2595
+ scrollToIndex(index);
2596
+ });
2597
+ })(i);
2598
+ }
2599
+
2520
2600
  window.addEventListener('scroll', onScrollOrResize, { passive: true });
2521
2601
  window.addEventListener('resize', onResize);
2522
2602
  update();
2523
2603
  };
2524
2604
 
2525
2605
 
2526
-
2527
2606
  // Refresh Gsap scrollTriggers
2528
2607
  window.scrollTriggerRefresh = function() {
2529
2608
  function refreshScrollTrigger() {
@@ -2537,7 +2616,7 @@ window.scrollTriggerRefresh = function() {
2537
2616
 
2538
2617
  // Info bar close animation
2539
2618
  window.closeInfoBar = function() {
2540
- const infoBarClose = gsap.timeline({});
2619
+ const infoBarClose = gsap.timeline({});
2541
2620
  infoBarClose.to('.info-bar', {
2542
2621
  height: 0,
2543
2622
  autoAlpha: 0,
@@ -2558,31 +2637,29 @@ window.closeInfoBar = function() {
2558
2637
  }
2559
2638
 
2560
2639
 
2640
+ // !!!!!!!!! Keep this Alpine init at the end !!!!!!!!!
2641
+ window.Webflow ||= [];
2642
+ window.Webflow.push(() => {
2561
2643
 
2562
-
2563
- // !!!!!!!!! Keep this Alpine init at the end !!!!!!!!!
2564
- window.Webflow ||= [];
2565
- window.Webflow.push(() => {
2566
-
2567
- console.log('The new code source is loaded!');
2568
- initAlpine();
2569
- lazyLoadVideos();
2570
- if (Webflow.env("editor") === undefined) {
2571
- lenisScroll();
2572
- lenis.start();
2573
- } else {
2574
- console.log('Editor mode ON');
2575
- lenis.destroy();
2576
- }
2577
- customGsapEasing();
2578
- reloadOnBack();
2579
- revealFooter();
2580
- pageLoadAnimation();
2581
- pageTransitionAnimation();
2582
- customCursorOnClick();
2583
- contactFormOpenAnimation();
2584
- disableScrollMenu();
2585
- scrollToHashOnLoad();
2586
- initClientLogosAnimation();
2587
- articleModalOpenAnimation();
2588
- });
2644
+ console.log('The new code source is loaded!');
2645
+ initAlpine();
2646
+ lazyLoadVideos();
2647
+ if (Webflow.env("editor") === undefined) {
2648
+ lenisScroll();
2649
+ lenis.start();
2650
+ } else {
2651
+ console.log('Editor mode ON');
2652
+ lenis.destroy();
2653
+ }
2654
+ customGsapEasing();
2655
+ reloadOnBack();
2656
+ revealFooter();
2657
+ pageLoadAnimation();
2658
+ pageTransitionAnimation();
2659
+ customCursorOnClick();
2660
+ contactFormOpenAnimation();
2661
+ disableScrollMenu();
2662
+ scrollToHashOnLoad();
2663
+ initClientLogosAnimation();
2664
+ articleModalOpenAnimation();
2665
+ });