@widelab-nc/widelab 1.1.46 → 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() {
@@ -550,6 +550,131 @@ window.hueAwardsAnimation = function(e) {
550
550
  };
551
551
 
552
552
 
553
+ window.expandableProcessSticky = function (e) {
554
+ var wrapper = e;
555
+ if (!wrapper || wrapper.dataset.expandableProcessStickyInit === 'true') return;
556
+ wrapper.dataset.expandableProcessStickyInit = 'true';
557
+
558
+ var items = wrapper.querySelectorAll('.process-item');
559
+ var count = items.length;
560
+ if (count === 0) return;
561
+
562
+ var currentActive = -1;
563
+ var ticking = false;
564
+
565
+ function setActive(index) {
566
+ if (index === currentActive) return;
567
+ currentActive = index;
568
+ for (var i = 0; i < items.length; i++) {
569
+ var isTarget = i === index;
570
+ items[i].classList.toggle('is-active', isTarget);
571
+ items[i].style.height = isTarget ? items[i].scrollHeight + 'px' : '0px';
572
+ }
573
+ }
574
+
575
+ function update() {
576
+ ticking = false;
577
+ var rect = wrapper.getBoundingClientRect();
578
+ var total = wrapper.offsetHeight - window.innerHeight;
579
+ if (total <= 0) { setActive(0); return; }
580
+ var scrolled = -rect.top;
581
+ var progress = Math.min(1, Math.max(0, scrolled / total));
582
+ var activeIndex = Math.min(count - 1, Math.floor(progress * (count + 1)));
583
+ setActive(activeIndex);
584
+ }
585
+
586
+ function onScrollOrResize() {
587
+ if (!ticking) { requestAnimationFrame(update); ticking = true; }
588
+ }
589
+
590
+ function onResize() {
591
+ onScrollOrResize();
592
+ if (currentActive !== -1) {
593
+ items[currentActive].style.height = items[currentActive].scrollHeight + 'px';
594
+ }
595
+ }
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
+
625
+ window.addEventListener('scroll', onScrollOrResize, { passive: true });
626
+ window.addEventListener('resize', onResize);
627
+ update();
628
+ };
629
+
630
+
631
+ window.faqDropdowns = function (e) {
632
+ var wrapper = e;
633
+ if (!wrapper || wrapper.dataset.faqDropdownsInit === 'true') return;
634
+ wrapper.dataset.faqDropdownsInit = 'true';
635
+
636
+ var faqItems = wrapper.querySelectorAll('.faq_ci');
637
+ var count = faqItems.length;
638
+ if (count === 0) return;
639
+
640
+ var currentActive = -1;
641
+
642
+ function setActive(index) {
643
+ currentActive = index;
644
+ for (var i = 0; i < count; i++) {
645
+ var isTarget = i === index;
646
+ var faqCi = faqItems[i];
647
+ var item = faqCi.querySelector('.faq-item');
648
+ var verticalBar = faqCi.querySelector('.is-vertical');
649
+
650
+ if (item) {
651
+ item.classList.toggle('is-active', isTarget);
652
+ item.style.height = isTarget ? item.scrollHeight + 'px' : '0px';
653
+ }
654
+ if (verticalBar) {
655
+ verticalBar.classList.toggle('is-active', isTarget);
656
+ }
657
+ }
658
+ }
659
+
660
+ // Keeps the open item's height correct if content reflows on resize (e.g. text wrapping)
661
+ function onResize() {
662
+ if (currentActive === -1) return;
663
+ var item = faqItems[currentActive].querySelector('.faq-item');
664
+ if (item) item.style.height = item.scrollHeight + 'px';
665
+ }
666
+
667
+ for (var i = 0; i < count; i++) {
668
+ (function (index) {
669
+ faqItems[index].addEventListener('click', function () {
670
+ var nextIndex = currentActive === index ? -1 : index;
671
+ setActive(nextIndex);
672
+ });
673
+ })(i);
674
+ }
675
+
676
+ window.addEventListener('resize', onResize);
677
+ };
553
678
 
554
679
 
555
680
  window.navbarThemeWatcher = function () {
@@ -578,10 +703,6 @@ window.navbarThemeWatcher = function () {
578
703
  };
579
704
 
580
705
 
581
-
582
-
583
-
584
-
585
706
  window.stickyServices = function (e) {
586
707
  var wrapper = e;
587
708
  if (!wrapper || wrapper.dataset.stickyServicesInit === 'true') return;
@@ -595,6 +716,7 @@ window.stickyServices = function (e) {
595
716
 
596
717
  var currentActive = -1;
597
718
  var displayedProgress = 0;
719
+ var pendingIndex = -1; // set while a click-triggered scroll is animating
598
720
 
599
721
  function setActive(index) {
600
722
  if (index === currentActive) return;
@@ -617,6 +739,21 @@ window.stickyServices = function (e) {
617
739
 
618
740
  function loop() {
619
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
+
620
757
  displayedProgress += (target - displayedProgress) * 0.18;
621
758
  if (Math.abs(target - displayedProgress) < 0.001) {
622
759
  displayedProgress = target;
@@ -626,12 +763,36 @@ window.stickyServices = function (e) {
626
763
  requestAnimationFrame(loop);
627
764
  }
628
765
 
629
- loop();
630
- };
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;
631
775
 
776
+ pendingIndex = index;
777
+ displayedProgress = progress;
778
+ setActive(index);
632
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
+ }
633
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
+ }
634
793
 
794
+ loop();
795
+ };
635
796
 
636
797
 
637
798
  window.heroAnimationOnLoad = function(e) {
@@ -743,8 +904,6 @@ window.heroAnimationOnLoad = function(e) {
743
904
  };
744
905
 
745
906
 
746
-
747
-
748
907
  // Case study mask animation + pill fade-in (full, iOS-safe, L->R reveal)
749
908
  window.caseStudyInteraction = function (e) {
750
909
  const mask = e.querySelector('.portfolio_item_image-mask');
@@ -826,220 +985,219 @@ window.caseStudyInteraction = function (e) {
826
985
  };
827
986
 
828
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');
829
997
 
830
- // Reviews slider
831
- window.reviewsSlider = function(e) {
832
- // Put content of static slide into list
833
- const staticContent = e.querySelector(
834
- '.splide__slide.reviews_collection_item.is-static'
835
- ).innerHTML;
836
- const dynamicElement = e.querySelector('.reviews_collection_item');
837
- dynamicElement.innerHTML = staticContent;
838
- dynamicElement.classList.add('is-static');
839
-
840
- // Init reviews splide
841
- const reviewsSplide = new Splide(e, {
842
- type: 'slide',
843
- fixedWidth: '24.5rem',
844
- rewind: true,
845
- focus: 0,
846
- padding: { left: '2.5rem', right: 0 },
847
- gap: 0,
848
- omitEnd: true,
849
- arrows: false,
850
- drag: false,
851
- easing: 'cubic-bezier(0.83, 0, 0.17, 1)',
852
- snap: true,
853
- classes: {
854
- pagination: 'splide__pagination reviews-pagination',
855
- page: 'splide__pagination__page reviews-page',
856
- },
857
- breakpoints: {
858
- 992: { fixedWidth: '17.438rem', padding: { left: '1.75rem' }, drag: 'free', snap: false },
859
- 480: { fixedWidth: '16.25rem', padding: { left: '1.375rem' }},
860
- },
861
- }).mount();
862
-
863
- // Next slide on click
864
- if (window.innerWidth > 992) {
865
- reviewsSplide.on('click', function () {
866
- reviewsSplide.go('+1');
867
- });
868
- }
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();
869
1020
 
870
- // Animation in
871
- gsap.from(e, {
872
- scrollTrigger: {
873
- trigger: e,
874
- start: 'top bottom',
875
- end: 'bottom bottom-=15%',
876
- scrub: 1,
877
- once: true,
878
- },
879
- x: '10%',
880
- opacity: 0,
881
- ease: 'linear',
1021
+ // Next slide on click
1022
+ if (window.innerWidth > 992) {
1023
+ reviewsSplide.on('click', function () {
1024
+ reviewsSplide.go('+1');
882
1025
  });
883
1026
  }
884
1027
 
885
- // Facts slider
886
- window.factsSlider = function(e) {
887
- // Facts slider splide initialize
888
- const factsSplide = new Splide(e, {
889
- type: 'loop',
890
- perPage: 1,
891
- gap: 0,
892
- arrows: false,
893
- drag: false,
894
- duration: 0.15,
895
- easing: 'cubic-bezier(0.83, 0, 0.17, 1)',
896
- classes: {
897
- pagination: 'splide__pagination facts-pagination',
898
- page: 'splide__pagination__page facts-page',
899
- },
900
- breakpoints: {
901
- 992: { gap: '1.75rem', drag: true },
902
- 480: { gap: '1.375rem' },
903
- },
904
- }).mount();
905
- // Next on click
906
- if (window.innerWidth > 992) {
907
- factsSplide.on('click', function () {
908
- factsSplide.go('+1');
909
- });
910
- }
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
+ }
911
1042
 
912
- // Click on external link
913
- const externalLink = e.querySelectorAll('.external_link.is-cursor');
914
- // Loop through each element and execute customCursorIn.reverse()
915
- externalLink.forEach((link) => {
916
- link.addEventListener('click', () => {
917
- event.stopPropagation();
918
- });
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');
919
1067
  });
1068
+ }
920
1069
 
921
- // Animations
922
- // Function to play video on the active slide
923
- function playActiveSlideVideo(newIndex) {
924
- var activeSlide = factsSplide.Components.Elements.slides[newIndex];
925
- var activeVideo = activeSlide.querySelector('video');
926
- if (activeVideo) {
927
- activeVideo.play();
928
- }
929
- }
930
-
931
- // Function to pause and rewind videos on inactive slides
932
- function pauseAndRewindInactiveVideos(newIndex) {
933
- var slides = factsSplide.Components.Elements.slides;
934
- slides.forEach(function (slide, index) {
935
- var video = slide.querySelector('video');
936
- if (video && index !== newIndex) {
937
- video.pause();
938
- video.currentTime = 0; // rewind the video
939
- }
940
- });
941
- }
942
- // Function to animate elements on the active slide
943
- function animateSlideElements(slide) {
944
- gsap.fromTo(
945
- [
946
- slide.querySelector('.is-h4'),
947
- slide.querySelector('.facts-slide_legend-wrapper'),
948
- slide.querySelector('.facts-slide_diagram-wrapper'),
949
- slide.querySelector('.facts-slide_source')
950
- ],
951
- {
952
- x: '2rem',
953
- opacity: 0
954
- },
955
- {
956
- x: '0',
957
- opacity: 1,
958
- stagger: 0.2,
959
- duration: 0.5,
960
- easing: 'loader2'
961
- }
962
- );
963
- }
964
- // Function to reset animation for the elements in the slide
965
- function resetSlideAnimation(slide) {
966
- gsap.set(
967
- [
968
- slide.querySelector('.is-h4'),
969
- slide.querySelector('.facts-slide_legend-wrapper'),
970
- slide.querySelector('.facts-slide_diagram-wrapper'),
971
- slide.querySelector('.facts-slide_source')
972
- ],
973
- {
974
- x: '2rem',
975
- opacity: 0
976
- }
977
- );
978
- }
979
- // Event listener for 'move' event
980
- factsSplide.on('move', function (newIndex) {
981
- playActiveSlideVideo(newIndex);
982
- var activeSlide = factsSplide.Components.Elements.slides[newIndex];
983
- animateSlideElements(activeSlide);
984
- });
985
- // Event listener for 'moved' event
986
- factsSplide.on('moved', function (oldIndex) {
987
- pauseAndRewindInactiveVideos(oldIndex);
988
- var previousSlide = factsSplide.Components.Elements.slides[oldIndex];
989
- 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();
990
1076
  });
1077
+ });
991
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
+ }
992
1087
  }
993
1088
 
994
- // Team slider
995
- window.teamSlider = function(e) {
996
- // Randomize order of slides
997
- const teamList = e.querySelector('.team_collection_list');
998
- const teamItems = Array.from(teamList.children);
999
- teamItems.sort(function () {
1000
- return 0.5 - Math.random();
1001
- });
1002
- teamItems.forEach(function (item) {
1003
- 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
+ }
1004
1098
  });
1005
-
1006
- // Team slider splide initialize
1007
- new Splide(e, {
1008
- type: 'slide',
1009
- fixedWidth: '20%',
1010
- padding: { left: '2.5rem', right: 0 },
1011
- focus: 0,
1012
- gap: 0,
1013
- pagination: false,
1014
- omitEnd: true,
1015
- arrows: false,
1016
- drag: true,
1017
- easing: 'cubic-bezier(0.83, 0, 0.17, 1)',
1018
- snap: true,
1019
- classes: {
1020
- pagination: 'splide__pagination facts-pagination',
1021
- page: 'splide__pagination__page facts-page',
1022
- },
1023
- breakpoints: {
1024
- 992: { fixedWidth: '40%', padding: { left: '1.75rem' }, drag: 'free', snap: false },
1025
- 560: { fixedWidth: '75%', padding: { left: '1.375rem' }, drag: 'free', snap: false },
1026
- },
1027
- }).mount();
1028
-
1029
- // Animation in
1030
- gsap.from(e, {
1031
- scrollTrigger: {
1032
- trigger: e,
1033
- start: 'top bottom',
1034
- end: 'bottom bottom',
1035
- scrub: 1,
1036
- 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
1037
1112
  },
1038
- x: '10%',
1039
- opacity: 0,
1040
- ease: 'linear',
1041
- });
1113
+ {
1114
+ x: '0',
1115
+ opacity: 1,
1116
+ stagger: 0.2,
1117
+ duration: 0.5,
1118
+ easing: 'loader2'
1119
+ }
1120
+ );
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
+ );
1042
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
+ }
1043
1201
 
1044
1202
  // Partner slider
1045
1203
  window.partnerSlider = function (e) {
@@ -1087,68 +1245,68 @@ window.partnerSlider = function (e) {
1087
1245
  ease: 'linear',
1088
1246
  });
1089
1247
  };
1090
- // Element padding change on scroll
1091
- window.elementPaddingChange = function(e) {
1092
- gsap.to(e, {
1093
- scrollTrigger: {
1094
- trigger: e,
1095
- start: 'top bottom',
1096
- end: 'top top',
1097
- toggleActions: 'restart none none reverse',
1098
- 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)',
1099
1305
  },
1100
- paddingLeft: '0rem',
1101
- paddingRight: '0rem',
1102
- ease: 'linear',
1103
- });
1306
+ '<'
1307
+ );
1104
1308
  }
1105
-
1106
- // Section bg change
1107
- window.sectionBgChange = function(e) {
1108
- gsap.set(e, { backgroundColor: '#fff' });
1109
- gsap.set('#heroNavbarLottie path', { fill: 'rgb(21, 21, 21)' });
1110
- const sectionsBgChange = gsap.timeline({
1111
- duration: 0.15,
1112
- ease: 'loader2',
1113
- scrollTrigger: {
1114
- trigger: e,
1115
- start: 'top center',
1116
- end: 'bottom top',
1117
- toggleActions: 'play reverse play reverse',
1118
- },
1119
- });
1120
- sectionsBgChange.to(['#skills', '#portfolio'], {
1121
- backgroundColor: '#151515',
1122
- }, '<');
1123
- sectionsBgChange.to(".info-bar_wrapper", {
1124
- backgroundColor: '#2E2E2E',
1125
- color: "#fff"
1126
- }, '<');
1127
- // Change navbar element on bg animation
1128
- sectionsBgChange.to(
1129
- [
1130
- '.button_small',
1131
- '.button_small_icon',
1132
- '.navbar_brand_svg',
1133
- '#heroNavbarLottie path ',
1134
- ],
1135
- {
1136
- color: '#fff',
1137
- fill: 'rgb(254, 254, 254)',
1138
- },
1139
- '<'
1140
- );
1141
- if (window.innerWidth > 992) {
1142
- sectionsBgChange.to(
1143
- '.navbar_menu_link',
1144
- {
1145
- color: '#fff',
1146
- fill: 'rgb(254, 254, 254)',
1147
- },
1148
- '<'
1149
- );
1150
- }
1151
- }
1309
+ }
1152
1310
 
1153
1311
  // Awwwards badge color change
1154
1312
  window.badgeColorChange = function(e) {
@@ -1170,262 +1328,261 @@ window.badgeColorChange = function(e) {
1170
1328
  }, '<');
1171
1329
  }
1172
1330
 
1173
- // Client logos animation
1174
- window.clientLogosAnimation = function(e) {
1175
- const logosStagger = 0.15;
1176
- const logoMask = e.querySelectorAll('[class*="item_mask"]');
1177
- const logoImg = e.querySelectorAll('[class*="image"]');
1178
- gsap.from(logoMask, {
1179
- scrollTrigger: {
1180
- trigger: logoMask,
1181
- start: 'top bottom-=25%',
1182
- },
1183
- width: '0%',
1184
- duration: 0.7,
1185
- ease: 'loader2',
1186
- 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();
1187
1368
  });
1188
- gsap.from(logoImg, {
1189
- scrollTrigger: {
1190
- trigger: logoMask,
1191
- start: 'top bottom-=25%',
1192
- },
1193
- opacity: 0,
1194
- delay: 0.4,
1195
- duration: 0.45,
1196
- ease: 'loader2',
1197
- stagger: logosStagger,
1369
+ e.addEventListener('mouseleave', () => {
1370
+ heroSpanContentAnimation.timeScale(2).reverse();
1198
1371
  });
1199
1372
  }
1373
+ }
1200
1374
 
1201
- // Hero span video on hover
1202
- window.heroSpanVideoOnHover = function(e) {
1203
- window.customCursorText(e);
1204
- const heroSpanContentAnimation = gsap.timeline({ paused: true, ease: 'loader2' });
1205
- heroSpanContentAnimation.to('.hero-line-mask', { clipPath: 'none', duration: 0.05 }, '>');
1206
- heroSpanContentAnimation.to(e, { scale: 2, duration: 0.35 }, '>');
1207
- if (window.innerWidth > 992) {
1208
- e.addEventListener('mouseenter', () => {
1209
- heroSpanContentAnimation.timeScale(1).play();
1210
- });
1211
- e.addEventListener('mouseleave', () => {
1212
- heroSpanContentAnimation.timeScale(2).reverse();
1213
- });
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();
1214
1418
  }
1215
- }
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
+ }
1216
1429
 
1217
- // Reel modal
1218
- window.reelModal = function() {
1219
- const reelTrigger = document.querySelectorAll('[wideClick="playReel"]');
1220
- const reelModal = document.querySelector('.reel-modal');
1221
- const reelModalPlayer = document.getElementById('fullReel');
1222
- const reelPlayback = 0;
1223
- const reelModalShow = gsap.timeline({ ease: 'loader2', paused: true });
1224
- reelModalShow.to(reelModal, { display: 'flex', opacity: 0, duration: 0 });
1225
- reelModalShow.to(reelModal, { opacity: 1, duration: 0.6 }, '>');
1226
- if (window.innerWidth > 992) {
1227
- reelTrigger.forEach((element) => {
1228
- element.addEventListener('click', () => {
1229
- lenis.stop();
1230
- reelModalShow.timeScale(1).play();
1231
- // Set the video source based on whether the player can handle WebM
1232
- if (reelPlayback === 0) {
1233
- if (reelModalPlayer.canPlayType('video/webm')) {
1234
- reelModalPlayer.src =
1235
- 'https://widelabco.sfo3.cdn.digitaloceanspaces.com/Widelab-reel.webm';
1236
- } else {
1237
- reelModalPlayer.src =
1238
- 'https://widelabco.sfo3.cdn.digitaloceanspaces.com/Widelab-reel.mp4';
1239
- }
1240
- // Load the video
1241
- reelModalPlayer.load();
1242
- } else {
1243
- return;
1244
- }
1430
+ // Load the video
1431
+ reelModalPlayer.load();
1245
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
1246
1438
  reelModalPlayer.play();
1247
- });
1248
- });
1249
- reelModal.addEventListener('click', () => {
1250
- reelModalShow.timeScale(4).reverse();
1251
- reelModalPlayer.pause();
1252
- lenis.start();
1253
- });
1254
- window.addEventListener('keydown', function (event) {
1255
- // The key code for the ESC key is 27
1256
- if (event.keyCode === 27) {
1257
- reelModalShow.timeScale(4).reverse();
1258
- reelModalPlayer.pause();
1259
- lenis.start();
1260
- }
1261
- });
1262
- } else {
1263
- reelTrigger.forEach((element) => {
1264
- element.addEventListener('click', () => {
1265
- // Set the video source based on whether the player can handle WebM
1266
- if (reelModalPlayer.canPlayType('video/webm')) {
1267
- reelModalPlayer.src = 'https://widelabco.sfo3.cdn.digitaloceanspaces.com/Widelab-reel.webm';
1268
- } else {
1269
- reelModalPlayer.src = 'https://widelabco.sfo3.cdn.digitaloceanspaces.com/Widelab-reel.mp4';
1270
- }
1271
-
1272
- // Load the video
1273
- reelModalPlayer.load();
1274
-
1275
- // Add a listener to the 'canplaythrough' event
1276
- reelModalPlayer.addEventListener(
1277
- 'canplaythrough',
1278
- () => {
1279
- // Once there's enough data loaded to play through, start playback
1280
- reelModalPlayer.play();
1281
- },
1282
- { once: true }
1283
- ); // Ensure this event only fires once per click
1284
- });
1285
- });
1286
- reelModal.addEventListener('click', () => {
1287
- reelModalPlayer.pause();
1288
- });
1289
- }
1439
+ },
1440
+ { once: true }
1441
+ ); // Ensure this event only fires once per click
1442
+ });
1443
+ });
1444
+ reelModal.addEventListener('click', () => {
1445
+ reelModalPlayer.pause();
1446
+ });
1290
1447
  }
1448
+ }
1291
1449
 
1292
- // Founders tooltip
1293
- window.foundersTooltip = function(e) {
1294
- const line = e.querySelector('.line');
1295
- const arrow = e.querySelector('.arrow');
1296
- const foundersHover = gsap.timeline({ paused: true, ease: 'loader2' });
1297
- foundersHover.from(e, {
1298
- x: '5%',
1299
- opacity: 0,
1300
- duration: 0.4,
1301
- });
1302
- foundersHover.from(
1303
- line,
1304
- {
1305
- drawSVG: '0% 0%',
1306
- duration: 0.2,
1307
- },
1308
- '>-0.2'
1309
- );
1310
- 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
+ {
1311
1463
  drawSVG: '0% 0%',
1312
- duration: 0.15,
1313
- }),
1314
- '>';
1315
- if (window.innerWidth > 992) {
1316
- e.addEventListener('mouseenter', () => {
1317
- foundersHover.timeScale(1).play();
1318
- });
1319
- e.addEventListener('mouseleave', () => {
1320
- foundersHover.timeScale(3).reverse();
1321
- });
1322
- }
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
+ });
1323
1480
  }
1481
+ }
1324
1482
 
1325
- // Clients map actions
1326
- window.clientsMapActions = function(e) {
1327
- // Map animation
1328
- const mapAnimation = gsap.timeline({
1329
- scrollTrigger: {
1330
- trigger: '.reviews_map_base',
1331
- start: 'bottom-=160px bottom',
1332
- },
1333
- });
1334
- 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
+ {
1335
1501
  duration: 1,
1336
1502
  opacity: 0,
1337
1503
  stagger: 0.1,
1338
1504
  ease: 'loader2',
1339
- });
1340
- mapAnimation.from(
1341
- '.map-pin_wrapper',
1342
- {
1343
- 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, {
1344
1520
  opacity: 0,
1345
- stagger: 0.1,
1346
1521
  ease: 'loader2',
1347
- },
1348
- '0.3'
1349
- );
1350
-
1351
- // Map pins animation on hover
1352
- const allMapPins = document.querySelectorAll('.map-pin_wrapper');
1353
- allMapPins.forEach(function (element) {
1354
- element.addEventListener('mouseenter', function () {
1355
- const mapPin = this.getAttribute('w-map-pin');
1356
- const oldPin = document.querySelectorAll('.map_info-collection-item');
1357
- const infoElements = document.querySelectorAll(
1358
- ".map_info-collection-item[w-map-info='" + mapPin + "']"
1359
- );
1360
- const infoElementsAppear = gsap.timeline({});
1361
- infoElementsAppear.to(oldPin, {
1362
- opacity: 0,
1363
- ease: 'loader2',
1364
- duration: 0.1,
1365
- });
1366
- infoElementsAppear.to(oldPin, {
1367
- display: 'none',
1368
- duration: 0.01,
1369
- });
1370
- infoElementsAppear.to(infoElements, {
1371
- display: 'block',
1372
- duration: 0.01,
1373
- });
1374
- infoElementsAppear.to(infoElements, {
1375
- opacity: 1,
1376
- ease: 'loader2',
1377
- duration: 0.2,
1378
- });
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,
1379
1536
  });
1380
1537
  });
1381
- // Map boxes link special code
1382
- const elements = document.querySelectorAll('.map_info-wrapper');
1383
- for (let i = 0; i < elements.length; i++) {
1384
- const href = elements[i].getAttribute('href');
1385
- if (href && href.length > 3) {
1386
- elements[i].style.cursor = 'pointer';
1387
- }
1388
- }
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
+ }
1389
1546
  }
1547
+ }
1390
1548
 
1391
1549
 
1392
-
1393
- // Stats section headline animation
1394
- window.statsHeadlineAnimation = function() {
1395
- const statsHeadlineAnimation = gsap.timeline({
1396
- scrollTrigger: {
1397
- trigger: '#statsKnow',
1398
- start: 'center center',
1399
- toggleActions: 'restart none none reverse',
1400
- end: '+=500',
1401
- },
1402
- pause: 'paused',
1403
- ease: 'defaultEase',
1404
- }),
1405
- homeStatsHeading = new SplitText('#statsDone', {
1406
- type: 'lines',
1407
- linesClass: 'stats-line',
1408
- }),
1409
- homeStatsHeadingMask = new SplitText('#statsDone', {
1410
- type: 'lines',
1411
- linesClass: 'stats-line-mask',
1412
- });
1413
- statsHeadlineAnimation.to(
1414
- '#statsKnow',
1415
- {
1416
- duration: 0.5,
1417
- opacity: 0,
1418
- 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',
1419
1558
  },
1420
- '>'
1421
- );
1422
- 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
+ {
1423
1573
  duration: 0.5,
1424
1574
  opacity: 0,
1425
- y: '100%',
1426
- stagger: 0.25,
1427
- });
1428
- }
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
+ }
1429
1586
 
1430
1587
  // Single entry you call from x-init
1431
1588
  window.clientFilters = function () {
@@ -2049,7 +2206,7 @@ window.initBentoRevealScrub = function (container) {
2049
2206
  start: 'top 90%', // start easing in slightly later
2050
2207
  end: 'bottom 65%', // full reveal by near the end of container
2051
2208
  scrub: 0.5, // smoothing; use true for no smoothing
2052
- markers: false, // uncomment for debugging
2209
+ markers: false, // uncomment for debugging
2053
2210
  }
2054
2211
  });
2055
2212
 
@@ -2151,101 +2308,101 @@ window.initPartnerVideos = function (container) {
2151
2308
  };
2152
2309
 
2153
2310
 
2154
- // Case study - What's next interaction
2155
- window.whatsNext = function() {
2156
- const caseItem = document.querySelectorAll('.whats-next_links_item.is-case');
2157
- const allCases = document.querySelector('.whats-next_links_item.is-all');
2158
- caseItem.forEach((item) => {
2159
- const imageMask = item.querySelector('.whats-next_links_item_image_mask');
2160
- const imageWrapper = item.querySelector('.whats-next_links_item_image-wrapper');
2161
- const whatsNextHover = gsap.timeline({ paused: true, ease: 'loader2' });
2162
- whatsNextHover.to(imageWrapper, { opacity: 0.8, duration: 0.15 });
2163
- whatsNextHover.to(imageMask, { width: '0%', duration: 0.3 }, '>-0.');
2164
- item.addEventListener('mouseenter', () => {
2165
- whatsNextHover.timeScale(1).play();
2166
- caseItem.forEach((i) => {
2167
- if (i !== event.target) {
2168
- gsap.to(i, { color: '#7A7A7A', duration: 0.2, ease: 'loader2' });
2169
- }
2170
- });
2171
- });
2172
- item.addEventListener('mouseleave', () => {
2173
- whatsNextHover.timeScale(3).reverse();
2174
- caseItem.forEach((i) => {
2175
- if (i !== event.target) {
2176
- gsap.to(i, { color: '#fff', duration: 0.1, ease: 'loader2' });
2177
- }
2178
- });
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
+ }
2179
2327
  });
2180
2328
  });
2181
- allCases.addEventListener('mouseenter', () => {
2182
- gsap.to(allCases, { color: '#fff', duration: 0.2, ease: 'loader2' });
2183
- caseItem.forEach((item) => {
2184
- 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
+ }
2185
2335
  });
2186
2336
  });
2187
- allCases.addEventListener('mouseleave', () => {
2188
- gsap.to(allCases, { color: '#7A7A7A', duration: 0.2, ease: 'loader2' });
2189
- caseItem.forEach((item) => {
2190
- gsap.to(item, { color: '#fff', duration: 0.2, ease: 'loader2' });
2191
- });
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' });
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' });
2192
2348
  });
2349
+ });
2193
2350
 
2194
- // Remove responsive image feature from CS pages
2195
- for (var i = 0; i < document.getElementsByTagName('img').length; i++) {
2196
- document.getElementsByTagName('img')[i].srcset = '';
2197
- }
2198
- for (var i = 0; i < document.getElementsByTagName('img').length; i++) {
2199
- document.getElementsByTagName('img')[i].sizes = '';
2200
- }
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 = '';
2201
2357
  }
2358
+ }
2202
2359
 
2203
- // Case study - images mask animation
2204
- window.csMaskAnimation = function() {
2205
- const csImageMasks = document.querySelectorAll('.portfolio_item_image-mask');
2206
- csImageMasks.forEach((mask, index) => {
2207
- if (index === 0) {
2208
- return;
2209
- }
2210
- const maskAnimation = gsap.from(mask, {
2211
- width: '100%',
2212
- duration: 0.7,
2213
- ease: 'loader2',
2214
- paused: true,
2215
- });
2216
- ScrollTrigger.create({
2217
- animation: maskAnimation,
2218
- trigger: mask,
2219
- start: 'top 80%',
2220
- onEnter: () => maskAnimation.play(),
2221
- });
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,
2222
2372
  });
2223
- }
2373
+ ScrollTrigger.create({
2374
+ animation: maskAnimation,
2375
+ trigger: mask,
2376
+ start: 'top 80%',
2377
+ onEnter: () => maskAnimation.play(),
2378
+ });
2379
+ });
2380
+ }
2224
2381
 
2225
- // Update the scroll trigger on page load
2382
+ // Update the scroll trigger on page load
2226
2383
  window.updateScrollTrigger = function() {
2227
2384
  window.onload = function() {
2228
2385
  ScrollTrigger.update();
2229
2386
  };
2230
2387
  }
2231
2388
 
2232
- // Blog post main image mask animation
2233
- window.blogPostMaskAnimation = function(e) {
2234
- const blogHero = document.querySelector('#heroSection');
2235
- const blogMaskAnimation = gsap.from('.post_main-mask-ract', {
2236
- left: '0%',
2237
- ease: 'loader2',
2238
- });
2239
- ScrollTrigger.create({
2240
- animation: blogMaskAnimation,
2241
- trigger: blogHero,
2242
- start: 'top -5%',
2243
- end: 'bottom 50%',
2244
- scrub: 0.5,
2245
- });
2246
- }
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
+ }
2247
2404
 
2248
- // Custom checkboxes
2405
+ // Custom checkboxes
2249
2406
  window.changeCheckboxLabelColor = function() {
2250
2407
  let checkboxInputs = document.querySelectorAll('.w-checkbox-input');
2251
2408
 
@@ -2270,7 +2427,7 @@ window.changeCheckboxLabelColor = function() {
2270
2427
  });
2271
2428
  }
2272
2429
 
2273
- // Contact modal open animation
2430
+ // Contact modal open animation
2274
2431
  window.openContactModal = function() {
2275
2432
  contactFormOpen.play();
2276
2433
  document.body.classList.add('is-scroll-off');
@@ -2315,15 +2472,15 @@ window.successMsgAnimation = function(e) {
2315
2472
  ease: 'loader2',
2316
2473
  }
2317
2474
  );
2318
- successMsgAnim.to(
2319
- e,
2320
- {
2321
- width: '0%',
2322
- duration: 0.6,
2323
- ease: 'loader2',
2324
- },
2325
- '>-0.5'
2326
- );
2475
+ successMsgAnim.to(
2476
+ e,
2477
+ {
2478
+ width: '0%',
2479
+ duration: 0.6,
2480
+ ease: 'loader2',
2481
+ },
2482
+ '>-0.5'
2483
+ );
2327
2484
  successMsgAnim.from(
2328
2485
  '#successParagraph',
2329
2486
  {
@@ -2370,7 +2527,6 @@ window.contactUsHide = function(e) {
2370
2527
  }
2371
2528
 
2372
2529
 
2373
-
2374
2530
  window.expandablePadSticky = function (e) {
2375
2531
  var wrapper = e;
2376
2532
  if (!wrapper || wrapper.dataset.expandablePadStickyInit === 'true') return;
@@ -2415,13 +2571,38 @@ window.expandablePadSticky = function (e) {
2415
2571
  }
2416
2572
  }
2417
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
+
2418
2600
  window.addEventListener('scroll', onScrollOrResize, { passive: true });
2419
2601
  window.addEventListener('resize', onResize);
2420
2602
  update();
2421
2603
  };
2422
2604
 
2423
2605
 
2424
-
2425
2606
  // Refresh Gsap scrollTriggers
2426
2607
  window.scrollTriggerRefresh = function() {
2427
2608
  function refreshScrollTrigger() {
@@ -2435,7 +2616,7 @@ window.scrollTriggerRefresh = function() {
2435
2616
 
2436
2617
  // Info bar close animation
2437
2618
  window.closeInfoBar = function() {
2438
- const infoBarClose = gsap.timeline({});
2619
+ const infoBarClose = gsap.timeline({});
2439
2620
  infoBarClose.to('.info-bar', {
2440
2621
  height: 0,
2441
2622
  autoAlpha: 0,
@@ -2456,31 +2637,29 @@ window.closeInfoBar = function() {
2456
2637
  }
2457
2638
 
2458
2639
 
2640
+ // !!!!!!!!! Keep this Alpine init at the end !!!!!!!!!
2641
+ window.Webflow ||= [];
2642
+ window.Webflow.push(() => {
2459
2643
 
2460
-
2461
- // !!!!!!!!! Keep this Alpine init at the end !!!!!!!!!
2462
- window.Webflow ||= [];
2463
- window.Webflow.push(() => {
2464
-
2465
- console.log('The new code source is loaded!');
2466
- initAlpine();
2467
- lazyLoadVideos();
2468
- if (Webflow.env("editor") === undefined) {
2469
- lenisScroll();
2470
- lenis.start();
2471
- } else {
2472
- console.log('Editor mode ON');
2473
- lenis.destroy();
2474
- }
2475
- customGsapEasing();
2476
- reloadOnBack();
2477
- revealFooter();
2478
- pageLoadAnimation();
2479
- pageTransitionAnimation();
2480
- customCursorOnClick();
2481
- contactFormOpenAnimation();
2482
- disableScrollMenu();
2483
- scrollToHashOnLoad();
2484
- initClientLogosAnimation();
2485
- articleModalOpenAnimation();
2486
- });
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
+ });