PageSourceSearch

https://issyliving.co/wp-content/themes/schon/assets/js/main.js?ver=1.0.0

js issyliving.co collected 2026-09-25 03:09:23 UTC 70,522 bytes, 2,048 lines download raw bytes

1function schon_content_load_scripts() {
2    var $ = jQuery;
3    "use strict";
4    /*=================================
5      JS Index Here
6    ==================================*/
7    /*
8    01. On Load Function
9    02. Preloader
10    03. Mobile Menu Active
11    04. Sticky fix
12    05. Scroll To Top
13    06. Set Background Image Color & Mask
14    07. Global Slider
15    08. Custom Animaiton For Slider
16    09. Ajax Contact Form
17    10. Search Box Popup
18    11. Popup Sidemenu
19    12. Magnific Popup
20    13. Section Position
21    14. Filter
22    15. Counter Up
23    16. AS Tab
24    17. Shape Mockup
25    18. Progress Bar Animation
26    19. Price Slider
27    21. Indicator
28    22. Circle Progress
29    00. Woocommerce Toggle
30    00. Right Click Disable
31  */
32    /*=================================
33      JS Index End
34  ==================================*/
35    /*
36
37  /*---------- 01. On Load Function ----------*/
38    $(window).on("load", function () {
39        $(".preloader").fadeOut();
40    });
41
42    /*---------- 02. Preloader ----------*/
43    if ($("#preloader").length) {
44        $("#preloader").delay(1600).fadeOut();
45        setTimeout(function () {
46            $(".preloader-bg-one").css("transform", "translateY(-100%)");
47            $(".preloader-bg-two").css("transform", "translateY(100%)");
48            $(".txt-loading").css("opacity", 0);
49        }, 1000);
50    }
51
52    // ------------ Preloader -----------
53
54    /**
55     * ======================================
56     * 02. custom cursor
57     * ======================================
58     */
59    if ($(".mouseCursor").length > 0) {
60        function itCursor() {
61            var myCursor = jQuery(".mouseCursor");
62            if (myCursor.length) {
63                if ($("body")) {
64                    const e = document.querySelector(".cursor-inner"),
65                        t = document.querySelector(".cursor-outer");
66                    let n,
67                        i = 0,
68                        o = !1;
69                    (window.onmousemove = function (s) {
70                        o ||
71                            (t.style.transform =
72                                "translate(" + s.clientX + "px, " + s.clientY + "px)"),
73                            (e.style.transform =
74                                "translate(" + s.clientX + "px, " + s.clientY + "px)"),
75                            (n = s.clientY),
76                            (i = s.clientX);
77                    }),
78                    $("body").on(
79                            "mouseenter",
80                            "button:not(.not-cursor), a:not(.not-cursor), .cursor-pointer",
81                            function () {
82                                e.classList.add("cursor-hover"),
83                                    t.classList.add("cursor-hover");
84                            }
85                        ),
86                        $("body").on(
87                            "mouseleave",
88                            "button, a, .cursor-pointer",
89                            function () {
90                                ($(this).is("a", "button") &&
91                                    $(this).closest(".cursor-pointer").length) ||
92                                (e.classList.remove("cursor-hover"),
93                                    t.classList.remove("cursor-hover"));
94                            }
95                        ),
96                        (e.style.visibility = "visible"),
97                        (t.style.visibility = "visible");
98
99                    // text view cursor
100                    $("h1, h2, h3, h4, h5, h6, .cursor-lg").on(
101                        "mouseenter",
102                        function () {
103                            $(".mouseCursor").addClass("cursor-big");
104                        }
105                    );
106
107                    $("h1, h2, h3, h4, h5, h6, .cursor-lg").on(
108                        "mouseleave",
109                        function () {
110                            $(".mouseCursor").removeClass("cursor-big");
111                        }
112                    );
113
114                    // no cursor
115                    $(".not-cursor").on("mouseenter", function () {
116                        $(".mouseCursor").addClass("not-cursor-outer");
117                    });
118
119                    $(".not-cursor").on("mouseleave", function () {
120                        $(".mouseCursor").removeClass("not-cursor-outer");
121                    });
122                }
123            }
124        }
125        itCursor();
126    }
127
128
129    // $('select').niceSelect(); 
130    if ($('.nice-select').length) {
131        $('.nice-select').niceSelect();
132    }
133
134
135    /*---------- 03. Mobile Menu Active ----------*/
136    $.fn.thmobilemenu = function (options) {
137        var opt = $.extend({
138                menuToggleBtn: ".th-menu-toggle",
139                bodyToggleClass: "th-body-visible",
140                subMenuClass: "th-submenu",
141                subMenuParent: "th-item-has-children",
142                subMenuParentToggle: "th-active",
143                meanExpandClass: "th-mean-expand",
144                appendElement: '<span class="th-mean-expand"></span>',
145                subMenuToggleClass: "th-open",
146                toggleSpeed: 400,
147            },
148            options
149        );
150
151        return this.each(function () {
152            var menu = $(this); // Select menu
153
154            // Menu Show & Hide
155            function menuToggle() {
156                menu.toggleClass(opt.bodyToggleClass);
157
158                // collapse submenu on menu hide or show
159                var subMenu = "." + opt.subMenuClass;
160                $(subMenu).each(function () {
161                    if ($(this).hasClass(opt.subMenuToggleClass)) {
162                        $(this).removeClass(opt.subMenuToggleClass);
163                        $(this).css("display", "none");
164                        $(this).parent().removeClass(opt.subMenuParentToggle);
165                    }
166                });
167            }
168
169            // Class Set Up for every submenu
170            menu.find("li").each(function () {
171                var submenu = $(this).find("ul");
172                submenu.addClass(opt.subMenuClass);
173                submenu.css("display", "none");
174                submenu.parent().addClass(opt.subMenuParent);
175                submenu.prev("a").append(opt.appendElement);
176                submenu.next("a").append(opt.appendElement);
177            });
178
179            // Toggle Submenu
180            function toggleDropDown($element) {
181                if ($($element).next("ul").length > 0) {
182                    $($element).parent().toggleClass(opt.subMenuParentToggle);
183                    $($element).next("ul").slideToggle(opt.toggleSpeed);
184                    $($element).next("ul").toggleClass(opt.subMenuToggleClass);
185                } else if ($($element).prev("ul").length > 0) {
186                    $($element).parent().toggleClass(opt.subMenuParentToggle);
187                    $($element).prev("ul").slideToggle(opt.toggleSpeed);
188                    $($element).prev("ul").toggleClass(opt.subMenuToggleClass);
189                }
190            }
191
192            // Submenu toggle Button
193            var expandToggler = "." + opt.meanExpandClass;
194            $(expandToggler).each(function () {
195                $(this).on("click", function (e) {
196                    e.preventDefault();
197                    toggleDropDown($(this).parent());
198                });
199            });
200
201            // Menu Show & Hide On Toggle Btn click
202            $(opt.menuToggleBtn).each(function () {
203                $(this).on("click", function () {
204                    menuToggle();
205                });
206            });
207
208            // Hide Menu On out side click
209            menu.on("click", function (e) {
210                e.stopPropagation();
211                menuToggle();
212            });
213
214            // Stop Hide full menu on menu click
215            menu.find("div").on("click", function (e) {
216                e.stopPropagation();
217            });
218        });
219    };
220
221    $(".th-menu-wrapper").thmobilemenu();
222
223    /*---------- 04. Sticky fix ----------*/
224    $(window).scroll(function () {
225        var topPos = $(this).scrollTop();
226        if (topPos > 500) {
227            $('.sticky-wrapper').addClass('sticky');
228        } else {
229            $('.sticky-wrapper').removeClass('sticky')
230        }
231    })
232
233    /*----------- 04.1.  One Page Nav ----------*/
234    function onePageNav(element) {
235        if ($(element).length > 0) {
236            $(element).each(function () {
237                var link = $(this).find('a');
238                $(this).find(link).each(function () {
239                    $(this).on('click', function () {
240                        var target = $(this.getAttribute('href'));
241                        if (target.length) {
242                            event.preventDefault();
243                            $('html, body').stop().animate({
244                                scrollTop: target.offset().top - 10
245                            }, 1000);
246                        };
247
248                    });
249                });
250            })
251        }
252    };
253    onePageNav('.onepage-nav');
254    onePageNav('.scroll-down');
255
256    /*---------- 05. Scroll To Top ----------*/
257    // progressAvtivation
258    if ($('.scroll-top').length) {
259        var scrollTopbtn = document.querySelector('.scroll-top');
260        var offset = 50;
261        var duration = 750;
262
263        jQuery(window).on('scroll', function () {
264            if (jQuery(this).scrollTop() > offset) {
265                jQuery(scrollTopbtn).addClass('show');
266            } else {
267                jQuery(scrollTopbtn).removeClass('show');
268            }
269        });
270
271        jQuery(scrollTopbtn).on('click', function (event) {
272            event.preventDefault();
273            jQuery('html, body').animate({
274                scrollTop: 0
275            }, duration);
276            return false;
277        });
278    }
279
280
281    /*---------- 06. Set Background Image Color & Mask ----------*/
282    if ($("[data-bg-src]").length > 0) {
283        $("[data-bg-src]").each(function () {
284            var src = $(this).attr("data-bg-src");
285            $(this).css("background-image", "url(" + src + ")");
286            $(this).removeAttr("data-bg-src").addClass("background-image");
287        });
288    }
289
290    if ($('[data-bg-color]').length > 0) {
291        $('[data-bg-color]').each(function () {
292            var color = $(this).attr('data-bg-color');
293            $(this).css('background-color', color);
294            $(this).removeAttr('data-bg-color');
295        });
296    };
297
298    $('[data-border]').each(function () {
299        var borderColor = $(this).data('border');
300        $(this).css('--th-border-color', borderColor);
301    });
302
303    if ($('[data-mask-src]').length > 0) {
304        $('[data-mask-src]').each(function () {
305            var mask = $(this).attr('data-mask-src');
306            $(this).css({
307                'mask-image': 'url(' + mask + ')',
308                '-webkit-mask-image': 'url(' + mask + ')'
309            });
310            $(this).addClass('bg-mask');
311            $(this).removeAttr('data-mask-src');
312        });
313    };
314
315
316
317   /*----------- 07. Global Slider ----------*/
318/* --------------------------------
319   WebGL Distortion with Displacement Map
320-------------------------------- */
321let scene, camera, renderer, material, uniforms;
322
323function initWebGL() {
324    const container = document.querySelector("#slider-webgl");
325    if (!container) return; // Stop if container is missing
326
327    scene = new THREE.Scene();
328    camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
329    renderer = new THREE.WebGLRenderer({ alpha: true });
330    renderer.setSize(window.innerWidth, window.innerHeight);
331    container.appendChild(renderer.domElement);
332
333    const slides = document.querySelectorAll(".swiper-slide");
334    if (!slides.length) return;
335
336    const firstImage = slides[0].getAttribute("data-image") || "";
337
338    const textureLoader = new THREE.TextureLoader();
339    const dispMapSrc = container.dataset.disp || "../img/icon/line-shape1.svg/hero/pattan.png";
340    const dispTexture = textureLoader.load(dispMapSrc);
341
342    uniforms = {
343        progress: { value: 0 },
344        texture1: { value: textureLoader.load(firstImage) },
345        texture2: { value: textureLoader.load(firstImage) },
346        disp: { value: dispTexture },
347        intensity: { value: 0.3 }
348    };
349
350    material = new THREE.ShaderMaterial({
351        uniforms,
352        vertexShader: `
353            varying vec2 vUv;
354            void main() {
355                vUv = uv;
356                gl_Position = vec4(position, 1.0);
357            }
358        `,
359        fragmentShader: `
360            varying vec2 vUv;
361            uniform sampler2D texture1;
362            uniform sampler2D texture2;
363            uniform sampler2D disp;
364            uniform float progress;
365            uniform float intensity;
366
367            void main() {
368                vec2 uv = vUv;
369                vec4 dispTex = texture2D(disp, uv);
370                vec2 distortedPosition = uv + (dispTex.rg * 2.0 - 1.0) * intensity * progress;
371                vec2 distortedPosition2 = uv - (dispTex.rg * 2.0 - 1.0) * intensity * (1.0 - progress);
372                vec4 _texture1 = texture2D(texture1, distortedPosition);
373                vec4 _texture2 = texture2D(texture2, distortedPosition2);
374                gl_FragColor = mix(_texture1, _texture2, progress);
375            }
376        `,
377        transparent: true
378    });
379
380    const geometry = new THREE.PlaneBufferGeometry(2, 2);
381    const mesh = new THREE.Mesh(geometry, material);
382    scene.add(mesh);
383
384    animate();
385}
386
387function animate() {
388    requestAnimationFrame(animate);
389    if (renderer && camera && scene) renderer.render(scene, camera);
390}
391
392function changeSlide(index) {
393    if (!uniforms) return;
394
395    const slides = document.querySelectorAll(".swiper-slide");
396    if (!slides[index]) return;
397
398    const nextImage = slides[index].getAttribute("data-image");
399    if (!nextImage) return;
400
401    const nextTexture = new THREE.TextureLoader().load(nextImage);
402    uniforms.texture2.value = nextTexture;
403    uniforms.progress.value = 0;
404
405    gsap.to(uniforms.progress, {
406        value: 1,
407        duration: 1.8,
408        ease: "power2.inOut",
409        onComplete: () => {
410            uniforms.texture1.value = nextTexture;
411            uniforms.progress.value = 0;
412        }
413    });
414}
415
416initWebGL();
417
418/* --------------------------------
419   Initialize .th-slider instances
420-------------------------------- */
421$('.th-slider').each(function () {
422    const thSlider = $(this);
423    let settings = {};
424    try {
425        settings = JSON.parse(thSlider.attr('data-slider-options') || '{}');
426    } catch (e) {
427        console.warn('Invalid data-slider-options JSON', e);
428    }
429
430    const prevArrow = thSlider.find('.slider-prev').length ? thSlider.find('.slider-prev').get(0) : null;
431    const nextArrow = thSlider.find('.slider-next').length ? thSlider.find('.slider-next').get(0) : null;
432
433    const paginationExternel = thSlider.siblings('.slider-controller').find('.slider-pagination');
434    const paginationEl = paginationExternel.length ? paginationExternel.get(0) : (thSlider.find('.slider-pagination').length ? thSlider.find('.slider-pagination').get(0) : undefined);
435    const paginationEl2 = paginationExternel.length ? paginationExternel.get(0) : thSlider.find('.slider-pagination2').get(0);
436    const paginationElN = thSlider.find('.slider-pagination.pagi-number');
437
438    const paginationType = settings['paginationType'] || 'bullets';
439    const autoplayCondition = settings['autoplay'] || { delay: 6000, disableOnInteraction: false };
440
441    const sliderDefault = {
442        slidesPerView: 1,
443        spaceBetween: settings['spaceBetween'] || 24,
444        loop: settings['loop'] !== false,
445        speed: 1800,
446        autoplay: autoplayCondition,
447        navigation: {
448            nextEl: nextArrow,
449            prevEl: prevArrow
450        },
451        pagination: {
452            el: paginationEl,
453            type: paginationType,
454            clickable: true,
455            renderBullet: function (index, className) {
456                const number = index + 1;
457                const formattedNumber = number < 10 ? '0' + number : number;
458                if (paginationElN.length) return `<span class="${className} number">${formattedNumber}</span>`;
459                return `<span class="${className}" aria-label="Go to Slide ${formattedNumber}"></span>`;
460            },
461            formatFractionCurrent: number => (number < 10 ? '0' + number : number),
462            formatFractionTotal: number => (number < 10 ? '0' + number : number)
463        },
464        on: {
465            init: function () {
466                if (paginationEl2) {
467                    const totalSlides = this.slides.length;
468                    $(paginationEl2).html('<span class="current-slide">01</span> <span class="total-slides">' + (totalSlides < 10 ? '0' + totalSlides : totalSlides) + '</span>');
469                }
470            },
471            slideChangeTransitionStart: function () {
472                if (typeof changeSlide === "function") changeSlide(this.realIndex);
473
474                if (paginationEl2) {
475                    const activeIndex = this.realIndex + 1;
476                    const totalSlides = this.slides.length;
477                    $(paginationEl2).html(
478                        `<span class="current-slide">${activeIndex < 10 ? '0' + activeIndex : activeIndex}</span> 
479                         <span class="total-slides">${totalSlides < 10 ? '0' + totalSlides : totalSlides}</span>`
480                    );
481                }
482            }
483        }
484    };
485
486    const options = $.extend({}, sliderDefault, settings);
487    new Swiper(thSlider.get(0), options);
488
489    if ($('.slider-area').length > 0) {
490        $('.slider-area').closest(".container").parent().addClass("arrow-wrap");
491    }
492});
493
494
495    /* ------------------------------
496       Wheel-like effect slider
497    -------------------------------- */
498    const multiplier = {
499        translate: 0.1,
500        rotate: 0.01
501    };
502
503
504    function calculateWheel() {
505        const slides = document.querySelectorAll('.swiper .single');
506        slides.forEach((slide) => {
507            const rect = slide.getBoundingClientRect();
508            const r = window.innerWidth * 0.5 - (rect.x + rect.width * 0.5);
509            let ty = Math.abs(r) * multiplier.translate - rect.width * multiplier.translate;
510
511            if (ty < 0) ty = 0;
512
513            const transformOrigin = r < 0 ? 'left top' : 'right top';
514            slide.style.transform = `translate(0, ${ty}px) rotate(${-r * multiplier.rotate}deg)`;
515            slide.style.transformOrigin = transformOrigin;
516        });
517    }
518
519    function raf() {
520        requestAnimationFrame(raf);
521        calculateWheel();
522    }
523    raf();
524
525
526    function animationProperties() {
527        $('[data-ani]').each(function () {
528            var animationName = $(this).data('ani');
529            $(this).addClass(animationName);
530        });
531
532        $('[data-ani-delay]').each(function () {
533            var delayTime = $(this).data('ani-delay');
534            $(this).css('animation-delay', delayTime);
535        });
536    }
537    animationProperties();
538
539    // Add click event handlers for external slider arrows based on data attributes
540    $('[data-slider-prev], [data-slider-next]').on('click', function () {
541        var sliderSelector = $(this).data('slider-prev') || $(this).data('slider-next');
542        var targetSlider = $(sliderSelector);
543
544        if (targetSlider.length) {
545            var swiper = targetSlider[0].swiper;
546
547            if (swiper) {
548                if ($(this).data('slider-prev')) {
549                    swiper.slidePrev();
550                } else {
551                    swiper.slideNext();
552                }
553            }
554        }
555    });
556
557
558
559    /*----------- 21. image Slider ----------*/
560    $("#slider").on("input change", (e) => {
561        const sliderPos = e.target.value;
562        $('.foreground-img').css('width', `${sliderPos}%`)
563        $('.slider-button').css('left', `calc(${sliderPos}% - 18px)`)
564    });
565
566    $(document).on('mouseover', '.hover-item', function () {
567        $(this).addClass('item-active');
568        $('.hover-item').removeClass('item-active');
569        $(this).addClass('item-active');
570    });
571    /*-------------- 08. Slider Tab -------------*/
572    $.fn.activateSliderThumbs = function (options) {
573        var opt = $.extend({
574                sliderTab: false,
575                tabButton: ".tab-btn",
576            },
577            options
578        );
579
580        return this.each(function () {
581            var $container = $(this);
582            var $thumbs = $container.find(opt.tabButton);
583            var $line = $('<span class="indicator"></span>').appendTo($container);
584
585            var sliderSelector = $container.data("slider-tab");
586            var $slider = $(sliderSelector);
587
588            var swiper = $slider[0].swiper;
589
590            $thumbs.on("click", function (e) {
591                e.preventDefault();
592                var clickedThumb = $(this);
593
594                clickedThumb.addClass("active").siblings().removeClass("active");
595                linePos(clickedThumb, $container);
596
597                if (opt.sliderTab) {
598                    var slideIndex = clickedThumb.index();
599                    swiper.slideTo(slideIndex);
600                }
601            });
602
603            if (opt.sliderTab) {
604                swiper.on("slideChange", function () {
605                    var activeIndex = swiper.realIndex;
606                    var $activeThumb = $thumbs.eq(activeIndex);
607
608                    $activeThumb.addClass("active").siblings().removeClass("active");
609                    linePos($activeThumb, $container);
610                });
611
612                var initialSlideIndex = swiper.activeIndex;
613                var $initialThumb = $thumbs.eq(initialSlideIndex);
614                $initialThumb.addClass("active").siblings().removeClass("active");
615                linePos($initialThumb, $container);
616            }
617
618            function linePos($activeThumb) {
619                var thumbOffset = $activeThumb.position();
620
621                var marginTop = parseInt($activeThumb.css('margin-top')) || 0;
622                var marginLeft = parseInt($activeThumb.css('margin-left')) || 0;
623
624                $line.css("--height-set", $activeThumb.outerHeight() + "px");
625                $line.css("--width-set", $activeThumb.outerWidth() + "px");
626                $line.css("--pos-y", thumbOffset.top + marginTop + "px");
627                $line.css("--pos-x", thumbOffset.left + marginLeft + "px");
628            }
629        });
630    };
631
632    if ($(".testi-thumb").length) {
633        $(".testi-thumb").activateSliderThumbs({
634            sliderTab: true,
635            tabButton: ".tab-btn",
636        });
637    }
638    // if ($(".hero-thumb").length) {
639    //     $(".hero-thumb").activateSliderThumbs({
640    //         sliderTab: true,
641    //         tabButton: ".tab-btn",
642    //     });
643    // }
644
645    if ($(".project-thumb").length) {
646        $(".project-thumb").activateSliderThumbs({
647            sliderTab: true,
648            tabButton: ".tab-btn",
649        });
650    }
651
652
653    /*----------- 09. Ajax Contact Form ----------*/
654    var form = ".ajax-contact";
655    var invalidCls = "is-invalid";
656    var $email = '[name="email"]';
657    var $validation =
658        '[name="name"],[name="email"],[name="subject"],[name="number"],[name="message"]'; // Must be use (,) without any space
659    var formMessages = $(".form-messages");
660
661    function sendContact() {
662        var formData = $(form).serialize();
663        var valid;
664        valid = validateContact();
665        if (valid) {
666            jQuery
667                .ajax({
668                    url: $(form).attr("action"),
669                    data: formData,
670                    type: "POST",
671                })
672                .done(function (response) {
673                    // Make sure that the formMessages div has the 'success' class.
674                    formMessages.removeClass("error");
675                    formMessages.addClass("success");
676                    // Set the message text.
677                    formMessages.text(response);
678                    // Clear the form.
679                    $(
680                        form +
681                        ' input:not([type="submit"]),' +
682                        form +
683                        " textarea"
684                    ).val("");
685                })
686                .fail(function (data) {
687                    // Make sure that the formMessages div has the 'error' class.
688                    formMessages.removeClass("success");
689                    formMessages.addClass("error");
690                    // Set the message text.
691                    if (data.responseText !== "") {
692                        formMessages.html(data.responseText);
693                    } else {
694                        formMessages.html(
695                            "Oops! An error occured and your message could not be sent."
696                        );
697                    }
698                });
699        }
700    }
701
702    function validateContact() {
703        var valid = true;
704        var formInput;
705
706        function unvalid($validation) {
707            $validation = $validation.split(",");
708            for (var i = 0; i < $validation.length; i++) {
709                formInput = form + " " + $validation[i];
710                if (!$(formInput).val()) {
711                    $(formInput).addClass(invalidCls);
712                    valid = false;
713                } else {
714                    $(formInput).removeClass(invalidCls);
715                    valid = true;
716                }
717            }
718        }
719        unvalid($validation);
720
721        if (
722            !$($email).val() ||
723            !$($email)
724            .val()
725            .match(/^([\w-\.]+@([\w-]+\.)+[\w-]{2,4})?$/)
726        ) {
727            $($email).addClass(invalidCls);
728            valid = false;
729        } else {
730            $($email).removeClass(invalidCls);
731            valid = true;
732        }
733        return valid;
734    }
735
736    $(form).on("submit", function (element) {
737        element.preventDefault();
738        sendContact();
739    });
740
741    /*---------- 10. Search Box Popup ----------*/
742    function popupSarchBox($searchBox, $searchOpen, $searchCls, $toggleCls) {
743        $($searchOpen).on("click", function (e) {
744            e.preventDefault();
745            $($searchBox).addClass($toggleCls);
746        });
747        $($searchBox).on("click", function (e) {
748            e.stopPropagation();
749            $($searchBox).removeClass($toggleCls);
750        });
751        $($searchBox)
752            .find("form")
753            .on("click", function (e) {
754                e.stopPropagation();
755                $($searchBox).addClass($toggleCls);
756            });
757        $($searchCls).on("click", function (e) {
758            e.preventDefault();
759            e.stopPropagation();
760            $($searchBox).removeClass($toggleCls);
761        });
762    }
763    popupSarchBox(
764        ".popup-search-box",
765        ".searchBoxToggler",
766        ".searchClose",
767        "show"
768    );
769
770    /*---------- 11. Popup Sidemenu ----------*/
771    function popupSideMenu($sideMenu, $sideMunuOpen, $sideMenuCls, $toggleCls) {
772        // Sidebar Popup
773        $($sideMunuOpen).on('click', function (e) {
774            e.preventDefault();
775            $($sideMenu).addClass($toggleCls);
776        });
777        $($sideMenu).on('click', function (e) {
778            e.stopPropagation();
779            $($sideMenu).removeClass($toggleCls)
780        });
781        var sideMenuChild = $sideMenu + ' > div';
782        $(sideMenuChild).on('click', function (e) {
783            e.stopPropagation();
784            $($sideMenu).addClass($toggleCls)
785        });
786        $($sideMenuCls).on('click', function (e) {
787            e.preventDefault();
788            e.stopPropagation();
789            $($sideMenu).removeClass($toggleCls);
790        });
791    };
792    popupSideMenu('.sidemenu-wrapper', '.sideMenuToggler', '.sideMenuCls', 'show');
793    /*---------- 12. Popup Sidemenu ----------*/
794    function popupSideMenu($sideMenu2, $sideMunuOpen2, $sideMenuCls2, $toggleCls2) {
795        // Sidebar Popup
796        $($sideMunuOpen2).on('click', function (e) {
797            e.preventDefault();
798            $($sideMenu2).addClass($toggleCls2);
799        });
800        $($sideMenu2).on('click', function (e) {
801            e.stopPropagation();
802            $($sideMenu2).removeClass($toggleCls2)
803        });
804        var sideMenuChild = $sideMenu2 + ' > div';
805        $(sideMenuChild).on('click', function (e) {
806            e.stopPropagation();
807            $($sideMenu2).addClass($toggleCls2)
808        });
809        $($sideMenuCls2).on('click', function (e) {
810            e.preventDefault();
811            e.stopPropagation();
812            $($sideMenu2).removeClass($toggleCls2);
813        });
814    };
815    popupSideMenu('.shopping-cart', '.sideMenuToggler2', '.sideMenuCls', 'show');
816
817    /*----------- 12. Magnific Popup ----------*/
818    /* magnificPopup img view */
819    $(".th-popup-image").magnificPopup({
820        type: "image",
821        mainClass: 'mfp-zoom-in',
822        removalDelay: 260,
823        gallery: {
824            enabled: true,
825        },
826    });
827
828    /* magnificPopup video view */
829    $(".popup-video").magnificPopup({
830        type: "iframe",
831        mainClass: 'mfp-zoom-in',
832        removalDelay: 260,
833    });
834
835    /* magnificPopup video view */
836    $(".popup-content").magnificPopup({
837        type: "inline",
838        midClick: true,
839    });
840
841
842    if ($('[data-theme-color]').length > 0) {
843        $('[data-theme-color]').each(function () {
844            var $color = $(this).attr('data-theme-color');
845            $(this).get(0).style.setProperty('--theme-color', $color);
846            $(this).removeAttr('data-theme-color');
847        });
848    };
849
850
851    /************lettering js***********/
852    function injector(t, splitter, klass, after) {
853        var a = t.text().split(splitter),
854            inject = '';
855        if (a.length) {
856            $(a).each(function (i, item) {
857                inject += '<span class="' + klass + (i + 1) + '">' + item + '</span>' + after;
858            });
859            t.empty().append(inject);
860        }
861    }
862
863    var methods = {
864        init: function () {
865
866            return this.each(function () {
867                injector($(this), '', 'char', '');
868            });
869
870        },
871
872        words: function () {
873
874            return this.each(function () {
875                injector($(this), ' ', 'word', ' ');
876            });
877
878        },
879
880        lines: function () {
881
882            return this.each(function () {
883                var r = "eefec303079ad17405c889e092e105b0";
884                // Because it's hard to split a <br/> tag consistently across browsers,
885                // (*ahem* IE *ahem*), we replaces all <br/> instances with an md5 hash 
886                // (of the word "split").  If you're trying to use this plugin on that 
887                // md5 hash string, it will fail because you're being ridiculous.
888                injector($(this).children("br").replaceWith(r).end(), r, 'line', '');
889            });
890
891        }
892    };
893
894    $.fn.lettering = function (method) {
895        // Method calling logic
896        if (method && methods[method]) {
897            return methods[method].apply(this, [].slice.call(arguments, 1));
898        } else if (method === 'letters' || !method) {
899            return methods.init.apply(this, [].slice.call(arguments, 0)); // always pass an array
900        }
901        $.error('Method ' + method + ' does not exist on jQuery.lettering');
902        return this;
903    };
904
905    $(".discount-anime").lettering();
906
907
908    /*---------- 13. Section Position ----------*/
909    // Interger Converter
910    function convertInteger(str) {
911        return parseInt(str, 10);
912    }
913
914    $.fn.sectionPosition = function (mainAttr, posAttr) {
915        $(this).each(function () {
916            var section = $(this);
917
918            function setPosition() {
919                var sectionHeight = Math.floor(section.height() / 2), // Main Height of section
920                    posData = section.attr(mainAttr), // where to position
921                    posFor = section.attr(posAttr), // On Which section is for positioning
922                    topMark = "top-half", // Pos top
923                    bottomMark = "bottom-half", // Pos Bottom
924                    parentPT = convertInteger($(posFor).css("padding-top")), // Default Padding of  parent
925                    parentPB = convertInteger($(posFor).css("padding-bottom")); // Default Padding of  parent
926
927                if (posData === topMark) {
928                    $(posFor).css(
929                        "padding-bottom",
930                        parentPB + sectionHeight + "px"
931                    );
932                    section.css("margin-top", "-" + sectionHeight + "px");
933                } else if (posData === bottomMark) {
934                    $(posFor).css(
935                        "padding-top",
936                        parentPT + sectionHeight + "px"
937                    );
938                    section.css("margin-bottom", "-" + sectionHeight + "px");
939                }
940            }
941            setPosition(); // Set Padding On Load
942        });
943    };
944
945    var postionHandler = "[data-sec-pos]";
946    if ($(postionHandler).length) {
947        $(postionHandler).imagesLoaded(function () {
948            $(postionHandler).sectionPosition("data-sec-pos", "data-pos-for");
949        });
950    }
951
952    /*----------- 15. Filter ----------*/
953    $(".filter-active").imagesLoaded(function () {
954        var $filter = ".filter-active",
955            $filterItem = ".filter-item",
956            $filterMenu = ".filter-menu-active";
957
958        if ($($filter).length > 0) {
959            var $grid = $($filter).isotope({
960                itemSelector: $filterItem,
961                filter: "*",
962                masonry: {
963                    // use outer width of grid-sizer for columnWidth
964                    columnWidth: 1,
965                },
966            });
967
968            // filter items on button click
969            $($filterMenu).on("click", "button", function () {
970                var filterValue = $(this).attr("data-filter");
971                $grid.isotope({
972                    filter: filterValue,
973                });
974            });
975
976            // Menu Active Class
977            $($filterMenu).on("click", "button", function (event) {
978                event.preventDefault();
979                $(this).addClass("active");
980                $(this).siblings(".active").removeClass("active");
981            });
982        }
983        $('.load-more-btn').on('click', function () {
984            var $icon = $(this).find('i');
985            $icon.addClass('fa-spin-pulse');
986
987            setTimeout(function () {
988                $icon.removeClass('fa-spin-pulse');
989            }, 1000);
990
991            var $button = $(this);
992            setTimeout(function () {
993                var $closestLoadMoreActive = $button.prev('.load-more-active');
994                if ($closestLoadMoreActive.length === 0) {
995                    $closestLoadMoreActive = $button.closest('.container').find('.load-more-active');
996                }
997                $closestLoadMoreActive.find('.load-more.d-none, .accordion-card.style2.d-none, .filter-item.d-none').removeClass('d-none');
998
999                var $grid = $($filter).isotope({
1000                    filter: "*",
1001                });
1002            }, 700);
1003        });
1004    });
1005
1006
1007    $(".masonary-active").imagesLoaded(function () {
1008        var $filter = ".masonary-active",
1009            $filterItem = ".filter-item";
1010
1011        if ($($filter).length > 0) {
1012            $($filter).isotope({
1013                itemSelector: $filterItem,
1014                filter: "*",
1015                masonry: {
1016                    // use outer width of grid-sizer for columnWidth
1017                    columnWidth: 1,
1018                },
1019            });
1020        }
1021    });
1022
1023    $(".masonary-active, .woocommerce-Reviews .comment-list").imagesLoaded(function () {
1024        var $filter = ".masonary-active, .woocommerce-Reviews .comment-list",
1025            $filterItem = ".filter-item, .woocommerce-Reviews .comment-list li";
1026
1027        if ($($filter).length > 0) {
1028            $($filter).isotope({
1029                itemSelector: $filterItem,
1030                filter: "*",
1031                masonry: {
1032                    // use outer width of grid-sizer for columnWidth
1033                    columnWidth: 1,
1034                },
1035            });
1036        }
1037        $('[data-bs-toggle="tab"]').on('shown.bs.tab', function (e) {
1038            $($filter).isotope({
1039                filter: "*",
1040            });
1041        });
1042    });
1043
1044    /*----------- 15. Counter Up ----------*/
1045    $(".counter-number").counterUp({
1046        delay: 10,
1047        time: 1000,
1048    });
1049
1050    /*----------- 17. Shape Mockup ----------*/
1051    $.fn.shapeMockup = function () {
1052        var $shape = $(this);
1053        $shape.each(function () {
1054            var $currentShape = $(this),
1055                shapeTop = $currentShape.data("top"),
1056                shapeRight = $currentShape.data("right"),
1057                shapeBottom = $currentShape.data("bottom"),
1058                shapeLeft = $currentShape.data("left");
1059            $currentShape
1060                .css({
1061                    top: shapeTop,
1062                    right: shapeRight,
1063                    bottom: shapeBottom,
1064                    left: shapeLeft,
1065                })
1066                .removeAttr("data-top")
1067                .removeAttr("data-right")
1068                .removeAttr("data-bottom")
1069                .removeAttr("data-left")
1070                .parent()
1071                .addClass("shape-mockup-wrap");
1072        });
1073    };
1074
1075    if ($(".shape-mockup")) {
1076        $(".shape-mockup").shapeMockup();
1077    }
1078
1079
1080    /*----------- 16. Shape Mockup ----------*/
1081    $.fn.shapeMockup2 = function () {
1082        var $shape = $(this);
1083        $shape.each(function () {
1084            var $currentShape = $(this),
1085                shapeTop = $currentShape.data("top"),
1086                shapeRight = $currentShape.data("right"),
1087                shapeBottom = $currentShape.data("bottom"),
1088                shapeLeft = $currentShape.data("left");
1089            $currentShape
1090                .css({
1091                    top: shapeTop,
1092                    right: shapeRight,
1093                    bottom: shapeBottom,
1094                    left: shapeLeft,
1095                })
1096                .removeAttr("data-top")
1097                .removeAttr("data-right")
1098                .removeAttr("data-bottom")
1099                .removeAttr("data-left")
1100                .parent()
1101                .addClass("shape-mockup-wrap2");
1102        });
1103    };
1104
1105    if ($(".shape-mockup2")) {
1106        $(".shape-mockup2").shapeMockup2();
1107    }
1108    
1109
1110
1111
1112    /*----------- 16. Progress Bar Animation ----------*/
1113    $('.progress-bar').waypoint(function () {
1114        $('.progress-bar').css({
1115            animation: "animate-positive 1.8s",
1116            opacity: "1"
1117        });
1118    }, {
1119        offset: '75%'
1120    });
1121
1122
1123
1124    /*  footer animation  */
1125    document.addEventListener("DOMContentLoaded", function () {
1126        const target = document.querySelector(".th-screen");
1127
1128        if (target) {
1129            const observer = new IntersectionObserver(
1130                (entries) => {
1131                    entries.forEach((entry) => {
1132                        if (entry.isIntersecting) {
1133                            target.classList.add("th-visible");
1134                        } else {
1135                            target.classList.remove("th-visible");
1136                        }
1137                    });
1138                }, {
1139                    root: null, // viewport
1140                    threshold: 0.2, // কমপক্ষে 20% element viewport-এ এলে trigger হবে
1141                }
1142            );
1143
1144            observer.observe(target);
1145        }
1146    });
1147
1148
1149
1150    /*----------- 00. Woocommerce Toggle ----------*/
1151    // Ship To Different Address
1152    $("#ship-to-different-address-checkbox").on("change", function () {
1153        if ($(this).is(":checked")) {
1154            $("#ship-to-different-address")
1155                .next(".shipping_address")
1156                .slideDown();
1157        } else {
1158            $("#ship-to-different-address").next(".shipping_address").slideUp();
1159        }
1160    });
1161
1162    // Login Toggle
1163    $(".woocommerce-form-login-toggle a").on("click", function (e) {
1164        e.preventDefault();
1165        $(".woocommerce-form-login").slideToggle();
1166    });
1167
1168    // Coupon Toggle
1169    $(".woocommerce-form-coupon-toggle a").on("click", function (e) {
1170        e.preventDefault();
1171        $(".woocommerce-form-coupon").slideToggle();
1172    });
1173
1174    // Woocommerce Shipping Method
1175    $(".shipping-calculator-button").on("click", function (e) {
1176        e.preventDefault();
1177        $(this).next(".shipping-calculator-form").slideToggle();
1178    });
1179
1180    // Woocommerce Payment Toggle
1181    $('.wc_payment_methods input[type="radio"]:checked')
1182        .siblings(".payment_box")
1183        .show();
1184    $('.wc_payment_methods input[type="radio"]').each(function () {
1185        $(this).on("change", function () {
1186            $(".payment_box").slideUp();
1187            $(this).siblings(".payment_box").slideDown();
1188        });
1189    });
1190
1191    // Woocommerce Rating Toggle
1192    $(".rating-select .stars a").each(function () {
1193        $(this).on("click", function (e) {
1194            e.preventDefault();
1195            $(this).siblings().removeClass("active");
1196            $(this).parent().parent().addClass("selected");
1197            $(this).addClass("active");
1198        });
1199    });
1200
1201    // Quantity Plus Minus ---------------------------
1202
1203    $(".quantity-plus").each(function () {
1204        $(this).on("click", function (e) {
1205            e.preventDefault();
1206            var $qty = $(this).siblings(".qty-input");
1207            var currentVal = parseInt($qty.val(), 10);
1208            if (!isNaN(currentVal)) {
1209                $qty.val(currentVal + 1);
1210            }
1211        });
1212    });
1213
1214    $(".quantity-minus").each(function () {
1215        $(this).on("click", function (e) {
1216            e.preventDefault();
1217            var $qty = $(this).siblings(".qty-input");
1218            var currentVal = parseInt($qty.val(), 10);
1219            if (!isNaN(currentVal) && currentVal > 1) {
1220                $qty.val(currentVal - 1);
1221            }
1222        });
1223    });
1224
1225    // /*----------- 00.Color Scheme ----------*/
1226    $('.color-switch-btns button').each(function () {
1227        // Get color for button
1228        const button = $(this);
1229        const color = button.data('color');
1230        button.css('--theme-color', color);
1231
1232        // Change theme color on click
1233        button.on('click', function () {
1234            const clickedColor = $(this).data('color');
1235            $('body').css('--theme-color', clickedColor);
1236        });
1237    });
1238    if ($('[theme-color]').length > 0) {
1239        $('[theme-color]').each(function () {
1240            var $color = $(this).attr('theme-color');
1241            $(this).get(0).style.setProperty('--theme-color', $color);
1242            $(this).removeAttr('theme-color');
1243        });
1244    };
1245    if ($('[title-color]').length > 0) {
1246        $('[title-color]').each(function () {
1247            var $color = $(this).attr('title-color');
1248            $(this).get(0).style.setProperty('--title-color', $color);
1249            $(this).removeAttr('title-color');
1250        });
1251    };
1252
1253    $(document).on('click', '.switchIcon', function () {
1254        $('.color-scheme-wrap').toggleClass('active');
1255    });
1256
1257    // /*----------- Pricing-switch & Tab ----------*/
1258    var e = document.getElementById("filt-monthly"),
1259        d = document.getElementById("filt-yearly"),
1260        t = document.getElementById("switcher"),
1261        m = document.getElementById("monthly"),
1262        y = document.getElementById("yearly");
1263
1264
1265    if ($('.pricing-tabs').length) {
1266        e.addEventListener("click", function () {
1267            t.checked = false;
1268            e.classList.add("toggler--is-active");
1269            d.classList.remove("toggler--is-active");
1270            m.classList.remove("hide");
1271            y.classList.add("hide");
1272        });
1273
1274        d.addEventListener("click", function () {
1275            t.checked = true;
1276            d.classList.add("toggler--is-active");
1277            e.classList.remove("toggler--is-active");
1278            m.classList.add("hide");
1279            y.classList.remove("hide");
1280        });
1281
1282        t.addEventListener("click", function () {
1283            d.classList.toggle("toggler--is-active");
1284            e.classList.toggle("toggler--is-active");
1285            m.classList.toggle("hide");
1286            y.classList.toggle("hide");
1287        });
1288    }
1289
1290    window.addEventListener("load", function () {
1291        if ($('.circle-text').length > 0) {
1292            const degreeToRadian = (angle) => angle * (Math.PI / 180);
1293
1294            // ellipse.png image width detect
1295            let ellipseImg = document.getElementById("ellipse-shape");
1296            let imgWidth = ellipseImg.offsetWidth;
1297
1298            // radius auto set = (image width / 2) - padding
1299            let radius = (imgWidth / 1) - 0;
1300            let diameter = radius * 2;
1301
1302            let circle = document.querySelector(".circle-text");
1303            circle.style.width = `${diameter}px`;
1304            circle.style.height = `${diameter}px`;
1305
1306            let text = circle.dataset.text;
1307            let characters = text.split("");
1308
1309            let deltaAngle = 360 / characters.length;
1310            let currentAngle = -90;
1311
1312            characters.forEach((character, index) => {
1313                let span = document.createElement("span");
1314                span.innerText = character;
1315
1316                let xPos = radius * (1 + Math.cos(degreeToRadian(currentAngle)));
1317                let yPos = radius * (1 + Math.sin(degreeToRadian(currentAngle)));
1318
1319                let transform = `translate(${xPos}px, ${yPos}px) rotate(${currentAngle + 90}deg)`;
1320                span.style.transform = transform;
1321
1322                currentAngle += deltaAngle;
1323                circle.appendChild(span);
1324            });
1325        }
1326    });
1327
1328
1329    /* ==================================================
1330            # Wow Init
1331         ===============================================*/
1332    var wow = new WOW({
1333        boxClass: 'wow',
1334        animateClass: 'animated',
1335        offset: 0,
1336        mobile: true,
1337        live: true
1338    });
1339    new WOW().init();
1340
1341  
1342
1343
1344
1345    // scale animation 
1346    var scale = document.querySelectorAll(".scale");
1347    var image = document.querySelectorAll(".scale img");
1348    scale.forEach((item) => {
1349        gsap.to(item, {
1350            scale: 1,
1351            duration: 1,
1352            ease: "power1.out",
1353            scrollTrigger: {
1354                trigger: item,
1355                start: 'top bottom',
1356                end: "bottom top",
1357                toggleActions: 'play reverse play reverse'
1358            }
1359        });
1360    });
1361    image.forEach((image) => {
1362        gsap.set(image, {
1363            scale: 1.3,
1364        });
1365        gsap.to(image, {
1366            scale: 1,
1367            duration: 1,
1368            scrollTrigger: {
1369                trigger: image,
1370                start: 'top bottom',
1371                end: "bottom top",
1372                toggleActions: 'play reverse play reverse'
1373            }
1374        });
1375    })
1376
1377
1378    /* gallery section area start */
1379    // ===============================
1380    // 3D Gallery Scroll Animation
1381    // ===============================
1382
1383    if ($(".gallery-grid-row").length > 0) {
1384        const $galleryContainer = $(".gallery-grid-row");
1385        const $galleryItems = $galleryContainer.find(".gallery-card");
1386
1387        // Grid setup (default 4x3, if 'l' then 3x4)
1388        let gridLayout = [4, 3];
1389        if (typeof l !== "undefined" && l) {
1390            gridLayout = [3, 4];
1391        }
1392
1393        // Helper function to generate random transforms
1394        function b(xRange = 0, yRange = 0, zRange = 0) {
1395            return {
1396                x: xRange ? gsap.utils.random(-xRange, xRange) : 0,
1397                y: yRange ? gsap.utils.random(-yRange, yRange) : 0,
1398                z: zRange ? gsap.utils.random(-zRange, zRange) : 0,
1399                rotateX: gsap.utils.random(-20, 20),
1400                rotateY: gsap.utils.random(-20, 20)
1401            };
1402        }
1403
1404        if (window.innerWidth > 768) {
1405            // Add perspective to container
1406            gsap.set($galleryContainer[0], {
1407                perspective: 1312
1408            });
1409
1410            const tl = gsap.timeline({
1411                defaults: {
1412                    ease: "power4.out"
1413                },
1414                scrollTrigger: {
1415                    trigger: $galleryContainer[0],
1416                    start: "top 80%",
1417                    end: "bottom 20%",
1418                    scrub: 0.5
1419                }
1420            });
1421
1422            // Animate gallery items from random position & rotation to normal
1423            tl.fromTo(
1424                $galleryItems.toArray(), {
1425                    x: i => {
1426                        const t = b(200, 200, 0);
1427                        return t.x;
1428                    },
1429                    y: i => {
1430                        const t = b(200, 200, 0);
1431                        return t.y;
1432                    },
1433                    rotateX: i => {
1434                        const t = b();
1435                        return t.rotateX;
1436                    },
1437                    rotateY: i => {
1438                        const t = b();
1439                        return t.rotateY;
1440                    },
1441                    autoAlpha: 0,
1442                    scale: 0.5
1443                }, {
1444                    x: 0,
1445                    y: 0,
1446                    rotateX: 0,
1447                    rotateY: 0,
1448                    autoAlpha: 1,
1449                    scale: 1,
1450                    stagger: {
1451                        amount: 0.3,
1452                        from: "center",
1453                        grid: gridLayout
1454                    }
1455                }
1456            );
1457
1458        } else {
1459            // Small devices: show static grid without animation
1460            gsap.set($galleryItems.toArray(), {
1461                clearProps: "all",
1462                autoAlpha: 1,
1463                scale: 1,
1464                x: 0,
1465                y: 0,
1466                rotateX: 0,
1467                rotateY: 0
1468            });
1469        }
1470    }
1471
1472
1473    /* gallery section area end */
1474
1475
1476    /* gallery section area end */
1477
1478    /* accordion-card */
1479    document.addEventListener("DOMContentLoaded", function () {
1480        document.querySelectorAll(".accordion-card").forEach(card => {
1481            const boxImg = card.querySelector(".box-img");
1482            const collapse = card.querySelector(".accordion-collapse");
1483
1484            if (collapse && boxImg) {
1485                // Accordion open হলে
1486                collapse.addEventListener("show.bs.collapse", () => {
1487                    boxImg.style.display = "none";
1488                });
1489
1490                // Accordion close হলে
1491                collapse.addEventListener("hide.bs.collapse", () => {
1492                    boxImg.style.display = "block";
1493                });
1494            }
1495        });
1496    });
1497
1498
1499
1500      /* Image Reveal Animation */
1501    if ($('.reveal').length) {
1502        gsap.registerPlugin(ScrollTrigger);
1503        let revealContainers = document.querySelectorAll(".reveal");
1504        revealContainers.forEach((container) => {
1505            let image = container.querySelector("img");
1506            let tl = gsap.timeline({
1507                scrollTrigger: {
1508                    trigger: container,
1509                    toggleActions: "play none none none"
1510                }
1511            });
1512            tl.set(container, {
1513                autoAlpha: 1
1514            });
1515            tl.from(container, 1, {
1516                xPercent: -100,
1517                ease: Power2.out
1518            });
1519            tl.from(image, 1, {
1520                xPercent: 100,
1521                scale: 1,
1522                delay: -1,
1523                ease: Power2.out
1524            });
1525        });
1526    }
1527
1528    /* Text Effect Animation */
1529    if ($('.text-anime-style-1').length) {
1530        let staggerAmount = 0.05,
1531            translateXValue = 0,
1532            delayValue = 0.5,
1533            animatedTextElements = document.querySelectorAll('.text-anime-style-1');
1534
1535        animatedTextElements.forEach((element) => {
1536            let animationSplitText = new SplitText(element, {
1537                type: "chars, words"
1538            });
1539            gsap.from(animationSplitText.words, {
1540                duration: 1,
1541                delay: delayValue,
1542                x: 20,
1543                autoAlpha: 0,
1544                stagger: staggerAmount,
1545                scrollTrigger: {
1546                    trigger: element,
1547                    start: "top 85%"
1548                },
1549            });
1550        });
1551    }
1552
1553    if ($('.text-anime-style-2').length) {
1554        let staggerAmount = 0.03,
1555            translateXValue = 20,
1556            delayValue = 0.1,
1557            easeType = "power2.out",
1558            animatedTextElements = document.querySelectorAll('.text-anime-style-2');
1559
1560        animatedTextElements.forEach((element) => {
1561            let animationSplitText = new SplitText(element, {
1562                type: "chars, words"
1563            });
1564            gsap.from(animationSplitText.chars, {
1565                duration: 2,
1566                delay: delayValue,
1567                x: translateXValue,
1568                autoAlpha: 0,
1569                stagger: staggerAmount,
1570                ease: easeType,
1571                scrollTrigger: {
1572                    trigger: element,
1573                    start: "top 85%"
1574                },
1575            });
1576        });
1577    }
1578
1579    if ($('.text-anime-style-3').length) {
1580        let animatedTextElements = document.querySelectorAll('.text-anime-style-3');
1581
1582        animatedTextElements.forEach((element) => {
1583            //Reset if needed
1584            if (element.animation) {
1585                element.animation.progress(1).kill();
1586                element.split.revert();
1587            }
1588
1589            element.split = new SplitText(element, {
1590                type: "lines,words,chars",
1591                linesClass: "split-line",
1592            });
1593            gsap.set(element, {
1594                perspective: 400
1595            });
1596
1597            gsap.set(element.split.chars, {
1598                opacity: 0,
1599                x: "50",
1600            });
1601
1602            element.animation = gsap.to(element.split.chars, {
1603                scrollTrigger: {
1604                    trigger: element,
1605                    start: "top 90%"
1606                },
1607                x: "0",
1608                y: "0",
1609                rotateX: "0",
1610                opacity: 1,
1611                duration: 1,
1612                ease: Back.easeOut,
1613                stagger: 0.02,
1614            });
1615        });
1616    }
1617
1618
1619
1620
1621    // Image Reveal Animation
1622    let img_anim_reveal = document.querySelectorAll(".img_anim_reveal");
1623
1624    img_anim_reveal.forEach((img_reveal) => {
1625        let image = img_reveal.querySelector("img");
1626        let tl = gsap.timeline({
1627            scrollTrigger: {
1628                trigger: img_reveal,
1629                start: "top 50%",
1630            }
1631        });
1632
1633        tl.set(img_reveal, {
1634            autoAlpha: 1
1635        });
1636        tl.from(img_reveal, 1.5, {
1637            yPercent: -100,
1638            ease: Power2.out
1639        });
1640        tl.from(image, 1.5, {
1641            yPercent: 100,
1642            scale: 1.3,
1643            delay: -1.5,
1644            ease: Power2.out
1645        });
1646    });
1647
1648    // hover reveal start
1649    if (document.querySelectorAll(".hover-reveal").length > 0) {
1650        const hoverText = document.querySelectorAll(".hover-reveal");
1651
1652        function moveText(e, hoverText) {
1653            const item = hoverText.getBoundingClientRect();
1654            const x = e.clientX - item.x;
1655            const y = e.clientY - item.y;
1656            if (hoverText.children[0]) {
1657                hoverText.children[0].style.transform = `translate(${x}px, ${y}px)`;
1658            }
1659        }
1660        hoverText.forEach((item, i) => {
1661            item.addEventListener("mousemove", (e) => {
1662                setInterval(moveText(e, item), 100);
1663            });
1664        });
1665    }
1666    // hover reveal end
1667
1668     /*---------- 04. Sticky fix ----------*/
1669      $(window).scroll(function () {
1670        var topPos = $(this).scrollTop();
1671        if (topPos > 500) {
1672            $('.footer-sticky').addClass('sticky');
1673        } else {
1674            $('.footer-sticky').removeClass('sticky')
1675        }
1676    })
1677
1678
1679    /* ---------  Counter Animation start --------*/
1680
1681    // Define device_width first
1682    const device_width = window.innerWidth;
1683
1684    const bounceItems = gsap.utils.toArray(".bounce_animation .bounce__anim");
1685
1686    if (bounceItems.length > 0) {
1687        // Initial state
1688        gsap.set(bounceItems, {
1689            y: -100,
1690            opacity: 0
1691        });
1692
1693        if (device_width < 1023) {
1694            // Mobile / Tablet
1695            bounceItems.forEach((item) => {
1696                let counterTl = gsap.timeline({
1697                    scrollTrigger: {
1698                        trigger: item,
1699                        start: "top center+=200",
1700                    },
1701                });
1702
1703                counterTl.to(item, {
1704                    y: 0,
1705                    opacity: 1,
1706                    ease: "bounce",
1707                    duration: 1.5,
1708                });
1709            });
1710        } else {
1711            // Desktop
1712            gsap.to(bounceItems, {
1713                scrollTrigger: {
1714                    trigger: ".bounce_animation",
1715                    start: "top center+=300",
1716                },
1717                y: 0,
1718                opacity: 1,
1719                ease: "bounce",
1720                duration: 1.5,
1721                stagger: {
1722                    each: 0.3,
1723                },
1724            });
1725        }
1726    }
1727
1728    /* ---------  Counter Animation end --------*/
1729
1730    /* webgl images hover animation -----------*/
1731
1732
1733
1734    if ($('.anim-wrap').length > 0) {
1735        const initImageHoverAnimation = function ($animElement, $images) {
1736            const hoverEffectInstance = new hoverEffect({
1737                parent: $animElement.get(0),
1738                intensity: $animElement.data("intensity") || 0.5,
1739                speedIn: $animElement.data("speedin") || 1.2,
1740                speedOut: $animElement.data("speedout") || 1.2,
1741                easing: $animElement.data("easing") || "power2.out",
1742                displacementImage: $animElement.data("displacement"),
1743                image1: $images.eq(0).attr("src"),
1744                image2: $images.eq(1).length ? $images.eq(1).attr("src") : $images.eq(0).attr("src"),
1745                hover: false
1746            });
1747
1748            // hide original images
1749            $images.css("opacity", 0);
1750
1751            // hover events
1752            $animElement.closest(".anim-wrap")
1753                .on("mouseenter", () => hoverEffectInstance.next())
1754                .on("mouseleave", () => hoverEffectInstance.previous());
1755
1756            // resize handler → fix crop issue
1757            const resizeCanvas = () => {
1758                const w = $animElement.width();
1759                const h = $animElement.height();
1760                if (hoverEffectInstance.renderer) {
1761                    hoverEffectInstance.renderer.setSize(w, h);
1762                }
1763
1764                if (hoverEffectInstance.material &&
1765                    hoverEffectInstance.material.uniforms.texture1.value &&
1766                    hoverEffectInstance.material.uniforms.texture1.value.image) {
1767                    const img = hoverEffectInstance.material.uniforms.texture1.value.image;
1768                    const imageAspect = img.width / img.height;
1769                    const aspect = w / h;
1770
1771                    if (aspect > imageAspect) {
1772                        hoverEffectInstance.mesh.scale.set(aspect / 
1772imageAspect, 1, 1);
1773                    } else {
1774                        hoverEffectInstance.mesh.scale.set(1, imageAspect / aspect, 1);
1775                    }
1776                }
1777            };
1778
1779            resizeCanvas();
1780            $(window).on("resize", resizeCanvas);
1781        };
1782
1783        const setupAllImageHoverAnimations = function () {
1784            $(".img-anim").each(function () {
1785                const $currentAnimElement = $(this);
1786                const $imgElements = $currentAnimElement.find("img");
1787                const $firstImage = $imgElements.eq(0);
1788
1789                if ($firstImage[0].complete) {
1790                    initImageHoverAnimation($currentAnimElement, $imgElements);
1791                } else {
1792                    $firstImage.on("load", function () {
1793                        initImageHoverAnimation($currentAnimElement, $imgElements);
1794                    });
1795                }
1796            });
1797        };
1798
1799        setupAllImageHoverAnimations();
1800    }
1801
1802
1803
1804    /* webgl images hover animation -----------*/
1805
1806
1807   
1808
1809    ///////////////////////
1810
1811    /* ==================================================
1812                  # Ripples
1813               ===============================================*/
1814
1815    $('.th-ripples').ripples({
1816        resolution: 256,
1817        dropRadius: 20,
1818        perturbance: 0.02,
1819    });
1820
1821
1822}
1823
1824
1825(function ($) {
1826
1827
1828   
1829
1830    setTimeout(function () {
1831        $('#loader').addClass('loaded');
1832        // Once the container has finished, the scroll appears
1833        if ($('#loader').hasClass('loaded')) {
1834            // It is so that once the container is gone, the entire preloader section is deleted
1835            $('#preloader').delay(9000).queue(function () {
1836                $(this).remove();
1837            });
1838        }
1839    }, 3000);
1840
1841
1842     /*----------- Video Image Animation start----------*/
1843
1844    gsap.registerPlugin(ScrollTrigger);
1845
1846    function handleResize() {
1847        const isMobile = window.innerWidth < 526;
1848
1849        // ----------- CTA Trigger -----------
1850        let ctaTrigger = ScrollTrigger.getById("ctaTrigger");
1851        if (isMobile) {
1852            if (ctaTrigger) {
1853                ctaTrigger.kill();
1854            }
1855            gsap.set(".cta-card-wrapp, .cta-trigger-thumb", {
1856                scale: 1,
1857                y: 0,
1858                opacity: 1
1859            });
1860        } else if (!ctaTrigger) {
1861            // Initial state
1862            gsap.set(".cta-card-wrapp", {
1863                scale: 0,
1864                y: 100,
1865                opacity: 0,
1866                transformOrigin: "center center",
1867                willChange: "transform, opacity"
1868            });
1869
1870            // ScrollTrigger animation
1871            ScrollTrigger.create({
1872                id: "ctaTrigger",
1873                trigger: ".cta-trigger-thumb",
1874                start: "top 80%",
1875                end: "top 50%",
1876                scrub: 1,
1877                markers: false,
1878                animation: gsap.to(".cta-card-wrapp", {
1879                    scale: 1,
1880                    y: 0,
1881                    opacity: 1,
1882                    ease: "power1.out",
1883                    duration: 1.5
1884                })
1885            });
1886
1887            ScrollTrigger.create({
1888                id: "ctaThumbTrigger",
1889                trigger: ".cta-trigger-thumb",
1890                start: "top 80%",
1891                end: "top 50%",
1892                scrub: 1,
1893                markers: false,
1894                animation: gsap.to(".cta-trigger-thumb", {
1895                    scale: 1,
1896                    borderRadius: "0px",
1897                    width: "100%",
1898                    top: "0",
1899                    ease: "linear"
1900                })
1901            });
1902        }
1903
1904        /*----------- Video Image Animation start----------*/
1905        let videoTrigger = ScrollTrigger.getById("videoTrigger");
1906        if (isMobile) {
1907            if (videoTrigger) {
1908                videoTrigger.kill();
1909            }
1910        } else if (!videoTrigger) {
1911            ScrollTrigger.create({
1912                id: "videoTrigger",
1913                trigger: ".video-trigger-thumb",
1914                start: "top 80%",
1915                end: "top 50%",
1916                scrub: 1,
1917                markers: false,
1918                animation: gsap.to(".video-trigger-thumb", {
1919                    duration: 2,
1920                    scale: 1,
1921                    borderRadius: "0px",
1922                    width: "100%",
1923                    top: "0",
1924                    ease: "linear"
1925                })
1926            });
1927        }
1928    }
1929
1930    window.addEventListener("load", handleResize);
1931    window.addEventListener("resize", handleResize);
1932    /*----------- Video Image Animation end----------*/
1933
1934
1935     ///////////////////////
1936    //image cliping effect
1937    document.addEventListener("DOMContentLoaded", () => {
1938
1939        const initialClipPaths = [
1940            "polygon(0% 0%, 0% 0%, 0% 0%, 0% 0%)",
1941            "polygon(33.33% 0%, 33.33% 0%, 33.33% 0%, 33.33% 0%)",
1942            "polygon(65.66% 0%, 66.66% 0%, 66.66% 0%, 66.66% 0%)",
1943            "polygon(0% 33.33%, 0% 33.33%, 0% 33.33%, 0% 33.33%)",
1944            "polygon(33.33% 33.33%, 33.33% 33.33%, 33.33% 33.33%, 33.33% 33.33%)",
1945            "polygon(65.66% 33.33%, 66.66% 33.33%, 66.66% 33.33%, 66.66% 33.33%)",
1946            "polygon(0% 66.66%, 0% 66.66%, 0% 66.66%, 0% 66.66%)",
1947            "polygon(33.33% 66.66%, 33.33% 66.66%, 33.33% 66.66%, 33.33% 66.66%)",
1948            "polygon(65.66% 66.66%, 66.66% 66.66%, 66.66% 66.66%, 66.66% 66.66%)"
1949        ];
1950
1951        const finalClipPaths = [
1952            "polygon(0% 0%, 34.33% 0%, 34.33% 34.33%, 0% 34.33%)",
1953            "polygon(32.33% 0%, 66.66% 0%, 66.66% 33.33%, 33.33% 34.33%)",
1954            "polygon(65.66% 0%, 100% 0%, 100% 33.33%, 65.66% 34.33%)",
1955            "polygon(0% 33.33%, 33.33% 33.33%, 33.33% 66.66%, 0% 66.66%)",
1956            "polygon(30.33% 33.33%, 66.66% 33.33%, 66.66% 66.66%, 33.33% 66.66%)",
1957            "polygon(65.66% 33.33%, 100% 32.33%, 100% 66.66%, 65.66% 66.66%)",
1958            "polygon(0% 65.66%, 33.33% 66.66%, 33.33% 100%, 0% 100%)",
1959            "polygon(30.33% 66.66%, 66.66% 65.66%, 66.66% 100%, 33.33% 100%)",
1960            "polygon(65.66% 66.66%, 100% 65.66%, 100% 100%, 65.66% 100%)"
1961        ];
1962
1963        // Create mask divs for each wrapper
1964        document.querySelectorAll(".th-clip-anim").forEach(wrapper => {
1965            const img = wrapper.querySelector(".th-anim-img[data-animate='true']");
1966            if (!img) return;
1967            const url = img.src;
1968
1969            // Remove old masks if any (reuse safe)
1970            wrapper.querySelectorAll(".mask").forEach(m => m.remove());
1971
1972            for (let i = 0; i < 9; i++) {
1973                const mask = document.createElement("div");
1974                mask.className = `mask mask-${i + 1}`;
1975                Object.assign(mask.style, {
1976                    backgroundImage: `url(${url})`,
1977                    backgroundSize: "cover",
1978                    backgroundPosition: "center",
1979                    position: "absolute",
1980                    inset: "0"
1981                });
1982                wrapper.appendChild(mask);
1983            }
1984        });
1985
1986        // Animate masks
1987        gsap.utils.toArray(".th-clip-anim").forEach(wrapper => {
1988            const masks = wrapper.querySelectorAll(".mask");
1989            if (!masks.length) return;
1990
1991            gsap.set(masks, {
1992                clipPath: (i) => initialClipPaths[i]
1993            });
1994
1995            const order = [
1996                [".mask-1"],
1997                [".mask-2", ".mask-4"],
1998                [".mask-3", ".mask-5", ".mask-7"],
1999                [".mask-6", ".mask-8"],
2000                [".mask-9"]
2001            ];
2002
2003            const tl = gsap.timeline({
2004                scrollTrigger: {
2005                    trigger: wrapper,
2006                    start: "top 75%"
2007                }
2008            });
2009
2010            order.forEach((targets, i) => {
2011                const validTargets = targets
2012                    .map(c => wrapper.querySelector(c))
2013                    .filter(el => el); // filter out nulls
2014
2015                if (validTargets.length) {
2016                    tl.to(validTargets, {
2017                        clipPath: (j, el) => finalClipPaths[Array.from(masks).indexOf(el)],
2018                        duration: 1,
2019                        ease: "power4.out",
2020                        stagger: 0.1
2021                    }, i * 0.125);
2022                }
2023            });
2024        });
2025    });
2026
2027    
2028
2029    // Elementor Frontend Load
2030    $(window).on('elementor/frontend/init', function () {
2031        if (elementorFrontend.isEditMode()) {
2032            elementorFrontend.hooks.addAction('frontend/element_ready/global', function () {
2033                setTimeout(function () {
2034                    schon_content_load_scripts();
2035                }, 500);
2036            });
2037        }
2038    });
2039
2040     /*----------- 19. Price Slider ----------*/
2041   
2042
2043    // Window Load
2044    $(window).on('load', function () {
2045        schon_content_load_scripts();
2046    });
2047    
2048})(jQuery);

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