PageSourceSearch

https://www.cmu.ac.th/Scripts/js/theme.js

js cmu.ac.th collected 2026-09-24 08:34:36 UTC 252,543 bytes, 9,479 lines download raw bytes

1/*
2Name: 			Theme Base
3Written by: 	Okler Themes - (http://www.okler.net)
4Theme Version:	12.0.0
5*/
6
7// Theme
8window.theme = {};
9
10// Theme Common Functions
11window.theme.fn = {
12
13	getOptions(opts) {
14
15		if (typeof(opts) == 'object') {
16
17			return opts;
18
19		} else if (typeof(opts) == 'string') {
20
21			try {
22				return JSON.parse(opts.replace(/'/g, '"').replace(';', ''));
23			} catch (e) {
24				return {};
25			}
26
27		} else {
28
29			return {};
30
31		}
32
33	},
34
35	execPluginFunction(functionName, context) {
36		const args = Array.prototype.slice.call(arguments, 2);
37		const namespaces = functionName.split(".");
38		const func = namespaces.pop();
39
40		for (let i = 0; i < namespaces.length; i++) {
41			context = context[namespaces[i]];
42		}
43
44		return context[func](...args);
45	},
46
47	intObs(selector, functionName, intObsOptions, alwaysObserve) {
48		const $el = document.querySelectorAll(selector);
49		let intersectionObserverOptions = {
50			rootMargin: '0px 0px 200px 0px'
51		};
52
53		if (Object.keys(intObsOptions).length) {
54			intersectionObserverOptions = $.extend(intersectionObserverOptions, intObsOptions);
55		}
56
57		const observer = new IntersectionObserver(entries => {
58            for (const entry of entries) {
59                if (entry.intersectionRatio > 0) {
60					if (typeof functionName === 'string') {
61						const func = Function('return ' + functionName)();
62					} else {
63						const callback = functionName;
64
65						callback.call($(entry.target));
66					}
67
68					// Unobserve
69					if (!alwaysObserve) {
70						observer.unobserve(entry.target);
71					}
72
73				}
74            }
75        }, intersectionObserverOptions);
76
77		$($el).each(function() {
78			observer.observe($(this)[0]);
79		});
80	},
81
82	intObsInit(selector, functionName) {
83		const $el = document.querySelectorAll(selector);
84		const intersectionObserverOptions = {
85			rootMargin: '200px'
86		};
87
88		const observer = new IntersectionObserver(entries => {
89            for (const entry of entries) {
90                if (entry.intersectionRatio > 0) {
91                    const $this = $(entry.target);
92                    let opts;
93
94                    const pluginOptions = theme.fn.getOptions($this.data('plugin-options'));
95                    if (pluginOptions)
96						opts = pluginOptions;
97
98                    theme.fn.execPluginFunction(functionName, $this, opts);
99
100                    // Unobserve
101                    observer.unobserve(entry.target);
102                }
103            }
104        }, intersectionObserverOptions);
105
106		$($el).each(function() {
107			observer.observe($(this)[0]);
108		});
109	},
110
111	dynIntObsInit(selector, functionName, pluginDefaults) {
112		const $el = document.querySelectorAll(selector);
113
114		$($el).each(function() {
115            const $this = $(this);
116            let opts;
117
118            const pluginOptions = theme.fn.getOptions($this.data('plugin-options'));
119            if (pluginOptions)
120				opts = pluginOptions;
121
122            const mergedPluginDefaults = theme.fn.mergeOptions(pluginDefaults, opts);
123
124            const intersectionObserverOptions = {
125				rootMargin: theme.fn.getRootMargin(functionName, mergedPluginDefaults),
126				threshold: 0
127			};
128
129            if (!mergedPluginDefaults.forceInit) {
130
131				const observer = new IntersectionObserver(entries => {
132                    for (const entry of entries) {
133                        if (entry.intersectionRatio > 0) {
134							theme.fn.execPluginFunction(functionName, $this, mergedPluginDefaults);
135
136							// Unobserve
137							observer.unobserve(entry.target);
138						}
139                    }
140                }, intersectionObserverOptions);
141
142				observer.observe($this[0]);
143
144			} else {
145				theme.fn.execPluginFunction(functionName, $this, mergedPluginDefaults);
146			}
147        });
148	},
149
150	getRootMargin(plugin, {accY}) {
151		switch (plugin) {
152			case 'themePluginCounter':
153				return accY ? `0px 0px ${accY}px 0px` : '0px 0px 200px 0px';
154				break;
155
156			case 'themePluginAnimate':
157				return accY ? `0px 0px ${accY}px 0px` : '0px 0px 200px 0px';
158				break;
159
160			case 'themePluginIcon':
161				return accY ? `0px 0px ${accY}px 0px` : '0px 0px 200px 0px';
162				break;
163
164			case 'themePluginRandomImages':
165				return accY ? `0px 0px ${accY}px 0px` : '0px 0px 200px 0px';
166				break;
167
168			default:
169				return '0px 0px 200px 0px';
170				break;
171		}
172	},
173
174	mergeOptions(obj1, obj2) {
175		const obj3 = {};
176
177		for (var attrname in obj1) {
178			obj3[attrname] = obj1[attrname];
179		}
180		for (var attrname in obj2) {
181			obj3[attrname] = obj2[attrname];
182		}
183
184		return obj3;
185	},
186
187	execOnceTroughEvent($el, event, callback) {
188		const self = this, dataName = self.formatDataName(event);
189
190		$($el).on(event, function() {
191			if (!$(this).data(dataName)) {
192
193				// Exec Callback Function
194				callback.call($(this));
195
196				// Add data name 
197				$(this).data(dataName, true);
198
199				// Unbind event
200				$(this).off(event);
201			}
202		});
203
204		return this;
205	},
206
207	execOnceTroughWindowEvent($el, event, callback) {
208		const self = this, dataName = self.formatDataName(event);
209
210		$($el).on(event, function() {
211			if (!$(this).data(dataName)) {
212
213				// Exec Callback Function
214				callback();
215
216				// Add data name 
217				$(this).data(dataName, true);
218
219				// Unbind event
220				$(this).off(event);
221			}
222		});
223
224		return this;
225	},
226
227	formatDataName(name) {
228		name = name.replace('.', '');
229		return name;
230	},
231
232	isElementInView($el) {
233		const rect = $el[0].getBoundingClientRect();
234
235		return (
236			rect.top <= (window.innerHeight / 3)
237		);
238	},
239
240	getScripts(arr, path) {
241		const _arr = $.map(arr, scr => $.getScript((path || "") + scr));
242
243		_arr.push($.Deferred(({resolve}) => {
244			$(resolve);
245		}));
246
247		return $.when(..._arr);
248	},
249
250	showErrorMessage(title, content) {
251
252		$('.modalThemeErrorMessage').remove();
253		$('body').append('<div class="modal fade" id="modalThemeErrorMessage" aria-hidden="true" tabindex="-1"><div class="modal-dialog modal-dialog-centered"><div class="modal-content"><div class="modal-header"><h5 class="modal-title">' + title + '</h5><button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button></div><div class="modal-body">' + content + '</div><div class="modal-footer"><button type="button" class="btn btn-primary" data-bs-dismiss="modal">Close</button></div></div></div></div>');
254
255		var modalThemeErrorMessage = document.getElementById('modalThemeErrorMessage');
256		var modalThemeErrorMessage = bootstrap.Modal.getOrCreateInstance(modalThemeErrorMessage);
257		modalThemeErrorMessage.show();
258
259	}
260
261};
262
263(((theme = {}, $) => {
264	/*
265	Local Environment Warning
266	*/
267	try {
268		if ("file://" === location.origin) {
269			if ($('[data-icon]').length || $('iframe').length) {
270
271				theme.fn.showErrorMessage('Local Environment Warning', 'SVG Objects, Icons, YouTube and Vimeo Videos might not show correctly on local environment. For better result, please preview on a server.');
272
273			}
274		}
275	} catch (e) {}
276
277	/*
278	Browser Selector
279	*/
280	$.extend({
281
282		browserSelector() {
283
284			// jQuery.browser.mobile (http://detectmobilebrowser.com/)
285			(a => {(jQuery.browser=jQuery.browser||{}).mobile=/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))})(navigator.userAgent||navigator.vendor||window.opera);
286
287			// Touch
288			const hasTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints;
289
290			const u = navigator.userAgent, ua = u.toLowerCase(), is = t => ua.includes(t), g = 'gecko', w = 'webkit', s = 'safari', o = 'opera', h = document.documentElement, b = [(!(/opera|webtv/i.test(ua)) && /msie\s(\d)/.test(ua)) ? (`ie ie${parseFloat(navigator.appVersion.split("MSIE")[1])}`) : is('firefox/2') ? `${g} ff2` : is('firefox/3.5') ? `${g} ff3 ff3_5` : is('firefox/3') ? `${g} ff3` : is('gecko/') ? g : is('opera') ? o + (/version\/(\d+)/.test(ua) ? ` ${o}${RegExp.jQuery1}` : (/opera(\s|\/)(\d+)/.test(ua) ? ` ${o}${RegExp.jQuery2}` : '')) : is('konqueror') ? 'konqueror' : is('chrome') ? `${w} chrome` : is('iron') ? `${w} iron` : is('applewebkit/') ? `${w} ${s}${/version\/(\d+)/.test(ua) ? ` ${s}${RegExp.jQuery1}` : ''}` : is('mozilla/') ? g : '', is('j2me') ? 'mobile' : is('iphone') ? 'iphone' : is('ipod') ? 'ipod' : is('mac') ? 'mac' : is('darwin') ? 'mac' : is('webtv') ? 'webtv' : is('win') ? 'win' : is('freebsd') ? 'freebsd' : (is('x11') || is('linux')) ? 'linux' : '', 'js'];
291
292			c = b.join(' ');
293
294			if ($.browser.mobile) {
295				c += ' mobile';
296			}
297
298			if (hasTouch) {
299				c += ' touch';
300			}
301
302			h.className += ` ${c}`;
303
304			// Edge Detect
305			const isEdge = /Edge/.test(navigator.userAgent);
306
307			if(isEdge) {
308				$('html').removeClass('chrome').addClass('edge');
309			}
310
311			// Dark and Boxed Compatibility
312			if($('body').hasClass('dark')) {
313				$('html').addClass('dark');
314			}
315
316			if($('body').hasClass('boxed')) {
317				$('html').addClass('boxed');
318			}
319
320		}
321
322	});
323
324	$.browserSelector();
325
326	/*
327	Browser Workarounds
328	*/
329	if (/iPad|iPhone|iPod/.test(navigator.platform)) {
330
331		// iPad/Iphone/iPod Hover Workaround
332		$(document).ready($ => {
333			$('.thumb-info').attr('onclick', 'return true');
334		});
335	}
336
337	/*
338	Tabs
339	*/
340	if( $('a[data-bs-toggle="tab"]').length ) {
341		$('a[data-bs-toggle="tab"]').on('shown.bs.tab', function({target}) {
342			const $tabPane = $($(target).attr('href'));
343
344			// Carousel Refresh
345			if($tabPane.length) {
346				$tabPane.find('.owl-carousel').trigger('refresh.owl.carousel');
347			}
348
349			// Change Active Class
350			$(this).parents('.nav-tabs').find('.active').removeClass('active');
351			$(this).addClass('active').parent().addClass('active');
352		});	
353
354		if( window.location.hash ) {
355			$(window).on('load', () => {
356				if( window.location.hash !== '*' && $( window.location.hash ).get(0) ) {
357					new bootstrap.Tab( $('a.nav-link[href="'+ window.location.hash +'"]:not([data-hash])')[0] ).show();
358				}
359			});
360		}
361	}
362
363	/*
364	On Load Scroll
365	*/
366	if( !$('html').hasClass('disable-onload-scroll') && window.location.hash && !['#*'].includes( window.location.hash ) ) {
367
368		window.scrollTo(0, 0);
369
370		$(window).on('load', () => {
371			setTimeout(() => {
372				const target = window.location.hash;
373				let offset = ( $(window).width() < 768 ) ? 180 : 90;
374
375				if (!$(target).length) {
376					return;
377				}
378
379				if ( $("a[href$='" + window.location.hash + "']").is('[data-hash-offset]') ) {
380					offset = parseInt( $("a[href$='" + window.location.hash + "']").first().attr('data-hash-offset') );
381				} else if ( $("html").is('[data-hash-offset]') ) {
382					offset = parseInt( $("html").attr('data-hash-offset') );
383				}
384
385				if (isNaN(offset)) {
386					offset = 0;
387				}
388
389				$('body').addClass('scrolling');
390
391				$('html, body').animate({
392					scrollTop: $(target).offset().top - offset
393				}, 600, 'easeOutQuad', () => {
394					$('body').removeClass('scrolling');
395				});
396			}, 1);
397		});
398	}
399
400	/*
401	* Text Rotator
402	*/
403	$.fn.extend({
404		textRotator(options) {
405
406			const defaults = {
407				fadeSpeed: 500,
408				pauseSpeed: 100,
409				child: null
410			};
411
412			var options = $.extend(defaults, options);
413
414			return this.each(function() {
415				const o = options;
416				const obj = $(this);
417				const items = $(obj.children(), obj);
418				items.each(function() {
419					$(this).hide();
420				})
421				if (!o.child) {
422					var next = $(obj).children(':first');
423				} else {
424					var next = o.child;
425				}
426				$(next).fadeIn(o.fadeSpeed, () => {
427					$(next).delay(o.pauseSpeed).fadeOut(o.fadeSpeed, function() {
428						let next = $(this).next();
429						if (next.length == 0) {
430							next = $(obj).children(':first');
431						}
432						$(obj).textRotator({
433							child: next,
434							fadeSpeed: o.fadeSpeed,
435							pauseSpeed: o.pauseSpeed
436						});
437					})
438				});
439			});
440		}
441	});
442
443	/*
444	* Notice Top bar
445	*/
446	const $noticeTopBar = {
447		$wrapper: $('.notice-top-bar'),
448		$closeBtn: $('.notice-top-bar-close'),
449		$header: $('#header'),
450		$body: $('.body'),
451		init() {
452			const self = this;
453
454			if( !$.cookie('portoNoticeTopBarClose') ) {
455				self
456					.build()
457					.events();
458			} else {
459				self.$wrapper.parent().prepend( '<!-- Notice Top Bar removed by cookie -->' );
460				self.$wrapper.remove();
461			}
462
463			return this;
464		},
465		build() {
466			const self = this;
467
468			$(window).on('load', () => {
469				setTimeout(() => {
470					self.$body.css({
471						'margin-top': self.$wrapper.outerHeight(),
472						'transition': 'ease margin 300ms'
473					});
474
475					$('#noticeTopBarContent').textRotator({
476						fadeSpeed: 500,
477						pauseSpeed: 5000
478					});
479
480					if( ['absolute', 'fixed'].includes( self.$header.css('position') ) ) {
481						self.$header.css({
482							'top': self.$wrapper.outerHeight(),
483							'transition': 'ease top 300ms'
484						});
485					}
486
487					$(window).trigger('notice.top.bar.opened');
488
489				}, 1000);
490			});
491
492			return this;
493		},
494		events() {
495			const self = this;
496
497			self.$closeBtn.on('click', e => {
498				e.preventDefault();
499
500				self.$body.animate({
501					'margin-top': 0,
502				}, 300, () => {
503					self.$wrapper.remove();
504					self.saveCookie();
505				});
506
507				if( ['absolute', 'fixed'].includes( self.$header.css('position') ) ) {
508					self.$header.animate({
509						top: 0
510					}, 300);
511				}
512
513				// When header has shrink effect
514				if( self.$header.hasClass('header-effect-shrink') ) {
515					self.$header.find('.header-body').animate({
516						top: 0
517					}, 300);
518				}
519
520				$(window).trigger('notice.top.bar.closed');
521			});
522
523			return this;
524		},
525		checkCookie() {
526			const self = this;
527
528			if( $.cookie('portoNoticeTopBarClose') ) {
529				return true;
530			} else {
531				return false;
532			}
533
534			return this;
535		},
536		saveCookie() {
537			const self = this;
538
539			$.cookie('portoNoticeTopBarClose', true);
540
541			return this;
542		}
543	};
544
545	if( $('.notice-top-bar').length ) {
546		$noticeTopBar.init();
547	}
548
549	/*
550	* Image Hotspots
551	*/
552	if( $('.image-hotspot').length ) {
553		$('.image-hotspot')
554			.append('<span class="ring"></span>')
555			.append('<span class="circle"></span>');
556	}
557
558	/*
559	* Reading Progress
560	*/
561	if( $('.progress-reading').length ) {
562
563		function updateScrollProgress() {
564			const pixels = $(document).scrollTop();
565				pageHeight = $(document).height() - $(window).height()
566				progress = 100 * pixels / pageHeight;
567
568			$('.progress-reading .progress-bar').width(parseInt(progress) + "%");
569		}
570
571		$(document).on('scroll ready', () => {
572			updateScrollProgress();
573		});
574
575		$(document).ready(() => {
576			$(window).afterResize(() => {
577				updateScrollProgress();
578			});
579		});
580
581	}
582
583	/*
584	* Page Transition
585	*/
586	if( $('body[data-plugin-page-transition]').length ) {
587		
588		let link_click = false;
589
590		$(document).on('click', 'a', function(e){
591			link_click = $(this);
592		});
593
594		$(window).on("beforeunload", e => {
595			if( typeof link_click === 'object' ) {
596				const href = link_click.attr('href');
597
598				if( href.indexOf('mailto:') != 0 && href.indexOf('tel:') != 0 && !link_click.data('rm-from-transition') ) {
599					$('body').addClass('page-transition-active');
600				}
601			}
602		});
603
604		$(window).on("pageshow", ({persisted, originalEvent}) => {
605			if( persisted || originalEvent.persisted) {
606				if( $('html').hasClass('safari') ) {
607					window.location.reload();
608				}
609				
610				$('body').removeClass('page-transition-active');
611			}
612		});
613	}
614
615	/*
616	* Clone Element
617	*/
618	if( $('[data-clone-element]').length ) {
619
620		$('[data-clone-element]').each(function() {
621
622			const $el = $(this), content = $el.html(), qty = $el.attr('data-clone-element');
623
624			for (let i = 0; i < qty; i++) {
625				$el.html($el.html() + content);
626			}
627
628		});
629
630	}
631
632	if( $('[data-clone-element-to]').length ) {
633
634		$('[data-clone-element-to]').each(function() {
635
636			const $el = $(this);
637			const content = $el.html();
638			const $to = $($el.attr('data-clone-element-to'));
639
640			$to.html($to.html() + content);
641
642		});
643
644	}
645
646	/*
647	* Thumb Info Floating Caption
648	*/
649	$('.thumb-info-floating-caption').each(function() {
650
651		$(this)
652			.addClass('thumb-info-floating-element-wrapper')
653			.append( '<span class="thumb-info-floating-element thumb-info-floating-caption-title d-none">'+ $(this).data('title') +'</span>' );
654
655		if( $(this).data('type') ) {
656			$('.thumb-info-floating-caption-title', $(this))
657				.append( '<div class="thumb-info-floating-caption-type">'+ $(this).data('type') +'</div>' )
658				.css({
659					'padding-bottom' : 22
660				});
661		}
662
663		if( $(this).hasClass('thumb-info-floating-caption-clean') ) {
664			$('.thumb-info-floating-element', $(this)).addClass('bg-transparent');
665		}
666
667	});
668
669	/*
670	* Thumb Info Floating Element
671	*/
672	if( $('.thumb-info-floating-element-wrapper').length ) {
673
674		if (typeof gsap !== 'undefined') {
675
676			$('.thumb-info-floating-element-wrapper').on('mouseenter', function({clientX, clientY}) {
677				
678				if(!$(this).data('offset')) {
679					$(this).data('offset', 0);
680				}
681
682				const offset = parseInt($(this).data('offset'));
683
684				$('.thumb-info-floating-element-clone').remove();
685
686				$('.thumb-info-floating-element', $(this)).clone().addClass('thumb-info-floating-element-clone p-fixed p-events-none').attr('style', 'transform: scale(0.1);').removeClass('d-none').appendTo('body');
687
688				$('.thumb-info-floating-element-clone').css({
689					left: clientX + (offset),
690					top: clientY + (offset)
691				}).fadeIn(300);
692
693				gsap.to('.thumb-info-floating-element-clone', 0.5, {
694					css: {
695						scaleX: 1,
696						scaleY: 1
697					}
698				});
699
700				$(document).off('mousemove').on('mousemove', ({clientX, clientY}) => {
701
702					gsap.to('.thumb-info-floating-element-clone', 0.5, {
703						css: {
704							left: clientX + (offset),
705							top: clientY + (offset)
706						}
707					});
708
709				});
710
711			}).on('mouseout', () => {
712
713				gsap.to('.thumb-info-floating-element-clone', 0.5, {
714					css: {
715						scaleX: 0.5,
716						scaleY: 0.5,
717						opacity: 0
718					}
719				});
720
721			});
722
723		} else {
724			theme.fn.showErrorMessage('Failed to Load File', 'Failed to load: GSAP - Include the following file(s): (vendor/gsap/gsap.min.js)');
725		}
726
727	}
728
729	/*
730	* Thumb Info Direction Aware
731	*/
732	$(window).on('load', () => {
733		$('.thumb-info-wrapper-direction-aware').each( function() {
734			$(this).hoverdir({
735				speed : 300,
736				easing : 'ease',
737				hoverDelay : 0,
738				inverse : false,
739				hoverElem: '.thumb-info-wrapper-overlay'
740			});
741		});
742	});
743
744	/*
745	* Thumb Info Container Full
746	*/
747	$('.thumb-info-container-full-img').each(function() {
748
749		const $container = $(this);
750
751		$('[data-full-width-img-src]', $container).each(function() {
752			const uniqueId = 'img' + Math.floor(Math.random() * 10000);
753			$(this).attr('data-rel', uniqueId);
754
755			$container.append('<div style="background-image: url(' + $(this).attr('data-full-width-img-src') + ');" id="' + uniqueId + '" class="thumb-info-container-full-img-large opacity-0"></div>');
756		});
757
758		$('.thumb-info', $container).on('mouseenter', function(e){
759			$('.thumb-info-container-full-img-large').removeClass('active');
760			$('#' + $(this).attr('data-rel')).addClass('active');
761		});
762
763	});
764
765	/*
766	* Toggle Text Click
767	*/
768	$('[data-toggle-text-click]').on('click', function () {
769		$(this).text(function(i, text){
770			return text === $(this).attr('data-toggle-text-click') ? $(this).attr('data-toggle-text-click-alt') : $(this).attr('data-toggle-text-click');
771		});
772	});
773
774	/*
775	* Toggle Class
776	*/
777	$('[data-toggle-class]').on('click', function (e) {
778		e.preventDefault();
779
780		$(this).toggleClass( $(this).data('toggle-class') );
781	});
782
783	/*
784	* Shape Divider Aspect Ratio
785	*/
786	if( $('.shape-divider').length ) {
787		aspectRatioSVG();
788		$(window).on('resize', () => {
789			aspectRatioSVG();
790		});
791	}
792
793	/*
794	* Shape Divider Animated
795	*/
796	if( $('.shape-divider-horizontal-animation').length ) {
797		theme.fn.intObs('.shape-divider-horizontal-animation', function(){
798			for( let i = 0; i <= 1; i++ ) {
799				const svgClone = $(this).find('svg:nth-child(1)').clone();
800
801				$(this).append( svgClone )
802			}
803
804			$(this).addClass('start');
805		}, {});
806	}
807
808	/*
809	* Shape Divider - SVG Aspect Ratio
810	*/
811	function aspectRatioSVG() {
812		if( $(window).width() < 1950 ) {
813			$('.shape-divider svg[preserveAspectRatio]').each(function(){
814				if( !$(this).parent().hasClass('shape-divider-horizontal-animation') ) {
815					$(this).attr('preserveAspectRatio', 'xMinYMin');
816				} else {
817					$(this).attr('preserveAspectRatio', 'none');
818				}
819			});
820		} else {
821			$('.shape-divider svg[preserveAspectRatio]').each(function(){
822				$(this).attr('preserveAspectRatio', 'none');
823			});
824		}
825	}
826
827	/*
828	* Content Switcher
829	*/
830	$('[data-content-switcher]').on('change', function(e, v) {
831		const switcherRel = ($(this).is(':checked') ? '1' : '2' ), switcherId = $(this).attr('data-content-switcher-content-id');
832
833		$('[data-content-switcher-id=' + switcherId + ']').addClass('initialized').removeClass('active');
834
835		const $activeEl = $('[data-content-switcher-id=' + switcherId + '][data-content-switcher-rel=' + switcherRel + ']');
836
837		$activeEl.addClass('active');
838
839		$activeEl.parent().css('height', $activeEl.height());
840	});
841
842	$('[data-content-switcher]').trigger('change');
843
844	/*
845	* Dynamic Height
846	*/
847	var $window = $(window);
848	$window.on('resize dynamic.height.resize', () => {
849		$('[data-dynamic-height]').each(function(){
850			const $this = $(this), values = JSON.parse($this.data('dynamic-height').replace(/'/g,'"').replace(';',''));
851
852			// XS
853			if( $window.width() < 576 ) {
854				$this.height( values[4] );
855			}
856
857			// SM
858			if( $window.width() > 575 && $window.width() < 768 ) {
859				$this.height( values[3] );
860			}
861
862			// MD
863			if( $window.width() > 767 && $window.width() < 992 ) {
864				$this.height( values[2] );
865			}
866
867			// LG
868			if( $window.width() > 991 && $window.width() < 1200 ) {
869				$this.height( values[1] );
870			}
871
872			// XS
873			if( $window.width() > 1199 ) {
874				$this.height( values[0] );
875			}
876		});
877	});
878
879	// Mobile First Load
880	if( $window.width() < 992 ) {
881		$window.trigger('dynamic.height.resize');
882	}
883
884	/*
885	* Video - Trigger Play
886	*/
887	if( $('[data-trigger-play-video]').length ) {
888		theme.fn.execOnceTroughEvent( '[data-trigger-play-video]', 'mouseover.trigger.play.video', function(){
889			const $video = $( $(this).data('trigger-play-video') );
890
891			$(this).on('click', function(e){
892				e.preventDefault();
893
894				if( $(this).data('trigger-play-video-remove') == 'yes' ) {
895					$(this).animate({
896						opacity: 0
897					}, 300, function(){
898						$video[0].play();
899
900						$(this).remove();
901					});
902				} else {
903					setTimeout(() => {
904						$video[0].play();
905					},300);
906				}
907			});
908		});
909	}
910
911	/*
912	* Video - Auto Play
913	*/
914	if( $('video[data-auto-play]').length ) {
915		$(window).on('load', () => {
916			$('video[data-auto-play]').each(function(){
917				const $video = $(this);
918
919				setTimeout(() => {
920					if( $( '#' + $video.attr('id') ).length ) {
921						if( $( '[data-trigger-play-video="#' + $video.attr('id') + '"]' ).data('trigger-play-video-remove') == 'yes' ) {
922							$( '[data-trigger-play-video="#' + $video.attr('id') + '"]' ).animate({
923								opacity: 0
924							}, 300, () => {
925								$video[0].play();
926
927								$( '[data-trigger-play-video="#' + $video.attr('id') + '"]' ).remove();
928							});
929						} else {
930							setTimeout(() => {
931								$video[0].play();
932							},300);
933						}
934					}
935				}, 100);
936
937			});
938		});
939	}
940
941	/*
942	* Remove min height after the load of page
943	*/
944	if( $('[data-remove-min-height]').length ) {
945		$(window).on('load', () => {
946			$('[data-remove-min-height]').each(function(){
947				$(this).css({
948					'min-height': 0
949				});
950			});
951		});
952	}
953
954	/*
955	* Lazy Load Background Images (with lazySizes plugin)
956	*/
957	document.addEventListener('lazybeforeunveil', ({target}) => {
958		const bg = target.getAttribute('data-bg-src');
959		if(bg) {
960			target.style.backgroundImage = 'url(' + bg + ')';
961		}
962	});
963
964	/*
965	* Title Border
966	*/
967	if($('[data-title-border]').length) {
968
969		const $pageHeaderTitleBorder = $('<span class="page-header-title-border"></span>'), $pageHeaderTitle = $('[data-title-border]'), $window = $(window);
970
971		$pageHeaderTitle.before($pageHeaderTitleBorder);
972
973		const setPageHeaderTitleBorderWidth = () => {
974			$pageHeaderTitleBorder.width($pageHeaderTitle.width());
975		};
976
977		$window.afterResize(() => {
978			setPageHeaderTitleBorderWidth();
979		});
980
981		setPageHeaderTitleBorderWidth();
982
983		$pageHeaderTitleBorder.addClass('visible');
984	}
985
986	/*
987	* Footer Reveal
988	*/
989	($ => {
990		const $footerReveal = {
991			$wrapper: $('.footer-reveal'),
992			init() {
993				const self = this;
994
995				self.build();
996				self.events();
997			},
998			build() {
999				const self = this, footer_height = self.$wrapper.outerHeight(true), window_height = ( $(window).height() - $('.header-body').height() );
1000
1001				if( footer_height > window_height ) {
1002					$('#footer').removeClass('footer-reveal');
1003					$('body').css('margin-bottom', 0);
1004				} else {
1005					$('#footer').addClass('footer-reveal');
1006					$('body').css('margin-bottom', footer_height);
1007				}
1008
1009			},
1010			events() {
1011				const self = this, $window = $(window);
1012
1013				$window.on('load', () => {
1014					$window.afterResize(() => {
1015						self.build();
1016					});
1017				});
1018			}
1019		};
1020
1021		if( $('.footer-reveal').length ) {
1022			$footerReveal.init();
1023		}
1024	})(jQuery);
1025
1026	/*
1027	* Re-Init Plugin
1028	*/
1029	if( $('[data-reinit-plugin]').length ) {
1030		$('[data-reinit-plugin]').on('click', function(e) {
1031			e.preventDefault();
1032
1033			const pluginInstance = $(this).data('reinit-plugin'), pluginFunction = $(this).data('reinit-plugin-function'), pluginElement  = $(this).data('reinit-plugin-element'), pluginOptions  = theme.fn.getOptions($(this).data('reinit-plugin-options'));
1034
1035			$( pluginElement ).data( pluginInstance ).destroy();
1036
1037			setTimeout(() => {
1038				theme.fn.execPluginFunction(pluginFunction, $( pluginElement ), pluginOptions);	
1039			}, 1000);
1040
1041		});
1042	}
1043
1044	/*
1045	* Simple Copy To Clipboard
1046	*/
1047	if( $('[data-copy-to-clipboard]').length ) {
1048		theme.fn.intObs( '[data-copy-to-clipboard]', function(){
1049			const $this = $(this);
1050
1051			$this.wrap( '<div class="copy-to-clipboard-wrapper position-relative"></div>' );
1052
1053			const $copyButton = $('<a href="#" class="btn btn-primary btn-px-2 py-1 text-0 position-absolute top-8 right-8">COPY</a>');
1054			$this.parent().prepend( $copyButton );
1055
1056			$copyButton.on('click', function(e){
1057				e.preventDefault();
1058
1059				const $btn       = $(this), $temp = $('<textarea class="d-block opacity-0" style="height: 0;">');
1060
1061				$btn.parent().append( $temp );
1062
1063				$temp.val( $this.text() );
1064					
1065				$temp[0].select();
1066				$temp[0].setSelectionRange(0, 99999);
1067
1068				document.execCommand("copy");
1069
1070				$btn.addClass('copied');
1071				setTimeout(() => {
1072					$btn.removeClass('copied');
1073				}, 1000);
1074
1075				$temp.remove();
1076			});
1077		}, {
1078			rootMargin: '0px 0px 0px 0px'
1079		} );
1080	}
1081
1082	/*
1083	* Marquee
1084	*/
1085	if( $('.marquee').length && $.isFunction($.fn.marquee) ) {
1086		$('.marquee').marquee({
1087			duration: 5000,
1088			gap: 0,
1089			delayBeforeStart: 0,
1090			direction: 'left',
1091			duplicated: true
1092		});
1093	}
1094
1095	/*
1096	* Style Switcher Open Loader Button
1097	*/
1098	if( $('.style-switcher-open-loader').length ) {
1099
1100		const urlParams = new URLSearchParams(window.location.search);
1101
1102		let hideStyleSwitcherAfterShow = false;
1103
1104		$('.style-switcher-open-loader').on('click', function(e){
1105			e.preventDefault();
1106
1107			const $this = $(this);
1108
1109			// Add Spinner to icon
1110			$this.addClass('style-switcher-open-loader-loading');
1111
1112			const basePath = $(this).data('base-path'), skinSrc = $(this).data('skin-src');
1113
1114			const script1 = document.createElement("script");
1115			script1.src = basePath + "master/style-switcher/style.switcher.localstorage.js";
1116
1117			const script2 = document.createElement("script");
1118			script2.src = basePath + "master/style-switcher/style.switcher.js";
1119			script2.id = "styleSwitcherScript";
1120			script2.setAttribute('data-base-path', basePath);
1121			script2.setAttribute('data-skin-src', skinSrc);
1122
1123			script2.onload = () => {
1124				setTimeout(() => {
1125					// Trigger a click to open the style switcher sidebar
1126					function checkIfReady() {
1127						if( !$('.style-switcher-open').length ) {
1128							window.setTimeout(checkIfReady, 100);
1129						} else {
1130							$('.style-switcher-open').trigger('click');
1131
1132							if (hideStyleSwitcherAfterShow) {
1133								setTimeout(() => {
1134									$('.style-switcher-open').trigger('click');
1135								}, 2000);
1136							}
1137						}
1138					}
1139					checkIfReady();
1140
1141				}, 500);
1142			}
1143
1144			document.body.appendChild(script1);
1145			document.body.appendChild(script2);	
1146
1147		});
1148
1149		let htmlDataOptions = $('html').data('style-switcher-options');
1150		let showSwitcher = false;
1151
1152		if(htmlDataOptions) {
1153			htmlDataOptions = htmlDataOptions.replace(/'/g, '"');
1154
1155			if (JSON.parse(htmlDataOptions).showSwitcher) {
1156				showSwitcher = true;
1157			}
1158
1159			if (JSON.parse(htmlDataOptions).hideStyleSwitcherAfterShow) {
1160				hideStyleSwitcherAfterShow = true;
1161			}
1162		}
1163
1164		if (urlParams.has("showStyleSwitcher")) {
1165			showSwitcher = true;
1166		}
1167
1168		if (urlParams.has("hideStyleSwitcherAfterShow")) {
1169			hideStyleSwitcherAfterShow = true;
1170		}
1171
1172		if (showSwitcher) {
1173			$('.style-switcher-open-loader').trigger('click');
1174		}
1175
1176	}
1177
1178})).apply(this, [ window.theme, jQuery ]);
1179
1180// Animate
1181(((theme = {}, $) => {
1182    const instanceName = '__animate';
1183
1184    class PluginAnimate {
1185        constructor($el, opts) {
1186            return this.initialize($el, opts);
1187        }
1188
1189        initialize($el, opts) {
1190			if ($el.data(instanceName)) {
1191				return this;
1192			}
1193
1194			this.$el = $el;
1195
1196			this
1197				.setData()
1198				.setOptions(opts)
1199				.build();
1200
1201			return this;
1202		}
1203
1204        setData() {
1205			this.$el.data(instanceName, this);
1206
1207			return this;
1208		}
1209
1210        setOptions(opts) {
1211			this.options = $.extend(true, {}, PluginAnimate.defaults, opts, {
1212				wrapper: this.$el
1213			});
1214
1215			return this;
1216		}
1217
1218        build() {
1219			const self = this;
1220
1221			// Flag Class Only
1222			// - Useful for simple animations like hightlight
1223			// - Less process and memory
1224			if( self.options.flagClassOnly ) {
1225				const delay = self.options.wrapper.attr('data-appear-animation-delay') ? self.options.wrapper.attr('data-appear-animation-delay') : self.options.delay;
1226				
1227				self.options.wrapper.css({
1228					'animation-delay': delay + 'ms',
1229					'transition-delay': delay + 'ms'
1230				});
1231				self.options.wrapper.addClass( self.options.wrapper.attr('data-appear-animation') );
1232
1233				return this;
1234			}
1235
1236			if($('body').hasClass('loading-overlay-showing')) {
1237				$(window).on('loading.overlay.ready', () => {
1238					self.animate();
1239				});
1240			} else {
1241				self.animate();
1242			}
1243
1244			return this;
1245		}
1246
1247        animate() {
1248            const self = this;
1249            const $el = this.options.wrapper;
1250            let delay = 0;
1251            let duration = this.options.duration;
1252            const elTopDistance = $el.offset().top;
1253            const windowTopDistance = $(window).scrollTop();
1254
1255            // If has appear animation elements inside a SVG. 
1256            // Intersection Observer API do not check elements inside SVG's, so we need initialize trough top parent SVG
1257            if( $el.data('appear-animation-svg') ) {
1258				$el.find('[data-appear-animation]').each(function(){
1259                    const $this = $(this);
1260                    let opts;
1261
1262                    const pluginOptions = theme.fn.getOptions($this.data('plugin-options'));
1263                    if (pluginOptions)
1264						opts = pluginOptions;
1265
1266                    $this.themePluginAnimate(opts);
1267                });
1268
1269				return this;
1270			}
1271
1272            // No animation at the first load of page. This is good for performance
1273            if( self.options.firstLoadNoAnim ) {
1274				$el.removeClass('appear-animation');
1275
1276				// Inside Carousel
1277				if( $el.closest('.owl-carousel').get(0) ) {
1278					setTimeout(() => {
1279						$el.closest('.owl-carousel').on('change.owl.carousel', () => {
1280							self.options.firstLoadNoAnim = false;
1281							$el.removeData('__animate');
1282							$el.themePluginAnimate( self.options );
1283						});
1284					}, 500);
1285				}
1286
1287				return this;
1288			}
1289
1290            $el.addClass('appear-animation animated');
1291
1292            if (!$('html').hasClass('no-csstransitions') && $(window).width() > self.options.minWindowWidth && elTopDistance >= windowTopDistance || self.options.forceAnimation == true) {
1293				delay = ($el.attr('data-appear-animation-delay') ? $el.attr('data-appear-animation-delay') : self.options.delay);
1294				duration = ($el.attr('data-appear-animation-duration') ? $el.attr('data-appear-animation-duration') : self.options.duration);
1295
1296				if (duration != '750ms') {
1297					$el.css('animation-duration', duration);
1298				}
1299
1300				$el.css('animation-delay', delay + 'ms');
1301				$el.addClass($el.attr('data-appear-animation') + ' appear-animation-visible');
1302				
1303				$el.trigger('animation:show');
1304
1305			} else {
1306				$el.addClass('appear-animation-visible');
1307			}
1308
1309            return this;
1310        }
1311    }
1312
1313    PluginAnimate.defaults = {
1314		accX: 0,
1315		accY: -80,
1316		delay: 100,
1317		duration: '750ms',
1318		minWindowWidth: 0,
1319		forceAnimation: false,
1320		flagClassOnly: false
1321	};
1322
1323    // expose to scope
1324    $.extend(theme, {
1325		PluginAnimate
1326	});
1327
1328    // jquery plugin
1329    $.fn.themePluginAnimate = function(opts) {
1330		return this.map(function() {
1331			const $this = $(this);
1332
1333			if ($this.data(instanceName)) {
1334				return $this.data(instanceName);
1335			} else {
1336				return new PluginAnimate($this, opts);
1337			}
1338
1339		});
1340	};
1341})).apply(this, [window.theme, jQuery]);
1342
1343// Animated Content
1344(((theme = {}, $) => {
1345    const instanceName = '__animatedContent';
1346
1347    class PluginAnimatedContent {
1348        constructor($el, opts) {
1349            return this.initialize($el, opts);
1350        }
1351
1352        initialize($el, opts) {
1353			if ($el.data(instanceName)) {
1354				return this;
1355			}
1356
1357			const self = this;
1358
1359			this.$el = $el;
1360			this.initialText = $el.text();
1361
1362			this
1363				.setData()
1364				.setOptions(opts)
1365				.build()
1366				.events();
1367
1368			return this;
1369		}
1370
1371        setData() {
1372			this.$el.data(instanceName, this);
1373
1374			return this;
1375		}
1376
1377        setOptions(opts) {
1378			this.options = $.extend(true, {}, PluginAnimatedContent.defaults, opts, {
1379				wrapper: this.$el
1380			});
1381
1382			return this;
1383		}
1384
1385        build() {
1386			const self    = this;
1387
1388			if( $(window).width() < self.options.minWindowWidth ) {
1389				return this;
1390			}
1391
1392			if( self.options.firstLoadNoAnim ) {
1393				self.$el.css({
1394					visibility: 'visible'
1395				});
1396
1397				// Inside Carousel
1398				if( self.$el.closest('.owl-carousel').get(0) ) {
1399					setTimeout(() => {
1400						self.$el.closest('.owl-carousel').on('change.owl.carousel', () => {
1401							self.options.firstLoadNoAnim = false;
1402							self.build();
1403						});
1404					}, 500);
1405				}
1406
1407				return this;
1408			}
1409
1410			// Set Min Height to avoid flicking issues
1411			self.setMinHeight();
1412
1413			// Letter
1414			if( self.options.contentType == 'letter' ) {
1415
1416				self.$el.addClass('initialized');
1417
1418				const letters = self.$el.text().split('');
1419
1420				self.$el.text('');
1421
1422				// Type Writer
1423				if( self.options.animationName == 'typeWriter' ) {
1424					self.$el.append( '<span class="letters-wrapper"></span><span class="typeWriter"></pre>' );
1425
1426					let index = 0;
1427
1428					setTimeout(() => {
1429
1430						const timeout = () => {
1431							const st = setTimeout(() => {
1432								const letter = letters[index];
1433								
1434								self.$el.find('.letters-wrapper').append( '<span class="letter '+ ( self.options.letterClass ? self.options.letterClass + ' ' : '' ) +'">' + letter + '</span>' );
1435
1436								index++;
1437								timeout();
1438							}, self.options.animationSpeed);
1439
1440							if( index >= letters.length ) {
1441								clearTimeout(st);
1442							}
1443						};
1444						timeout();
1445
1446					}, self.options.startDelay);
1447
1448				// Class Animation
1449				} else {
1450					setTimeout(() => {
1451						for( let i = 0; i < letters.length; i++ ) {
1452							const letter = letters[i];
1453							
1454							self.$el.append( '<span class="animated-letters-wrapper ' + self.options.wrapperClass + '"><span class="animated-letters-item letter '+ ( self.options.letterClass ? self.options.letterClass + ' ' : '' ) + self.options.animationName +' animated" style="animation-delay: '+ ( i * self.options.animationSpeed ) +'ms;">' + ( letter == ' ' ? '&nbsp;' : letter ) + '</span></span>' );
1455		
1456						}
1457					}, self.options.startDelay);
1458				}
1459
1460			// Words
1461			} else if( self.options.contentType == 'word' ) {
1462                const words = self.$el.text().split(" ");
1463                let delay = self.options.startDelay;
1464
1465                self.$el.empty();
1466
1467                $.each(words, (i, v) => {
1468					self.$el.append( $('<span class="animated-words-wrapper ' + self.options.wrapperClass + '">').html('<span class="animated-words-item ' + self.options.wordClass + ' appear-animation" data-appear-animation="' + self.options.animationName + '" data-appear-animation-delay="' + delay + '">' + v + '&nbsp;</span>') );
1469					delay = delay + self.options.animationSpeed;
1470				});
1471
1472                if ($.isFunction($.fn['themePluginAnimate']) && $('.animated-words-item[data-appear-animation]').length) {
1473					theme.fn.dynIntObsInit( '.animated-words-item[data-appear-animation]', 'themePluginAnimate', theme.PluginAnimate.defaults );
1474				}
1475
1476                self.$el.addClass('initialized');
1477            }
1478
1479			return this;
1480		}
1481
1482        setMinHeight() {
1483			const self = this;
1484
1485			// if it's inside carousel
1486			if( self.$el.closest('.owl-carousel').get(0) ) {
1487				self.$el.closest('.owl-carousel').addClass('d-block');
1488				self.$el.css( 'min-height', self.$el.height() );
1489				self.$el.closest('.owl-carousel').removeClass('d-block');
1490			} else {
1491				self.$el.css( 'min-height', self.$el.height() );
1492			}
1493
1494			return this;
1495		}
1496
1497        destroy() {
1498			const self = this;
1499
1500			self.$el
1501				.html( self.initialText )
1502				.css( 'min-height', '' );
1503
1504			return this;
1505		}
1506
1507        events() {
1508			const self = this;
1509
1510			// Destroy
1511			self.$el.on('animated.letters.destroy', () => {
1512				self.destroy();
1513			});
1514
1515			// Initialize
1516			self.$el.on('animated.letters.initialize', () => {
1517				self.build();
1518			});
1519
1520			return this;
1521		}
1522    }
1523
1524    PluginAnimatedContent.defaults = {
1525		contentType: 'letter',
1526		animationName: 'fadeIn',
1527		animationSpeed: 50,
1528		startDelay: 500,
1529		minWindowWidth: 768,
1530		letterClass: '',
1531		wordClass: '',
1532		wrapperClass: ''
1533	};
1534
1535    // expose to scope
1536    $.extend(theme, {
1537		PluginAnimatedContent
1538	});
1539
1540    // jquery plugin
1541    $.fn.themePluginAnimatedContent = function(opts) {
1542		return this.map(function() {
1543			const $this = $(this);
1544
1545			if ($this.data(instanceName)) {
1546				return $this.data(instanceName);
1547			} else {
1548				return new PluginAnimatedContent($this, opts);
1549			}
1550
1551		});
1552	}
1553})).apply(this, [window.theme, jQuery]);
1554
1555// Before / After
1556(((theme = {}, $) => {
1557    const instanceName = '__beforeafter';
1558
1559    class PluginBeforeAfter {
1560        constructor($el, opts) {
1561            return this.initialize($el, opts);
1562        }
1563
1564        initialize($el, opts) {
1565			this.$el = $el;
1566
1567			this
1568				.setData()
1569				.setOptions(opts)
1570				.build();
1571
1572			return this;
1573		}
1574
1575        setData() {
1576			this.$el.data(instanceName, this);
1577
1578			return this;
1579		}
1580
1581        setOptions(opts) {
1582			this.options = $.extend(true, {}, PluginBeforeAfter.defaults, opts, {
1583				wrapper: this.$el
1584			});
1585
1586			return this;
1587		}
1588
1589        build() {
1590
1591			if ($.isFunction($.fn.twentytwenty)) {
1592
1593				const self = this;
1594
1595				self.options.wrapper.waitForImages(() => {
1596					self.options.wrapper.twentytwenty(self.options);
1597				});
1598
1599			} else {
1600
1601				theme.fn.showErrorMessage('Failed to Load File', 'Failed to load: twentytwenty - Include the following file(s): (vendor/twentytwenty/css/twentytwenty.css, vendor/twentytwenty/js/jquery.event.move.js, vendor/twentytwenty/js/jquery.twentytwenty.js)');
1602
1603			}
1604
1605			return this;
1606
1607		}
1608    }
1609
1610    PluginBeforeAfter.defaults = {
1611		forceInit: true,
1612		default_offset_pct: 0.5,
1613		orientation: 'horizontal',
1614		before_label: 'Before',
1615		after_label: 'After',
1616		no_overlay: false,
1617		move_slider_on_hover: false,
1618		move_with_handle_only: true,
1619		click_to_move: false
1620	};
1621
1622    // expose to scope
1623    $.extend(theme, {
1624		PluginBeforeAfter
1625	});
1626
1627    // jquery plugin
1628    $.fn.themePluginBeforeAfter = function(opts) {
1629		return this.map(function() {
1630			const $this = $(this);
1631
1632			if ($this.data(instanceName)) {
1633				return $this.data(instanceName);
1634			} else {
1635				return new PluginBeforeAfter($this, opts);
1636			}
1637
1638		});
1639	}
1640})).apply(this, [window.theme, jQuery]);
1641
1642// Carousel Light
1643(((theme = {}, $) => {
1644    const instanceName = '__carouselLight';
1645
1646    class PluginCarouselLight {
1647        constructor($el, opts) {
1648            return this.initialize($el, opts);
1649        }
1650
1651        initialize($el, opts) {
1652			if ($el.data(instanceName)) {
1653				return this;
1654			}
1655
1656			this.$el = $el;
1657			this.clickFlag = true;
1658
1659			this
1660				.setData()
1661				.setOptions(opts)
1662				.build()
1663				.owlNav()
1664				.owlDots()
1665				.autoPlay()
1666				.events();
1667
1668			return this;
1669		}
1670
1671        setData() {
1672			this.$el.data(instanceName, this);
1673
1674			return this;
1675		}
1676
1677        setOptions(opts) {
1678			this.options = $.extend(true, {}, PluginCarouselLight.defaults, opts, {
1679				wrapper: this.$el
1680			});
1681
1682			return this;
1683		}
1684
1685        build() {
1686			const self = this;
1687
1688			self.$el
1689				.css('opacity', 1)
1690				.find('.owl-item:first-child')
1691				.addClass('active');
1692
1693			self.$el.trigger('initialized.owl.carousel');
1694
1695			// Carousel Navigate By ID and item index
1696			self.carouselNavigate();
1697
1698			return this;
1699		}
1700
1701        changeSlide($nextSlide) {
1702			const self = this, $prevSlide = self.$el.find('.owl-item.active');
1703
1704			self.$el.find('.owl-item.active').addClass('removing');
1705
1706			$prevSlide
1707				.removeClass('fadeIn')
1708				.addClass( 'fadeOut animated' );
1709
1710			setTimeout(() => {
1711				setTimeout(() => {
1712					$prevSlide.removeClass('active');
1713				}, 400);
1714
1715				$nextSlide
1716					.addClass('active')
1717					.removeClass('fadeOut')
1718					.addClass( 'fadeIn animated' );
1719
1720			}, 200);
1721
1722			// Dots
1723			self.$el
1724				.find('.owl-dot')
1725				.removeClass('active')
1726				.eq( $nextSlide.index() )
1727				.addClass('active');
1728
1729			self.$el.trigger({
1730				type: 'change.owl.carousel',
1731				nextSlideIndex: $nextSlide.index(),
1732				prevSlideIndex: $prevSlide.index()
1733			});
1734
1735			setTimeout(() => {
1736				self.$el.trigger({
1737					type: 'changed.owl.carousel',
1738					nextSlideIndex: $nextSlide.index(),
1739					prevSlideIndex: $prevSlide.index()
1740				});
1741			}, 500);
1742		}
1743
1744        owlNav() {
1745			const self = this, $owlNext = self.$el.find('.owl-next'), $owlPrev = self.$el.find('.owl-prev');
1746
1747			$owlPrev.on('click', e => {
1748				e.preventDefault();
1749
1750				if( self.options.disableAutoPlayOnClick ) {
1751					window.clearInterval(self.autoPlayInterval);
1752				}
1753
1754				if( self.avoidMultipleClicks() ) {
1755					return false;
1756				}
1757
1758				self.owlPrev();
1759			});
1760
1761			$owlNext.on('click', e => {
1762				e.preventDefault();
1763
1764				if( self.options.disableAutoPlayOnClick ) {
1765					window.clearInterval(self.autoPlayInterval);
1766				}
1767
1768				if( self.avoidMultipleClicks() ) {
1769					return false;
1770				}
1771
1772				self.owlNext();
1773			});
1774
1775			return this;
1776		}
1777
1778        owlDots() {
1779			const self = this, $owlDot = self.$el.find('.owl-dot');
1780
1781			$owlDot.on('click', function(e){
1782				$this = $(this);
1783
1784				e.preventDefault();
1785
1786				if( self.options.disableAutoPlayOnClick ) {
1787					window.clearInterval(self.autoPlayInterval);
1788				}
1789
1790				if( self.avoidMultipleClicks() ) {
1791					return false;
1792				}
1793
1794				const dotIndex = $(this).index();
1795
1796				// Do nothing if respective dot slide is active/showing
1797				if( $this.hasClass('active') ) {
1798					return false;
1799				}
1800
1801				self.changeSlide( self.$el.find('.owl-item').eq( dotIndex ) );
1802			});
1803
1804			return this;
1805		}
1806
1807        owlPrev() {
1808			const self = this;
1809
1810			if( self.$el.find('.owl-item.active').prev().get(0) ) {
1811				self.changeSlide( self.$el.find('.owl-item.active').prev() );
1812			} else {
1813				self.changeSlide( self.$el.find('.owl-item:last-child') );
1814			}
1815		}
1816
1817        owlNext() {
1818			const self = this;
1819
1820			if( self.$el.find('.owl-item.active').next().get(0) ) {
1821				self.changeSlide( self.$el.find('.owl-item.active').next() );
1822			} else {
1823				self.changeSlide( self.$el.find('.owl-item').eq(0) );
1824			}
1825		}
1826
1827        avoidMultipleClicks() {
1828			const self = this;
1829
1830			if( !self.clickFlag ) {
1831				return true;
1832			}
1833
1834			if( self.clickFlag ) {
1835				self.clickFlag = false;
1836				setTimeout(() => {
1837					self.clickFlag = true; 
1838				}, 1000);
1839			}
1840
1841			return false;
1842		}
1843
1844        autoPlay() {
1845			const self = this, $el  = this.options.wrapper;
1846
1847			if( self.options.autoplay ) {
1848				self.autoPlayInterval = window.setInterval(() => {
1849					self.owlNext();
1850				}, self.options.autoplayTimeout);
1851			}
1852
1853			return this;
1854		}
1855
1856        carouselNavigate() {
1857			const self      = this, $el       = this.options.wrapper, $carousel = $el;
1858
1859			if( $('[data-carousel-navigate]').get(0) ) {
1860				$('[data-carousel-navigate-id="#'+ $el.attr('id') +'"]').each(function(){
1861					const $this = $(this), hasCarousel = $( $this.data('carousel-navigate-id') ).get(0), toIndex = $this.data('carousel-navigate-to');
1862
1863					if( hasCarousel ) {
1864
1865						$this.on('click', () => {
1866
1867							if( self.options.disableAutoPlayOnClick ) {
1868								window.clearInterval(self.autoPlayInterval);
1869							}
1870							
1871							self.changeSlide( self.$el.find('.owl-item').eq( parseInt(toIndex) - 1 ) );
1872						});
1873
1874					}
1875				});
1876
1877				$el.on('change.owl.carousel', e => {
1878					$('[data-carousel-navigate-id="#'+ $el.attr('id') +'"]').removeClass('active');
1879				});
1880
1881				$el.on('changed.owl.carousel', ({nextSlideIndex}) => {
1882					$('[data-carousel-navigate-id="#'+ $el.attr('id') +'"][data-carousel-navigate-to="'+ ( nextSlideIndex + 1 ) +'"]').addClass('active');
1883				});
1884			}
1885
1886			return this;
1887		}
1888
1889        events() {
1890			const self = this;
1891
1892			self.$el.on('change.owl.carousel', event => {
1893
1894				// Hide elements inside carousel
1895			    self.$el.find('[data-appear-animation]:not(.background-image-wrapper), [data-plugin-animated-letters]').addClass('invisible');
1896
1897			    // Animated Letters
1898			    self.$el.find('[data-plugin-animated-letters]').trigger('animated.letters.destroy');
1899
1900			    // Remove "d-none" class before show the element. This is useful when using background images inside a carousel. Like ken burns effect
1901			    self.$el.find('.owl-item:not(.active) [data-carousel-onchange-show]').removeClass('d-none');
1902
1903			});
1904
1905			self.$el.on('changed.owl.carousel', event => {
1906				setTimeout(() => {
1907
1908				    // Appear Animation
1909				    if( self.$el.find('.owl-item.cloned [data-appear-animation]').get(0) ) {
1910				    	self.$el.find('.owl-item.cloned [data-appear-animation]').each(function() {
1911                            const $this = $(this);
1912                            let opts;
1913
1914                            const pluginOptions = theme.fn.getOptions($this.data('plugin-options'));
1915                            if (pluginOptions)
1916								opts = pluginOptions;
1917
1918                            $this.themePluginAnimate(opts);
1919                        });
1920				    }
1921
1922					// Show elements inside carousel
1923				    self.$el.find('.owl-item.active [data-appear-animation]:not(.background-image-wrapper), [data-plugin-animated-letters]').removeClass('invisible');
1924
1925				    // Animated Letters
1926				    self.$el.find('.owl-item.active [data-plugin-animated-letters]').trigger('animated.letters.initialize');
1927
1928				    // Background Video
1929				    self.$el.find('.owl-item.cloned.active [data-plugin-video-background]').trigger('video.background.initialize');
1930
1931				}, 500);
1932			    
1933			});
1934
1935			if( self.options.swipeEvents ) {
1936				self.$el.swipe({
1937					swipe(event, direction, distance, duration, fingerCount, fingerData) {
1938						switch ( direction ) {
1939							case 'right':
1940								self.owlPrev();
1941							break;
1942				
1943							case 'left':
1944								self.owlNext();
1945							break;
1946						}
1947					},
1948					allowPageScroll: "vertical"
1949				});
1950			}
1951		}
1952    }
1953
1954    PluginCarouselLight.defaults = {
1955		autoplay: true,
1956		autoplayTimeout: 7000,
1957		disableAutoPlayOnClick: true,
1958		swipeEvents: true
1959	};
1960
1961    // expose to scope
1962    $.extend(theme, {
1963		PluginCarouselLight
1964	});
1965
1966    // jquery plugin
1967    $.fn.themePluginCarouselLight = function(opts) {
1968		return this.map(function() {
1969			const $this = $(this);
1970
1971			if ($this.data(instanceName)) {
1972				return $this.data(instanceName);
1973			} else {
1974				return new PluginCarouselLight($this, opts);
1975			}
1976
1977		});
1978	};
1979})).apply(this, [window.theme, jQuery]);
1980
1981// Carousel
1982(((theme = {}, $) => {
1983    const instanceName = '__carousel';
1984
1985    class PluginCarousel {
1986        constructor($el, opts) {
1987            return this.initialize($el, opts);
1988        }
1989
1990        initialize($el, opts) {
1991			if ($el.data(instanceName)) {
1992				return this;
1993			}
1994
1995			this.$el = $el;
1996
1997			// If has data-icon inside, initialize only after icons get rendered
1998			// Prevent flicking issues
1999			if( $el.find('[data-icon]').get(0) ) {
2000				const self = this;
2001
2002				$(window).on('icon.rendered', function(){
2003					if ($el.data(instanceName)) {
2004						return this;
2005					}
2006
2007					setTimeout(() => {
2008						self
2009							.setData()
2010							.setOptions(opts)
2011							.build();
2012					}, 1000);
2013				});
2014
2015				return this;
2016			}
2017
2018			this
2019				.setData()
2020				.setOptions(opts)
2021				.build();
2022
2023			return this;
2024		}
2025
2026        setData() {
2027			this.$el.data(instanceName, this);
2028
2029			return this;
2030		}
2031
2032        setOptions(opts) {
2033			this.options = $.extend(true, {}, PluginCarousel.defaults, opts, {
2034				wrapper: this.$el
2035			});
2036
2037			return this;
2038		}
2039
2040        build() {
2041			if (!($.isFunction($.fn.owlCarousel))) {
2042				return this;
2043			}
2044
2045			const self = this, $el = this.options.wrapper;
2046
2047			// Add Theme Class
2048			$el.addClass('owl-theme');
2049
2050			// Add Loading
2051			$el.addClass('owl-loading');
2052
2053			// Force RTL according to HTML dir attribute
2054			if ($('html').attr('dir') == 'rtl') {
2055				this.options = $.extend(true, {}, this.options, {
2056					rtl: true
2057				});
2058			}
2059
2060			if (this.options.items == 1) {
2061				this.options.responsive = {}
2062			}
2063
2064			if (this.options.items > 4) {
2065				this.options = $.extend(true, {}, this.options, {
2066					responsive: {
2067						1199: {
2068							items: this.options.items
2069						}
2070					}
2071				});
2072			}
2073
2074			// Auto Height Fixes
2075			if (this.options.autoHeight) {
2076				const itemsHeight = [];
2077
2078				$el.find('.owl-item').each(function(){
2079					if( $(this).hasClass('active') ) {
2080						itemsHeight.push( $(this).height() );
2081					}
2082				});
2083
2084				$(window).afterResize(() => {
2085					$el.find('.owl-stage-outer').height( Math.max.apply(null, itemsHeight) );
2086				});
2087
2088				$(window).on('load', () => {
2089					$el.find('.owl-stage-outer').height( Math.max.apply(null, itemsHeight) );
2090				});
2091			}
2092
2093			// Initialize OwlCarousel
2094			$el.owlCarousel(this.options).addClass('owl-carousel-init animated fadeIn');
2095
2096			// Remove "animated fadeIn" class to prevent conflicts
2097			setTimeout(() => {
2098				$el.removeClass('animated fadeIn');
2099			}, 1000);
2100
2101			// Owl Carousel Wrapper
2102			if( $el.closest('.owl-carousel-wrapper').get(0) ) {
2103				setTimeout(() => {
2104					$el.closest('.owl-carousel-wrapper').css({
2105						height: ''
2106					});
2107				}, 500);
2108			}
2109
2110			// Owl Carousel Loader
2111			if( $el.prev().hasClass('owl-carousel-loader') ) {
2112				$el.prev().remove();
2113			}
2114
2115			// Nav Offset
2116			self.navigationOffsets();
2117
2118			// Nav Outside
2119			if( $el.hasClass('nav-outside') ) {
2120				$(window).on('owl.carousel.nav.outside', () => {
2121					if( $(window).width() < 992 ) {
2122						self.options.stagePadding = 40;
2123						$el.addClass('stage-margin');
2124					} else {
2125						self.options.stagePadding = 0;
2126						$el.removeClass('stage-margin');
2127					}
2128
2129					$el.owlCarousel('destroy').owlCarousel( self.options );
2130
2131					// Nav Offset
2132					self.navigationOffsets();
2133				});
2134
2135				// Window Resize
2136				$(window).on('load', () => {
2137					$(window).afterResize(() => {
2138						$(window).trigger('owl.carousel.nav.outside');
2139					});
2140				});
2141
2142				// First Load
2143				$(window).trigger('owl.carousel.nav.outside');
2144			}
2145
2146			// Nav style 5 (SVG Arrows)
2147			if( $el.hasClass('nav-svg-arrows-1') ) {
2148				const svg_arrow = '' +
2149					'<svg version="1.1" viewBox="0 0 15.698 8.706" width="17" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">' +
2150						'<polygon stroke="#212121" stroke-width="0.1" fill="#212121" points="11.354,0 10.646,0.706 13.786,3.853 0,3.853 0,4.853 13.786,4.853 10.646,8 11.354,8.706 15.698,4.353 "/>' +
2151					'</svg>';
2152
2153				$el.find('.owl-next, .owl-prev').append( svg_arrow );
2154			}
2155
2156			// Sync
2157			if( $el.attr('data-sync') ) {
2158				$el.on('change.owl.carousel', ({namespace, property, relatedTarget}) => {
2159					if (namespace && property.name === 'position') {
2160					    const target = relatedTarget.relative(property.value, true);
2161					    $( $el.data('sync') ).owlCarousel('to', target, 300, true);				        
2162				  	}
2163				});
2164			}
2165
2166			// Carousel Center Active Item
2167			if( $el.hasClass('carousel-center-active-item') ) {
2168				const itemsActive    = $el.find('.owl-item.active'), indexCenter    = Math.floor( ($el.find('.owl-item.active').length - 1) / 2 ), itemCenter     = itemsActive.eq
2168(indexCenter);
2169
2170				itemCenter.addClass('current');
2171
2172				$el.on('change.owl.carousel', event => {
2173				  	$el.find('.owl-item').removeClass('current');
2174					
2175					setTimeout(() => {
2176					  	const itemsActive    = $el.find('.owl-item.active'), indexCenter    = Math.floor( ($el.find('.owl-item.active').length - 1) / 2 ), itemCenter     = itemsActive.eq(indexCenter);
2177
2178					  	itemCenter.addClass('current');
2179					}, 100);
2180				});
2181
2182				// Refresh
2183				$el.trigger('refresh.owl.carousel');
2184
2185			}
2186
2187			// AnimateIn / AnimateOut Fix
2188			if( self.options.animateIn || self.options.animateOut ) {
2189				$el.on('change.owl.carousel', event => {
2190
2191					// Hide elements inside carousel
2192				    $el.find('[data-appear-animation], [data-plugin-animated-letters]').addClass('d-none');
2193
2194				    // Animated Letters
2195				    $el.find('[data-plugin-animated-letters]').trigger('animated.letters.destroy');
2196
2197				    // Remove "d-none" class before show the element. This is useful when using background images inside a carousel. Like ken burns effect
2198				    $el.find('.owl-item:not(.active) [data-carousel-onchange-show]').removeClass('d-none');
2199
2200				});
2201
2202				$el.on('changed.owl.carousel', event => {
2203					setTimeout(() => {
2204
2205					    // Appear Animation
2206				    	$el.find('[data-appear-animation]').each(function() {
2207                            const $this = $(this);
2208                            let opts;
2209
2210                            const pluginOptions = theme.fn.getOptions($this.data('plugin-options'));
2211                            if (pluginOptions)
2212								opts = pluginOptions;
2213
2214                            $this.themePluginAnimate(opts);
2215                        });
2216
2217						// Show elements inside carousel
2218					    $el.find('.owl-item.active [data-appear-animation], [data-plugin-animated-letters]').removeClass('d-none');
2219
2220					    // Animated Letters
2221					    $el.find('.owl-item.active [data-plugin-animated-letters]').trigger('animated.letters.initialize');
2222
2223					    // Background Video
2224					    $el.find('.owl-item.cloned.active [data-plugin-video-background]').trigger('video.background.initialize');
2225
2226					}, 10);
2227				    
2228				});
2229			}
2230
2231			// data-icon inside carousel
2232			if( $el.find('[data-icon]').length ) {
2233				$el.on('change.owl.carousel drag.owl.carousel', () => {
2234					$el.find('.owl-item.cloned [data-icon]').each(function(){
2235                        const $this = $(this);
2236                        let opts;
2237
2238                        const pluginOptions = theme.fn.getOptions($this.data('plugin-options'));
2239                        if (pluginOptions)
2240							opts = pluginOptions;
2241
2242                        $this.themePluginIcon(opts);
2243                    });
2244				});
2245			}
2246
2247			// Render Background Videos inside carousel. Just a trigger on window is sufficient to render
2248			if( $el.find('[data-plugin-video-background]').get(0) ) {
2249				$(window).resize();
2250			}
2251
2252			// Remove Loading
2253			$el.removeClass('owl-loading');
2254
2255			// Remove Height
2256			$el.css('height', 'auto');
2257
2258			// Carousel Navigate By ID and item index
2259			self.carouselNavigate();
2260
2261			// Refresh Carousel
2262			if( self.options.refresh ) {
2263				$el.owlCarousel('refresh');
2264			}
2265
2266			return this;
2267		}
2268
2269        navigationOffsets() {
2270			const self 			 = this, $el  			 = this.options.wrapper, navHasTransform  = $el.find('.owl-nav').css('transform') == 'none' ? false : true, dotsHasTransform = $el.find('.owl-dots').css('transform') == 'none' ? false : true;
2271
2272			// ************* NAV *****************
2273			// Nav Offset - Horizontal
2274			if( self.options.navHorizontalOffset && !self.options.navVerticalOffset ) {
2275				if( !navHasTransform ) {
2276					$el.find('.owl-nav').css({
2277						transform: 'translate3d('+ self.options.navHorizontalOffset +', 0, 0)'
2278					});
2279				} else {
2280					$el.find('.owl-nav').css({
2281						left: self.options.navHorizontalOffset
2282					});
2283				}
2284			}
2285
2286			// Nav Offset - Vertical
2287			if( self.options.navVerticalOffset && !self.options.navHorizontalOffset ) {
2288				if( !navHasTransform ) {
2289					$el.find('.owl-nav').css({
2290						transform: 'translate3d(0, '+ self.options.navVerticalOffset +', 0)'
2291					});
2292				} else {
2293					$el.find('.owl-nav').css({
2294						top: 'calc( 50% - '+ self.options.navVerticalOffset +' )'
2295					});
2296				}
2297			}
2298
2299			// Nav Offset - Horizontal & Vertical
2300			if( self.options.navVerticalOffset && self.options.navHorizontalOffset ) {
2301				if( !navHasTransform ) {
2302					$el.find('.owl-nav').css({
2303						transform: 'translate3d('+ self.options.navHorizontalOffset +', '+ self.options.navVerticalOffset +', 0)'
2304					});
2305				} else {
2306					$el.find('.owl-nav').css({
2307						top: 'calc( 50% - '+ self.options.navVerticalOffset +' )',
2308						left: self.options.navHorizontalOffset
2309					});
2310				}
2311			}
2312
2313			// ********** DOTS *********************
2314			// Dots Offset - Horizontal
2315			if( self.options.dotsHorizontalOffset && !self.options.dotsVerticalOffset ) {
2316				$el.find('.owl-dots').css({
2317					transform: 'translate3d('+ self.options.dotsHorizontalOffset +', 0, 0)'
2318				});
2319			}
2320
2321			// Dots Offset - Vertical
2322			if( self.options.dotsVerticalOffset && !self.options.dotsHorizontalOffset ) {
2323				if( !dotsHasTransform ) {
2324					$el.find('.owl-dots').css({
2325						transform: 'translate3d(0, '+ self.options.dotsVerticalOffset +', 0)'
2326					});
2327				} else {
2328					$el.find('.owl-dots').css({
2329						top: 'calc( 50% - '+ self.options.dotsVerticalOffset +' )'
2330					});
2331				}
2332			}
2333
2334			// Dots Offset - Horizontal & Vertical
2335			if( self.options.dotsVerticalOffset && self.options.dotsHorizontalOffset ) {
2336				$el.find('.owl-dots').css({
2337					transform: 'translate3d('+ self.options.dotsHorizontalOffset +', '+ self.options.dotsVerticalOffset +', 0)'
2338				});
2339			}
2340
2341			return this;
2342		}
2343
2344        carouselNavigate() {
2345			const self      = this, $el       = this.options.wrapper, $carousel = $el.data('owl.carousel');
2346
2347			if( $('[data-carousel-navigate]').get(0) ) {
2348				$('[data-carousel-navigate-id="#'+ $el.attr('id') +'"]').each(function(){
2349					const $this = $(this), hasCarousel = $( $this.data('carousel-navigate-id') ).get(0), toIndex = $this.data('carousel-navigate-to');
2350
2351					if( hasCarousel ) {
2352
2353						$this.on('click', () => {
2354							$carousel.to( parseInt(toIndex) - 1 );
2355						});
2356
2357					}
2358				});
2359
2360				$el.on('change.owl.carousel', () => {
2361					$('[data-carousel-navigate-id="#'+ $el.attr('id') +'"]').removeClass('active');
2362				});
2363
2364				$el.on('changed.owl.carousel', ({item}) => {
2365					$('[data-carousel-navigate-id="#'+ $el.attr('id') +'"][data-carousel-navigate-to="'+ ( item.index + 1 ) +'"]').addClass('active');
2366				});
2367			}
2368
2369			return this;
2370		}
2371    }
2372
2373    PluginCarousel.defaults = {
2374		loop: true,
2375		responsive: {
2376			0: {
2377				items: 1
2378			},
2379			479: {
2380				items: 1
2381			},
2382			768: {
2383				items: 2
2384			},
2385			979: {
2386				items: 3
2387			},
2388			1199: {
2389				items: 4
2390			}
2391		},
2392		navText: [],
2393		refresh: false
2394	};
2395
2396    // expose to scope
2397    $.extend(theme, {
2398		PluginCarousel
2399	});
2400
2401    // jquery plugin
2402    $.fn.themePluginCarousel = function(opts) {
2403		return this.map(function() {
2404			const $this = $(this);
2405
2406			if ($this.data(instanceName)) {
2407				return $this.data(instanceName);
2408			} else {
2409				return new PluginCarousel($this, opts);
2410			}
2411
2412		});
2413	}
2414})).apply(this, [window.theme, jQuery]);
2415
2416// Chart Circular
2417(((theme = {}, $) => {
2418    const instanceName = '__chartCircular';
2419
2420    class PluginChartCircular {
2421        constructor($el, opts) {
2422            return this.initialize($el, opts);
2423        }
2424
2425        initialize($el, opts) {
2426			if ($el.data(instanceName)) {
2427				return this;
2428			}
2429
2430			this.$el = $el;
2431
2432			this
2433				.setData()
2434				.setOptions(opts)
2435				.build();
2436
2437			return this;
2438		}
2439
2440        setData() {
2441			this.$el.data(instanceName, this);
2442
2443			return this;
2444		}
2445
2446        setOptions(opts) {
2447			this.options = $.extend(true, {}, PluginChartCircular.defaults, opts, {
2448				wrapper: this.$el
2449			});
2450
2451			return this;
2452		}
2453
2454        build() {
2455			if (!($.isFunction($.fn.easyPieChart))) {
2456				return this;
2457			}
2458
2459			const self = this, $el = this.options.wrapper, value = ($el.attr('data-percent') ? $el.attr('data-percent') : 0), percentEl = $el.find('.percent');
2460
2461			$.extend(true, self.options, {
2462				onStep(from, to, currentValue) {
2463					percentEl.html(parseInt(currentValue));
2464				}
2465			});
2466
2467			$el.attr('data-percent', 0);
2468
2469			$el.easyPieChart(self.options);
2470
2471			setTimeout(() => {
2472
2473				$el.data('easyPieChart').update(value);
2474				$el.attr('data-percent', value);
2475
2476			}, self.options.delay);
2477
2478			return this;
2479		}
2480    }
2481
2482    PluginChartCircular.defaults = {
2483		accX: 0,
2484		accY: -150,
2485		delay: 1,
2486		barColor: '#0088CC',
2487		trackColor: '#f2f2f2',
2488		scaleColor: false,
2489		scaleLength: 5,
2490		lineCap: 'round',
2491		lineWidth: 13,
2492		size: 175,
2493		rotate: 0,
2494		animate: ({
2495			duration: 2500,
2496			enabled: true
2497		})
2498	};
2499
2500    // expose to scope
2501    $.extend(theme, {
2502		PluginChartCircular
2503	});
2504
2505    // jquery plugin
2506    $.fn.themePluginChartCircular = function(opts) {
2507		return this.map(function() {
2508			const $this = $(this);
2509
2510			if ($this.data(instanceName)) {
2511				return $this.data(instanceName);
2512			} else {
2513				return new PluginChartCircular($this, opts);
2514			}
2515
2516		});
2517	}
2518})).apply(this, [window.theme, jQuery]);
2519
2520// Countdown
2521(((theme = {}, $) => {
2522    const instanceName = '__countdown';
2523
2524    class PluginCountdown {
2525        constructor($el, opts) {
2526            return this.initialize($el, opts);
2527        }
2528
2529        initialize($el, opts) {
2530			if ($el.data(instanceName)) {
2531				return this;
2532			}
2533
2534			this.$el = $el;
2535
2536			this
2537				.setData()
2538				.setOptions(opts)
2539				.build();
2540
2541			return this;
2542		}
2543
2544        setData() {
2545			this.$el.data(instanceName, this);
2546
2547			return this;
2548		}
2549
2550        setOptions(opts) {
2551			this.options = $.extend(true, {}, PluginCountdown.defaults, opts, {
2552				wrapper: this.$el
2553			});
2554
2555			return this;
2556		}
2557
2558        build() {
2559			if (!($.isFunction($.fn.countTo))) {
2560				return this;
2561			}
2562
2563			const self = this, $el = this.options.wrapper, numberClass = ( self.options.numberClass ) ? ' ' + self.options.numberClass : '', wrapperClass = ( self.options.wrapperClass ) ? ' ' + self.options.wrapperClass : '';
2564
2565			if( self.options.uppercase ) {
2566				$el.countdown(self.options.date).on('update.countdown', function(event) {
2567					const $this = $(this).html(event.strftime(self.options.insertHTMLbefore
2568						+ '<span class="days'+ wrapperClass +'"><span class="'+ numberClass +'">%D</span> '+ self.options.textDay +'</span> '
2569						+ '<span class="hours'+ wrapperClass +'"><span class="'+ numberClass +'">%H</span> '+ self.options.textHour +'</span> '
2570						+ '<span class="minutes'+ wrapperClass +'"><span class="'+ numberClass +'">%M</span> '+ self.options.textMin +'</span> '
2571						+ '<span class="seconds'+ wrapperClass +'"><span class="'+ numberClass +'">%S</span> '+ self.options.textSec +'</span> '
2572						+ self.options.insertHTMLafter
2573					));
2574				});
2575			} else {
2576				$el.countdown(self.options.date).on('update.countdown', function(event) {
2577					const $this = $(this).html(event.strftime(self.options.insertHTMLbefore
2578						+ '<span class="days'+ wrapperClass +'"><span class="'+ numberClass +'">%D</span> '+ self.options.textDay +'</span> '
2579						+ '<span class="hours'+ wrapperClass +'"><span class="'+ numberClass +'">%H</span> '+ self.options.textHour +'</span> '
2580						+ '<span class="minutes'+ wrapperClass +'"><span class="'+ numberClass +'">%M</span> '+ self.options.textMin +'</span> '
2581						+ '<span class="seconds'+ wrapperClass +'"><span class="'+ numberClass +'">%S</span> '+ self.options.textSec +'</span> '
2582						+ self.options.insertHTMLafter
2583					));
2584				});
2585			}
2586
2587			return this;
2588		}
2589    }
2590
2591    PluginCountdown.defaults = {
2592		date: '2030/06/10 12:00:00',
2593		textDay: 'DAYS',
2594		textHour: 'HRS',
2595		textMin: 'MIN',
2596		textSec: 'SEC',
2597		uppercase: true,
2598		numberClass: '',
2599		wrapperClass: '',
2600		insertHTMLbefore: '',
2601		insertHTMLafter: ''
2602	};
2603
2604    // expose to scope
2605    $.extend(theme, {
2606		PluginCountdown
2607	});
2608
2609    // jquery plugin
2610    $.fn.themePluginCountdown = function(opts) {
2611		return this.map(function() {
2612			const $this = $(this);
2613
2614			if ($this.data(instanceName)) {
2615				return $this.data(instanceName);
2616			} else {
2617				return new PluginCountdown($this, opts);
2618			}
2619
2620		});
2621	}
2622})).apply(this, [window.theme, jQuery]);
2623
2624// Counter
2625(((theme = {}, $) => {
2626    const instanceName = '__counter';
2627
2628    class PluginCounter {
2629        constructor($el, opts) {
2630            return this.initialize($el, opts);
2631        }
2632
2633        initialize($el, opts) {
2634			if ($el.data(instanceName)) {
2635				return this;
2636			}
2637
2638			this.$el = $el;
2639
2640			this
2641				.setData()
2642				.setOptions(opts)
2643				.build();
2644
2645			return this;
2646		}
2647
2648        setData() {
2649			this.$el.data(instanceName, this);
2650
2651			return this;
2652		}
2653
2654        setOptions(opts) {
2655			this.options = $.extend(true, {}, PluginCounter.defaults, opts, {
2656				wrapper: this.$el
2657			});
2658
2659			return this;
2660		}
2661
2662        build() {
2663			if (!($.isFunction($.fn.countTo))) {
2664				return this;
2665			}
2666
2667			const self = this, $el = this.options.wrapper;
2668
2669			if (self.options.comma) {
2670				self.options.formatter = (value, {decimals}) => value.toFixed(decimals).toString().replace('.',',')
2671			}
2672
2673			$.extend(self.options, {
2674				onComplete() {
2675					
2676					if ($el.data('append')) {
2677						if( self.options.appendWrapper ) {
2678							const appendWrapper = $( self.options.appendWrapper );
2679
2680							appendWrapper.append( $el.data('append') );
2681
2682							$el.html( $el.html() + appendWrapper[0].outerHTML );
2683						} else {
2684							$el.html($el.html() + $el.data('append'));
2685						}
2686					}
2687
2688					if ($el.data('prepend')) {
2689						if( self.options.prependWrapper ) {
2690							const prependWrapper = $( self.options.prependWrapper );
2691
2692							prependWrapper.append( $el.data('prepend') );
2693
2694							$el.html( $el.html() + prependWrapper[0].outerHTML );
2695						} else {
2696							$el.html($el.data('prepend') + $el.html());
2697						}
2698					}
2699				}
2700			});
2701
2702			$el.countTo(self.options);
2703
2704			return this;
2705		}
2706    }
2707
2708    PluginCounter.defaults = {
2709		accX: 0,
2710		accY: 0,
2711		appendWrapper: false,
2712		prependWrapper: false,
2713		speed: 3000,
2714		refreshInterval: 100,
2715		decimals: 0,
2716		comma: false,
2717		onUpdate: null,
2718		onComplete: null
2719	}
2720
2721    // expose to scope
2722    $.extend(theme, {
2723		PluginCounter
2724	});
2725
2726    // jquery plugin
2727    $.fn.themePluginCounter = function(opts) {
2728		return this.map(function() {
2729			const $this = $(this);
2730
2731			if ($this.data(instanceName)) {
2732				return $this.data(instanceName);
2733			} else {
2734				return new PluginCounter($this, opts);
2735			}
2736
2737		});
2738	}
2739})).apply(this, [window.theme, jQuery]);
2740
2741// CursorEffect
2742(((theme = {}, $) => {
2743    const instanceName = '__cursorEffect';
2744
2745    class PluginCursorEffect {
2746        constructor($el, opts) {
2747            return this.initialize($el, opts);
2748        }
2749
2750        initialize($el, opts) {
2751			if ($el.data(instanceName)) {
2752				return this;
2753			}
2754
2755			this.$el = $el;
2756
2757			this
2758				.setData()
2759				.setOptions(opts)
2760				.build()
2761				.events();
2762
2763			return this;
2764		}
2765
2766        setData() {
2767			this.$el.data(instanceName, this);
2768
2769			return this;
2770		}
2771
2772        setOptions(opts) {
2773			this.options = $.extend(true, {}, PluginCursorEffect.defaults, opts, {
2774				wrapper: this.$el
2775			});
2776
2777			return this;
2778		}
2779
2780        build() {
2781			const self = this;
2782
2783			// Global Variables for cursor position
2784			self.clientX = -100;
2785			self.clientY = -100;
2786
2787			// Hide Mouse Cursor
2788			if( self.options.hideMouseCursor ) {
2789				self.$el.addClass('hide-mouse-cursor');
2790			}
2791
2792			// Creates the cursor wrapper node
2793			const cursorOuter = document.createElement('DIV');
2794				cursorOuter.className = 'cursor-outer';
2795
2796			// Creates the cursor inner node
2797			const cursorInner = document.createElement('DIV');
2798				cursorInner.className = 'cursor-inner';
2799
2800			// Custom Cursor Outer Color
2801			if( self.options.cursorOuterColor ) {
2802				cursorOuter.style = 'border-color: ' + self.options.cursorOuterColor + ';';
2803			}
2804
2805			// Custom Cursor Inner Color
2806			if( self.options.cursorInnerColor ) {
2807				cursorInner.style = 'background-color: ' + self.options.cursorInnerColor + ';';
2808			}
2809
2810			// Size
2811			if( self.options.size ) {
2812				switch ( self.options.size ) {
2813					case 'small':
2814						self.$el.addClass( 'cursor-effect-size-small' );
2815						break;
2816					
2817					case 'big':
2818						self.$el.addClass( 'cursor-effect-size-big' );
2819						break;
2820				}
2821			}
2822
2823			// Style
2824			if( self.options.style ) {
2825				self.$el.addClass( self.options.style );
2826			}
2827
2828			// Prepend cursor wrapper node to the body
2829			document.body.prepend( cursorOuter );
2830
2831			// Prepend cursor inner node to the body
2832			document.body.prepend( cursorInner );
2833
2834			// Loop for render
2835			const render = () => {
2836				cursorOuter.style.transform = 'translate('+ self.clientX +'px, '+ self.clientY +'px)';
2837				cursorInner.style.transform = 'translate('+ self.clientX +'px, '+ self.clientY +'px)';
2838
2839				self.loopInside = requestAnimationFrame(render);
2840			};
2841			self.loop = requestAnimationFrame(render);
2842
2843			return this;
2844		}
2845
2846        events() {
2847			const self = this, $cursorOuter = $('.cursor-outer'), $cursorInner = $('.cursor-inner');
2848
2849			const initialCursorOuterBox    = $cursorOuter[0].getBoundingClientRect(), initialCursorOuterRadius = $cursorOuter.css('border-radius');
2850
2851			// Update Cursor Position
2852			document.addEventListener('mousemove', ({clientX, clientY}) => {
2853				if( !self.isStuck ) {
2854					self.clientX = clientX - 20;
2855					self.clientY = clientY - 20;
2856				}
2857
2858				$cursorOuter.removeClass('opacity-0');
2859			});
2860
2861			self.isStuck = false;
2862			$('[data-cursor-effect-hover]').on('mouseenter', function(e){
2863
2864				// Identify Event With Hover Class
2865				$cursorOuter.addClass('cursor-outer-hover');
2866				$cursorInner.addClass('cursor-inner-hover');
2867
2868				// Hover Color
2869				const hoverColor = $(this).data('cursor-effect-hover-color');
2870				$cursorOuter.addClass( 'cursor-color-' + hoverColor );
2871				$cursorInner.addClass( 'cursor-color-' + hoverColor );
2872
2873				// Effect Types
2874				switch ( $(this).data('cursor-effect-hover') ) {
2875					case 'fit':
2876						const thisBox = $(this)[0].getBoundingClientRect();
2877
2878						self.clientX = thisBox.x;
2879						self.clientY = thisBox.y;
2880
2881						$cursorOuter.css({
2882							width: thisBox.width,
2883							height: thisBox.height,
2884							'border-radius': $(this).css('border-radius')
2885						}).addClass('cursor-outer-fit');
2886
2887						$cursorInner.addClass('opacity-0');
2888
2889						self.isStuck = true;
2890						break;
2891
2892					case 'plus':
2893						$cursorInner.addClass('cursor-inner-plus');
2894						break;
2895				}
2896			});
2897
2898			$('[data-cursor-effect-hover]').on('mouseleave', function(){
2899				
2900				// Identify Event With Hover Class
2901				$cursorOuter.removeClass('cursor-outer-hover');
2902				$cursorInner.removeClass('cursor-inner-hover');
2903
2904				// Remove Color Class
2905				const hoverColor = $(this).data('cursor-effect-hover-color');
2906				$cursorOuter.removeClass( 'cursor-color-' + hoverColor );
2907				$cursorInner.removeClass( 'cursor-color-' + hoverColor );
2908
2909				// Effect Types
2910				switch ( $(this).data('cursor-effect-hover') ) {
2911					case 'fit':
2912						$cursorOuter.css({
2913							width: initialCursorOuterBox.width,
2914							height: initialCursorOuterBox.height,
2915							'border-radius': initialCursorOuterRadius
2916						}).removeClass('cursor-outer-fit');
2917
2918						$cursorInner.removeClass('opacity-0');
2919
2920						self.isStuck = false;
2921						break;
2922
2923					case 'plus':
2924						$cursorInner.removeClass('cursor-inner-plus');
2925						break;
2926				}
2927			});
2928
2929			$(window).on('scroll', () => {
2930				if( $cursorOuter.hasClass('cursor-outer-fit') ) {
2931					$cursorOuter.addClass('opacity-0').removeClass('cursor-outer-fit');
2932				}
2933			});
2934
2935			return this;
2936		}
2937
2938        destroy() {
2939			const self = this;
2940
2941			self.$el.removeClass('hide-mouse-cursor cursor-effect-size-small cursor-effect-size-big cursor-effect-style-square');		
2942
2943			cancelAnimationFrame( self.loop );
2944			cancelAnimationFrame( self.loopInside );
2945
2946			document.querySelector('.cursor-outer').remove();
2947			document.querySelector('.cursor-inner').remove();
2948
2949			self.$el.removeData( instanceName, self );
2950		}
2951    }
2952
2953    PluginCursorEffect.defaults = {
2954
2955	}
2956
2957    // expose to scope
2958    $.extend(theme, {
2959		PluginCursorEffect
2960	});
2961
2962    // jquery plugin
2963    $.fn.themePluginCursorEffect = function(opts) {
2964		return this.map(function() {
2965			const $this = $(this);
2966
2967			if ($this.data(instanceName)) {
2968				return $this.data(instanceName);
2969			} else {
2970				return new PluginCursorEffect($this, opts);
2971			}
2972
2973		});
2974	}
2975})).apply(this, [window.theme, jQuery]);
2976
2977// Float Element
2978(((theme = {}, $) => {
2979    const instanceName = '__floatElement';
2980
2981    class PluginFloatElement {
2982        constructor($el, opts) {
2983            return this.initialize($el, opts);
2984        }
2985
2986        initialize($el, opts) {
2987			if ($el.data(instanceName)) {
2988				return this;
2989			}
2990
2991			this.$el = $el;
2992
2993			this
2994				.setData()
2995				.setOptions(opts)
2996				.build();
2997
2998			return this;
2999		}
3000
3001        setData() {
3002			this.$el.data(instanceName, this);
3003
3004			return this;
3005		}
3006
3007        setOptions(opts) {
3008			this.options = $.extend(true, {}, PluginFloatElement.defaults, opts, {
3009				wrapper: this.$el
3010			});
3011
3012			return this;
3013		}
3014
3015        build() {
3016            const self = this;
3017            const $el = this.options.wrapper;
3018            const $window = $(window);
3019            let minus;
3020
3021            // If has floating elements inside a SVG. 
3022            // Intersection Observer API do not check elements inside SVG's, so we need initialize trough top parent SVG
3023            if( $el.data('plugin-float-element-svg') ) {
3024				$el.find('[data-plugin-float-element]').each(function(){
3025                    const $this = $(this);
3026                    let opts;
3027
3028                    const pluginOptions = theme.fn.getOptions($this.data('plugin-options'));
3029                    if (pluginOptions)
3030						opts = pluginOptions;
3031
3032                    $this.themePluginFloatElement(opts);
3033                });
3034
3035				return this;
3036			}
3037
3038            if( self.options.style ) {
3039				$el.attr('style', self.options.style);
3040			}
3041
3042            if( $window.width() > self.options.minWindowWidth ) {
3043
3044				// Set Start Position
3045				if( self.options.startPos == 'none' ) {
3046					minus = '';
3047				} else if( self.options.startPos == 'top' ) {
3048					$el.css({
3049						top: 0
3050					});
3051					minus = '';
3052				} else {
3053					$el.css({
3054						bottom: 0
3055					});
3056					minus = '-';
3057				}
3058
3059				// Set Transition
3060				if( self.options.transition ) {
3061					$el.css({
3062						transition: 'ease-out transform '+ self.options.transitionDuration +'ms ' + self.options.transitionDelay + 'ms'
3063					});
3064				}
3065
3066				// First Load
3067				self.movement(minus);	
3068
3069				// Scroll
3070				$window.on('scroll', () => {
3071					self.movement(minus);				   
3072				});
3073
3074			}
3075
3076            return this;
3077        }
3078
3079        movement(minus) {
3080			const self = this, $el = this.options.wrapper, $window = $(window), scrollTop = $window.scrollTop(), elementOffset = $el.offset().top, currentElementOffset = (elementOffset - scrollTop), factor = ( self.options.isInsideSVG ) ? 2 : 100;
3081
3082		   	const scrollPercent = factor * currentElementOffset / ($window.height());
3083
3084		   	if( $el.visible( true ) ) {
3085
3086		   		if( !self.options.horizontal ) {
3087
3088		   			$el.css({
3089			   			transform: 'translate3d(0, '+ minus + scrollPercent / self.options.speed +'%, 0)'
3090			   		});
3091
3092		   		} else {
3093
3094		   			$el.css({
3095			   			transform: 'translate3d('+ minus + scrollPercent / self.options.speed +'%, 0, 0)'
3096			   		});
3097
3098		   		}
3099		   		
3100		   	}
3101
3102		}
3103    }
3104
3105    PluginFloatElement.defaults = {
3106		startPos: 'top',
3107		speed: 3,
3108		horizontal: false,
3109		isInsideSVG: false,
3110		transition: false,
3111		transitionDelay: 0,
3112		transitionDuration: 500,
3113		minWindowWidth: 991
3114	};
3115
3116    // expose to scope
3117    $.extend(theme, {
3118		PluginFloatElement
3119	});
3120
3121    // jquery plugin
3122    $.fn.themePluginFloatElement = function(opts) {
3123		return this.map(function() {
3124			const $this = $(this);
3125
3126			if ($this.data(instanceName)) {
3127				return $this.data(instanceName);
3128			} else {
3129				return new PluginFloatElement($this, opts);
3130			}
3131
3132		});
3133	}
3134})).apply(this, [window.theme, jQuery]);
3135
3136// GDPR
3137(((theme = {}, $) => {
3138    const instanceName = '__gdpr';
3139
3140    class PluginGDPR {
3141        constructor($el, opts) {
3142            return this.initialize($el, opts);
3143        }
3144
3145        initialize($el, opts) {
3146			const self = this;
3147
3148			this.$el = $el;
3149
3150			this
3151				.setData()
3152				.setOptions(opts)
3153				.build()
3154				.events();
3155
3156			return this;
3157		}
3158
3159        setData() {
3160			this.$el.data(instanceName, this);
3161
3162			return this;
3163		}
3164
3165        setOptions(opts) {
3166			this.options = $.extend(true, {}, PluginGDPR.defaults, opts, {
3167				wrapper: this.$el
3168			});
3169
3170			return this;
3171		}
3172
3173        build() {
3174			const self = this;
3175
3176			// Show
3177			if( !$.cookie( 'porto-privacy-bar' ) ) {
3178				setTimeout(() => {
3179					self.options.wrapper.addClass('show');
3180				}, self.options.cookieBarShowDelay);
3181			}
3182
3183			// If already has preferences cookie, check inputs according preferences cookie data
3184			if( $.cookie( 'porto-gdpr-preferences' ) ) {
3185				const preferencesArr = $.cookie( 'porto-gdpr-preferences' ).split(',');
3186
3187				for( let i = 0; i < preferencesArr.length; i++ ) {
3188					if( $('input[value="'+ preferencesArr[i] +'"]').get(0) ) {
3189						if( $('input[value="'+ preferencesArr[i] +'"]').is(':checkbox') ) {
3190							$('input[value="'+ preferencesArr[i] +'"]').prop('checked', true);
3191						}
3192					}
3193				}
3194			}
3195
3196			return this;
3197
3198		}
3199
3200        events() {
3201			const self = this;
3202
3203			// Agree Trigger
3204			self.options.wrapper.find('.gdpr-agree-trigger').on('click', e => {
3205				e.preventDefault();
3206
3207				$('.gdpr-preferences-form').find('.gdpr-input').each(function(){
3208					if( $(this).is(':checkbox') || $(this).is(':hidden') ) {
3209						$(this).prop('checked', true);
3210					}
3211				});
3212
3213				$('.gdpr-preferences-form').trigger('submit').removeClass('show');
3214
3215				self.removeCookieBar();
3216			});
3217
3218			// Preferences Trigger
3219			self.options.wrapper.find('.gdpr-preferences-trigger').on('click', e => {
3220				e.preventDefault();
3221
3222				$('.gdpr-preferences-popup').addClass('show');
3223			});
3224
3225			// Close Popup Button
3226			$('.gdpr-close-popup').on('click', e => {
3227				e.preventDefault();
3228
3229				$('.gdpr-preferences-popup').removeClass('show');
3230			});
3231
3232			// Close Popup When Click Outside of popup area
3233			$('.gdpr-preferences-popup').on('click', ({target}) => {
3234				if( !$(target).closest('.gdpr-preferences-popup-content').get(0) ) {
3235					$('.gdpr-preferences-popup').removeClass('show');
3236				}
3237			});
3238
3239			// Preference Form
3240			$('.gdpr-preferences-form').on('submit', function(e){
3241				e.preventDefault();
3242
3243				const $this = $(this);
3244
3245				// Save Preferences Button
3246				$this.find('button[type="submit"]').text( 'SAVING...' );
3247
3248				// Form Data
3249				const formData = [];
3250				$this.find('.gdpr-input').each(function(){
3251					if( $(this).is(':checkbox') && $(this).is(':checked') || $(this).is(':hidden') ) {
3252						formData.push( $(this).val() );
3253					}
3254				});
3255
3256				$.cookie( 'porto-privacy-bar', true, {expires: self.options.expires} );
3257
3258				setTimeout(() => {
3259					$this.find('button[type="submit"]').text( 'SAVED!' ).removeClass('btn-primary').addClass('btn-success');
3260
3261					setTimeout(() => {
3262						$('.gdpr-preferences-popup').removeClass('show');
3263						self.removeCookieBar();
3264
3265						$this.find('button[type="submit"]').text( 'SAVE PREFERENCES' ).removeClass('btn-success').addClass('btn-primary');
3266
3267						if( $.cookie( 'porto-gdpr-preferences' ) ) {
3268
3269							$.cookie( 'porto-gdpr-preferences', formData, {expires: self.options.expires} );
3270							location.reload();
3271
3272						} else {
3273
3274							$.cookie( 'porto-gdpr-preferences', formData, {expires: self.options.expires} );
3275
3276							if ($.isFunction($.fn['themePluginGDPRWrapper']) && $('[data-plugin-gdpr-wrapper]').length) {
3277
3278								$(() => {
3279									$('[data-plugin-gdpr-wrapper]:not(.manual)').each(function() {
3280                                        const $this = $(this);
3281                                        let opts;
3282
3283                                        $this.removeData('__gdprwrapper');
3284
3285                                        const pluginOptions = theme.fn.getOptions($this.data('plugin-options'));
3286                                        if (pluginOptions)
3287											opts = pluginOptions;
3288
3289                                        $this.themePluginGDPRWrapper(opts);
3290                                    });
3291								});
3292
3293							}
3294
3295						}
3296
3297					}, 500);
3298				}, 1000);
3299			});
3300
3301			// Remove/Reset Cookies
3302			$('.gdpr-reset-cookies').on('click', e => {
3303				e.preventDefault();
3304
3305				self.clearCookies();
3306
3307				location.reload();
3308			});
3309
3310			// Open Preferences
3311			$('.gdpr-open-preferences').on('click', e => {
3312				e.preventDefault();
3313
3314				$('.gdpr-preferences-popup').toggleClass('show');
3315			});
3316
3317			return this;
3318		}
3319
3320        removeCookieBar() {
3321			const self = this;
3322
3323			self.options.wrapper.addClass('removing').on('transitionend', () => {
3324				setTimeout(() => {
3325					self.options.wrapper.removeClass('show removing');
3326				}, 500);
3327			});
3328
3329			return this;
3330		}
3331
3332        clearCookies() {
3333			const self = this;
3334
3335			$.removeCookie( 'porto-privacy-bar' );
3336			$.removeCookie( 'porto-gdpr-preferences' );
3337
3338			return this;
3339		}
3340    }
3341
3342    PluginGDPR.defaults = {
3343		cookieBarShowDelay: 3000,
3344		expires: 365
3345	};
3346
3347    // expose to scope
3348    $.extend(theme, {
3349		PluginGDPR
3350	});
3351
3352    // jquery plugin
3353    $.fn.themePluginGDPR = function(opts) {
3354		return this.map(function() {
3355			const $this = $(this);
3356
3357			if ($this.data(instanceName)) {
3358				return $this.data(instanceName);
3359			} else {
3360				return new PluginGDPR($this, opts);
3361			}
3362
3363		});
3364	}
3365})).apply(this, [window.theme, jQuery]);
3366
3367// GDPR Wrapper
3368(((theme = {}, $) => {
3369    const instanceName = '__gdprwrapper';
3370
3371    class PluginGDPRWrapper {
3372        constructor($el, opts) {
3373            return this.initialize($el, opts);
3374        }
3375
3376        initialize($el, opts) {
3377			const self = this;
3378
3379			this.$el = $el;
3380
3381			this
3382				.setData()
3383				.setOptions(opts)
3384				.build();
3385				
3386			return this;
3387		}
3388
3389        setData() {
3390			this.$el.data(instanceName, this);
3391
3392			return this;
3393		}
3394
3395        setOptions(opts) {
3396			this.options = $.extend(true, {}, PluginGDPRWrapper.defaults, opts, {
3397				wrapper: this.$el
3398			});
3399
3400			return this;
3401		}
3402
3403        build() {
3404			const self = this;
3405
3406			if( $.cookie( 'porto-gdpr-preferences' ) && $.cookie( 'porto-gdpr-preferences' ).includes(self.options.checkCookie) ) {
3407
3408				$.ajax({
3409					url: self.options.ajaxURL,
3410					cache: false,
3411					complete({responseText}) {
3412					
3413						setTimeout(() => {
3414
3415							self.options.wrapper.html(responseText).addClass('show');
3416
3417						}, 1000);
3418
3419					}
3420				});
3421
3422			} else {
3423				self.options.wrapper.addClass('show');
3424			}
3425
3426			return this;
3427
3428		}
3429    }
3430
3431    PluginGDPRWrapper.defaults = {
3432
3433	};
3434
3435    // expose to scope
3436    $.extend(theme, {
3437		PluginGDPRWrapper
3438	});
3439
3440    // jquery plugin
3441    $.fn.themePluginGDPRWrapper = function(opts) {
3442		return this.map(function() {
3443			const $this = $(this);
3444
3445			if ($this.data(instanceName)) {
3446				return $this.data(instanceName);
3447			} else {
3448				return new PluginGDPRWrapper($this, opts);
3449			}
3450
3451		});
3452	}
3453})).apply(this, [window.theme, jQuery]);
3454
3455// Hover Effect
3456(((theme = {}, $) => {
3457    const instanceName = '__hoverEffect';
3458
3459    class PluginHoverEffect {
3460        constructor($el, opts) {
3461            return this.initialize($el, opts);
3462        }
3463
3464        initialize($el, opts) {
3465			if ($el.data(instanceName)) {
3466				return this;
3467			}
3468
3469			this.$el = $el;
3470
3471			this
3472				.setData()
3473				.setOptions(opts)
3474				.build();
3475
3476			return this;
3477		}
3478
3479        setData() {
3480			this.$el.data(instanceName, this);
3481
3482			return this;
3483		}
3484
3485        setOptions(opts) {
3486			this.options = $.extend(true, {}, PluginHoverEffect.defaults, opts, {
3487				wrapper: this.$el
3488			});
3489
3490			return this;
3491		}
3492
3493        build() {
3494			const self = this;
3495
3496			if(self.$el.hasClass('hover-effect-3d')) {
3497				self.options.effect = '3d';
3498			}
3499
3500			// Magnetic
3501			if(self.options.effect == 'magnetic') {
3502				self.magnetic();
3503			}
3504
3505			// 3d
3506			if(self.options.effect == '3d') {
3507				self.hover3d();
3508			}
3509
3510			return this;
3511		}
3512
3513        magnetic() {
3514			const self = this;
3515
3516			self.$el.mousemove(function({clientX, clientY}) {
3517
3518				const pos = this.getBoundingClientRect();
3519				const mx = clientX - pos.left - pos.width/2; 
3520				const my = clientY - pos.top - pos.height/2;
3521
3522				this.style.transform = 'translate('+ mx * self.options.magneticMx +'px, '+ my * self.options.magneticMx +'px)';
3523
3524			});
3525
3526			self.$el.mouseleave(function(e) {
3527
3528				this.style.transform = 'translate3d(0px, 0px, 0px)';
3529
3530			});
3531
3532			return this;
3533
3534		}
3535
3536        hover3d() {
3537			const self = this;
3538
3539			if ($.isFunction($.fn['hover3d'])) {
3540
3541				self.$el.hover3d({
3542					selector: self.options.selector,
3543					sensitivity: self.options.sensitivity
3544				});
3545
3546			}
3547
3548			return this;
3549
3550		}
3551    }
3552
3553    PluginHoverEffect.defaults = {
3554		effect: 'magnetic',
3555		magneticMx: 0.15,
3556		magneticMy: 0.3,
3557		magneticDeg: 12,
3558		selector: '.thumb-info, .hover-effect-3d-wrapper',
3559		sensitivity: 20
3560	};
3561
3562    // expose to scope
3563    $.extend(theme, {
3564		PluginHoverEffect
3565	});
3566
3567    // jquery plugin
3568    $.fn.themePluginHoverEffect = function(opts) {
3569		return this.map(function() {
3570			const $this = $(this);
3571
3572			if ($this.data(instanceName)) {
3573				return $this.data(instanceName);
3574			} else {
3575				return new PluginHoverEffect($this, opts);
3576			}
3577
3578		});
3579	};
3580})).apply(this, [window.theme, jQuery]);
3581
3582// Icon
3583(((theme = {}, $) => {
3584    const instanceName = '__icon';
3585
3586    class PluginIcon {
3587        constructor($el, opts) {
3588            return this.initialize($el, opts);
3589        }
3590
3591        initialize($el, opts) {
3592			if ($el.data(instanceName)) {
3593				return this;
3594			}
3595
3596			this.$el = $el;
3597
3598			this
3599				.setData()
3600				.setOptions(opts)
3601				.build();
3602
3603			return this;
3604		}
3605
3606        setData() {
3607			this.$el.data(instanceName, this);
3608
3609			return this;
3610		}
3611
3612        setOptions(opts) {
3613			this.options = $.extend(true, {}, PluginIcon.defaults, opts, {
3614				wrapper: this.$el
3615			});
3616
3617			return this;
3618		}
3619
3620        build() {
3621            const self  	 = this;
3622            let $el   	 = this.options.wrapper;
3623            const color 	 = self.options.color;
3624            const elTopDistance = $el.offset().top;
3625            const windowTopDistance = $(window).scrollTop();
3626            let duration = ( self.options.animated && !self.options.strokeBased ) ? 200 : 100;
3627
3628            // Check origin
3629            if( window.location.protocol === 'file:' ) {
3630				$el.css({
3631					opacity: 1,
3632					width: $el.attr('width')
3633				});
3634
3635				if( self.options.extraClass ) {
3636					$el.addClass( self.options.extraClass );
3637				}
3638
3639				if( self.options.extraClass.indexOf('-color-light') > 0 ) {
3640					$el.css({
3641						filter: 'invert(1)'
3642					});
3643				}
3644
3645				$(window).trigger('icon.rendered');
3646				return;
3647			}
3648
3649            // Duration
3650            if( self.options.duration ) {
3651				duration = self.options.duration;
3652			}
3653
3654            // SVG Content
3655			const fileName = $el.attr('src');
3656
3657			if(fileName.split('.').pop() == 'svg') {
3658				const SVGContent = $.get({
3659					url: fileName, 
3660					success(data, status, {responseText}) {
3661						const iconWrapper = self.options.fadeIn ? $('<div class="animated-icon animated fadeIn">'+ responseText +'</div>') : $('<div class="animated-icon animated">'+ responseText +'</div>'), uniqid = 'icon_' + Math.floor(Math.random() * 26) + Date.now();
3662
3663						// Add ID
3664						iconWrapper.find('svg').attr('id', uniqid);
3665
3666						// Identify with filename
3667						iconWrapper.find('svg').attr('data-filename', $el.attr('src').split(/(\\|\/)/g).pop());
3668
3669						if( $el.attr('width') ) {
3670							iconWrapper.find('svg')
3671								.attr('width', $el.attr('width'))
3672								.attr('height', $el.attr('width'));						
3673						}
3674
3675						if( $el.attr('height') ) {
3676							iconWrapper.find('svg')
3677								.attr('height', $el.attr('height'));	
3678						}
3679
3680						if( self.options.svgViewBox ) {
3681							iconWrapper.find('svg')
3682								.attr('viewBox', self.options.svgViewBox);
3683						}
3684
3685						$el.replaceWith(iconWrapper);
3686
3687						if( self.options.extraClass ) {
3688							iconWrapper.addClass( self.options.extraClass );
3689						}
3690
3691						if( self.options.removeClassAfterInit ) {
3692							iconWrapper.removeClass(self.options.removeClassAfterInit);
3693						}
3694
3695						if( self.options.onlySVG ) {
3696							$(window).trigger('icon.rendered');
3697							return this;
3698						}
3699
3700						$el = iconWrapper;
3701
3702						const icon = new Vivus(uniqid, {start: 'manual', type: 'sync', selfDestroy: true, duration, onReady({el}) {
3703							const styleElement = document.createElementNS("http://www.w3.org/2000/svg", "style");
3704							let animateStyle = '';
3705
3706							// SVG Fill Based
3707							if( self.options.animated && !self.options.strokeBased || !self.options.animated && color && !self.options.strokeBased ) {
3708								animateStyle = 'stroke-width: 0.1px; fill-opacity: 0; transition: ease fill-opacity 300ms;';
3709								
3710								// Set Style on SVG inside object
3711								styleElement.textContent = '#' + uniqid + ' path, #' + uniqid + ' line, #' + uniqid + ' rect, #' + uniqid + ' circle, #' + uniqid + ' polyline { fill: '+ color +'; stroke: '+ color +'; '+ animateStyle + (self.options.svgStyle ? self.options.svgStyle : "") + ' } .finished path { fill-opacity: 1; }';
3712								el.appendChild(styleElement);
3713							}
3714
3715							// SVG Stroke Based
3716							if( self.options.animated && self.options.strokeBased || !self.options.animated && color && self.options.strokeBased ) {
3717
3718								// Set Style on SVG inside object
3719								styleElement.textContent = '#' + uniqid + ' path, #' + uniqid + ' line, #' + uniqid + ' rect, #' + uniqid + ' circle, #' + uniqid + ' polyline { stroke: '+ color +'; ' + (self.options.svgStyle ? self.options.svgStyle : "") + '}';
3720								el.appendChild(styleElement);
3721							}
3722
3723							$.event.trigger('theme.plugin.icon.svg.ready');
3724						}});
3725
3726						// Isn't animated
3727						if( !self.options.animated ) {
3728							setTimeout(() => {
3729								icon.finish();
3730							}, 10);
3731							$el.css({ opacity: 1 });
3732						}
3733
3734						// Animated
3735						if( self.options.animated && $(window).width() > 767 ) {
3736							
3737							// First Load
3738							if( $el.visible( true ) ) {
3739								self.startIconAnimation( icon, $el );
3740							} else if( elTopDistance < windowTopDistance ) {
3741								self.startIconAnimation( icon, $el );
3742							}
3743
3744							// On Scroll
3745							$(window).on('scroll', () => {
3746								if( $el.visible( true ) ) {
3747									self.startIconAnimation( icon, $el );
3748								}
3749							});
3750
3751						} else {
3752							
3753							$el.css({ opacity: 1 });
3754							icon.finish();
3755							
3756							$(window).on('theme.plugin.icon.svg.ready', () => {
3757								setTimeout(() => {
3758									icon.el.setAttribute('class', 'finished');
3759									icon.finish();
3760								}, 300);
3761							});
3762							
3763						}
3764
3765						$(window).trigger('icon.rendered');
3766					}
3767				});
3768			} else {
3769				$el.removeAttr('data-icon');
3770			}
3771
3772            return this;
3773        }
3774
3775        startIconAnimation(icon, $el) {
3776			const self = this;
3777
3778			// Animate for better performance
3779			$({to:0}).animate({to:1}, ((self.options.strokeBased) ? self.options.delay : self.options.delay + 300 ), () => {
3780				$el.css({ opacity: 1 });
3781			});
3782
3783			$({to:0}).animate({to:1}, self.options.delay, () => {
3784				icon.play(1);
3785
3786				setTimeout(() => {
3787					icon.el.setAttribute('class', 'finished');
3788				}, icon.duration * 5 );
3789			});
3790		}
3791    }
3792
3793    PluginIcon.defaults = {
3794		color: '#2388ED',
3795		animated: false,
3796		delay: 300,
3797		onlySVG: false,
3798		removeClassAfterInit: false,
3799		fadeIn: true,
3800		accY: 0
3801	};
3802
3803    // expose to scope
3804    $.extend(theme, {
3805		PluginIcon
3806	});
3807
3808    // jquery plugin
3809    $.fn.themePluginIcon = function(opts) {
3810		return this.map(function() {
3811			const $this = $(this);
3812
3813			if ($this.data(instanceName)) {
3814				return $this.data(instanceName);
3815			} else {
3816				return new PluginIcon($this, opts);
3817			}
3818
3819		});
3820	};
3821})).apply(this, [window.theme, jQuery]);
3822
3823// In Viewport Style
3824(((theme = {}, $) => {
3825    const instanceName = '__inviewportstyle';
3826
3827    class PluginInViewportStyle {
3828        constructor($el, opts) {
3829            return this.initialize($el, opts);
3830        }
3831
3832        initialize($el, opts) {
3833			if ($el.data(instanceName)) {
3834				return this;
3835			}
3836
3837			this.$el = $el;
3838
3839			this
3840				.setData()
3841				.setOptions(opts)
3842				.build();
3843
3844			return this;
3845		}
3846
3847        setData() {
3848			this.$el.data(instanceName, this);
3849
3850			return this;
3851		}
3852
3853        setOptions(opts) {
3854			this.options = $.extend(true, {}, PluginInViewportStyle.defaults, opts, {});
3855
3856			return this;
3857		}
3858
3859        build() {
3860			const self = this, el = self.$el.get(0);
3861
3862			self.$el.css(self.options.style);
3863
3864		    if (typeof window.IntersectionObserver === 'function') {
3865			    const un = observeElementInViewport.observeElementInViewport(
3866			        el, () => {
3867			        	self.$el.css(self.options.styleIn);
3868			        	self.$el
3869			        		.addClass(self.options.classIn)
3870			        		.removeClass(self.options.classOut);
3871			        }, () => {
3872			        	self.$el.css(self.options.styleOut);
3873			        	self.$el
3874			        		.addClass(self.options.classOut)
3875			        		.removeClass(self.options.classIn);
3876			        }, {
3877			        	viewport: self.options.viewport, 
3878			            threshold: self.options.threshold,
3879						modTop: self.options.modTop,
3880						modBottom: self.options.modBottom
3881			        }
3882			    )
3883		    };
3884
3885			return this;
3886		}
3887    }
3888
3889    PluginInViewportStyle.defaults = {
3890		viewport: window, 
3891		threshold: [0],
3892		modTop: '-200px',
3893		modBottom: '-200px',
3894		style: {'transition': 'all 1s ease-in-out'},
3895		styleIn: '',
3896		styleOut: '',
3897		classIn: '',
3898		classOut: ''
3899	};
3900
3901    // expose to scope
3902    $.extend(theme, {
3903		PluginInViewportStyle
3904	});
3905
3906    // jquery plugin
3907    $.fn.themePluginInViewportStyle = function(opts) {
3908		return this.map(function() {
3909			const $this = $(this);
3910
3911			if ($this.data(instanceName)) {
3912				return $this.data(instanceName);
3913			} else {
3914				return new PluginInViewportStyle($this, opts);
3915			}
3916
3917		});
3918	}
3919})).apply(this, [window.theme, jQuery]);
3920
3921// Lightbox
3922(((theme = {}, $) => {
3923    const instanceName = '__lightbox';
3924
3925    class PluginLightbox {
3926        constructor($el, opts) {
3927            return this.initialize($el, opts);
3928        }
3929
3930        initialize($el, opts) {
3931			if ($el.data(instanceName)) {
3932				return this;
3933			}
3934
3935			this.$el = $el;
3936
3937			this
3938				.setData()
3939				.setOptions(opts)
3940				.build();
3941
3942			return this;
3943		}
3944
3945        setData() {
3946			this.$el.data(instanceName, this);
3947
3948			return this;
3949		}
3950
3951        setOptions(opts) {
3952			this.options = $.extend(true, {}, PluginLightbox.defaults, opts, {
3953				wrapper: this.$el
3954			});
3955
3956			return this;
3957		}
3958
3959        build() {
3960			if (!($.isFunction($.fn.magnificPopup))) {
3961				return this;
3962			}
3963
3964			this.options.wrapper.magnificPopup(this.options);
3965
3966			return this;
3967		}
3968    }
3969
3970    PluginLightbox.defaults = {
3971		tClose: 'Close (Esc)', // Alt text on close button
3972		tLoading: 'Loading...', // Text that is displayed during loading. Can contain %curr% and %total% keys
3973		gallery: {
3974			tPrev: 'Previous (Left arrow key)', // Alt text on left arrow
3975			tNext: 'Next (Right arrow key)', // Alt text on right arrow
3976			tCounter: '%curr% of %total%' // Markup for "1 of 7" counter
3977		},
3978		image: {
3979			tError: '<a href="%url%">The image</a> could not be loaded.' // Error message when image could not be loaded
3980		},
3981		ajax: {
3982			tError: '<a href="%url%">The content</a> could not be loaded.' // Error message when ajax request failed
3983		},
3984		callbacks: {
3985			open() {
3986				$('html').addClass('lightbox-opened');
3987			},
3988			close() {
3989				$('html').removeClass('lightbox-opened');
3990			}
3991		}
3992	};
3993
3994    // expose to scope
3995    $.extend(theme, {
3996		PluginLightbox
3997	});
3998
3999    // jquery plugin
4000    $.fn.themePluginLightbox = function(opts) {
4001		return this.map(function() {
4002			const $this = $(this);
4003
4004			if ($this.data(instanceName)) {
4005				return $this.data(instanceName);
4006			} else {
4007				return new PluginLightbox($this, opts);
4008			}
4009
4010		});
4011	}
4012})).apply(this, [window.theme, jQuery]);
4013
4014// Loading Overlay
4015(((theme = {}, $) => {
4016    // Default
4017    const loadingOverlayDefaultTemplate = [
4018		'<div class="loading-overlay">',
4019			'<div class="bounce-loader"><div class="bounce1"></div><div class="bounce2"></div><div class="bounce3"></div></div>',
4020		'</div>'
4021	].join('');
4022
4023    // Percentage
4024    const loadingOverlayPercentageTemplate = [
4025		'<div class="loading-overlay loading-overlay-percentage">',
4026			'<div class="page-loader-progress-wrapper"><span class="page-loader-progress">0</span><span class="page-loader-progress-symbol">%</span></div>',
4027		'</div>'
4028	].join('');
4029
4030    // Cubes
4031    const loadingOverlayCubesTemplate = [
4032		'<div class="loading-overlay">',
4033			'<div class="bounce-loader"><div class="cssload-thecube"><div class="cssload-cube cssload-c1"></div><div class="cssload-cube cssload-c2"></div><div class="cssload-cube cssload-c4"></div><div class="cssload-cube cssload-c3"></div></div></div>',
4034		'</div>'
4035	].join('');
4036
4037    // Cube Progress
4038    const loadingOverlayCubeProgressTemplate = [
4039		'<div class="loading-overlay">',
4040			'<div class="bounce-loader"><span class="cssload-cube-progress"><span class="cssload-cube-progress-inner"></span></span></div>',
4041		'</div>'
4042	].join('');
4043
4044    // Float Rings
4045    const loadingOverlayFloatRingsTemplate = [
4046		'<div class="loading-overlay">',
4047			'<div class="bounce-loader"><div class="cssload-float-rings-loader"><div class="cssload-float-rings-inner cssload-one"></div><div class="cssload-float-rings-inner cssload-two"></div><div class="cssload-float-rings-inner cssload-three"></div></div></div>',
4048		'</div>'
4049	].join('');
4050
4051    // Floating Bars
4052    const loadingOverlayFloatBarsTemplate = [
4053		'<div class="loading-overlay">',
4054			'<div class="bounce-loader"><div class="cssload-float-bars-container"><ul class="cssload-float-bars-flex-container"><li><span class="cssload-float-bars-loading"></span></li></div></div></div>',
4055		'</div>'
4056	].join('');
4057
4058    // Speeding Wheel
4059    const loadingOverlaySpeedingWheelTemplate = [
4060		'<div class="loading-overlay">',
4061			'<div class="bounce-loader"><div class="cssload-speeding-wheel-container"><div class="cssload-speeding-wheel"></div></div></div>',
4062		'</div>'
4063	].join('');
4064
4065    // Zenith
4066    const loadingOverlayZenithTemplate = [
4067		'<div class="loading-overlay">',
4068			'<div class="bounce-loader"><div class="cssload-zenith-container"><div class="cssload-zenith"></div></div></div>',
4069		'</div>'
4070	].join('');
4071
4072    // Spinning Square
4073    const loadingOverlaySpinningSquareTemplate = [
4074		'<div class="loading-overlay">',
4075			'<div class="bounce-loader"><div class="cssload-spinning-square-loading"></div></div>',
4076		'</div>'
4077	].join('');
4078
4079    // Pulse
4080    const loadingOverlayPulseTemplate = [
4081		'<div class="loading-overlay">',
4082			'<div class="bounce-loader"><div class="wrapper-pulse"><div class="cssload-pulse-loader"></div></div></div>',
4083		'</div>'
4084	].join('');
4085
4086    const LoadingOverlay = function( $wrapper, options, noInheritOptions ) {
4087		return this.initialize( $wrapper, options, noInheritOptions );
4088	};
4089
4090    LoadingOverlay.prototype = {
4091
4092		options: {
4093			css: {},
4094			hideDelay: 500,
4095			progressMinTimeout: 0,
4096			effect: 'default'
4097		},
4098
4099		initialize($wrapper, options, noInheritOptions) {
4100			this.$wrapper = $wrapper;
4101
4102			this
4103				.setVars()
4104				.setOptions( options, noInheritOptions )
4105				.build()
4106				.events()
4107				.dynamicShowHideEvents();
4108
4109			this.$wrapper.data( 'loadingOverlay', this );
4110		},
4111
4112		setVars() {
4113			this.$overlay = this.$wrapper.find('.loading-overlay');
4114			this.pageStatus = null;
4115			this.progress = null;
4116			this.animationInterval = 33;
4117
4118			return this;
4119		},
4120
4121		setOptions(options, noInheritOptions) {
4122			if ( !this.$overlay.get(0) ) {
4123				this.matchProperties();
4124			}
4125			
4126			if( noInheritOptions ) {
4127				this.options     = $.extend( true, {}, this.options, options );
4128			} else {
4129				this.options     = $.extend( true, {}, this.options, options, theme.fn.getOptions(this.$wrapper.data('plugin-options')) );
4130			}
4131
4132			this.loaderClass = this.getLoaderClass( this.options.css.backgroundColor );
4133
4134			return this;
4135		},
4136
4137		build() {
4138			const _self = this;
4139
4140			if ( !this.$overlay.closest(document.documentElement).get(0) ) {
4141				if ( !this.$cachedOverlay ) {
4142
4143					switch ( _self.options.effect ) {
4144						case 'percentageProgress1':
4145							this.$overlay = $( loadingOverlayPercentageTemplate ).clone();
4146							break;
4147
4148						case 'percentageProgress2':
4149							this.$overlay = $( loadingOverlayPercentageTemplate ).clone();
4150							this.$overlay
4151								.addClass('loading-overlay-percentage-effect-2')
4152								.prepend('<div class="loading-overlay-background-layer"></div>');
4153							break;
4154
4155						case 'cubes':
4156							this.$overlay = $( loadingOverlayCubesTemplate ).clone();
4157							break;
4158
4159						case 'cubeProgress':
4160							this.$overlay = $( loadingOverlayCubeProgressTemplate ).clone();
4161							break;
4162
4163						case 'floatRings':
4164							this.$overlay = $( loadingOverlayFloatRingsTemplate ).clone();
4165							break;
4166
4167						case 'floatBars':
4168							this.$overlay = $( loadingOverlayFloatBarsTemplate ).clone();
4169							break;
4170
4171						case 'speedingWheel':
4172							this.$overlay = $( loadingOverlaySpeedingWheelTemplate ).clone();
4173							break;
4174
4175						case 'zenith':
4176							this.$overlay = $( loadingOverlayZenithTemplate ).clone();
4177							break;
4178
4179						case 'spinningSquare':
4180							this.$overlay = $( loadingOverlaySpinningSquareTemplate ).clone();
4181							break;
4182
4183						case 'pulse':
4184							this.$overlay = $( loadingOverlayPulseTemplate ).clone();
4185							break;
4186
4187						case 'default':
4188						default:
4189							this.$overlay = $( loadingOverlayDefaultTemplate ).clone();
4190							break;
4191					}
4192					
4193					if ( this.options.css ) {
4194						this.$overlay.css( this.options.css );
4195						this.$overlay.find( '.loader' ).addClass( this.loaderClass );
4196					}
4197				} else {
4198					this.$overlay = this.$cachedOverlay.clone();
4199				}
4200
4201				this.$wrapper.prepend( this.$overlay );
4202			}
4203
4204			if ( !this.$cachedOverlay ) {
4205				this.$cachedOverlay = this.$overlay.clone();
4206			}
4207
4208			if( ['percentageProgress1', 'percentageProgress2'].includes(_self.options.effect) ) {
4209				_self.updateProgress();
4210
4211				if( _self.options.isDynamicHideShow ) {
4212					setTimeout(() => {
4213						_self.progress = 'complete';
4214						
4215						$('.page-loader-progress').text(100);
4216
4217						if( ['percentageProgress2'].includes(_self.options.effect) ) {
4218			            	$('.loading-overlay-background-layer').css({
4219			            		width: '100%'
4220			            	});
4221			            }
4222					}, 2800);
4223				}
4224			}
4225
4226			return this;
4227		},
4228
4229		events() {
4230			const _self = this;
4231
4232			if ( this.options.startShowing ) {
4233				_self.show();
4234			}
4235
4236			if ( this.$wrapper.is('body') || this.options.hideOnWindowLoad ) {
4237				$( window ).on( 'load error', () => {
4238					setTimeout(() => {
4239						_self.hide();
4240					}, _self.options.progressMinTimeout);
4241				});
4242			}
4243
4244			if ( this.options.listenOn ) {
4245				$( this.options.listenOn )
4246					.on( 'loading-overlay:show beforeSend.ic', e => {
4247						e.stopPropagation();
4248						_self.show();
4249					})
4250					.on( 'loading-overlay:hide complete.ic', e => {
4251						e.stopPropagation();
4252						_self.hide();
4253					});
4254			}
4255
4256			this.$wrapper
4257				.on( 'loading-overlay:show beforeSend.ic', e => {
4258					if ( e.target === _self.$wrapper.get(0) ) {
4259						e.stopPropagation();
4260						_self.show();
4261						return true;
4262					}
4263					return false;
4264				})
4265				.on( 'loading-overlay:hide complete.ic', e => {
4266					if ( e.target === _self.$wrapper.get(0) ) {
4267						e.stopPropagation();
4268						_self.hide();
4269						return true;
4270					}
4271					return false;
4272				});
4273
4274			if( ['percentageProgress1', 'percentageProgress2'].includes(_self.options.effect) ) {
4275				$(window).on('load', () => {
4276		            setTimeout(() => {
4277			            _self.pageStatus = "complete";
4278
4279			            $('.page-loader-progress').text(100);
4280
4281			            if( ['percentageProgress2'].includes(_self.options.effect) ) {
4282			            	$('.loading-overlay-background-layer').css({
4283			            		width: '100%'
4284			            	});
4285			            }
4286		            }, _self.options.progressMinTimeout);
4287				});
4288			}
4289		        
4290			return this;
4291		},
4292
4293		show() {
4294			this.build();
4295
4296			this.position = this.$wrapper.css( 'position' ).toLowerCase();
4297			if ( this.position != 'relative' || this.position != 'absolute' || this.position != 'fixed' ) {
4298				this.$wrapper.css({
4299					position: 'relative'
4300				});
4301			}
4302			this.$wrapper.addClass( 'loading-overlay-showing' );
4303		},
4304
4305		hide() {
4306			const _self = this;
4307
4308			setTimeout(function() {
4309				_self.$wrapper.removeClass( 'loading-overlay-showing' );
4310				
4311				if ( this.position != 'relative' || this.position != 'absolute' || this.position != 'fixed' ) {
4312					_self.$wrapper.css({ position: '' });
4313				}
4314
4315				$(window).trigger('loading.overlay.ready');
4316			}, _self.options.hideDelay);
4317		},
4318
4319		updateProgress() {
4320			const _self = this;
4321
4322			const render = () => {
4323				if(_self.pageStatus == "complete"){
4324		            $('.page-loader-progress').text(100);
4325		            setTimeout(() => {
4326		                $('.page-loader-progress').addClass('d-none');    
4327		            }, 700);
4328		        }
4329		        else{            
4330		            if(_self.progress == null){
4331		                _self.progress = 1;
4332		            }
4333		           
4334		            _self.progress = _self.progress + 1;
4335		            if(_self.progress >= 0 && _self.progress <= 30){
4336		                _self.animationInterval += 1;
4337		                $('.page-loader-progress').text(_self.progress);
4338		            }
4339		            else if(_self.progress > 30 && _self.progress <= 60){
4340		                _self.animationInterval += 2;
4341		                $('.page-loader-progress').text(_self.progress);
4342		            }
4343		            else if(_self.progress > 60 && _self.progress <= 80){
4344		                _self.animationInterval += 40;
4345		                $('.page-loader-progress').text(_self.progress);
4346		            }
4347		            else if(_self.progress > 80 && _self.progress <= 90){
4348		                _self.animationInterval += 80;
4349		                $('.page-loader-progress').text(_self.progress);
4350		            }
4351		            else if(_self.progress > 90 && _self.progress <= 95){
4352		                _self.animationInterval += 150;
4353		                $('.page-loader-progress').text(_self.progress);
4354		            }
4355		            else if(_self.progress > 95 && _self.progress <= 99){
4356		                _self.animationInterval += 400;
4357		                $('.page-loader-progress').text(_self.progress);
4358		            }
4359		            else if(_self.progress >= 100){
4360		                $('.page-loader-progress').text(99);
4361		            }
4362
4363		            if( ['percentageProgress2'].includes(_self.options.effect) ) {
4364		            	$('.loading-overlay-background-layer').css({
4365		            		width: _self.progress + '%'
4366		            	});
4367		            }
4368		              
4369					self.loopInside = setTimeout(render, _self.animationInterval);
4370		        }
4371
4372			};
4373			render();
4374
4375			return this;
4376		},
4377
4378		matchProperties() {
4379			let i, l, properties;
4380
4381			properties = [
4382				'backgroundColor',
4383				'borderRadius'
4384			];
4385
4386			l = properties.length;
4387
4388			for( i = 0; i < l; i++ ) {
4389				const obj = {};
4390				obj[ properties[ i ] ] = this.$wrapper.css( properties[ i ] );
4391
4392				$.extend( this.options.css, obj );
4393			}
4394		},
4395
4396		getLoaderClass(backgroundColor) {
4397			if ( !backgroundColor || backgroundColor === 'transparent' || backgroundColor === 'inherit' ) {
4398				return 'black';
4399			}
4400
4401			let hexColor, r, g, b, yiq;
4402
4403			const colorToHex = color => {
4404				let hex, rgb;
4405
4406				if( color.includes('#') ){
4407					hex = color.replace('#', '');
4408				} else {
4409					rgb = color.match(/\d+/g);
4410					hex = ('0' + parseInt(rgb[0], 10).toString(16)).slice(-2) + ('0' + parseInt(rgb[1], 10).toString(16)).slice(-2) + ('0' + parseInt(rgb[2], 10).toString(16)).slice(-2);
4411				}
4412
4413				if ( hex.length === 3 ) {
4414					hex = hex + hex;
4415				}
4416
4417				return hex;
4418			};
4419
4420			hexColor = colorToHex( backgroundColor );
4421
4422			r = parseInt( hexColor.substr( 0, 2), 16 );
4423			g = parseInt( hexColor.substr( 2, 2), 16 );
4424			b = parseInt( hexColor.substr( 4, 2), 16 );
4425			yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
4426
4427			return ( yiq >= 128 ) ? 'black' : 'white';
4428		},
4429
4430		dynamicShowHide(effect) {
4431			const _self = this;
4432
4433			// Remove Loading Overlay Data
4434			$('body').removeData('loadingOverlay');
4435
4436			// Remove Html Of Loading Overlay
4437			$('.loading-overlay').remove();
4438
4439			if( effect == '' ) {
4440				return this;
4441			}
4442
4443			// Initialize New Loading Overlay (second parameter is to NO inherit data-plugin-options)
4444			$('body').loadingOverlay({
4445				effect: effect ? effect : 'pulse',
4446				isDynamicHideShow: true
4447			}, true);
4448
4449			// Show Loading Overlay Loader
4450			$('body').data('loadingOverlay').show();
4451
4452			// Hide Loading Overlay Loader
4453			setTimeout(() => {
4454				$('body').data('loadingOverlay').hide();
4455			}, 3000);
4456
4457			return this;
4458		},
4459
4460		dynamicShowHideEvents() {
4461			const _self = this;
4462
4463			// Button
4464			$(document).off('click.loading-overlay-button').on('click.loading-overlay-button', '.loading-overlay-button', function(e){
4465				e.preventDefault();
4466
4467				_self.dynamicShowHide( $(this).data('effect') );
4468			});
4469
4470			// Select
4471			$(document).off('change.loading-overlay-select').on('change.loading-overlay-select', '.loading-overlay-select', function(){
4472				_self.dynamicShowHide( $(this).val() );
4473			});
4474
4475			return this;
4476		}
4477
4478	};
4479
4480    // expose to scope
4481    $.extend(theme, {
4482		LoadingOverlay
4483	});
4484
4485    // expose as a jquery plugin
4486    $.fn.loadingOverlay = function( opts, noInheritOptions ) {
4487		return this.each(function() {
4488			const $this = $( this );
4489
4490			const loadingOverlay = $this.data( 'loadingOverlay' );
4491			if ( loadingOverlay ) {
4492				return loadingOverlay;
4493			} else {
4494				const options = opts || $this.data( 'loading-overlay-options' ) || {};
4495				return new LoadingOverlay( $this, options, noInheritOptions );
4496			}
4497		});
4498	}
4499
4500    // auto init
4501    $('[data-loading-overlay]').loadingOverlay();
4502})).apply(this, [window.theme, jQuery]);
4503
4504// Masonry
4505(((theme = {}, $) => {
4506    const instanceName = '__masonry';
4507
4508    class PluginMasonry {
4509        constructor($el, opts) {
4510            return this.initialize($el, opts);
4511        }
4512
4513        initialize($el, opts) {
4514			if ($el.data(instanceName)) {
4515				return this;
4516			}
4517
4518			this.$el = $el;
4519
4520			this
4521				.setData()
4522				.setOptions(opts)
4523				.build();
4524
4525			return this;
4526		}
4527
4528        setData() {
4529			this.$el.data(instanceName, this);
4530
4531			return this;
4532		}
4533
4534        setOptions(opts) {
4535			this.options = $.extend(true, {}, PluginMasonry.defaults, opts, {
4536				wrapper: this.$el
4537			});
4538
4539			return this;
4540		}
4541
4542        build() {
4543			if (!($.isFunction($.fn.isotope))) {
4544				return this;
4545			}
4546
4547			const self = this, $window = $(window);
4548
4549			self.$loader = false;
4550
4551			if (self.options.wrapper.parents('.masonry-loader').get(0)) {
4552				self.$loader = self.options.wrapper.parents('.masonry-loader');
4553				self.createLoader();
4554			}
4555
4556			self.options.wrapper.one('layoutComplete', (event, laidOutItems) => {
4557				self.removeLoader();
4558			});
4559
4560			self.options.wrapper.waitForImages(() => {
4561				self.options.wrapper.isotope(self.options);	
4562			});
4563
4564			$(window).on('resize', () => {
4565				setTimeout(() => {
4566					self.options.wrapper.isotope('layout');
4567				}, 300);
4568			});
4569
4570			setTimeout(() => {
4571				self.removeLoader();
4572			}, 3000);
4573
4574			return this;
4575		}
4576
4577        createLoader() {
4578			const self = this;
4579
4580			const loaderTemplate = [
4581				'<div class="bounce-loader">',
4582					'<div class="bounce1"></div>',
4583					'<div class="bounce2"></div>',
4584					'<div class="bounce3"></div>',
4585				'</div>'
4586			].join('');
4587
4588			self.$loader.append(loaderTemplate);
4589
4590			return this;
4591		}
4592
4593        removeLoader() {
4594
4595			const self = this;
4596
4597			if (self.$loader) {
4598
4599				self.$loader.removeClass('masonry-loader-showing');
4600
4601				setTimeout(() => {
4602					self.$loader.addClass('masonry-loader-loaded');
4603				}, 300);
4604
4605			}
4606
4607		}
4608    }
4609
4610    PluginMasonry.defaults = {
4611
4612	};
4613
4614    // expose to scope
4615    $.extend(theme, {
4616		PluginMasonry
4617	});
4618
4619    // jquery plugin
4620    $.fn.themePluginMasonry = function(opts) {
4621		return this.map(function() {
4622			const $this = $(this);
4623
4624			if ($this.data(instanceName)) {
4625				return $this.data(instanceName);
4626			} else {
4627				return new PluginMasonry($this, opts);
4628			}
4629
4630		});
4631	}
4632})).apply(this, [window.theme, jQuery]);
4633
4634// Match Height
4635(((theme = {}, $) => {
4636    const instanceName = '__matchHeight';
4637
4638    class PluginMatchHeight {
4639        constructor($el, opts) {
4640            return this.initialize($el, opts);
4641        }
4642
4643        initialize($el, opts) {
4644			if ($el.data(instanceName)) {
4645				return this;
4646			}
4647
4648			this.$el = $el;
4649
4650			this
4651				.setData()
4652				.setOptions(opts)
4653				.build();
4654
4655			return this;
4656		}
4657
4658        setData() {
4659			this.$el.data(instanceName, this);
4660
4661			return this;
4662		}
4663
4664        setOptions(opts) {
4665			this.options = $.extend(true, {}, PluginMatchHeight.defaults, opts, {
4666				wrapper: this.$el
4667			});
4668
4669			return this;
4670		}
4671
4672        build() {
4673			if (!($.isFunction($.fn.matchHeight))) {
4674				return this;
4675			}
4676
4677			const self = this;
4678
4679			self.options.wrapper.matchHeight(self.options);
4680
4681			return this;
4682		}
4683    }
4684
4685    PluginMatchHeight.defaults = {
4686		byRow: true,
4687		property: 'height',
4688		target: null,
4689		remove: false
4690	};
4691
4692    // expose to scope
4693    $.extend(theme, {
4694		PluginMatchHeight
4695	});
4696
4697    // jquery plugin
4698    $.fn.themePluginMatchHeight = function(opts) {
4699		return this.map(function() {
4700			const $this = $(this);
4701
4702			if ($this.data(instanceName)) {
4703				return $this.data(instanceName);
4704			} else {
4705				return new PluginMatchHeight($this, opts);
4706			}
4707
4708		});
4709	}
4710})).apply(this, [window.theme, jQuery]);
4711
4712// Parallax
4713(((theme = {}, $) => {
4714    const instanceName = '__parallax';
4715
4716    class PluginParallax {
4717        constructor($el, opts) {
4718            return this.initialize($el, opts);
4719        }
4720
4721        initialize($el, opts) {
4722			if ($el.data(instanceName)) {
4723				return this;
4724			}
4725
4726			this.$el = $el;
4727
4728			this
4729				.setData()
4730				.setOptions(opts)
4731				.build();
4732
4733			return this;
4734		}
4735
4736        setData() {
4737			this.$el.data(instanceName, this);
4738
4739			return this;
4740		}
4741
4742        setOptions(opts) {
4743			this.options = $.extend(true, {}, PluginParallax.defaults, opts, {
4744				wrapper: this.$el
4745			});
4746
4747			return this;
4748		}
4749
4750        build() {
4751            const self = this;
4752            const $window = $(window);
4753            let offset;
4754            let yPos;
4755            let plxPos;
4756            let background;
4757            let rotateY;
4758
4759            // Mouse Parallax
4760            if( self.options.mouseParallax ) {
4761
4762				$window.mousemove(({clientX, clientY}) => {
4763
4764					$('.parallax-mouse-object', self.options.wrapper).each(function() {
4765
4766				        const moving_value = $( this ).attr('data-value');
4767				        const x = (clientX * moving_value) / 250;
4768				        const y = (clientY * moving_value) / 250;
4769
4770				        $( this ).css('transform', 'translateX(' + x + 'px) translateY(' + y + 'px)');
4771				    });
4772
4773				});
4774
4775				return this;
4776
4777			}
4778
4779            // Scrollable
4780            if( self.options.scrollableParallax && $(window).width() > self.options.scrollableParallaxMinWidth ) {
4781				const $scrollableWrapper = self.options.wrapper.find('.scrollable-parallax-wrapper');
4782
4783				if( $scrollableWrapper.get(0) ) {
4784                    let progress 	 = ( $(window).scrollTop() > ( self.options.wrapper.offset().top + $(window).outerHeight() ) ) ? self.options.cssValueEnd : self.options.cssValueStart;
4785                    const cssValueUnit = self.options.cssValueUnit ? self.options.cssValueUnit : '';
4786
4787                    $scrollableWrapper.css({
4788						'background-image' : 'url(' + self.options.wrapper.data('image-src') + ')',
4789						'background-size' : 'cover',
4790						'background-position' : 'center',
4791						'background-attachment' : 'fixed',
4792						'transition' : 'ease '+ self.options.cssProperty +' '+ self.options.transitionDuration,
4793						'width' : progress + '%'
4794					});
4795
4796                    $(window).on('scroll', e => {
4797						if( self.options.wrapper.visible( true ) ) {
4798							const $window = $(window), scrollTop = $window.scrollTop(), elementOffset = self.options.wrapper.offset().top, currentElementOffset = (elementOffset - scrollTop);
4799
4800						   	const scrollPercent = Math.abs( +( currentElementOffset - $window.height() ) / (self.options.startOffset ? self.options.startOffset : 7) );
4801						 	
4802						 	// Increment progress value according scroll position
4803						 	if( scrollPercent <= self.options.cssValueEnd && progress <= self.options.cssValueEnd ) {
4804						 		progress = self.options.cssValueStart + scrollPercent;
4805						 	}
4806
4807						 	// Adjust CSS end value
4808						 	if( progress > self.options.cssValueEnd ) {
4809						 		progress = self.options.cssValueEnd;
4810						 	}
4811
4812						 	// Adjust CSS start value
4813						 	if( progress < self.options.cssValueStart ) {
4814						 		progress = self.options.cssValueStart;
4815						 	}
4816
4817						 	const styles = {};
4818						 	styles[self.options.cssProperty] = progress + cssValueUnit;
4819
4820							$scrollableWrapper.css(styles);
4821						}
4822					});
4823                }
4824
4825				return;
4826			}
4827
4828            // Create Parallax Element
4829            if( self.options.fadeIn ) {
4830				background = $('<div class="parallax-background fadeIn animated"></div>');
4831			} else {
4832				background = $('<div class="parallax-background"></div>');
4833			}
4834
4835            // Set Style for Parallax Element
4836            background.css({
4837				'background-image' : 'url(' + self.options.wrapper.data('image-src') + ')',
4838				'background-size' : 'cover',
4839				'position' : 'absolute',
4840				'top' : 0,
4841				'left' : 0,
4842				'width' : '100%',
4843				'height' : self.options.parallaxHeight
4844			});
4845
4846            if( self.options.parallaxScale ) {
4847				background.css({
4848					'transition' : 'transform 500ms ease-out'
4849				});
4850			}
4851
4852            // Add Parallax Element on DOM
4853            self.options.wrapper.prepend(background);
4854
4855            // Set Overlfow Hidden and Position Relative to Parallax Wrapper
4856            self.options.wrapper.css({
4857				'position' : 'relative',
4858				'overflow' : 'hidden'
4859			});
4860
4861            // Parallax Effect on Scroll & Resize
4862            const parallaxEffectOnScrolResize = () => {
4863				$window.on('scroll resize', () => {
4864					offset  = self.options.wrapper.offset();
4865					yPos    = -($window.scrollTop() - (offset.top - 100)) / ((self.options.speed + 2 ));
4866					plxPos  = (yPos < 0) ? Math.abs(yPos) : -Math.abs(yPos);
4867					rotateY = ( $('html[dir="rtl"]').get(0) ) ? ' rotateY(180deg)' : ''; // RTL
4868					
4869					offset  = self.options.wrapper.offset();
4870					yPos    = -($window.scrollTop() - (offset.top - 100)) / ((self.options.speed + 2 ));
4871					plxPos  = (yPos < 0) ? Math.abs(yPos) : -Math.abs(yPos);
4872					rotateY = ( $('html[dir="rtl"]').get(0) ) ? ' rotateY(180deg)' : ''; // RTL
4873
4874					if( !self.options.parallaxScale ) {
4875
4876						if( self.options.parallaxDirection == 'bottom' ) {
4877							self.options.offset = 250;
4878						}
4879
4880						let y = ( (plxPos - 50) + (self.options.offset) );
4881						if( self.options.parallaxDirection == 'bottom' ) {
4882							y = ( y < 0 ) ? Math.abs( y ) : -Math.abs( y );
4883						}
4884
4885						background.css({
4886							'transform' : 'translate3d(0, '+ y +'px, 0)' + rotateY,
4887							'background-position-x' : self.options.horizontalPosition
4888						});
4889
4890					} else {
4891                        const scrollTop = $window.scrollTop();
4892                        const elementOffset = self.options.wrapper.offset().top;
4893                        const currentElementOffset = (elementOffset - scrollTop);
4894                        let scrollPercent = Math.abs( +( currentElementOffset - $window.height() ) / (self.options.startOffset ? self.options.startOffset : 7) );
4895
4896                        scrollPercent = parseInt((scrollPercent >= 100) ? 100 : scrollPercent);
4897
4898                        const currentScale = (scrollPercent / 100) * 50;
4899
4900                        if ( !self.options.parallaxScaleInvert ) {
4901							background.css({
4902								'transform' : 'scale(1.' + String(currentScale).padStart(2, '0') + ', 1.' + String(currentScale).padStart(2, '0') + ')'
4903							});
4904						} else {
4905							background.css({
4906								'transform' : 'scale(1.' + String(50 - currentScale).padStart(2, '0') + ', 1.' + String(50 - currentScale).padStart(2, '0') + ')'
4907							});
4908						}
4909                    }
4910				});
4911
4912				$window.trigger('scroll');
4913			};
4914
4915            if (!$.browser.mobile) {
4916				parallaxEffectOnScrolResize();
4917			} else {
4918				if( self.options.enableOnMobile == true ) {
4919					parallaxEffectOnScrolResize();
4920				} else {
4921					self.options.wrapper.addClass('parallax-disabled');
4922				}
4923			}
4924
4925            return this;
4926        }
4927    }
4928
4929    PluginParallax.defaults = {
4930		speed: 1.5,
4931		horizontalPosition: '50%',
4932		offset: 0,
4933		parallaxDirection: 'top',
4934		parallaxHeight: '180%',
4935		parallaxScale: false,
4936		parallaxScaleInvert: false,
4937		scrollableParallax: false,
4938		scrollableParallaxMinWidth: 991,
4939		startOffset: 7,
4940		transitionDuration: '200ms',
4941		cssProperty: 'width',
4942		cssValueStart: 40,
4943		cssValueEnd: 100,
4944		cssValueUnit: 'vw',
4945		mouseParallax: false,
4946		enableOnMobile: true
4947	};
4948
4949    // expose to scope
4950    $.extend(theme, {
4951		PluginParallax
4952	});
4953
4954    // jquery plugin
4955    $.fn.themePluginParallax = function(opts) {
4956		return this.map(function() {
4957			const $this = $(this);
4958
4959			if ($this.data(instanceName)) {
4960				return $this.data(instanceName);
4961			} else {
4962				return new PluginParallax($this, opts);
4963			}
4964
4965		});
4966	}
4967})).apply(this, [window.theme, jQuery]);
4968
4969// Progress Bar
4970(((theme = {}, $) => {
4971    const instanceName = '__progressBar';
4972
4973    class PluginProgressBar {
4974        constructor($el, opts) {
4975            return this.initialize($el, opts);
4976        }
4977
4978        initialize($el, opts) {
4979			if ($el.data(instanceName)) {
4980				return this;
4981			}
4982
4983			this.$el = $el;
4984
4985			this
4986				.setData()
4987				.setOptions(opts)
4988				.build();
4989
4990			return this;
4991		}
4992
4993        setData() {
4994			this.$el.data(instanceName, this);
4995
4996			return this;
4997		}
4998
4999        setOptions(opts) {
5000			this.options = $.extend(true, {}, PluginProgressBar.defaults, opts, {
5001				wrapper: this.$el
5002			});
5003
5004			return this;
5005		}
5006
5007        build() {
5008            const self = this;
5009            const $el = this.options.wrapper;
5010            let delay = 1;
5011
5012            delay = ($el.attr('data-appear-animation-delay') ? $el.attr('data-appear-animation-delay') : self.options.delay);
5013
5014            $el.addClass($el.attr('data-appear-animation'));
5015
5016            setTimeout(() => {
5017
5018				$el.animate({
5019					width: $el.attr('data-appear-progress-animation')
5020				}, 1500, 'easeOutQuad', () => {
5021					$el.find('.progress-bar-tooltip').animate({
5022						opacity: 1
5023					}, 500, 'easeOutQuad');
5024				});
5025
5026			}, delay);
5027
5028            return this;
5029        }
5030    }
5031
5032    PluginProgressBar.defaults = {
5033		accX: 0,
5034		accY: -50,
5035		delay: 1
5036	};
5037
5038    // expose to scope
5039    $.extend(theme, {
5040		PluginProgressBar
5041	});
5042
5043    // jquery plugin
5044    $.fn.themePluginProgressBar = function(opts) {
5045		return this.map(function() {
5046			const $this = $(this);
5047
5048			if ($this.data(instanceName)) {
5049				return $this.data(instanceName);
5050			} else {
5051				return new PluginProgressBar($this, opts);
5052			}
5053
5054		});
5055	}
5056})).apply(this, [window.theme, jQuery]);
5057
5058// Random Images
5059(((theme = {}, $) => {
5060    const instanceName = '__randomimages';
5061
5062    class PluginRandomImages {
5063        constructor($el, opts) {
5064            return this.initialize($el, opts);
5065        }
5066
5067        initialize($el, opts) {
5068			this.$el = $el;
5069            this.st = '';
5070			this.times = 0;
5071			this.perImageIndex = 0;
5072
5073            if( $el.is('img') && typeof opts.imagesListURL == 'undefined' ) {
5074                return false;
5075            }
5076
5077            this
5078				.setData()
5079				.setOptions(opts)
5080				.build();
5081
5082			return this;
5083		}
5084
5085        setData() {
5086			this.$el.data(instanceName, this);
5087
5088			return this;
5089		}
5090
5091        setOptions(opts) {
5092			this.options = $.extend(true, {}, PluginRandomImages.defaults, opts, {
5093				wrapper: this.$el
5094			});
5095
5096			return this;
5097		}
5098
5099        build() {
5100            const self = this;
5101			
5102			// Control the screens size we want to have the plugin working
5103			if( $(window).width() < self.options.minWindowWidth  ) {
5104				return false;
5105			}
5106
5107			// Check if is single image or wrapper with images inside
5108            if( self.$el.is('img') ) {
5109				
5110				// Check it's inside a lightbox
5111				self.isInsideLightbox = self.$el.closest('.lightbox').length ? true : false;
5112
5113				// Push the initial image to lightbox list/array
5114				if( self.isInsideLightbox && self.options.lightboxImagesListURL ) {
5115					self.options.lightboxImagesListURL.push( self.$el.closest('.lightbox').attr('href') );
5116				}
5117	
5118				// Push the current image src to the array
5119				self.options.imagesListURL.push( self.$el.attr('src') );
5120
5121				// Start with lastIndex as the first image loaded on the page
5122				self.lastIndex = self.options.imagesListURL.length - 1;
5123
5124				// Identify the last random image element (if has more than one on the page)
5125				if( self.options.random == false ) {
5126					$('.plugin-random-images').each(function(i){
5127						if( i == $('.plugin-random-images').length - 1 ) {
5128							$(this).addClass('the-last');
5129						}
5130					});
5131				}
5132
5133				// Start the recursive timeout
5134				setTimeout(() => {
5135					self.recursiveTimeout( 
5136						self.perImageTag, 
5137						self.options.delay == null ? 3000 : self.options.delay
5138					);
5139				}, self.options.delay == null ? 300 : self.options.delay / 3);
5140
5141			} else {
5142				
5143				// Start the recursive timeout
5144				setTimeout( self.recursiveTimeout( 
5145					self.perWrapper, 
5146					self.options.delay ? self.options.delay : getPerWrapperHighDelay(), 
5147					false 
5148				), 300);
5149
5150			}
5151
5152			// Stop After Few Seconds
5153			if( self.options.stopAfterFewSeconds ) {
5154				setTimeout(() => {
5155					clearTimeout(self.st);
5156				}, self.options.stopAfterFewSeconds);
5157			}
5158			
5159			return this;
5160
5161		}
5162
5163        perImageTag() {
5164			const self = this;
5165
5166			// Generate a random index to make the images rotate randomly
5167			let index = self.options.random ? Math.floor(Math.random() * self.options.imagesListURL.length) : self.lastIndex;
5168
5169			// Avoid repeat the same image
5170			if( self.lastIndex !== '' && self.lastIndex == index ) {
5171				if( self.options.random ) {
5172					while( index == self.lastIndex ) {
5173						index = Math.floor(Math.random() * self.options.imagesListURL.length);
5174					}
5175				} else {
5176					index = index - 1;
5177					if( index == -1 ) {
5178						index = self.options.imagesListURL.length - 1;
5179					}
5180				}
5181			}
5182
5183			// Turn the image ready for animations
5184			self.$el.addClass('animated');
5185
5186			// Remove the entrance animation class and add the out animation class
5187			self.$el.removeClass( self.options.animateIn ).addClass( self.options.animateOut );
5188			
5189			// Change the image src and add the class for entrance animation
5190			setTimeout( () => {
5191				self.$el.attr('src', self.options.imagesListURL[index]).removeClass( self.options.animateOut ).addClass(self.options.animateIn);
5192
5193				if( self.isInsideLightbox && self.options.lightboxImagesListURL ) {
5194					self.$el.closest('.lightbox').attr('href', self.options.lightboxImagesListURL[index]);
5195				}
5196			}, 1000);
5197			
5198			// Save the last index for future checks
5199			self.lastIndex = index;
5200			
5201			// Increment the times var
5202			self.times++;
5203
5204			// Save the index for stopAtImageIndex option
5205			self.perImageIndex = index;
5206
5207			return this;
5208		}
5209
5210        // Iterate the imaes loop and get the higher value
5211        getPerWrapperHighDelay() {
5212            const self = this;
5213            const $wrapper = self.$el;
5214            let delay = 0;
5215
5216            $wrapper.find('img').each(function(){
5217				const $image = $(this);
5218				
5219				if( $image.data('rimage-delay') && parseInt( $image.data('rimage-delay') ) > delay ) {
5220					delay = parseInt( $image.data('rimage-delay') );
5221				}
5222			});
5223
5224            return delay;
5225        }
5226
5227        perWrapper() {
5228			const self = this, $wrapper = self.$el;
5229
5230			// Turns the imageLlistURL into an array
5231			self.options.imagesListURL = [];
5232
5233			// Find all images inside the element wrapper and push their sources to image list array
5234			$wrapper.find('img').each(function(){
5235				const $image = $(this);
5236				self.options.imagesListURL.push( $image.attr('src') ); 
5237			});
5238
5239			// Shuffle the images list array (random effect)
5240			self.options.imagesListURL = self.shuffle( self.options.imagesListURL );
5241
5242			// Iterate over each image and make some checks like delay for each image, animations, etc...
5243			$wrapper.find('img').each(function(index){
5244				const $image = $(this), animateIn  = $image.data('rimage-animate-in') ? $image.data('rimage-animate-in') : self.options.animateIn, animateOut = $image.data('rimage-animate-out') ? $image.data('rimage-animate-out') : self.options.animateOut, delay      = $image.data('rimage-delay') ? $image.data('rimage-delay') : 2000;
5245
5246				$image.addClass('animated');
5247
5248				setTimeout( () => {
5249					$image.removeClass( animateIn ).addClass( animateOut );
5250				}, delay / 2);
5251
5252				setTimeout( () => {
5253					$image.attr('src', self.options.imagesListURL[index]).removeClass( animateOut ).addClass(animateIn);
5254				}, delay);
5255
5256			});
5257			
5258			// Increment the times variable
5259			self.times++;
5260
5261			return this;
5262		}
5263
5264        recursiveTimeout(callback, delay) {
5265			const self = this;
5266
5267			const timeout = () => {
5268
5269				if( callback !== null ) {
5270					callback.call(self);
5271				}
5272
5273				// Recursive
5274				self.st = setTimeout(timeout, delay == null ? 1000 : delay);
5275
5276				if( self.options.random == false ) {
5277					if( self.$el.hasClass('the-last') ) {
5278						$('.plugin-random-images').trigger('rimages.start');
5279					} else {
5280						clearTimeout(self.st);
5281					}
5282				}
5283
5284				// Stop At Image Index
5285				if( self.options.stopAtImageIndex && parseInt(self.options.stopAtImageIndex) == self.perImageIndex ) {
5286					clearTimeout(self.st);
5287				}
5288
5289				// Stop After X Timers
5290				if( self.options.stopAfterXTimes == self.times ) {
5291					clearTimeout(self.st);
5292				}
5293			};
5294			timeout();
5295
5296			self.$el.on('rimages.start', () => {
5297				clearTimeout(self.st);
5298				self.st = setTimeout(timeout, delay == null ? 1000 : delay);
5299			});
5300
5301		}
5302
5303        shuffle(array) {
5304			for (let i = array.length - 1; i > 0; i--) {
5305				const j = Math.floor(Math.random() * (i + 1));
5306				const temp = array[i];
5307				array[i] = array[j];
5308				array[j] = temp;
5309			}
5310
5311			return array;
5312		}
5313    }
5314
5315    PluginRandomImages.defaults = {
5316		minWindowWidth: 0,
5317		random: true,
5318		imagesListURL: null,
5319		lightboxImagesListURL: null,
5320        delay: null,
5321        animateIn: 'fadeIn',
5322		animateOut: 'fadeOut',
5323		stopAtImageIndex: false, // The value shoudl be the index value of array with images as string. Eg: '2' 
5324		stopAfterFewSeconds: false, // The value should be in mili-seconds. Eg: 10000 = 10 seconds
5325		stopAfterXTimes: false,
5326		accY: 0
5327	};
5328
5329    // expose to scope
5330    $.extend(theme, {
5331		PluginRandomImages
5332	});
5333
5334    // jquery plugin
5335    $.fn.themePluginRandomImages = function(opts) {
5336		return this.map(function() {
5337			const $this = $(this);
5338
5339			if ($this.data(instanceName)) {
5340				return $this.data(instanceName);
5341			} else {
5342				return new PluginRandomImages($this, opts);
5343			}
5344
5345		});
5346	}
5347})).apply(this, [window.theme, jQuery]);
5348
5349// Read More
5350(((theme = {}, $) => {
5351    const instanceName = '__readmore';
5352
5353    class PluginReadMore {
5354        constructor($el, opts) {
5355            return this.initialize($el, opts);
5356        }
5357
5358        initialize($el, opts) {
5359			const self = this;
5360
5361			this.$el = $el;
5362
5363			this
5364				.setData()
5365				.setOptions(opts)
5366				.build()
5367				.events();
5368
5369			if( self.options.startOpened ) {
5370				self.options.wrapper.find('.readmore-button-wrapper > a').trigger('click');
5371			}
5372
5373			return this;
5374		}
5375
5376        setData() {
5377			this.$el.data(instanceName, this);
5378
5379			return this;
5380		}
5381
5382        setOptions(opts) {
5383			this.options = $.extend(true, {}, PluginReadMore.defaults, opts, {
5384				wrapper: this.$el
5385			});
5386
5387			return this;
5388		}
5389
5390        build() {
5391			const self = this;
5392
5393			self.options.wrapper.addClass('position-relative');
5394
5395			// Overlay
5396			self.options.wrapper.append( '<div class="readmore-overlay"></div>' );
5397
5398			// Check if is Safari
5399			let backgroundCssValue = 'linear-gradient(180deg, rgba(2, 0, 36, 0) 0%, '+ self.options.overlayColor +' 100%)';
5400			if( $('html').hasClass('safari') ) {
5401				backgroundCssValue = '-webkit-linear-gradient(top, rgba(2, 0, 36, 0) 0%, '+ self.options.overlayColor +' 100%)'
5402			}
5403			
5404			self.options.wrapper.find('.readmore-overlay').css({
5405				background: backgroundCssValue,
5406				position: 'absolute',
5407				bottom: 0,
5408				left: 0,
5409				width: '100%',
5410				height: self.options.overlayHeight,
5411				'z-index': 1
5412			});
5413
5414			// Read More Button
5415			self.options.wrapper.find('.readmore-button-wrapper').removeClass('d-none').css({
5416				position: 'absolute',
5417				bottom: 0,
5418				left: 0,
5419				width: '100%',
5420				'z-index': 2
5421			});	
5422
5423			// Button Label
5424			self.options.wrapper.find('.readmore-button-wrapper > a').html( self.options.buttonOpenLabel );
5425
5426			self.options.wrapper.css({
5427				'height': self.options.maxHeight,
5428				'overflow-y': 'hidden'
5429			});
5430
5431			// Alignment
5432			switch ( self.options.align ) {
5433				case 'center':
5434					self.options.wrapper.find('.readmore-button-wrapper').addClass('text-center');
5435					break;
5436
5437				case 'end':
5438					self.options.wrapper.find('.readmore-button-wrapper').addClass('text-end');
5439					break;
5440
5441				case 'start':
5442				default:
5443					self.options.wrapper.find('.readmore-button-wrapper').addClass('text-start');
5444					break;
5445			}
5446
5447			return this;
5448
5449		}
5450
5451        events() {
5452			const self = this;
5453
5454			// Read More
5455			self.readMore = () => {
5456				self.options.wrapper.find('.readmore-button-wrapper > a:not(.readless)').on('click', function(e){
5457					e.preventDefault();
5458
5459					const $this = $(this);
5460
5461					setTimeout(() => {
5462						self.options.wrapper.animate({
5463							'height': self.options.wrapper[0].scrollHeight
5464						}, () => {
5465							if( !self.options.enableToggle ) {
5466								$this.fadeOut();
5467							}
5468
5469							$this.html( self.options.buttonCloseLabel ).addClass('readless').off('click');
5470
5471							self.readLess();
5472
5473							self.options.wrapper.find('.readmore-overlay').fadeOut();
5474							self.options.wrapper.css({
5475								'max-height': 'none',
5476								'overflow': 'visible'
5477							});
5478
5479							self.options.wrapper.find('.readmore-button-wrapper').animate({
5480								bottom: -20
5481							});
5482						});
5483					}, 200);
5484				});
5485			}
5486
5487			// Read Less
5488			self.readLess = () => {
5489				self.options.wrapper.find('.readmore-button-wrapper > a.readless').on('click', function(e){
5490					e.preventDefault();
5491
5492					const $this = $(this);
5493
5494					// Button
5495					self.options.wrapper.find('.readmore-button-wrapper').animate({
5496						bottom: 0
5497					});
5498
5499					// Overlay
5500					self.options.wrapper.find('.readmore-overlay').fadeIn();
5501
5502					setTimeout(() => {
5503						self.options.wrapper.height(self.options.wrapper[0].scrollHeight).animate({
5504							'height': self.options.maxHeight
5505						}, () => {
5506							$this.html( self.options.buttonOpenLabel ).removeClass('readless').off('click');
5507
5508							self.readMore();
5509
5510							self.options.wrapper.css({
5511								'overflow': 'hidden'
5512							});
5513						});
5514					}, 200);
5515				});
5516			}
5517
5518			// First Load
5519			self.readMore();
5520
5521			return this;
5522		}
5523    }
5524
5525    PluginReadMore.defaults = {
5526		buttonOpenLabel: 'Read More <i class="fas fa-chevron-down text-2 ms-1"></i>',
5527		buttonCloseLabel: 'Read Less <i class="fas fa-chevron-up text-2 ms-1"></i>',
5528		enableToggle: true,
5529		maxHeight: 110,
5530		overlayColor: '#FFF',
5531		overlayHeight: 100,
5532		startOpened: false,
5533		align: 'left'
5534	};
5535
5536    // expose to scope
5537    $.extend(theme, {
5538		PluginReadMore
5539	});
5540
5541    // jquery plugin
5542    $.fn.themePluginReadMore = function(opts) {
5543		return this.map(function() {
5544			const $this = $(this);
5545
5546			if ($this.data(instanceName)) {
5547				return $this.data(instanceName);
5548			} else {
5549				return new PluginReadMore($this, opts);
5550			}
5551
5552		});
5553	}
5554})).apply(this, [window.theme, jQuery]);
5555
5556// Revolution Slider
5557(((theme = {}, $) => {
5558    const instanceName = '__revolution';
5559
5560    class PluginRevolutionSlider {
5561        constructor($el, opts) {
5562            return this.initialize($el, opts);
5563        }
5564
5565        initialize($el, opts) {
5566			if ($el.data(instanceName)) {
5567				return this;
5568			}
5569
5570			this.$el = $el;
5571
5572			this
5573				.setData()
5574				.setOptions(opts)
5575				.build()
5576				.events();
5577
5578			return this;
5579		}
5580
5581        setData() {
5582			this.$el.data(instanceName, this);
5583
5584			return this;
5585		}
5586
5587        setOptions(opts) {
5588			this.options = $.extend(true, {}, PluginRevolutionSlider.defaults, opts, {
5589				wrapper: this.$el
5590			});
5591
5592			return this;
5593		}
5594
5595        build() {
5596			if (!($.isFunction($.fn.revolution))) {
5597				return this;
5598			}
5599
5600			// Single Slider Class
5601			if(this.options.wrapper.find('> ul > li').length == 1) {
5602				this.options.wrapper.addClass('slider-single-slide');
5603
5604				// Remove Bullets
5605				// this.options.navigation.bullets.enable = false;
5606				$.extend(this.options.navigation, {
5607					bullets: {
5608						enable: false
5609					}
5610				});
5611
5612			}
5613
5614			// Full Screen Class
5615			if(this.options.sliderLayout == 'fullscreen') {
5616				this.options.wrapper.closest('.slider-container').addClass('fullscreen-slider');
5617			}
5618			
5619			// Initialize Revolution Slider
5620			this.options.wrapper.revolution(this.options);
5621
5622			// Addon Init - Typewriter
5623			if(this.options.addOnTypewriter.enable) {
5624				RsTypewriterAddOn($, this.options.wrapper);
5625			}
5626
5627			// Addon Init - Whiteboard
5628			if(this.options.addOnWhiteboard.enable) {
5629				this.options.wrapper.rsWhiteBoard();
5630			}
5631
5632			// Addon Init - Particles
5633			if(this.options.addOnParticles.enable) {
5634				RsParticlesAddOn(this.options.wrapper);
5635			}
5636
5637			// Addon Init - Countdown
5638			if(this.options.addOnCountdown.enable) {
5639				tp_countdown(this.options.wrapper, this.options.addOnCountdown.targetdate, this.options.addOnCountdown.slidechanges);
5640			}
5641
5642			// Addon Init - Slicey
5643			if(this.options.addOnSlicey.enable) {
5644				this.options.wrapper.revSliderSlicey();
5645			}
5646
5647			// Addon Init - Filmstrip
5648			if(this.options.addOnFilmstrip.enable) {
5649				RsFilmstripAddOn($, this.options.wrapper, '../vendor/rs-plugin/revolution-addons/filmstrip/', false);
5650			}
5651
5652			// Addon Init - Before After
5653			if(this.options.addOnBeforeAfter.enable) {
5654				RevSliderBeforeAfter($, this.options.wrapper, this.options.addOnBeforeAfter.options);
5655			}
5656
5657			// Addon Init - Panorama
5658			if(this.options.addOnPanorama.enable) {
5659				RsAddonPanorama($, this.options.wrapper);
5660			}
5661
5662			// Addon Init - Revealer
5663			if(this.options.addOnRevealer.enable) {
5664				RsRevealerAddOn($, this.options.wrapper, this.options.revealer.spinnerHtml);
5665			}
5666
5667			// Addon Init - Duotone
5668			if(this.options.addOnDuotone.enable) {
5669				RsAddonDuotone($, this.options.wrapper, true, "cubic-bezier(0.645, 0.045, 0.355, 1.000)", "1000");
5670			}
5671
5672			// Addon Init - Bubblemorph
5673			if(this.options.addOnBubblemorph.enable) {
5674				BubbleMorphAddOn($, this.options.wrapper, false);
5675			}
5676
5677			// Addon Init - Distortion
5678			if(this.options.addOnDistortion.enable) {
5679				RsLiquideffectAddOn($, this.options.wrapper);
5680			}
5681
5682			return this;
5683		}
5684
5685        events() {
5686
5687			return this;
5688		}
5689    }
5690
5691    PluginRevolutionSlider.defaults = {
5692		sliderType: 'standard',
5693		sliderLayout: 'fullwidth',
5694		delay: 9000,
5695		gridwidth: 1170,
5696		gridheight: 500,
5697		spinner: 'spinner3',
5698		disableProgressBar: 'on',
5699		parallax: {
5700			type: 'off',
5701			bgparallax: 'off'
5702		},
5703		navigation: {
5704			keyboardNavigation: 'off',
5705			keyboard_direction: 'horizontal',
5706			mouseScrollNavigation: 'off',
5707			onHoverStop: 'off',
5708			touch: {
5709				touchenabled: 'on',
5710				swipe_threshold: 75,
5711				swipe_min_touches: 1,
5712				swipe_direction: 'horizontal',
5713				drag_block_vertical: false
5714			},
5715			arrows: {
5716				enable: true,
5717				hide_onmobile: false,
5718				hide_under: 0,
5719				hide_onleave: true,
5720				hide_delay: 200,
5721				hide_delay_mobile: 1200,
5722				left: {
5723					h_align: 'left',
5724					v_align: 'center',
5725					h_offset: 30,
5726					v_offset: 0
5727				},
5728				right: {
5729					h_align: 'right',
5730					v_align: 'center',
5731					h_offset: 30,
5732					v_offset: 0
5733				}
5734			}
5735		},
5736
5737		/* ADDONS */
5738	    addOnTypewriter: {
5739			enable: false
5740		},
5741		addOnWhiteboard: {
5742			enable: false,
5743
5744		},
5745	    whiteboard: {
5746	        movehand: {
5747	            src: '../vendor/rs-plugin/revolution-addons/whiteboard/assets/images/hand_point_right.png',
5748	            width: 400,
5749	            height: 1000,
5750	            handtype: 'right',
5751	            transform: {
5752	                transformX: 50,
5753	                transformY: 50
5754	            },
5755	            jittering: {
5756	                distance: '80',
5757	                distance_horizontal: '100',
5758	                repeat: '5',
5759	                offset: '10',
5760	                offset_horizontal: '0'
5761	            },
5762	            rotation: {
5763	                angle: '10',
5764	                repeat: '3'
5765	            }
5766	        },
5767	        writehand: {
5768	            src: '../vendor/rs-plugin/revolution-addons/whiteboard/assets/images/write_right_angle.png',
5769	            width: 572,
5770	            height: 691,
5771	            handtype: 'right',
5772	            transform: {
5773	                transformX: 50,
5774	                transformY: 50
5775	            },
5776	            jittering: {
5777	                distance: '80',
5778	                distance_horizontal: '100',
5779	                repeat: '5',
5780	                offset: '10',
5781	                offset_horizontal: '0'
5782	            },
5783	            rotation:{
5784	                angle: '10',
5785	                repeat: '3'
5786	            }
5787	        }
5788	    },
5789	    addOnParticles: {
5790	    	enable: false
5791	    },
5792	    particles: {
5793			startSlide: "first", 
5794			endSlide: "last", 
5795			zIndex: "1",
5796			particles: {
5797				number: {value: 80}, color: {value: "#ffffff"},
5798				shape: {
5799					type: "circle", stroke: {width: 0, color: "#ffffff", opacity: 1},
5800					image: {src: ""}
5801				},
5802				opacity: {value: 0.5, random: true, min: 0.25, anim: {enable: false, speed: 3, opacity_min: 0, sync: false}},
5803				size: {value: 2, random: false, min: 30, anim: {enable: false, speed: 40, size_min: 1, sync: false}},
5804				line_linked: {enable: true, distance: 150, color: "#ffffff", opacity: 0.4, width: 1},
5805				move: {enable: true, speed: 6, direction: "none", random: true, min_speed: 6, straight: false, out_mode: "out"}
5806			},
5807			interactivity: {
5808				events: {onhover: {enable: false, mode: "repulse"}, onclick: {enable: false, mode: "repulse"}},
5809				modes: {grab: {distance: 400, line_linked: {opacity: 0.5}}, bubble: {distance: 400, size: 40, opacity: 0.4}, repulse: {distance: 200}}
5810			}
5811		},
5812		addOnCountdown: {
5813			enable: false,
5814			targetdate: new Date().getTime() + 864000000, // http://www.freeformatter.com/epoch-timestamp-to-date-converter.html
5815			slidechanges: [{days: 0, hours: 0, minutes: 0, seconds: 0, slide: 2}]
5816		},
5817		addOnSlicey: {
5818			enable: false
5819		},
5820		addOnFilmstrip: {
5821			enable: false
5822		},
5823		addOnBeforeAfter : {
5824			enable: false,
5825			options: {
5826				cursor: "move",
5827			    carousel: false,
5828			    arrowStyles: {
5829			        leftIcon: "fa-icon-caret-left",
5830			        rightIcon: "fa-icon-caret-right",
5831			        topIcon: "fa-icon-caret-up",
5832			        bottomIcon: "fa-icon-caret-down",
5833			        size: "35",
5834			        color: "#ffffff",
5835			        spacing: "10",
5836			        bgColor: "transparent",
5837			        padding: "0",
5838			        borderRadius: "0"
5839			    },
5840			    dividerStyles: {
5841			        width: "1",
5842			        color: "rgba(255, 255, 255, 0.5)"
5843			    }
5844			}
5845		},
5846		addOnPanorama: {
5847			enable: false
5848		},
5849		addOnRevealer: {
5850			enable: false,
5851		},
5852		revealer: {
5853			direction: "open_horizontal",
5854			color: "#ffffff",
5855			duration: "1500",
5856			delay: "0",
5857			easing: "Power2.easeInOut",
5858			overlay_enabled: true,
5859			overlay_color: "#000000",
5860			overlay_duration: "1500",
5861			overlay_delay: "0",
5862			overlay_easing: "Power2.easeInOut",
5863			spinner: "1",
5864			spinnerColor: "#006dd2",
5865			spinnerHtml: "<div class='rsaddon-revealer-spinner rsaddon-revealer-spinner-1'><div class='rsaddon-revealer-1'><span style='background: {{color}}'><\/span><span style='background: {{color}}'><\/span><span style='background: {{color}}'><\/span><span style='background: {{color}}'><\/span><span style='background: {{color}}'><\/span><span style='background: {{color}}'><\/span><span style='background: {{color}}'><\/span><span style='background: {{color}}'><\/span><span style='background: {{color}}'><\/span><span style='background: {{color}}'><\/span><\/div><\/div \/>"
5866		},
5867		addOnDuotone: {
5868			enable: false
5869		},
5870		addOnBubblemorph: {
5871			enable: false
5872		},
5873		addOnDistortion: {
5874			enable: false
5875		}
5876		
5877	};
5878
5879    // expose to scope
5880    $.extend(theme, {
5881		PluginRevolutionSlider
5882	});
5883
5884    // jquery plugin
5885    $.fn.themePluginRevolutionSlider = function(opts) {
5886		return this.map(function() {
5887			const $this = $(this);
5888
5889			if ($this.data(instanceName)) {
5890				return $this.data(instanceName);
5891			} else {
5892				return new PluginRevolutionSlider($this, opts);
5893			}
5894
5895		});
5896	}
5897})).apply(this, [window.theme, jQuery]);
5898
5899// Scroll Spy
5900(((theme = {}, $) => {
5901    const instanceName = '__scrollSpy';
5902
5903    class PluginScrollSpy {
5904        constructor($el, opts) {
5905            return this.initialize($el, opts);
5906        }
5907
5908        initialize($el, opts) {
5909
5910			if( document.querySelector( opts.target ) == null ) {
5911				return false;
5912			}
5913
5914			this.$el = $el;
5915
5916			this
5917				.setData()
5918				.setOptions(opts);
5919			
5920			this.build();
5921
5922			return this;
5923		}
5924
5925        setData() {
5926			this.$el.data(instanceName, this);
5927
5928			return this;
5929		}
5930
5931        setOptions(opts) {
5932			this.options = $.extend(true, {}, PluginScrollSpy.defaults, opts, {
5933				wrapper: this.$el
5934			});
5935
5936			return this;
5937		}
5938
5939        build() {
5940            const self = this, target = document.querySelector( self.options.target ) != null ? document.querySelector( self.options.target ) : false, navItems = target == '#header' || target == '.wrapper-spy' ? target.querySelectorAll('.header-nav .nav > li a') : target.querySelectorAll('.nav > li a');
5941
5942			// Get all section ID's
5943			let sectionIDs = Object.keys(navItems).map((key, index) => navItems[key].hash);
5944
5945			// Remove empty values from sectionIDs array
5946			sectionIDs = sectionIDs.filter(value => value != '');
5947
5948			// Store in a global variable
5949			self.sectionIDs = sectionIDs;
5950
5951			for( let i = 0; i < sectionIDs.length; i++ ) {
5952
5953				// Default Root Margin
5954				let rootMargin = '-20% 0px -79.9% 0px';
5955				
5956				// Spy Offset
5957				if( $( sectionIDs[i] ).data('spy-offset') ) {
5958					const rootMarginOffset = $( sectionIDs[i] ).data('spy-offset'), isNegativeOffset = parseInt( rootMarginOffset ) < 0 ? true : false;
5959
5960					// Mount a new rootMargin based on offset value
5961					rootMargin = rootMargin.split(' ').map((element, index) => {
5962						if( element.indexOf('%') > 0 ) {
5963                            const valueToInt = parseInt( element.replace('%','') );
5964                            let newValue = 0;
5965
5966                            switch ( index ) {
5967								case 0:
5968									if( isNegativeOffset ) {
5969										newValue = valueToInt - rootMarginOffset;
5970									} else {
5971										newValue = Math.abs(valueToInt) + rootMarginOffset;
5972									}
5973									break;
5974
5975								case 2:
5976									if( isNegativeOffset ) {
5977										newValue = valueToInt + rootMarginOffset;
5978									} else {
5979										newValue = Math.abs(valueToInt) - rootMarginOffset;
5980									}
5981									break;
5982							
5983							}
5984
5985                            if( isNegativeOffset ) {
5986								newValue = newValue + '%';
5987							} else {
5988								newValue = '-' + newValue + '%';
5989							}
5990
5991                            return newValue;
5992                        } else {
5993							return element;
5994						}
5995					}).join(' ');
5996				}
5997
5998				const selector = sectionIDs[i],
5999                      callback = function() {
6000                          const $section = $(this);
6001
6002                          if( target == '#header' || target == '.wrapper-spy' ) {
6003                              $('#header .header-nav .nav > li a').removeClass('active');
6004                              $('#header .header-nav .nav > li a[href="#'+ $section[0].id +'"]').addClass('active');
6005                          } else {
6006                              $( target ).find('.nav > li a').removeClass('active');
6007                              $( target ).find('.nav > li a[href="#'+ $section[0].id +'"]').addClass('active');
6008                          }
6009                          
6010                      };
6011
6012				this.scrollSpyIntObs( selector, callback, { 
6013					rootMargin,
6014					threshold: 0
6015				}, true, i, true);
6016
6017            }
6018
6019            return this;
6020
6021		}
6022
6023        scrollSpyIntObs(selector, functionName, intObsOptions, al
6023waysObserve, index, firstLoad) {
6024			const self = this;
6025
6026			const $el = document.querySelectorAll( selector );
6027			let intersectionObserverOptions = {
6028				rootMargin: '0px 0px 200px 0px'
6029			};
6030
6031			if( Object.keys(intObsOptions).length ) {
6032				intersectionObserverOptions = $.extend(intersectionObserverOptions, intObsOptions);
6033			}
6034
6035			const observer = new IntersectionObserver(entries => {
6036                for (const entry of entries) {
6037                    if (entry.intersectionRatio > 0 ) {
6038						if( typeof functionName === 'string' ) {
6039							const func = Function( 'return ' + functionName )();
6040						} else {
6041							const callback = functionName;
6042
6043							callback.call( $(entry.target) );
6044						}
6045
6046						// Unobserve
6047						if( !alwaysObserve ) {
6048							observer.unobserve(entry.target);   
6049						}
6050
6051					} else {
6052						if( firstLoad == false ) {
6053							if( index == self.sectionIDs.length - 1 ) {
6054								$('#header .header-nav .nav > li a').removeClass('active');
6055								$('#header .header-nav .nav > li a[href="#'+ entry.target.id +'"]').parent().prev().find('a').addClass('active');
6056							}
6057						}
6058						firstLoad = false;
6059
6060					}
6061                }
6062            }, intersectionObserverOptions);
6063			
6064			$( $el ).each(function(){
6065				observer.observe( $(this)[0] );
6066			});
6067
6068			return this;
6069		}
6070    }
6071
6072    PluginScrollSpy.defaults = {
6073		target: '#header'
6074	};
6075
6076    // expose to scope
6077    $.extend(theme, {
6078		PluginScrollSpy
6079	});
6080
6081    // jquery plugin
6082    $.fn.themePluginScrollSpy = function(opts) {
6083		return this.map(function() {
6084			const $this = $(this);
6085
6086			if ($this.data(instanceName)) {
6087				return $this.data(instanceName);
6088			} else {
6089				return new PluginScrollSpy($this, opts);
6090			}
6091
6092		});
6093	}
6094})).apply(this, [window.theme, jQuery]);
6095
6096// Scroll to Top
6097(((theme = {}, $) => {
6098    $.extend(theme, {
6099
6100		PluginScrollToTop: {
6101
6102			defaults: {
6103				wrapper: $('body'),
6104				offset: 150,
6105				buttonClass: 'scroll-to-top',
6106				buttonAriaLabel: 'Scroll To Top',
6107				iconClass: 'fas fa-chevron-up',
6108				delay: 1000,
6109				visibleMobile: false,
6110				label: false,
6111				easing: 'easeOutBack'
6112			},
6113
6114			initialize(opts) {
6115				initialized = true;
6116
6117				// Don't initialize if the page has Section Scroll
6118				if( $('body[data-plugin-section-scroll]').get(0) ) {
6119					return;
6120				}
6121
6122				this
6123					.setOptions(opts)
6124					.build()
6125					.events();
6126
6127				return this;
6128			},
6129
6130			setOptions(opts) {
6131				this.options = $.extend(true, {}, this.defaults, opts);
6132
6133				return this;
6134			},
6135
6136			build() {
6137                const self = this;
6138                let $el;
6139
6140                // Base HTML Markup
6141                $el = $('<a />')
6142					.addClass(self.options.buttonClass)
6143					.attr({
6144						'href': '#',
6145						'aria-label': self.options.buttonAriaLabel
6146					})
6147					.append(
6148						$('<i />')
6149						.addClass(self.options.iconClass)
6150				);
6151
6152                // Visible Mobile
6153                if (!self.options.visibleMobile) {
6154					$el.addClass('hidden-mobile');
6155				}
6156
6157                // Label
6158                if (self.options.label) {
6159					$el.append(
6160						$('<span />').html(self.options.label)
6161					);
6162				}
6163
6164                this.options.wrapper.append($el);
6165
6166                this.$el = $el;
6167
6168                return this;
6169            },
6170
6171			events() {
6172                const self = this;
6173                let _isScrolling = false;
6174
6175                // Click Element Action
6176                self.$el.on('click', e => {
6177					e.preventDefault();
6178					$('html').animate({
6179						scrollTop: 0
6180					}, self.options.delay, self.options.easing);
6181					return false;
6182				});
6183
6184                // Show/Hide Button on Window Scroll event.
6185                $(window).scroll(() => {
6186
6187					if (!_isScrolling) {
6188
6189						_isScrolling = true;
6190
6191						if ($(window).scrollTop() > self.options.offset) {
6192
6193							self.$el.stop(true, true).addClass('visible');
6194							_isScrolling = false;
6195
6196						} else {
6197
6198							self.$el.stop(true, true).removeClass('visible');
6199							_isScrolling = false;
6200
6201						}
6202
6203					}
6204
6205				});
6206
6207                return this;
6208            }
6209
6210		}
6211
6212	});
6213})).apply(this, [window.theme, jQuery]);
6214
6215// Scrollable
6216(((theme = {}, $) => {
6217    const instanceName = '__scrollable';
6218
6219    class PluginScrollable {
6220        constructor($el, opts) {
6221            return this.initialize($el, opts);
6222        }
6223
6224        static updateModals() {
6225            PluginScrollable.updateBootstrapModal();
6226        }
6227
6228        static updateBootstrapModal() {
6229            let updateBoostrapModal;
6230
6231            updateBoostrapModal = typeof $.fn.modal !== 'undefined';
6232            updateBoostrapModal = updateBoostrapModal && typeof $.fn.modal.Constructor !== 'undefined';
6233            updateBoostrapModal = updateBoostrapModal && typeof $.fn.modal.Constructor.prototype !== 'undefined';
6234            updateBoostrapModal = updateBoostrapModal && typeof $.fn.modal.Constructor.prototype.enforceFocus !== 'undefined';
6235
6236            if ( !updateBoostrapModal ) {
6237                return false;
6238            }
6239
6240            const originalFocus = $.fn.modal.Constructor.prototype.enforceFocus;
6241            $.fn.modal.Constructor.prototype.enforceFocus = function() {
6242                originalFocus.apply( this );
6243
6244                const $scrollable = this.$element.find('.scrollable');
6245                if ( $scrollable ) {
6246                    if ( $.isFunction($.fn['themePluginScrollable'])  ) {
6247                        $scrollable.themePluginScrollable();
6248                    }
6249
6250                    if ( $.isFunction($.fn['nanoScroller']) ) {
6251                        $scrollable.nanoScroller();
6252                    }
6253                }
6254            };
6255        }
6256
6257        initialize($el, opts) {
6258			if ( $el.data( instanceName ) ) {
6259				return this;
6260			}
6261
6262			this.$el = $el;
6263
6264			this
6265				.setData()
6266				.setOptions(opts)
6267				.build();
6268
6269			return this;
6270		}
6271
6272        setData() {
6273			this.$el.data(instanceName, this);
6274
6275			return this;
6276		}
6277
6278        setOptions(opts) {
6279			this.options = $.extend(true, {}, PluginScrollable.defaults, opts, {
6280				wrapper: this.$el
6281			});
6282
6283			return this;
6284		}
6285
6286        build() {
6287			this.options.wrapper.nanoScroller(this.options);
6288
6289			return this;
6290		}
6291    }
6292
6293    PluginScrollable.defaults = {
6294		contentClass: 'scrollable-content',
6295		paneClass: 'scrollable-pane',
6296		sliderClass: 'scrollable-slider',
6297		alwaysVisible: true,
6298		preventPageScrolling: true
6299	};
6300
6301    // expose to scope
6302    $.extend(theme, {
6303		PluginScrollable
6304	});
6305
6306    // jquery plugin
6307    $.fn.themePluginScrollable = function(opts) {
6308		return this.each(function() {
6309			const $this = $(this);
6310
6311			if ($this.data(instanceName)) {
6312				return $this.data(instanceName);
6313			} else {
6314				return new PluginScrollable($this, opts);
6315			}
6316
6317		});
6318	};
6319
6320    $(() => {
6321		PluginScrollable.updateModals();
6322	});
6323})).apply(this, [window.theme, jQuery]);
6324
6325// Section Scroll
6326(((theme = {}, $) => {
6327    const instanceName = '__sectionScroll';
6328
6329    class PluginSectionScroll {
6330        constructor($el, opts) {
6331            return this.initialize($el, opts);
6332        }
6333
6334        initialize($el, opts) {
6335			if ($el.data(instanceName)) {
6336				return this;
6337			}
6338
6339			this.$el = $el;
6340
6341			this
6342				.setData()
6343				.setOptions(opts)
6344				.build()
6345				.events();
6346
6347			return this;
6348		}
6349
6350        setData() {
6351			this.$el.data(instanceName, this);
6352
6353			return this;
6354		}
6355
6356        setOptions(opts) {
6357			this.options = $.extend(true, {}, PluginSectionScroll.defaults, opts, {
6358				wrapper: this.$el
6359			});
6360
6361			return this;
6362		}
6363
6364        build() {
6365			const self = this, $el = this.options.wrapper;
6366
6367			// Check type of header and change the target for header (by change header color purpose)
6368			if( $('html').hasClass('side-header-overlay-full-screen') ) {
6369				self.$header = $('.sticky-wrapper');
6370			} else {
6371				self.$header = $('#header');
6372			}
6373
6374			// Turn the section full height or not depeding on the content size
6375			self.updateSectionsHeight();
6376
6377			// Wrap all sections in a section wrapper
6378			$( this.options.targetClass ).wrap('<div class="section-wrapper"></div>');
6379
6380			// Set the section wrapper height
6381	  		$('.section-wrapper').each(function(){
6382	  			$(this).height( $(this).find('.section-scroll').outerHeight() );
6383	  		});
6384
6385	  		// Add active class to the first section on page load
6386	  		$('.section-wrapper').first().addClass('active');
6387			
6388	        let flag = false, scrollableFlag = false, touchDirection = '', touchstartY = 0, touchendY = 0;
6389
6390	        $(window).on('touchstart', ({changedTouches}) => {
6391			    touchstartY = changedTouches[0].screenY;
6392			});
6393
6394	        let wheelEvent = 'onwheel' in document ? 'wheel' : document.onmousewheel !== undefined ? 'mousewheel' : 'DOMMouseScroll';
6395	        if( $(window).width() < 992 && $('html').hasClass('touch') ) {
6396	        	wheelEvent = 'onwheel' in document ? 'wheel touchend' : document.onmousewheel !== undefined ? 'mousewheel touchend' : 'DOMMouseScroll touchend';
6397	        }
6398
6399        	if( $(window).width() < 992 ) {
6400	    		$('html').removeClass('overflow-hidden');
6401			    $(window).on('scroll', () => {
6402
6403		    		let index = 0;
6404		    		$('.section-scroll').each(function(){
6405		    			if( $(this).offset().top <= $(window).scrollTop() + 50 ) {
6406		    				const $currentSection2 = $('.section-wrapper').eq( index ).find('.section-scroll');
6407
6408			            	$('.section-scroll-dots-navigation > ul > li').removeClass('active');
6409							$('.section-scroll-dots-navigation > ul > li').eq( index ).addClass('active');
6410
6411							$(window).trigger({
6412								type: 'section.scroll.mobile.change.header.color',
6413								currentSection: $currentSection2
6414							});
6415		    			}
6416
6417		    			index++;
6418		    		});
6419		    		
6420			    });
6421
6422			    $(window).on('section.scroll.mobile.change.header.color', ({currentSection}) => {
6423			    	if( typeof currentSection == 'undefined' ) {
6424			    		return;
6425			    	}
6426
6427			    	const $currentSection = currentSection, headerColor     = $currentSection.data('section-scroll-header-color');
6428								    	
6429			    	$('#header .header-nav').removeClass('header-nav-light-text header-nav-dark-text').addClass('header-nav-' + headerColor + '-text');
6430			    	$('#header .header-nav-features').removeClass('header-nav-features-dark header-nav-features-light').addClass('header-nav-features-' + headerColor);
6431			    	$('#header .header-social-icons').removeClass('social-icons-icon-dark social-icons-icon-light').addClass('social-icons-icon-' + headerColor);
6432
6433			    	// Change Logo
6434			    	if( self.options.changeHeaderLogo && headerColor != undefined ) {
6435				    	if( headerColor == 'light' ) {
6436				    		$('#header .header-logo img').attr('src', self.options.headerLogoLight);
6437				    	} else if( headerColor == 'dark' ) {
6438				    		$('#header .header-logo img').attr('src', self.options.headerLogoDark);
6439				    	}
6440			    	}
6441
6442			    	self.$header.css({
6443			    		opacity: 1
6444			    	});
6445
6446			    });
6447        	}
6448
6449	        $(window).on(wheelEvent, ({target, originalEvent}) => {
6450                if( $(window).width() < 992 ) {
6451	        		return;
6452	        	}
6453
6454                if( $(window).width() < 992 && $('html').hasClass('touch') ) {
6455		        	if( $(target).closest('.section-scroll-dots-navigation').get(0) || $(target).closest('.header-body').get(0) || $(target).closest('.owl-carousel').get(0) ) {
6456		        		return;
6457		        	}
6458		        }
6459
6460                // Side Header Overlay Full Screen
6461                if( $('html.side-header-overlay-full-screen.side-header-hide').get(0) ) {
6462		        	return;
6463		        }
6464
6465                const wheelDirection = originalEvent.wheelDelta == undefined ? originalEvent.deltaY > 0 : originalEvent.wheelDelta < 0;
6466                if( $(window).width() < 992 && $('html').hasClass('touch') ) {
6467		        	touchendY = event.changedTouches[0].screenY;
6468	        		
6469				    if( touchendY <= touchstartY ) {
6470				    	touchDirection = 'up';
6471				    }
6472
6473				    if( touchendY >= touchstartY ) {
6474				    	touchDirection = 'down';
6475				    }
6476
6477				    if( touchendY == touchstartY ) {
6478				    	return;
6479				    }
6480	        	}
6481
6482                const $currentSection = $('.section-wrapper').eq( self.getCurrentIndex() ).find('.section-scroll');
6483                const $nextSection = self.getNextSection(wheelDirection, touchDirection);
6484                let nextSectionOffsetTop;
6485
6486                // If is the last section, then change the offsetTop value
6487                if( self.getCurrentIndex() == $('.section-wrapper').length - 1 ) {
6488            		nextSectionOffsetTop = $(document).height();
6489            	} else {
6490            		nextSectionOffsetTop = $nextSection.offset().top;
6491            	}
6492
6493                if( $(window).width() < 992 && $('html').hasClass('touch') ) {
6494				    setTimeout(() => {
6495					    if( $('.section-wrapper').eq( self.getCurrentIndex() ).find('.section-scroll').hasClass('section-scroll-scrollable') ) {
6496					    	$('html').removeClass('overflow-hidden');
6497					    } else {
6498					    	$('html').addClass('overflow-hidden');
6499					    }
6500				    }, 1200);
6501				}
6502
6503                // For non full height sections
6504                if( $currentSection.hasClass('section-scroll-scrollable') ) {
6505	        		if( !flag && !scrollableFlag ) {
6506
6507		        		// Scroll Direction
6508		        		if(wheelDirection || touchDirection == 'up') {
6509		        			if( ( $(window).scrollTop() + $(window).height() ) >= nextSectionOffsetTop ) {
6510		        				flag = true;
6511								setTimeout(() => {
6512									$(window).trigger('section.scroll.change.header.color');
6513
6514					            	setTimeout(() => {
6515										flag = false;
6516									}, 500);
6517								}, 1000);
6518
6519		        				if( self.getCurrentIndex() == ( $('.section-wrapper').length - 1 )  ) {
6520						    		return false;
6521						    	}
6522
6523		        				// Move to the next section
6524		        				self.moveTo( $currentSection.offset().top + $currentSection.outerHeight() );
6525
6526		        				// Change Section Active Class
6527					   			self.changeSectionActiveState( $nextSection );
6528
6529					   			self.$header.css({
6530							    	opacity: 0,
6531							    	transition: 'ease opacity 500ms'
6532							    });
6533					        }
6534
6535			        		if( !$('html').hasClass('touch') ) {
6536				        		for( var i = 1; i < 100; i++ ) {
6537					        		$('body, html').scrollTop( $(window).scrollTop() + 1 );
6538
6539					        		if( ( $(window).scrollTop() + $(window).height() ) >= nextSectionOffsetTop ) {
6540					        			scrollableFlag = true;
6541										setTimeout(() => {
6542											$(window).trigger('section.scroll.change.header.color');
6543							            	scrollableFlag = false;
6544										}, 500);
6545					        			break;
6546					        		}
6547				        		}
6548				        	}
6549					    } else {
6550					    	if( $(window).scrollTop() <= $currentSection.offset().top ) {
6551					    		flag = true;
6552								setTimeout(() => {
6553									$(window).trigger('section.scroll.change.header.color');
6554
6555					            	setTimeout(() => {
6556										flag = false;
6557									}, 500);
6558								}, 1000);
6559
6560					    		if( self.getCurrentIndex() == 0  ) {
6561						    		return false;
6562						    	}
6563
6564					   			// Move to the next section
6565		        				self.moveTo( $currentSection.offset().top - $(window).height() );
6566
6567		        				// Change Section Active Class
6568					   			self.changeSectionActiveState( $nextSection );
6569
6570					   			self.$header.css({
6571							    	opacity: 0,
6572							    	transition: 'ease opacity 500ms'
6573							    });
6574					        }
6575
6576					    	if( !$('html').hasClass('touch') ) {
6577				        		for( var i = 1; i < 100; i++ ) {
6578					        		$('body, html').scrollTop( $(window).scrollTop() - 1 );
6579
6580					        		if( $(window).scrollTop() <= $currentSection.offset().top ) {
6581					        			scrollableFlag = true;
6582										setTimeout(() => {
6583											$(window).trigger('section.scroll.change.header.color');
6584							            	scrollableFlag = false;
6585										}, 500);
6586					        			break;
6587					        		}
6588				        		}
6589				        	}
6590					    }
6591
6592			   			// Change Dots Active Class
6593				        self.changeDotsActiveState();
6594
6595		        		return;
6596
6597		        	}
6598	        	}
6599
6600                // For full height sections
6601                if( !flag && !scrollableFlag ) {
6602				    if(wheelDirection || touchDirection == 'up') {
6603				    	if( self.getCurrentIndex() == ( $('.section-wrapper').length - 1 )  ) {
6604				    		return false;
6605				    	}
6606
6607				   		// Change Section Active Class
6608			   			self.changeSectionActiveState( $nextSection );
6609
6610				   		setTimeout(() => {
6611				   			// Move to the next section
6612	        				self.moveTo( $nextSection.offset().top );
6613
6614				   		}, 150);
6615				    } else {
6616				    	if( self.getCurrentIndex() == 0  ) {
6617				    		return false;
6618				    	}
6619
6620				   		// Change Section Active Class
6621			   			self.changeSectionActiveState( $nextSection );
6622
6623				   		if( $nextSection.height() > $(window).height() ) {
6624				   			// Move to the next section
6625	        				self.moveTo( $currentSection.offset().top - $(window).height() );
6626				   		} else {
6627					        setTimeout(() => {
6628					   			// Move to the next section
6629		        				self.moveTo( $nextSection.offset().top );
6630
6631					   		}, 150);
6632				   		}
6633				    }
6634
6635				    // Change Dots Active Class
6636			        self.changeDotsActiveState();
6637
6638				    self.$header.css({
6639				    	opacity: 0,
6640				    	transition: 'ease opacity 500ms'
6641				    });
6642
6643				    // Style next section
6644	            	$nextSection.css({
6645	            		position: 'relative',
6646	            		opacity: 1,
6647	            		'z-index': 1,
6648	            		transform: 'translate3d(0,0,0) scale(1)'
6649	            	});
6650
6651	            	// Style previous section
6652	            	$currentSection.css({
6653	            		position: 'fixed',
6654	            		width: '100%',
6655	            		top: 0,
6656	            		left: 0,
6657	            		opacity: 0,
6658	            		'z-index': 0,
6659	            		transform: 'translate3d(0,0,-10px) scale(0.7)',
6660	            		transition: 'ease transform 600ms, ease opacity 600ms',
6661	            	});
6662
6663					setTimeout(() => {
6664						$currentSection.css({
6665		            		position: 'relative',
6666		            		opacity: 1,
6667		            		transform: 'translate3d(0,0,-10px) scale(1)'
6668		            	});
6669
6670						$(window).trigger('section.scroll.change.header.color');
6671
6672		            	setTimeout(() => {
6673							flag = false;
6674						}, 500);
6675					}, 1000);
6676
6677					flag = true;
6678
6679				}
6680
6681                return;
6682            });
6683
6684	        // Dots Navigation
6685	        if( this.options.dotsNav ) {
6686	        	self.dotsNavigation();
6687	        }
6688
6689	        // First Load
6690	        setTimeout(() => {
6691		        if( $(window.location.hash).get(0) ) {
6692		        	self.moveTo( $(window.location.hash).parent().offset().top );
6693
6694		        	self.changeSectionActiveState( $(window.location.hash) );
6695
6696		        	// Change Dots Active Class
6697			        self.changeDotsActiveState();
6698
6699		        	self.updateHash( true );
6700		        } else {
6701                    const hash  = window.location.hash;
6702                    let index = hash.replace('#','');
6703
6704                    if( !hash ) {
6705		        		index = 1;
6706		        	}
6707
6708                    self.moveTo( $('.section-wrapper').eq( index - 1 ).offset().top );
6709
6710                    self.changeSectionActiveState( $('.section-wrapper').eq( index - 1 ).find('.section-scroll') );
6711
6712                    // Change Dots Active Class
6713                    self.changeDotsActiveState();
6714
6715                    self.updateHash( true );
6716                }
6717
6718				$(window).trigger('section.scroll.ready');
6719				$(window).trigger('section.scroll.change.header.color');
6720			}, 500);
6721
6722			return this;
6723		}
6724
6725        updateSectionsHeight() {
6726			const self = this;
6727
6728			$('.section-scroll').css({ height: '' });
6729
6730			$('.section-scroll').each(function(){
6731				if( $(this).outerHeight() < ( $(window).height() + 3 ) ) {
6732					$(this).css({ height: '100vh' });		
6733				} else {
6734					$(this).addClass('section-scroll-scrollable');
6735				}
6736			});
6737
6738			// Set the section wrapper height
6739	  		$('.section-wrapper').each(function(){
6740	  			$(this).height( $(this).find('.section-scroll').outerHeight() );
6741	  		});
6742
6743			return this;
6744		}
6745
6746        updateHash(first_load) {
6747			const self = this;
6748
6749			if( !window.location.hash ) {
6750				window.location.hash = 1;
6751			} else {
6752				if(!first_load) {
6753					const $section = $('.section-wrapper').eq( self.getCurrentIndex() ).find('.section-scroll'), section_id = $section.attr('id') ? $section.attr('id') : $section.parent().index() + 1;
6754
6755					window.location.hash = section_id;
6756				}
6757			}
6758
6759			return this;
6760		}
6761
6762        getCurrentIndex() {
6763            const self = this;
6764            let currentIndex = 0;
6765
6766            currentIndex = $('.section-wrapper.active').index();
6767
6768            return currentIndex;
6769        }
6770
6771        moveTo($scrollTopValue, first_load) {
6772			const self = this;
6773
6774			$('body, html').animate({
6775   				scrollTop: $scrollTopValue
6776   			}, 1000, 'easeOutQuint');
6777
6778   			setTimeout(() => {
6779	   			self.updateHash();
6780   			}, 500);
6781
6782			return this;
6783		}
6784
6785        getNextSection(wheelDirection, touchDirection) {
6786            const self = this;
6787            let $nextSection = '';
6788
6789            // Scroll Direction
6790            if(wheelDirection || touchDirection == 'up') {
6791				$nextSection = $('.section-wrapper').eq( self.getCurrentIndex() + 1 ).find('.section-scroll');
6792        	} else {
6793        		$nextSection = $('.section-wrapper').eq( self.getCurrentIndex() - 1 ).find('.section-scroll');
6794        	}
6795
6796            return $nextSection;
6797        }
6798
6799        changeSectionActiveState($nextSection) {
6800			const self = this;
6801
6802			$('.section-wrapper').removeClass('active');
6803	   		$nextSection.parent().addClass('active');
6804
6805			return this;
6806		}
6807
6808        changeDotsActiveState() {
6809			const self = this;
6810
6811			$('.section-scroll-dots-navigation > ul > li').removeClass('active');
6812			$('.section-scroll-dots-navigation > ul > li').eq( self.getCurrentIndex() ).addClass('active');
6813
6814			return this;
6815		}
6816
6817        dotsNavigation() {
6818			const self = this;
6819
6820			const dotsNav = $('<div class="section-scroll-dots-navigation"><ul class="list list-unstyled"></ul></div>'), currentSectionIndex = self.getCurrentIndex();
6821
6822        	if( self.options.dotsClass ) {
6823        		dotsNav.addClass( self.options.dotsClass );
6824        	}
6825
6826        	for( let i = 0; i < $('.section-scroll').length; i++ ) {
6827        		const title = $('.section-wrapper').eq( i ).find('.section-scroll').data('section-scroll-title');
6828
6829        		dotsNav.find('> ul').append( '<li'+ ( ( currentSectionIndex == i ) ? ' class="active"' : '' ) +'><a href="#'+ i +'" data-nav-id="'+ i +'"><span>'+ title +'</span></a></li>' );
6830        	}
6831
6832        	$('.body').append( dotsNav );
6833
6834        	dotsNav.find('a[data-nav-id]').on('click touchstart', function(e){
6835        		e.preventDefault();
6836        		const $this = $(this);
6837
6838        		$('.section-scroll').css({
6839        			opacity: 0,
6840        			transition: 'ease opacity 300ms'
6841        		});
6842
6843        		self.$header.css({
6844			    	opacity: 0,
6845			    	transition: 'ease opacity 500ms'
6846			    });
6847
6848        		setTimeout(() => {
6849	        		self.moveTo( $('.section-wrapper').eq( $this.data('nav-id') ).offset().top )
6850
6851		   			$('.section-wrapper').removeClass('active');
6852			   		$('.section-wrapper').eq( $this.data('nav-id') ).addClass('active');
6853
6854	        		$('.section-wrapper').eq( self.getCurrentIndex() ).find('.section-scroll').css({
6855	        			opacity: 1
6856	        		});
6857
6858	        		setTimeout(() => {
6859		        		$('.section-scroll').css({ opacity: 1 });
6860
6861		        		$(window).trigger('section.scroll.change.header.color');
6862	        		}, 500);
6863
6864	        		if( $(window).width() > 991 ) {
6865		        		self.changeDotsActiveState();
6866	        		}
6867        		}, 500);
6868        	});
6869
6870			return this;
6871		}
6872
6873        events() {
6874			const self = this;
6875
6876			$(window).on('section.scroll.ready', () => {
6877				$(window).scrollTop(0);
6878			});
6879
6880			$(window).on('section.scroll.change.header.color', () => {
6881		    	const headerColor = $('.section-wrapper').eq( self.getCurrentIndex() ).find('.section-scroll').data('section-scroll-header-color');
6882		    	
6883		    	$('#header .header-nav').removeClass('header-nav-light-text header-nav-dark-text').addClass('header-nav-' + headerColor + '-text');
6884		    	$('#header .header-nav-features').removeClass('header-nav-features-dark header-nav-features-light').addClass('header-nav-features-' + headerColor);
6885		    	$('#header .header-social-icons').removeClass('social-icons-icon-dark social-icons-icon-light').addClass('social-icons-icon-' + headerColor);
6886
6887		    	// Change Logo
6888		    	if( self.options.changeHeaderLogo && headerColor != undefined ) {
6889			    	if( headerColor == 'light' ) {
6890			    		$('#header .header-logo img').attr('src', self.options.headerLogoLight);
6891			    	} else if( headerColor == 'dark' ) {
6892			    		$('#header .header-logo img').attr('src', self.options.headerLogoDark);
6893			    	}
6894		    	}
6895
6896		    	self.$header.css({
6897		    		opacity: 1
6898		    	});
6899		    });
6900
6901			$(document).ready(() => {
6902			    $(window).afterResize(() => {
6903			    	self.updateSectionsHeight();
6904
6905			    	if( $(window).width() < 992 ) {
6906			    		$('html').removeClass('overflow-hidden');
6907			    	}
6908			    });
6909			});
6910
6911		    return this;
6912		}
6913    }
6914
6915    PluginSectionScroll.defaults = {
6916		targetClass: '.section',
6917		dotsNav: true,
6918		changeHeaderLogo: true,
6919		headerLogoDark: 'img/logo-default-slim.png',
6920		headerLogoLight: 'img/logo-default-slim-dark.png'
6921	};
6922
6923    // expose to scope
6924    $.extend(theme, {
6925		PluginSectionScroll
6926	});
6927
6928    // jquery plugin
6929    $.fn.themePluginSectionScroll = function(opts) {
6930		return this.map(function() {
6931			const $this = $(this);
6932
6933			if ($this.data(instanceName)) {
6934				return $this.data(instanceName);
6935			} else {
6936				return new PluginSectionScroll($this, opts);
6937			}
6938
6939		});
6940	};
6941})).apply(this, [window.theme, jQuery]);
6942
6943// Sort
6944(((theme = {}, $) => {
6945    const instanceName = '__sort';
6946
6947    class PluginSort {
6948        constructor($el, opts) {
6949            return this.initialize($el, opts);
6950        }
6951
6952        initialize($el, opts) {
6953			if ($el.data(instanceName)) {
6954				return this;
6955			}
6956
6957			this.$el = $el;
6958
6959			this
6960				.setData()
6961				.setOptions(opts)
6962				.build();
6963
6964			return this;
6965		}
6966
6967        setData() {
6968			this.$el.data(instanceName, this);
6969
6970			return this;
6971		}
6972
6973        setOptions(opts) {
6974			this.options = $.extend(true, {}, PluginSort.defaults, opts, {
6975				wrapper: this.$el
6976			});
6977
6978			return this;
6979		}
6980
6981        build() {
6982			if (!($.isFunction($.fn.isotope))) {
6983				return this;
6984			}
6985
6986			const self = this, $source = this.options.wrapper, $destination = $('.sort-destination[data-sort-id="' + $source.attr('data-sort-id') + '"]'), $window = $(window);
6987
6988			if ($destination.get(0)) {
6989
6990				self.$source = $source;
6991				self.$destination = $destination;
6992				self.$loader = false;
6993
6994				self.setParagraphHeight($destination);
6995
6996				if (self.$destination.parents('.sort-destination-loader').get(0)) {
6997					self.$loader = self.$destination.parents('.sort-destination-loader');
6998					self.createLoader();
6999				}
7000
7001				$destination.attr('data-filter', '*');
7002
7003				$destination.one('layoutComplete', (event, laidOutItems) => {
7004					self.removeLoader();
7005
7006					// If has data-plugin-sticky on the page we need recalculate sticky position
7007					if( $('[data-plugin-sticky]').length ) {
7008						setTimeout(() => {
7009							$('[data-plugin-sticky]').each(function(){
7010								$(this).data('__sticky').build();
7011								$(window).trigger('resize');
7012							});
7013						}, 500);
7014					}
7015				});
7016
7017				if ( $('#' + self.options.filterFieldId).length ) {
7018
7019					const $filterField = $('#' + self.options.filterFieldId);
7020
7021					$filterField.keyup(function() {
7022						self.options.filterFieldText = $(this).val();
7023						self.setFilter(self.options.filter);
7024					});
7025
7026				}
7027
7028				$destination.waitForImages(() => {
7029					$destination.isotope(self.options);
7030					self.events();
7031				});
7032
7033				setTimeout(() => {
7034					self.removeLoader();
7035				}, 3000);
7036
7037			}
7038
7039			return this;
7040		}
7041
7042        events() {
7043            const self = this;
7044            let filter = null;
7045            const $window = $(window);
7046
7047            self.$source.find('a').click(function(e) {
7048				e.preventDefault();
7049
7050				filter = $(this).parent().data('option-value');
7051
7052				self.setFilter(filter);
7053
7054				if (e.originalEvent) {
7055					self.$source.trigger('filtered');
7056				}
7057
7058				return this;
7059			});
7060
7061            self.$destination.trigger('filtered');
7062            self.$source.trigger('filtered');
7063
7064            if (self.options.useHash) {
7065				self.hashEvents();
7066			}
7067
7068            $window.on('resize sort.resize', () => {
7069				setTimeout(() => {
7070					self.$destination.isotope('layout');
7071				}, 300);
7072			});
7073
7074            setTimeout(() => {
7075				$window.trigger('sort.resize');
7076			}, 300);
7077
7078            return this;
7079        }
7080
7081        setFilter(filter) {
7082            const self = this;
7083            const page = false;
7084            let currentFilter = filter;
7085
7086            self.$source.find('.active').removeClass('active');
7087            self.$source.find('li[data-option-value="' + filter + '"], li[data-option-value="' + filter + '"] > a').addClass('active');
7088
7089            self.options.filter = currentFilter;
7090
7091            if (self.$destination.attr('data-current-page')) {
7092				currentFilter = currentFilter + '[data-page-rel=' + self.$destination.attr('data-current-page') + ']';
7093			}
7094
7095            if (self.options.filterFieldText != '') {
7096				currentFilter = currentFilter + '[data-sort-search*=' + self.options.filterFieldText.toLowerCase() + ']';
7097			}
7098
7099            self.$destination.attr('data-filter', filter).isotope({
7100				filter: currentFilter
7101			}).one('arrangeComplete', (event, filteredItems) => {
7102				
7103				if (self.options.useHash) {
7104					if (window.location.hash != '' || self.options.filter.replace('.', '') != '*') {
7105						window.location.hash = self.options.filter.replace('.', '');
7106					}
7107				}
7108				
7109				$(window).trigger('scroll');
7110
7111			}).trigger('filtered');
7112
7113            return this;
7114        }
7115
7116        hashEvents() {
7117            const self = this;
7118            let hash = null;
7119            let hashFilter = null;
7120            let initHashFilter = '.' + location.hash.replace('#', '');
7121
7122            // Check if has scroll to section trough URL hash and prevent the sort plugin from show nothing
7123            if( $(location.hash).length ) {
7124				initHashFilter = '.';
7125			}
7126
7127            if (initHashFilter != '.' && initHashFilter != '.*') {
7128				self.setFilter(initHashFilter);
7129			}
7130
7131            $(window).on('hashchange', e => {
7132
7133				hashFilter = '.' + location.hash.replace('#', '');
7134				hash = (hashFilter == '.' || hashFilter == '.*' ? '*' : hashFilter);
7135
7136				self.setFilter(hash);
7137
7138			});
7139
7140            return this;
7141        }
7142
7143        setParagraphHeight() {
7144            const self = this;
7145            let minParagraphHeight = 0;
7146            const paragraphs = $('span.thumb-info-caption p', self.$destination);
7147
7148            paragraphs.each(function() {
7149				if ($(this).height() > minParagraphHeight) {
7150					minParagraphHeight = ($(this).height() + 10);
7151				}
7152			});
7153
7154            paragraphs.height(minParagraphHeight);
7155
7156            return this;
7157        }
7158
7159        createLoader() {
7160			const self = this;
7161
7162			const loaderTemplate = [
7163				'<div class="bounce-loader">',
7164					'<div class="bounce1"></div>',
7165					'<div class="bounce2"></div>',
7166					'<div class="bounce3"></div>',
7167				'</div>'
7168			].join('');
7169
7170			self.$loader.append(loaderTemplate);
7171
7172			return this;
7173		}
7174
7175        removeLoader() {
7176
7177			const self = this;
7178
7179			if (self.$loader) {
7180
7181				self.$loader.removeClass('sort-destination-loader-showing');
7182
7183				setTimeout(() => {
7184					self.$loader.addClass('sort-destination-loader-loaded');
7185				}, 300);
7186
7187			}
7188
7189		}
7190    }
7191
7192    PluginSort.defaults = {
7193		useHash: true,
7194		itemSelector: '.isotope-item',
7195		layoutMode: 'masonry',
7196		filter: '*',
7197		filterFieldId: false,
7198		filterFieldText: '',
7199		hiddenStyle: {
7200			opacity: 0
7201		},
7202		visibleStyle: {
7203			opacity: 1
7204		},
7205		stagger: 30,
7206		isOriginLeft: ($('html').attr('dir') == 'rtl' ? false : true)
7207	};
7208
7209    // expose to scope
7210    $.extend(theme, {
7211		PluginSort
7212	});
7213
7214    // jquery plugin
7215    $.fn.themePluginSort = function(opts) {
7216		return this.map(function() {
7217			const $this = $(this);
7218
7219			if ($this.data(instanceName)) {
7220				return $this.data(instanceName);
7221			} else {
7222				return new PluginSort($this, opts);
7223			}
7224
7225		});
7226	}
7227})).apply(this, [window.theme, jQuery]);
7228
7229// Star Rating
7230(((theme = {}, $) => {
7231    const instanceName = '__starrating';
7232
7233    class PluginStarRating {
7234        constructor($el, opts) {
7235            return this.initialize($el, opts);
7236        }
7237
7238        initialize($el, opts) {
7239			this.$el = $el;
7240
7241			this
7242				.setData()
7243				.setOptions(opts)
7244				.build();
7245
7246			return this;
7247		}
7248
7249        setData() {
7250			this.$el.data(instanceName, this);
7251
7252			return this;
7253		}
7254
7255        setOptions(opts) {
7256			this.options = $.extend(true, {}, PluginStarRating.defaults, opts, {
7257				wrapper: this.$el
7258			});
7259
7260			return this;
7261		}
7262
7263        build() {
7264
7265			if (!($.isFunction($.fn.rating))) {
7266				return this;
7267			}
7268
7269			const self = this;
7270
7271			self.options.wrapper
7272				.rating(self.options);
7273
7274			self.options.wrapper.parents('.rating-container')
7275				.addClass('rating-' + self.options.color);
7276
7277			if( self.options.extraClass ) {
7278				self.options.wrapper.parents('.rating-container')
7279					.addClass(self.options.extraClass);
7280			}
7281
7282			return this;
7283
7284		}
7285    }
7286
7287    PluginStarRating.defaults = {
7288		theme: 'krajee-fas',
7289		color: 'primary',
7290		showClear: false,
7291		showCaption: false
7292	};
7293
7294    // expose to scope
7295    $.extend(theme, {
7296		PluginStarRating
7297	});
7298
7299    // jquery plugin
7300    $.fn.themePluginStarRating = function(opts) {
7301		return this.map(function() {
7302			const $this = $(this);
7303
7304			if ($this.data(instanceName)) {
7305				return $this.data(instanceName);
7306			} else {
7307				return new PluginStarRating($this, opts);
7308			}
7309
7310		});
7311	}
7312})).apply(this, [window.theme, jQuery]);
7313
7314// Sticky
7315(((theme = {}, $) => {
7316    const instanceName = '__sticky';
7317
7318    class PluginSticky {
7319        constructor($el, opts) {
7320            return this.initialize($el, opts);
7321        }
7322
7323        initialize($el, opts) {
7324			if ( $el.data( instanceName ) ) {
7325				return this;
7326			}
7327
7328			this.$el = $el;
7329
7330			this
7331				.setData()
7332				.setOptions(opts)
7333				.build()
7334				.events();
7335
7336			return this;
7337		}
7338
7339        setData() {
7340			this.$el.data(instanceName, this);
7341
7342			return this;
7343		}
7344
7345        setOptions(opts) {
7346			this.options = $.extend(true, {}, PluginSticky.defaults, opts, {
7347				wrapper: this.$el
7348			});
7349
7350			return this;
7351		}
7352
7353        build() {
7354			if (!($.isFunction($.fn.pin))) {
7355				return this;
7356			}
7357
7358			const self = this, $window = $(window);
7359			
7360			self.options.wrapper.pin(self.options);
7361
7362			if( self.options.wrapper.hasClass('sticky-wrapper-transparent') ) {
7363				self.options.wrapper.parent().addClass('position-absolute w-100');
7364			}
7365
7366			$window.afterResize(() => {
7367				self.options.wrapper.removeAttr('style').removeData('pin');
7368				self.options.wrapper.pin(self.options);
7369				$window.trigger('scroll');
7370			});
7371
7372			// Change Logo Src
7373			if( self.options.wrapper.find('img').attr('data-change-src') ) {
7374				const $logo = self.options.wrapper.find('img'), logoSrc = $logo.attr('src'), logoNewSrc = $logo.attr('data-change-src');
7375
7376				self.changeLogoSrc = activate => {
7377					if(activate) {
7378						$logo.attr('src', logoNewSrc);
7379					} else {
7380						$logo.attr('src', logoSrc);
7381					}
7382				}
7383			}
7384			
7385			return this;
7386		}
7387
7388        events() {
7389            const self = this;
7390            const $window = $(window);
7391            const $logo = self.options.wrapper.find('img');
7392            const classToCheck = ( self.options.wrapper.hasClass('sticky-wrapper-effect-1') ) ? 'sticky-effect-active' : 'sticky-active';
7393            let stickyActivateFlag = true;
7394            let stickyDeactivateFlag = false;
7395
7396            $window.on('scroll sticky.effect.active', () => {
7397				if( self.options.wrapper.hasClass( classToCheck ) ) {		
7398					if( stickyActivateFlag ) {			
7399						if( $logo.attr('data-change-src') ) {
7400							self.changeLogoSrc(true);
7401						}
7402
7403						stickyActivateFlag = false;
7404						stickyDeactivateFlag = true;
7405					}
7406				} else {	
7407					if( stickyDeactivateFlag ) {				
7408						if( $logo.attr('data-change-src') ) {
7409							self.changeLogoSrc(false);
7410						}
7411
7412						stickyDeactivateFlag = false;
7413						stickyActivateFlag = true;
7414					}
7415				}
7416			});
7417
7418            let isGoingUp = false;
7419            if( self.options.stickyStartEffectAt ) {
7420
7421				// First Load
7422				if( self.options.stickyStartEffectAt < $window.scrollTop() ) {
7423					self.options.wrapper.addClass('sticky-effect-active');
7424
7425					$window.trigger('sticky.effect.active');
7426				}
7427
7428				$window.on('scroll', () => {
7429					if( self.options.stickyStartEffectAt < $window.scrollTop() ) {	
7430						self.options.wrapper.addClass('sticky-effect-active');
7431						isGoingUp = true;
7432
7433						$window.trigger('sticky.effect.active');
7434					} else {	
7435						if( isGoingUp ) {
7436							self.options.wrapper.find('.sticky-body').addClass('position-fixed');
7437							isGoingUp = false;
7438						}
7439
7440						if( $window.scrollTop() == 0 ) {
7441							self.options.wrapper.find('.sticky-body').removeClass('position-fixed');
7442						}
7443
7444						self.options.wrapper.removeClass('sticky-effect-active');
7445					}
7446				});
7447			}
7448
7449            // Refresh Sticky Plugin if click in a data-toggle="collapse"
7450            if( $('[data-bs-toggle="collapse"]').get(0) ) {
7451
7452				$('[data-bs-toggle="collapse"]').on('click', () => {
7453					setTimeout(() => {
7454						self.build();
7455						$(window).trigger('scroll');
7456					}, 1000);
7457				});
7458
7459			}
7460
7461			// Visibility Issue
7462			document.addEventListener('visibilitychange', () => {
7463				$(window).trigger('resize');
7464			});
7465
7466			setInterval(() => {
7467				$(window).trigger('resize');
7468			}, 1000);
7469
7470        }
7471    }
7472
7473    PluginSticky.defaults = {
7474		minWidth: 991,
7475		activeClass: 'sticky-active'
7476	};
7477
7478    // expose to scope
7479    $.extend(theme, {
7480		PluginSticky
7481	});
7482
7483    // jquery plugin
7484    $.fn.themePluginSticky = function(opts) {
7485		return this.map(function() {
7486			const $this = $(this);
7487
7488			if ($this.data(instanceName)) {
7489				return $this.data(instanceName);
7490			} else {
7491				return new PluginSticky($this, opts);
7492			}
7493			
7494		});
7495	}
7496})).apply(this, [ window.theme, jQuery ]);
7497
7498// Toggle
7499(((theme = {}, $) => {
7500    const instanceName = '__toggle';
7501
7502    class PluginToggle {
7503        constructor($el, opts) {
7504            return this.initialize($el, opts);
7505        }
7506
7507        initialize($el, opts) {
7508			if ($el.data(instanceName)) {
7509				return this;
7510			}
7511
7512			this.$el = $el;
7513
7514			this
7515				.setData()
7516				.setOptions(opts)
7517				.build();
7518
7519			return this;
7520		}
7521
7522        setData() {
7523			this.$el.data(instanceName, this);
7524
7525			return this;
7526		}
7527
7528        setOptions(opts) {
7529			this.options = $.extend(true, {}, PluginToggle.defaults, opts, {
7530				wrapper: this.$el
7531			});
7532
7533			return this;
7534		}
7535
7536        build() {
7537            const self = this;
7538            const $wrapper = this.options.wrapper;
7539            const $items = $wrapper.find('> .toggle');
7540            let $el = null;
7541
7542            $items.each(function() {
7543				$el = $(this);
7544
7545				if ($el.hasClass('active')) {
7546					$el.find('> p').addClass('preview-active');
7547					$el.find('> .toggle-content').slideDown(self.options.duration);
7548				}
7549
7550				self.events($el);
7551			});
7552
7553            if (self.options.isAccordion) {
7554				self.options.duration = self.options.duration / 2;
7555			}
7556
7557            return this;
7558        }
7559
7560        events($el) {
7561            const self = this;
7562            let previewParCurrentHeight = 0;
7563            let previewParAnimateHeight = 0;
7564            let toggleContent = null;
7565
7566            $el.find('> label, > .toggle-title').click(function({originalEvent}) {
7567                const $this = $(this);
7568                const parentSection = $this.parent();
7569                const parentWrapper = $this.parents('.toggle');
7570                let previewPar = null;
7571                let closeElement = null;
7572
7573                if (self.options.isAccordion && typeof(originalEvent) != 'undefined') {
7574					closeElement = parentWrapper.find('.toggle.active > label, .toggle.active > .toggle-title');
7575
7576					if (closeElement[0] == $this[0]) {
7577						return;
7578					}
7579				}
7580
7581                parentSection.toggleClass('active');
7582
7583                // Preview Paragraph
7584                if (parentSection.find('> p').get(0)) {
7585
7586					previewPar = parentSection.find('> p');
7587					previewParCurrentHeight = previewPar.css('height');
7588					previewPar.css('height', 'auto');
7589					previewParAnimateHeight = previewPar.css('height');
7590					previewPar.css('height', previewParCurrentHeight);
7591
7592				}
7593
7594                // Content
7595                toggleContent = parentSection.find('> .toggle-content');
7596
7597                if (parentSection.hasClass('active')) {
7598
7599					$(previewPar).animate({
7600						height: previewParAnimateHeight
7601					}, self.options.duration, function() {
7602						$(this).addClass('preview-active');
7603					});
7604
7605					toggleContent.slideDown(self.options.duration, () => {
7606						if (closeElement) {
7607							closeElement.trigger('click');
7608						}
7609					});
7610
7611				} else {
7612
7613					$(previewPar).animate({
7614						height: 0
7615					}, self.options.duration, function() {
7616						$(this).removeClass('preview-active');
7617					});
7618
7619					toggleContent.slideUp(self.options.duration);
7620
7621				}
7622            });
7623        }
7624    }
7625
7626    PluginToggle.defaults = {
7627		duration: 350,
7628		isAccordion: false
7629	};
7630
7631    // expose to scope
7632    $.extend(theme, {
7633		PluginToggle
7634	});
7635
7636    // jquery plugin
7637    $.fn.themePluginToggle = function(opts) {
7638		return this.map(function() {
7639			const $this = $(this);
7640
7641			if ($this.data(instanceName)) {
7642				return $this.data(instanceName);
7643			} else {
7644				return new PluginToggle($this, opts);
7645			}
7646
7647		});
7648	}
7649})).apply(this, [window.theme, jQuery]);
7650
7651// Validation
7652(((theme = {}, $) => {
7653    $.extend(theme, {
7654
7655		PluginValidation: {
7656
7657			defaults: {
7658				formClass: 'needs-validation',
7659				validator: {
7660					highlight(element) {
7661						$(element)
7662							.addClass('is-invalid')
7663							.removeClass('is-valid')
7664							.parent()
7665							.removeClass('has-success')
7666							.addClass('has-danger');
7667					},
7668					success(label, element) {
7669						$(element)
7670							.removeClass('is-invalid')
7671							.addClass('is-valid')
7672							.parent()
7673							.removeClass('has-danger')
7674							.addClass('has-success')
7675							.find('label.error')
7676							.remove();
7677					},
7678					errorPlacement(error, element) {
7679						if (element.attr('type') == 'radio' || element.attr('type') == 'checkbox') {
7680							error.appendTo(element.parent().parent());
7681						} else {
7682							error.insertAfter(element);
7683						}
7684					}
7685				}
7686			},
7687
7688			initialize(opts) {
7689				initialized = true;
7690
7691				this
7692					.setOptions(opts)
7693					.build();
7694
7695				return this;
7696			},
7697
7698			setOptions(opts) {
7699				this.options = $.extend(true, {}, this.defaults, opts);
7700
7701				return this;
7702			},
7703
7704			build() {
7705				const self = this;
7706
7707				if (!($.isFunction($.validator))) {
7708					return this;
7709				}
7710
7711				self.setMessageGroups();
7712
7713				$.validator.setDefaults(self.options.validator);
7714
7715				$('.' + self.options.formClass).validate();
7716
7717				return this;
7718			},
7719
7720			setMessageGroups() {
7721
7722				$('.checkbox-group[data-msg-required], .radio-group[data-msg-required]').each(function() {
7723					const message = $(this).data('msg-required');
7724					$(this).find('input').attr('data-msg-required', message);
7725				});
7726
7727			}
7728
7729		}
7730
7731	});
7732})).apply(this, [window.theme, jQuery]);
7733
7734// Video Background
7735(((theme = {}, $) => {
7736    const instanceName = '__videobackground';
7737
7738    class PluginVideoBackground {
7739        constructor($el, opts) {
7740            return this.initialize($el, opts);
7741        }
7742
7743        initialize($el, opts) {
7744			this.$el = $el;
7745
7746			this
7747				.setData()
7748				.setOptions(opts)
7749				.build()
7750				.events();
7751
7752			return this;
7753		}
7754
7755        setData() {
7756			this.$el.data(instanceName, this);
7757
7758			return this;
7759		}
7760
7761        setOptions(opts) {
7762			this.options = $.extend(true, {}, PluginVideoBackground.defaults, opts, {
7763				path: this.$el.data('video-path'),
7764				wrapper: this.$el
7765			});
7766
7767			return this;
7768		}
7769
7770        build() {
7771			const self = this;
7772
7773			if (!($.isFunction($.fn.vide)) || (!this.options.path)) {
7774				return this;
7775			}
7776
7777			if (this.options.overlay) {
7778
7779				const overlayClass = this.options.overlayClass;
7780
7781				this.options.wrapper.prepend(
7782					$('<div />').addClass(overlayClass)
7783				);
7784			}
7785
7786			this.options.wrapper
7787				.vide(this.options.path, this.options)
7788				.first()
7789				.css('z-index', 0);
7790
7791			// Change Poster
7792			self.changePoster();
7793
7794			// Initialize Vide inside a carousel
7795			if( self.options.wrapper.closest('.owl-carousel').get(0) ) {
7796				self.options.wrapper.closest('.owl-carousel').on('initialized.owl.carousel', () => {
7797					$('.owl-item.cloned')
7798						.find('[data-plugin-video-background] .vide-video-wrapper')
7799						.remove();
7800
7801					$('.owl-item.cloned')
7802						.find('[data-plugin-video-background]')
7803						.vide(self.options.path, self.options)
7804						.first()
7805						.css('z-index', 0);
7806
7807					self.changePoster( self.options.wrapper.closest('.owl-carousel') );
7808				});
7809			}
7810
7811			// Play Video Button
7812			const $playButton = self.options.wrapper.find('.video-background-play');
7813
7814			if( $playButton.get(0) ) {
7815				const $playWrapper = self.options.wrapper.find('.video-background-play-wrapper');
7816
7817				self.options.wrapper.find('.video-background-play').on('click', e => {
7818					e.preventDefault();
7819
7820					if( $playWrapper.get(0) ) {
7821						$playWrapper.animate({
7822							opacity: 0
7823						}, 300, () => {
7824							$playWrapper.parent().height( $playWrapper.outerHeight() );
7825							$playWrapper.remove();
7826						});
7827					} else {
7828						$playButton.animate({
7829							opacity: 0
7830						}, 300, () => {
7831							$playButton.remove();
7832						});
7833					}
7834
7835					setTimeout(() => {
7836						self.options.wrapper.find('video')[0].play();
7837					}, 500)
7838				});
7839			}
7840
7841			$(window).trigger('vide.video.inserted.on.dom');
7842
7843			return this;
7844		}
7845
7846        changePoster($carousel) {
7847			const self = this;
7848
7849			// If it's inside carousel
7850			if( $carousel && self.options.changePoster ) {
7851				$carousel.find('.owl-item [data-plugin-video-background] .vide-video-wrapper').css({
7852					'background-image': 'url(' + self.options.changePoster + ')'
7853				});
7854
7855				return this;
7856			}
7857
7858			if( self.options.changePoster ) {
7859				self.options.wrapper.find('.vide-video-wrapper').css({
7860					'background-image': 'url(' + self.options.changePoster + ')'
7861				});
7862			}
7863
7864			return this;
7865		}
7866
7867        events() {
7868			const self = this;
7869
7870			// Initialize
7871			self.options.wrapper.on('video.background.initialize', () => {
7872				self.build();
7873			});
7874
7875			return this;
7876		}
7877    }
7878
7879    PluginVideoBackground.defaults = {
7880		overlay: false,
7881		volume: 1,
7882		playbackRate: 1,
7883		muted: true,
7884		loop: true,
7885		autoplay: true,
7886		position: '50% 50%',
7887		posterType: 'detect',
7888		className: 'vide-video-wrapper'
7889	};
7890
7891    // expose to scope
7892    $.extend(theme, {
7893		PluginVideoBackground
7894	});
7895
7896    // jquery plugin
7897    $.fn.themePluginVideoBackground = function(opts) {
7898		return this.map(function() {
7899			const $this = $(this);
7900
7901			if ($this.data(instanceName)) {
7902				return $this.data(instanceName);
7903			} else {
7904				return new PluginVideoBackground($this, opts);
7905			}
7906
7907		});
7908	}
7909})).apply(this, [window.theme, jQuery]);
7910
7911// Account
7912(((theme = {}, $) => {
7913    let initialized = false;
7914
7915    $.extend(theme, {
7916
7917		Account: {
7918
7919			defaults: {
7920				wrapper: $('#headerAccount')
7921			},
7922
7923			initialize($wrapper, opts) {
7924				if (initialized) {
7925					return this;
7926				}
7927
7928				initialized = true;
7929				this.$wrapper = ($wrapper || this.defaults.wrapper);
7930
7931				this
7932					.setOptions(opts)
7933					.events();
7934
7935				return this;
7936			},
7937
7938			setOptions(opts) {
7939				this.options = $.extend(true, {}, this.defaults, opts, theme.fn.getOptions(this.$wrapper.data('plugin-options')));
7940
7941				return this;
7942			},
7943
7944			events() {
7945				const self = this;
7946
7947				$(window).on('load', () => {
7948					$(document).ready(() => {
7949						setTimeout(() => {
7950
7951							self.$wrapper.find('input').on('focus', () => {
7952								self.$wrapper.addClass('open');
7953
7954								$(document).mouseup(({target}) => {
7955									if (!self.$wrapper.is(target) && self.$wrapper.has(target).length === 0) {
7956										self.$wrapper.removeClass('open');
7957									}
7958								});
7959							});
7960
7961						}, 1500);
7962					});
7963				});
7964
7965				$('#headerSignUp').on('click', e => {
7966					e.preventDefault();
7967					self.$wrapper.addClass('signup').removeClass('signin').removeClass('recover');
7968					self.$wrapper.find('.signup-form input:first').focus();
7969				});
7970
7971				$('#headerSignIn').on('click', e => {
7972					e.preventDefault();
7973					self.$wrapper.addClass('signin').removeClass('signup').removeClass('recover');
7974					self.$wrapper.find('.signin-form input:first').focus();
7975				});
7976
7977				$('#headerRecover').on('click', e => {
7978					e.preventDefault();
7979					self.$wrapper.addClass('recover').removeClass('signup').removeClass('signin');
7980					self.$wrapper.find('.recover-form input:first').focus();
7981				});
7982
7983				$('#headerRecoverCancel').on('click', e => {
7984					e.preventDefault();
7985					self.$wrapper.addClass('signin').removeClass('signup').removeClass('recover');
7986					self.$wrapper.find('.signin-form input:first').focus();
7987				});
7988			}
7989
7990		}
7991
7992	});
7993})).apply(this, [window.theme, jQuery]);
7994
7995// Nav
7996(((theme = {}, $) => {
7997    let initialized = false;
7998
7999    $.extend(theme, {
8000
8001		Nav: {
8002
8003			defaults: {
8004				wrapper: $('#mainNav'),
8005				scrollDelay: 600,
8006				scrollAnimation: 'easeOutQuad'
8007			},
8008
8009			initialize($wrapper, opts) {
8010				if (initialized) {
8011					return this;
8012				}
8013
8014				initialized = true;
8015				this.$wrapper = ($wrapper || this.defaults.wrapper);
8016
8017				this
8018					.setOptions(opts)
8019					.build()
8020					.events();
8021
8022				return this;
8023			},
8024
8025			setOptions(opts) {
8026				this.options = $.extend(true, {}, this.defaults, opts, theme.fn.getOptions(this.$wrapper.data('plugin-options')));
8027
8028				return this;
8029			},
8030
8031			build() {
8032                const self = this;
8033                const $html = $('html');
8034                const $header = $('#header');
8035                const $headerNavMain = $('#header .header-nav-main');
8036                let thumbInfoPreview;
8037
8038                // Preview Thumbs
8039                if( self.$wrapper.find('a[data-thumb-preview]').length ) {
8040					self.$wrapper.find('a[data-thumb-preview]').each(function() {
8041						thumbInfoPreview = $('<span />').addClass('thumb-info thumb-info-preview')
8042												.append($('<span />').addClass('thumb-info-wrapper')
8043													.append($('<span />').addClass('thumb-info-image').css('background-image', 'url(' + $(this).data('thumb-preview') + ')')
8044											   )
8045										   );
8046
8047						$(this).append(thumbInfoPreview);
8048					});
8049				}
8050
8051                // Side Header / Side Header Hamburguer Sidebar (Reverse Dropdown)
8052                if($html.hasClass('side-header') || $html.hasClass('side-header-hamburguer-sidebar')) {
8053					
8054					// Side Header Right / Side Header Hamburguer Sidebar Right
8055					if($html.hasClass('side-header-right') || $html.hasClass('side-header-hamburguer-sidebar-right')) {
8056						if(!$html.hasClass('side-header-right-no-reverse')) {
8057							$header.find('.dropdown-submenu').addClass('dropdown-reverse');
8058						}
8059					}
8060
8061				} else {
8062					
8063					// Reverse
8064					let checkReverseFlag = false;
8065					self.checkReverse = () => {
8066						if( !checkReverseFlag ) {
8067							self.$wrapper.find('.dropdown, .dropdown-submenu').removeClass('dropdown-reverse');
8068
8069							self.$wrapper.find('.dropdown:not(.manual):not(.dropdown-mega), .dropdown-submenu:not(.manual)').each(function() {
8070								if(!$(this).find('.dropdown-menu').visible( false, true, 'horizontal' )  ) {
8071									$(this).addClass('dropdown-reverse');
8072								}
8073							});
8074
8075							checkReverseFlag = true;
8076						}
8077					}
8078
8079					$(window).on('resize', () => {
8080						checkReverseFlag = false;
8081					});
8082
8083					$header.on('mouseover', () => {
8084						self.checkReverse();
8085					});
8086
8087				}
8088
8089                // Clone Items
8090                if($headerNavMain.hasClass('header-nav-main-clone-items')) {
8091
8092			    	$headerNavMain.find('nav > ul > li > a').each(function(){
8093				    	const parent = $(this).parent(), clone  = $(this).clone(), clone2 = $(this).clone(), wrapper = $('<span class="wrapper-items-cloned"></span>');
8094
8095				    	// Config Classes
8096				    	$(this).addClass('item-original');
8097				    	clone2.addClass('item-two');
8098
8099				    	// Insert on DOM
8100				    	parent.prepend(wrapper);
8101				    	wrapper.append(clone).append(clone2);
8102				    });
8103
8104				}
8105
8106                // Floating
8107                if($('#header.header-floating-icons').length && $(window).width() > 991) {
8108
8109					const menuFloatingAnim = {
8110						$menuFloating: $('#header.header-floating-icons .header-container > .header-row'),
8111
8112						build() {
8113							const self = this;
8114
8115							self.init();
8116						},
8117						init() {
8118                            const self  = this;
8119                            let divisor = 0;
8120
8121                            $(window).scroll(function() {
8122							    const scrollPercent = 100 * $(window).scrollTop() / ($(document).height() - $(window).height()), st = $(this).scrollTop();
8123
8124								divisor = $(document).height() / $(window).height();
8125
8126							    self.$menuFloating.find('.header-column > .header-row').css({
8127							    	transform : 'translateY( calc('+ scrollPercent +'vh - '+ st / divisor +'px) )' 
8128							    });
8129							});
8130                        }
8131					};
8132
8133					menuFloatingAnim.build();
8134
8135				}
8136
8137                // Slide
8138                if($('.header-nav-links-vertical-slide').length) {
8139					const slideNavigation = {
8140						$mainNav: $('#mainNav'),
8141						$mainNavItem: $('#mainNav li'),
8142
8143						build() {
8144							const self = this;
8145
8146							self.menuNav();
8147						},
8148						menuNav() {
8149							const self = this;
8150
8151							self.$mainNavItem.on('click', function(e){
8152								const currentMenuItem 	= $(this), currentMenu 		= $(this).parent(), nextMenu        	= $(this).find('ul').first(), prevMenu        	= $(this).closest('.next-menu'), isSubMenu       	= currentMenuItem.hasClass('dropdown') || currentMenuItem.hasClass('dropdown-submenu'), isBack          	= currentMenuItem.hasClass('back-button'), nextMenuHeightDiff  = ( ( nextMenu.find('> li').length * nextMenu.find('> li').outerHeight() ) - nextMenu.outerHeight() ), prevMenuHeightDiff  = ( ( prevMenu.find('> li').length * prevMenu.find('> li').outerHeight() ) - prevMenu.outerHeight() );
8153
8154								if( isSubMenu ) {
8155									currentMenu.addClass('next-menu');
8156									nextMenu.addClass('visible');
8157									currentMenu.css({
8158										overflow: 'visible',
8159										'overflow-y': 'visible'
8160									});
8161									
8162									if( nextMenuHeightDiff > 0 ) {
8163										nextMenu.css({
8164											overflow: 'hidden',
8165											'overflow-y': 'scroll'
8166										});
8167									}
8168
8169									for( i = 0; i < nextMenu.find('> li').length; i++ ) {
8170										if( nextMenu.outerHeight() < ($('.header-row-side-header').outerHeight() - 100) ) {
8171											nextMenu.css({
8172												height: nextMenu.outerHeight() + nextMenu.find('> li').outerHeight()
8173											});
8174										}
8175									}
8176
8177									nextMenu.css({
8178										'padding-top': nextMenuHeightDiff + 'px'
8179									});
8180								}
8181
8182								if( isBack ) {
8183									currentMenu.parent().parent().removeClass('next-menu');
8184									currentMenu.removeClass('visible');
8185
8186									if( prevMenuHeightDiff > 0 ) {
8187										prevMenu.css({
8188											overflow: 'hidden',
8189											'overflow-y': 'scroll'
8190										});
8191									}
8192								}
8193
8194								e.stopPropagation();
8195							});
8196						}
8197					};
8198
8199					$(window).trigger('resize');
8200					
8201					if( $(window).width() > 991 ) {
8202						slideNavigation.build();
8203					}
8204
8205					$(document).ready(() => {
8206						$(window).afterResize(() => {
8207							if( $(window).width() > 991 ) {
8208								slideNavigation.build();
8209							}
8210						});
8211					});
8212				}
8213
8214                // Header Nav Main Mobile Dark
8215                if($('.header-nav-main-mobile-dark').length) {
8216					$('#header:not(.header-transparent-dark-bottom-border):not(.header-transparent-light-bottom-border)').addClass('header-no-border-bottom');
8217				}
8218
8219                // Keyboard Navigation / Accessibility
8220                if( $(window).width() > 991 ) {
8221					let focusFlag = false;
8222					$header.find('.header-nav-main nav > ul > li > a').on('focus', function(){
8223						
8224						if( $(window).width() > 991 ) {
8225							if( !focusFlag ) {
8226								focusFlag = true;
8227								$(this).trigger('blur');
8228								
8229								self.focusMenuWithChildren();
8230							}
8231						}
8232
8233					});
8234				}
8235
8236                return this;
8237            },
8238
8239			focusMenuWithChildren() {
8240                // Get all the link elements within the primary menu.
8241                let links;
8242
8243                let i;
8244                let len;
8245                const menu = document.querySelector( 'html:not(.side-header):not(.side-header-hamburguer-sidebar):not(.side-header-overlay-full-screen) .header-nav-main > nav' );
8246
8247                if ( ! menu ) {
8248					return false;
8249				}
8250
8251                links = menu.getElementsByTagName( 'a' );
8252
8253                // Each time a menu link is focused or blurred, toggle focus.
8254                for ( i = 0, len = links.length; i < len; i++ ) {
8255					links[i].addEventListener( 'focus', toggleFocus, true );
8256					links[i].addEventListener( 'blur', toggleFocus, true );
8257				}
8258
8259                //Sets or removes the .focus class on an element.
8260                function toggleFocus() {
8261					let self = this;
8262
8263					// Move up through the ancestors of the current link until we hit .primary-menu.
8264					while ( !self.className.includes('header-nav-main') ) {
8265						// On li elements toggle the class .focus.
8266						if ( 'li' === self.tagName.toLowerCase() ) {
8267							if ( self.className.includes('accessibility-open') ) {
8268								self.className = self.className.replace( ' accessibility-open', '' );
8269							} else {
8270								self.className += ' accessibility-open';
8271							}
8272						}
8273						self = self.parentElement;
8274					}
8275				}
8276            },
8277
8278			events() {
8279                const self    = this;
8280                const $html   = $('html');
8281                let $header = $('#header');
8282                const $window = $(window);
8283                let headerBodyHeight = $('.header-body').outerHeight();
8284
8285                if( $header.hasClass('header') ) {
8286					$header = $('.header');
8287				}
8288
8289                $header.find('a[href="#"]').on('click', e => {
8290					e.preventDefault();
8291				});
8292
8293                // Mobile Arrows
8294                if( $html.hasClass('side-header-hamburguer-sidebar') ) {
8295					$header.find('.dropdown-toggle, .dropdown-submenu > a')
8296						.append('<i class="fas fa-chevron-down fa-chevron-right"></i>');
8297				} else {
8298					$header.find('.dropdown-toggle, .dropdown-submenu > a')
8299						.append('<i class="fas fa-chevron-down"></i>');
8300				}
8301
8302                $header.find('.dropdown-toggle[href="#"], .dropdown-submenu a[href="#"], .dropdown-toggle[href!="#"] .fa-chevron-down, .dropdown-submenu a[href!="#"] .fa-chevron-down').on('click', function(e) {
8303					e.preventDefault();
8304					if ($window.width() < 992) {
8305						$(this).closest('li').toggleClass('open');
8306
8307						// Adjust Header Body Height
8308						const height = ( $header.hasClass('header-effect-shrink') && $html.hasClass('sticky-header-active') ) ? theme.StickyHeader.options.stickyHeaderContainerHeight : headerBodyHeight;
8309						$('.header-body').animate({
8310					 		height: ($('.header-nav-main nav').outerHeight(true) + height) + 10
8311					 	}, 0);
8312					}
8313				});
8314
8315                $header.find('li a.active').addClass('current-page-active');
8316
8317                // Add Open Class
8318                $header.find('.header-nav-click-to-open .dropdown-toggle[href="#"], .header-nav-click-to-open .dropdown-submenu a[href="#"], .header-nav-click-to-open .dropdown-toggle > i').on('click', function(e) {
8319					if( !$('html').hasClass('side-header-hamburguer-sidebar') && $window.width() > 991 ) {
8320						e.preventDefault();
8321						e.stopPropagation();
8322					}
8323
8324					if ($window.width() > 991) {
8325						e.preventDefault();
8326						e.stopPropagation();
8327
8328						$header.find('li a.active').removeClass('active');
8329
8330						if( $(this).prop('tagName') == 'I' ) {
8331							$(this).parent().addClass('active');
8332						} else {
8333							$(this).addClass('active');
8334						}
8335
8336						if (!$(this).closest('li').hasClass('open')) {
8337                            const $li = $(this).closest('li');
8338                            let isSub = false;
8339
8340                            if( $(this).prop('tagName') == 'I' ) {
8341								$('#header .dropdown.open').removeClass('open');
8342								$('#header .dropdown-menu .dropdown-submenu.open').removeClass('open');
8343							}
8344
8345                            if ( $(this).parent().hasClass('dropdown-submenu') ) {
8346								isSub = true;
8347							}
8348
8349                            $(this).closest('.dropdown-menu').find('.dropdown-submenu.open').removeClass('open');
8350                            $(this).parent('.dropdown').parent().find('.dropdown.open').removeClass('open');
8351
8352                            if (!isSub) {
8353								$(this).parent().find('.dropdown-submenu.open').removeClass('open');
8354							}
8355
8356                            $li.addClass('open');
8357
8358                            $(document).off('click.nav-click-to-open').on('click.nav-click-to-open', ({target}) => {
8359								if (!$li.is(target) && $li.has(target).length === 0) {
8360									$li.removeClass('open');
8361									$li.parents('.open').removeClass('open');
8362									$header.find('li a.active').removeClass('active');
8363									$header.find('li a.current-page-active').addClass('active');
8364								}
8365							});
8366                        } else {
8367							$(this).closest('li').removeClass('open');
8368							$header.find('li a.active').removeClass('active');
8369							$header.find('li a.current-page-active').addClass('active');
8370						}
8371
8372						$window.trigger({
8373							type: 'resize',
8374							from: 'header-nav-click-to-open'
8375						});
8376					}
8377				});
8378
8379                // Collapse Nav
8380                $header.find('[data-collapse-nav]').on('click', function(e) {
8381					$(this).parents('.collapse').removeClass('show');
8382				});
8383
8384                // Top Features
8385                $header.find('.header-nav-features-toggle').on('click', function(e) {
8386					e.preventDefault();
8387
8388					const $toggleParent = $(this).parent();
8389
8390					if (!$(this).siblings('.header-nav-features-dropdown').hasClass('show')) {
8391
8392						const $dropdown = $(this).siblings('.header-nav-features-dropdown');
8393
8394						$('.header-nav-features-dropdown.show').removeClass('show');
8395
8396						$dropdown.addClass('show');
8397
8398						$(document).off('click.header-nav-features-toggle').on('click.header-nav-features-toggle', ({target}) => {
8399							if (!$toggleParent.is(target) && $toggleParent.has(target).length === 0) {
8400								$('.header-nav-features-dropdown.show').removeClass('show');
8401							}
8402						});
8403
8404						if ($(this).attr('data-focus')) {
8405							$('#' + $(this).attr('data-focus')).focus();
8406						}
8407
8408					} else {
8409						$(this).siblings('.header-nav-features-dropdown').removeClass('show');
8410					}
8411				});
8412
8413                // Hamburguer Menu
8414                const $hamburguerMenuBtn = $('.hamburguer-btn:not(.side-panel-toggle)'), $hamburguerSideHeader = $('#header.side-header, #header.side-header-overlay-full-screen');
8415
8416                $hamburguerMenuBtn.on('click', function(){
8417					if($(this).attr('data-set-active') != 'false') {
8418						$(this).toggleClass('active');
8419					}
8420					$hamburguerSideHeader.toggleClass('side-header-hide');
8421					$html.toggleClass('side-header-hide');
8422
8423					$window.trigger('resize');
8424				});
8425
8426                // Toggle Side Header
8427                $('.toggle-side-header').on('click', () => {
8428					$('.hamburguer-btn-side-header.active').trigger('click');
8429				});
8430
8431                $('.hamburguer-close:not(.side-panel-toggle)').on('click', () => {
8432					$('.hamburguer-btn:not(.hamburguer-btn-side-header-mobile-show)').trigger('click');
8433				});
8434
8435                // Set Header Body Height when open mobile menu
8436                $('.header-nav-main nav').on('show.bs.collapse', function () {
8437				 	$(this).removeClass('closed');
8438
8439				 	// Add Mobile Menu Opened Class
8440				 	$('html').addClass('mobile-menu-opened');
8441
8442			 		$('.header-body').animate({
8443				 		height: ($('.header-body').outerHeight() + $('.header-nav-main nav').outerHeight(true)) + 10
8444				 	});
8445
8446				 	// Header Below Slider / Header Bottom Slider - Scroll to menu position
8447				 	if( $('#header').is('.header-bottom-slider, .header-below-slider') && !$('html').hasClass('sticky-header-active') ) {
8448				 		self.scrollToTarget( $('#header'), 0 );
8449				 	}
8450				});
8451
8452                // Set Header Body Height when collapse mobile menu
8453                $('.header-nav-main nav').on('hide.bs.collapse', function () {
8454				 	$(this).addClass('closed');
8455
8456				 	// Remove Mobile Menu Opened Class
8457				 	$('html').removeClass('mobile-menu-opened');
8458
8459			 		$('.header-body').animate({
8460				 		height: ($('.header-body').outerHeight() - $('.header-nav-main nav').outerHeight(true))
8461				 	}, function(){
8462				 		$(this).height('auto');
8463				 	});
8464				});
8465
8466                // Header Effect Shrink - Adjust header body height on mobile
8467                $window.on('stickyHeader.activate', () => {
8468					if( $window.width() < 992 && $header.hasClass('header-effect-shrink') ) {
8469						if( $('.header-btn-collapse-nav').attr('aria-expanded') == 'true' ) {
8470							$('.header-body').animate({
8471						 		height: ( $('.header-nav-main nav').outerHeight(true) + theme.StickyHeader.options.stickyHeaderContainerHeight ) + ( ($('.header-nav-bar').length) ? $('.header-nav-bar').outerHeight() : 0 ) 
8472						 	});
8473						}
8474					}
8475				});
8476
8477                $window.on('stickyHeader.deactivate', () => {
8478					if( $window.width() < 992 && $header.hasClass('header-effect-shrink') ) {
8479						if( $('.header-btn-collapse-nav').attr('aria-expanded') == 'true' ) {
8480							$('.header-body').animate({
8481						 		height: headerBodyHeight + $('.header-nav-main nav').outerHeight(true) + 10
8482						 	});
8483						}
8484					}
8485				});
8486
8487                // Remove Open Class on Resize		
8488                $window.on('resize.removeOpen', ({from}) => {
8489					if( from == 'header-nav-click-to-open' ) {
8490						return;
8491					}
8492					
8493					setTimeout(() => {
8494						if( $window.width() > 991 ) {
8495							$header.find('.dropdown.open').removeClass('open');
8496						}
8497					}, 100);
8498				});
8499
8500                // Side Header - Change value of initial header body height
8501                $(document).ready(() => {
8502					if( $window.width() > 991 ) {
8503						let flag = false;
8504						
8505						$window.on('resize', ({from}) => {
8506							if( from == 'header-nav-click-to-open' ) {
8507								return;
8508							}
8509
8510							$header.find('.dropdown.open').removeClass('open');
8511
8512							if( $window.width() < 992 && flag == false ) {
8513								headerBodyHeight = $('.header-body').outerHeight();
8514								flag = true;
8515
8516								setTimeout(() => {
8517									flag = false;
8518								}, 500);
8519							}
8520						});
8521					}
8522				});
8523
8524                // Side Header - Set header height on mobile
8525                if( $html.hasClass('side-header') ) {
8526					if( $window.width() < 992 ) {
8527						$header.css({
8528							height: $('.header-body .header-container').outerHeight() + (parseInt( $('.header-body').css('border-top-width') ) + parseInt( $('.header-body').css('border-bottom-width') ))
8529						});
8530					}
8531
8532					$(document).ready(() => {
8533						$window.afterResize(() => {
8534							if( $window.width() < 992 ) {
8535								$header.css({
8536									height: $('.header-body .header-container').outerHeight() + (parseInt( $('.header-body').css('border-top-width') ) + parseInt( $('.header-body').css('border-bottom-width') ))
8537								});
8538							} else {
8539								$header.css({
8540									height: ''
8541								});
8542							}
8543						});
8544					});
8545				}
8546
8547                // Anchors Position
8548                if( $('[data-hash]').length ) {
8549					$('[data-hash]').on('mouseover', function(){
8550						const $this = $(this);
8551
8552						if( !$this.data('__dataHashBinded') ) {
8553                            let target = $this.attr('href');
8554                            let offset = ($this.is("[data-hash-offset]") ? $this.data('hash-offset') : 0);
8555                            const delay  = ($this.is("[data-hash-delay]") ? $this.data('hash-delay') : 0);
8556                            const force  = ($this.is("[data-hash-force]") ? true : false);
8557                            const windowWidth = $(window).width();
8558
8559                            // Hash Offset SM
8560                            if ($this.is("[data-hash-offset-sm]") && windowWidth > 576) {
8561								offset = $this.data('hash-offset-sm');
8562							}
8563
8564                            // Hash Offset MD
8565                            if ($this.is("[data-hash-offset-md]") && windowWidth > 768) {
8566								offset = $this.data('hash-offset-md');
8567							}
8568
8569                            // Hash Offset LG
8570                            if ($this.is("[data-hash-offset-lg]") && windowWidth > 992) {
8571								offset = $this.data('hash-offset-lg');
8572							}
8573
8574                            // Hash Offset XL
8575                            if ($this.is("[data-hash-offset-xl]") && windowWidth > 1200) {
8576								offset = $this.data('hash-offset-xl');
8577							}
8578
8579                            // Hash Offset XXL
8580                            if ($this.is("[data-hash-offset-xxl]") && windowWidth > 1400) {
8581								offset = $this.data('hash-offset-xxl');
8582							}
8583
8584                            if( !$(target).length ) {
8585								target = target.split('#');
8586								target = '#'+target[1];
8587							}
8588
8589                            if( target.includes('#') && $(target).length) {
8590								$this.on('click', e => {
8591									e.preventDefault();
8592
8593									if( !$(e.target).is('i') || force ) {
8594
8595										setTimeout(() => {
8596
8597											// Close Collapse if open
8598											$this.parents('.collapse.show').collapse('hide');
8599
8600											// Close Side Header
8601											$hamburguerSideHeader.addClass('side-header-hide');
8602											$html.addClass('side-header-hide');
8603											
8604											$window.trigger('resize');
8605
8606											self.scrollToTarget(target, offset);
8607
8608											// Data Hash Trigger Click
8609											if( $this.data('hash-trigger-click') ) {
8610
8611												const $clickTarget = $( $this.data('hash-trigger-click') ), clickDelay = $this.data('hash-trigger-click-delay') ? $this.data('hash-trigger-click-delay') : 0;
8612
8613												if( $clickTarget.length ) {
8614
8615													setTimeout(() => {
8616														// If is a "Tabs" plugin link
8617														if( $clickTarget.closest('.nav-tabs').length ) {
8618															new bootstrap.Tab( $clickTarget[0] ).show();
8619														} else {
8620															$clickTarget.trigger('click');
8621														}
8622														
8623													}, clickDelay);
8624												}
8625
8626											}
8627
8628										}, delay);
8629										
8630									}
8631
8632									return;
8633								});
8634							}
8635
8636                            $(this).data('__dataHashBinded', true);
8637                        }
8638					});
8639				}
8640
8641                // Floating
8642                if($('#header.header-floating-icons').length) {
8643
8644					$('#header.header-floating-icons [data-hash]').off().each(function() {
8645
8646						const target = $(this).attr('href'), offset = ($(this).is("[data-hash-offset]") ? $(this).data('hash-offset') : 0);
8647
8648						if($(target).length) {
8649							$(this).on('click', e => {
8650								e.preventDefault();
8651
8652									$('html, body').animate({
8653										scrollTop: $(target).offset().top - offset
8654									}, 600, 'easeOutQuad', () => {
8655
8656									});
8657
8658								return;
8659							});
8660						}
8661
8662					});
8663
8664				}
8665
8666                // Side Panel Toggle
8667                if( $('.side-panel-toggle').length ) {
8668					const init_html_class = $('html').attr('class');
8669
8670					$('.side-panel-toggle').on('click', function(e){
8671						const extra_class = $(this).data('extra-class'), delay       = ( extra_class ) ? 100 : 0, isActive    = $(this).data('is-active') ? $(this).data('is-active') : false;
8672
8673						e.preventDefault();
8674
8675						if( isActive ) {
8676							$('html').removeClass('side-panel-open');
8677							$(this).data('is-active', false);
8678							return false;
8679						}
8680
8681						if( extra_class ) {
8682							$('.side-panel-wrapper').css('transition','none');
8683							$('html')
8684								.removeClass()
8685								.addClass( init_html_class )
8686								.addClass( extra_class );
8687						}
8688						setTimeout(() => {
8689							$('.side-panel-wrapper').css('transition','');
8690							$('html').toggleClass('side-panel-open');
8691						}, delay);
8692
8693						$(this).data('is-active', true);						
8694					});
8695
8696					$(document).on('click', ({target}) => {
8697						if( !$(target).closest('.side-panel-wrapper').length && !$(target).hasClass('side-panel-toggle') ) {
8698							$('.hamburguer-btn.side-panel-toggle:not(.side-panel-close)').removeClass('active');
8699							$('html').removeClass('side-panel-open');
8700							$('.side-panel-toggle').data('is-active', false);
8701						}
8702					});
8703				}
8704
8705				// OffCanvas
8706				self.offCanvasMenu();
8707
8708                return this;
8709            },
8710
8711			scrollToTarget(target, offset) {
8712				const self = this, targetPosition = $(target).offset().top;
8713
8714				$('body').addClass('scrolling');
8715
8716				$('html, body').animate({
8717					scrollTop: $(target).offset().top - offset
8718				}, self.options.scrollDelay, self.options.scrollAnimation, () => {
8719					$('body').removeClass('scrolling');
8720
8721					// If by some reason the scroll finishes in a wrong position, this code will run the scrollToTarget() again until get the correct position
8722					// We need do it just one time to prevent infinite recursive loop at scrollToTarget() function
8723					if( $(target).offset().top !=  targetPosition) {
8724						$('html, body').animate({
8725							scrollTop: $(target).offset().top - offset
8726						}, 1, self.options.scrollAnimation, () => {});
8727					}
8728				});
8729
8730				return this;
8731
8732			},
8733
8734			offCanvasMenu() {
8735                const $headerNavMain = $('#header .header-nav-main');
8736				const $offCanvasNav = $('.offcanvas-nav');
8737
8738				if($offCanvasNav.length > 0) {
8739					const $navToClone = $headerNavMain.find('nav');
8740
8741					if($navToClone.length > 0) {
8742						$offCanvasNav.html($offCanvasNav.html() + $navToClone.html());
8743						$offCanvasNav.find('#mainNav').removeAttr('id').removeClass().addClass('nav flex-column w-100');
8744
8745						// Clean Classes
8746						$offCanvasNav.find('.dropdown').removeClass().addClass('dropdown');
8747
8748						$offCanvasNav.find('.dropdown-item:not(.dropdown-toggle)').removeClass().addClass('dropdown-item');
8749						$offCanvasNav.find('.dropdown-item.dropdown-toggle').removeClass().addClass('dropdown-item dropdown-toggle');
8750
8751						$offCanvasNav.find('.nav-link:not(.dropdown-toggle)').removeClass().addClass('nav-link');
8752						$offCanvasNav.find('.nav-link.dropdown-toggle').removeClass().addClass('nav-link dropdown-toggle');
8753
8754						$offCanvasNav.find('.dropdown-menu').removeClass().addClass('dropdown-menu');
8755
8756						// Dropdowns
8757						$offCanvasNav.find('.dropdown-toggle').each(function() {
8758							const $el = $(this);
8759							const $arrow = $el.find('i');
8760
8761							$arrow.on('click', function(e) {
8762								e.preventDefault();
8763								e.stopPropagation();
8764								$el.parents('li').toggleClass('open');
8765							})
8766
8767							if ($el.attr('href') == '#') {
8768								$el.on('click', function() {
8769									$arrow.trigger('click');
8770								});
8771							}
8772						});
8773					}
8774				}
8775
8776				return this;
8777			}
8778
8779		}
8780
8781	});
8782})).apply(this, [window.theme, jQuery]);
8783
8784
8785// Newsletter
8786(((theme = {}, $) => {
8787    let initialized = false;
8788
8789    $.extend(theme, {
8790
8791		Newsletter: {
8792
8793			defaults: {
8794				wrapper: $('#newsletterForm')
8795			},
8796
8797			initialize($wrapper, opts) {
8798				if (initialized) {
8799					return this;
8800				}
8801
8802				initialized = true;
8803				this.$wrapper = ($wrapper || this.defaults.wrapper);
8804
8805				this
8806					.setOptions(opts)
8807					.build();
8808
8809				return this;
8810			},
8811
8812			setOptions(opts) {
8813				this.options = $.extend(true, {}, this.defaults, opts, theme.fn.getOptions(this.$wrapper.data('plugin-options')));
8814
8815				return this;
8816			},
8817
8818			build() {
8819				if (!($.isFunction($.fn.validate))) {
8820					return this;
8821				}
8822
8823				const self = this, $email = self.$wrapper.find('#newsletterEmail'), $success = $('#newsletterSuccess'), $error = $('#newsletterError');
8824
8825				self.$wrapper.validate({
8826					submitHandler(form) {
8827
8828						$.ajax({
8829							type: 'POST',
8830							url: self.$wrapper.attr('action'),
8831							data: {
8832								'email': $email.val()
8833							},
8834							dataType: 'json',
8835							success({response, message}) {
8836								if (response == 'success') {
8837
8838									$success.removeClass('d-none');
8839									$error.addClass('d-none');
8840
8841									$email
8842										.val('')
8843										.blur()
8844										.closest('.control-group')
8845										.removeClass('success')
8846										.removeClass('error');
8847
8848								} else {
8849
8850									$error.html(message);
8851									$error.removeClass('d-none');
8852									$success.addClass('d-none');
8853
8854									$email
8855										.blur()
8856										.closest('.control-group')
8857										.removeClass('success')
8858										.addClass('error');
8859
8860								}
8861							}
8862						});
8863
8864					},
8865					rules: {
8866						newsletterEmail: {
8867							required: true,
8868							email: true
8869						}
8870					},
8871					errorPlacement(error, element) {
8872
8873					}
8874				});
8875
8876				return this;
8877			}
8878
8879		}
8880
8881	});
8882})).apply(this, [window.theme, jQuery]);
8883
8884// Search
8885(((theme = {}, $) => {
8886    let initialized = false;
8887
8888    $.extend(theme, {
8889
8890		Search: {
8891
8892			defaults: {
8893				wrapper: $('#searchForm')
8894			},
8895
8896			initialize($wrapper, opts) {
8897				if (initialized) {
8898					return this;
8899				}
8900
8901				initialized = true;
8902				this.$wrapper = ($wrapper || this.defaults.wrapper);
8903
8904				this
8905					.setOptions(opts)
8906					.build();
8907
8908				return this;
8909			},
8910
8911			setOptions(opts) {
8912				this.options = $.extend(true, {}, this.defaults, opts, theme.fn.getOptions(this.$wrapper.data('plugin-options')));
8913
8914				return this;
8915			},
8916
8917			build() {
8918				if (!($.isFunction($.fn.validate))) {
8919					return this;
8920				}
8921
8922				this.$wrapper.validate({
8923					errorPlacement(error, element) {}
8924				});
8925
8926				// Search Reveal
8927				theme.fn.execOnceTroughEvent( '#header', 'mouseover.search.reveal', () => {
8928					$('.header-nav-features-search-reveal').each(function() {
8929						const $el = $(this), $header = $('#header'), $html = $('html');
8930
8931						$el.find('.header-nav-features-search-show-icon').on('click', () => {
8932							$el.addClass('show');
8933							$header.addClass('search-show');
8934							$html.addClass('search-show');
8935							$('#headerSearch').focus();
8936						});
8937
8938						$el.find('.header-nav-features-search-hide-icon').on('click', () => {
8939							$el.removeClass('show');
8940							$header.removeClass('search-show');
8941							$html.removeClass('search-show');
8942						});
8943					});
8944				} );
8945
8946				return this;
8947			}
8948
8949		}
8950
8951	});
8952})).apply(this, [window.theme, jQuery]);
8953
8954// Sticky Header
8955(((theme = {}, $) => {
8956    let initialized = false;
8957
8958    $.extend(theme, {
8959
8960		StickyHeader: {
8961
8962			defaults: {
8963				wrapper: $('#header'),
8964				headerBody: $('#header .header-body'),
8965				stickyEnabled: true,
8966				stickyEnableOnBoxed: true,
8967				stickyEnableOnMobile: false,
8968				stickyStartAt: 0,
8969				stickyStartAtElement: false,
8970				stickySetTop: 0,
8971				stickyEffect: '',
8972				stickyHeaderContainerHeight: false,
8973				stickyChangeLogo: false,
8974				stickyChangeLogoWrapper: true,
8975				stickyForce: false,
8976				stickyScrollUp: false,
8977				stickyScrollValue: 0
8978			},
8979
8980			initialize($wrapper, opts) {
8981				if (initialized) {
8982					return this;
8983				}				
8984
8985				initialized = true;
8986				this.$wrapper = ($wrapper || this.defaults.wrapper);
8987
8988				if( this.$wrapper.hasClass('header') ) {
8989					this.$wrapper = $('.header[data-plugin-options]');
8990				}
8991
8992				this
8993					.setOptions(opts)
8994					.build()
8995					.events();
8996
8997				return this;
8998			},
8999
9000			setOptions(opts) {
9001				this.options = $.extend(true, {}, this.defaults, opts, theme.fn.getOptions(this.$wrapper.data('plugin-options')));
9002				return this;
9003			},
9004
9005			build() {
9006                if( $(window).width() < 992 && this.options.stickyEnableOnMobile == false ) {
9007					$('html').addClass('sticky-header-mobile-disabled');
9008					return this;
9009				}
9010
9011                if (!this.options.stickyEnableOnBoxed && $('html').hasClass('boxed') || $('html').hasClass('side-header-hamburguer-sidebar') && !this.options.stickyForce || !this.options.stickyEnabled) {
9012					return this;
9013				}
9014
9015                const self = this;
9016
9017                if( self.options.wrapper.hasClass('header') ) {
9018					self.options.wrapper = $('.header');
9019					self.options.headerBody = $('.header .header-body');
9020				}
9021
9022                const $html = $('html');
9023                const $window = $(window);
9024                const sideHeader = $html.hasClass('side-header');
9025                const initialHeaderTopHeight = self.options.wrapper.find('.header-top').outerHeight();
9026                const initialHeaderContainerHeight = self.options.wrapper.find('.header-container').outerHeight();
9027                let minHeight;
9028
9029                // HTML Classes
9030                $html.addClass('sticky-header-enabled');
9031
9032                if (parseInt(self.options.stickySetTop) < 0) {
9033					$html.addClass('sticky-header-negative');
9034				}
9035
9036                if (self.options.stickyScrollUp) {
9037					$html.addClass('sticky-header-scroll-direction');
9038				}
9039
9040                // Notice Top Bar First Load
9041                if( $('.notice-top-bar').get(0) ) {
9042					if (parseInt(self.options.stickySetTop) == 1 || self.options.stickyEffect == 'shrink') {
9043						$('.body').on('transitionend webkitTransitionEnd oTransitionEnd', () => {
9044						    setTimeout(() => {
9045								if( !$html.hasClass('sticky-header-active') ) {
9046								    self.options.headerBody.animate({
9047								    	top: $('.notice-top-bar').outerHeight()
9048								    }, 300, () => {
9049								    	if( $html.hasClass('sticky-header-active') ) {
9050								    		self.options.headerBody.css('top', 0);
9051								    	}
9052								    });
9053								}
9054						    }, 0);
9055						});
9056					}					
9057				}
9058
9059                // Set Start At
9060                if(self.options.stickyStartAtElement) {
9061
9062					const $stickyStartAtElement = $(self.options.stickyStartAtElement);
9063
9064					$(window).on('scroll resize sticky.header.resize', () => {
9065						self.options.stickyStartAt = $stickyStartAtElement.offset().top;
9066					});
9067
9068					$(window).trigger('sticky.header.resize');
9069				}
9070
9071                // Define Min Height value
9072                if( self.options.wrapper.find('.header-top').get(0) ) {
9073					minHeight = ( initialHeaderTopHeight + initialHeaderContainerHeight );
9074				} else {
9075					minHeight = initialHeaderContainerHeight;
9076				}
9077
9078                // Set Wrapper Min-Height
9079                if( !sideHeader ) {
9080					if( !$('.header-logo-sticky-change').get(0) ) {
9081						self.options.wrapper.css('height', self.options.headerBody.outerHeight());
9082					} else {
9083						$window.on('stickyChangeLogo.loaded', () => {
9084							self.options.wrapper.css('height', self.options.headerBody.outerHeight());
9085						});
9086					}
9087
9088					if( self.options.stickyEffect == 'shrink' ) {
9089						
9090						// Prevent wrong visualization of header when reload on middle of page
9091						$(document).ready(() => {
9092							if( $window.scrollTop() >= self.options.stickyStartAt ) {
9093								self.options.wrapper.find('.header-container').on('transitionend webkitTransitionEnd oTransitionEnd', () => {
9094									self.options.headerBody.css('position', 'fixed');
9095								});
9096							} else {
9097								if( !$html.hasClass('boxed') ) {
9098									self.options.headerBody.css('position', 'fixed');
9099								}
9100							}
9101						});
9102
9103						self.options.wrapper.find('.header-container').css('height', initialHeaderContainerHeight);
9104						self.options.wrapper.find('.header-top').css('height', initialHeaderTopHeight);
9105					}
9106				}
9107
9108                // Sticky Header Container Height
9109                if( self.options.stickyHeaderContainerHeight ) {
9110					self.options.wrapper.find('.header-container').css('height', self.options.wrapper.find('.header-container').outerHeight());
9111				}
9112
9113                // Boxed
9114                if($html.hasClass('boxed') && self.options.stickyEffect == 'shrink') {
9115					self.boxedLayout();
9116				}
9117
9118                // Check Sticky Header / Flags prevent multiple runs at same time
9119                let activate_flag   	 = true;
9120
9121                let deactivate_flag 	 = false;
9122                const initialStickyStartAt = self.options.stickyStartAt;
9123
9124                self.checkStickyHeader = () => {
9125
9126					// Notice Top Bar
9127					const $noticeTopBar = $('.notice-top-bar');
9128					if ( $noticeTopBar.get(0) ) {
9129						self.options.stickyStartAt = ( $noticeTopBar.data('sticky-start-at') ) ? $noticeTopBar.data('sticky-start-at') : $('.notice-top-bar').outerHeight();
9130					} else {
9131						if( $html.hasClass('boxed') ) {
9132							self.options.stickyStartAt = initialStickyStartAt + 25;
9133						} else {
9134							self.options.stickyStartAt = initialStickyStartAt;
9135						}
9136					}
9137
9138					if( $window.width() > 991 && $html.hasClass('side-header') ) {
9139						$html.removeClass('sticky-header-active');
9140						activate_flag = true;
9141						return;
9142					}
9143
9144					if ($window.scrollTop() >= parseInt(self.options.stickyStartAt)) {
9145						if( activate_flag ) {
9146							self.activateStickyHeader();
9147							activate_flag = false;
9148							deactivate_flag = true;
9149						}
9150					} else {
9151						if( deactivate_flag ) {
9152							self.deactivateStickyHeader();
9153							deactivate_flag = false;
9154							activate_flag = true;
9155						}
9156					}
9157
9158					// Scroll Up
9159					if (self.options.stickyScrollUp) {
9160						
9161					    // Get the new Value
9162					    self.options.stickyScrollNewValue = window.pageYOffset;
9163
9164					    //Subtract the two and conclude
9165					    if(self.options.stickyScrollValue - self.options.stickyScrollNewValue < 0){
9166					        $html.removeClass('sticky-header-scroll-up').addClass('sticky-header-scroll-down');
9167					    } else if(self.options.stickyScrollValue - self.options.stickyScrollNewValue > 0){
9168					        $html.removeClass('sticky-header-scroll-down').addClass('sticky-header-scroll-up');
9169					    }
9170
9171					    // Update the old value
9172					    self.options.stickyScrollValue = self.options.stickyScrollNewValue;
9173
9174					}
9175				};
9176
9177                // Activate Sticky Header
9178                self.activateStickyHeader = () => {
9179					if ($window.width() < 992) {
9180						if (self.options.stickyEnableOnMobile == false) {
9181							self.deactivateStickyHeader();
9182							self.options.headerBody.css({
9183								position: 'relative'
9184							});
9185							return false;
9186						}
9187					} else {
9188						if (sideHeader) {
9189							self.deactivateStickyHeader();
9190							return;
9191						}
9192					}
9193
9194					$html.addClass('sticky-header-active');
9195
9196					// Sticky Effect - Reveal
9197					if( self.options.stickyEffect == 'reveal' ) {
9198
9199						self.options.headerBody.css('top','-' + self.options.stickyStartAt + 'px');
9200
9201						self.options.headerBody.animate({
9202							top: self.options.stickySetTop
9203						}, 400, () => {});
9204
9205					}
9206
9207					// Sticky Effect - Shrink
9208					if( self.options.stickyEffect == 'shrink' ) {
9209
9210						// If Header Top
9211						if( self.options.wrapper.find('.header-top').get(0) ) {
9212							self.options.wrapper.find('.header-top').css({
9213								height: 0,
9214								'min-height': 0,
9215								overflow: 'hidden'
9216							});
9217						}
9218
9219						// Header Container
9220						if( self.options.stickyHeaderContainerHeight ) {
9221							self.options.wrapper.find('.header-container').css({
9222								height: self.options.stickyHeaderContainerHeight,
9223								'min-height': 0
9224							});
9225						} else {
9226							self.options.wrapper.find('.header-container').css({
9227								height: (initialHeaderContainerHeight / 3) * 2, // two third of container height
9228								'min-height': 0
9229							});
9230
9231							const y = initialHeaderContainerHeight - ((initialHeaderContainerHeight / 3) * 2);
9232							$('.main').css({
9233								transform: 'translate3d(0, -'+ y +'px, 0)',
9234								transition: 'ease transform 300ms'
9235							}).addClass('has-sticky-header-transform');
9236
9237							if($html.hasClass('boxed')) {
9238								self.options.headerBody.css('position','fixed');
9239							}
9240						}
9241
9242					}
9243
9244					self.options.headerBody.css('top', self.options.stickySetTop);
9245
9246					if (self.options.stickyChangeLogo) {
9247						self.changeLogo(true);
9248					}
9249
9250					// Set Elements Style
9251					if( $('[data-sticky-header-style]').length ) {
9252						$('[data-sticky-header-style]').each(function() {
9253							const $el = $(this), css = theme.fn.getOptions($el.data('sticky-header-style-active')), opts = theme.fn.getOptions($el.data('sticky-header-style'));
9254
9255							if( $window.width() > opts.minResolution ) {
9256								$el.css(css);
9257							}
9258						});
9259					}
9260
9261					$.event.trigger({
9262						type: 'stickyHeader.activate'
9263					});
9264				};
9265
9266                // Deactivate Sticky Header
9267                self.deactivateStickyHeader = () => {
9268					$html.removeClass('sticky-header-active');
9269
9270					if ( $(window).width() < 992 && self.options.stickyEnableOnMobile == false) {
9271						return false;
9272					}
9273
9274					// Sticky Effect - Shrink
9275					if( self.options.stickyEffect == 'shrink' ) {
9276
9277						// Boxed Layout
9278						if( $html.hasClass('boxed') ) {
9279
9280							// Set Header Body Position Absolute
9281							self.options.headerBody.css('position','absolute');
9282
9283							if( $window.scrollTop() > $('.body').offset().top ) {
9284								// Set Header Body Position Fixed
9285								self.options.headerBody.css('position','fixed');								
9286							}
9287
9288						} else {
9289							// Set Header Body Position Fixed
9290							self.options.headerBody.css('position','fixed');
9291						}
9292
9293						// If Header Top
9294						if( self.options.wrapper.find('.header-top').get(0) ) {
9295							self.options.wrapper.find('.header-top').css({
9296								height: initialHeaderTopHeight,
9297								overflow: 'visible'
9298							});
9299
9300							// Fix [data-icon] issue when first load is on middle of the page
9301							if( self.options.wrapper.find('.header-top [data-icon]').length ) {
9302								theme.fn.intObsInit( '.header-top [data-icon]:not(.svg-inline--fa)', 'themePluginIcon' );
9303							}
9304						}
9305
9306						// Header Container
9307						self.options.wrapper.find('.header-container').css({
9308							height: initialHeaderContainerHeight
9309						});
9310
9311					}
9312
9313					self.options.headerBody.css('top', 0);
9314
9315					if (self.options.stickyChangeLogo) {
9316						self.changeLogo(false);
9317					}
9318
9319					// Set Elements Style
9320					if( $('[data-sticky-header-style]').length ) {
9321						$('[data-sticky-header-style]').each(function() {
9322							const $el = $(this), css = theme.fn.getOptions($el.data('sticky-header-style-deactive')), opts = theme.fn.getOptions($el.data('sticky-header-style'));
9323
9324							if( $window.width() > opts.minResolution ) {
9325								$el.css(css);
9326							}
9327						});
9328					}
9329
9330					$.event.trigger({
9331						type: 'stickyHeader.deactivate'
9332					});
9333				};
9334
9335                // Always Sticky
9336                if (parseInt(self.options.stickyStartAt) <= 0) {
9337					self.activateStickyHeader();
9338				}
9339
9340                // Set Logo
9341                if (self.options.stickyChangeLogo) {
9342
9343					const $logoWrapper = self.options.wrapper.find('.header-logo'), $logo = $logoWrapper.find('img'), logoWidth = $logo.attr('width'), logoHeight = $logo.attr('height'), logoSmallTop = parseInt($logo.attr('data-sticky-top') ? $logo.attr('data-sticky-top') : 0), logoSmallWidth = parseInt($logo.attr('data-sticky-width') ? $logo.attr('data-sticky-width') : 'auto'), logoSmallHeight = parseInt($logo.attr('data-sticky-height') ? $logo.attr('data-sticky-height') : 'auto');
9344
9345					if (self.options.stickyChangeLogoWrapper) {
9346						$logoWrapper.css({
9347							'width': $logo.outerWidth(true),
9348							'height': $logo.outerHeight(true)
9349						});
9350					}
9351
9352					self.changeLogo = activate => {
9353						if(activate) {
9354							
9355							$logo.css({
9356								'top': logoSmallTop,
9357								'width': logoSmallWidth,
9358								'height': logoSmallHeight
9359							});
9360
9361						} else {
9362							
9363							$logo.css({
9364								'top': 0,
9365								'width': logoWidth,
9366								'height': logoHeight
9367							});
9368
9369						}
9370					}
9371
9372					$.event.trigger({
9373						type: 'stickyChangeLogo.loaded'
9374					});
9375
9376				}
9377
9378                // Side Header
9379                let headerBodyHeight, flag = false;
9380
9381                self.checkSideHeader = () => {
9382					if($window.width() < 992 && flag == false) {
9383						headerBodyHeight = self.options.headerBody.height();
9384						flag = true;
9385					}
9386
9387					if(self.options.stickyStartAt == 0 && sideHeader) {
9388						self.options.wrapper.css('min-height', 0);
9389					}
9390
9391					if(self.options.stickyStartAt > 0 && sideHeader && $window.width() < 992) {
9392						self.options.wrapper.css('min-height', headerBodyHeight);
9393					}
9394				}
9395
9396                return this;
9397            },
9398
9399			events() {
9400				const self = this;
9401
9402				if( $(window).width() < 992 && this.options.stickyEnableOnMobile == false ) {
9403					return this;
9404				}
9405
9406				if (!this.options.stickyEnableOnBoxed && $('body').hasClass('boxed') || $('html').hasClass('side-header-hamburguer-sidebar') && !this.options.stickyForce || !this.options.stickyEnabled) {
9407					return this;
9408				}
9409
9410				if (!self.options.alwaysStickyEnabled) {
9411					$(window).on('scroll resize', () => {
9412						if ( $(window).width() < 992 && self.options.stickyEnableOnMobile == false) {
9413							self.options.headerBody.css({
9414								position: ''
9415							});
9416
9417							if( self.options.stickyEffect == 'shrink' ) {
9418								self.options.wrapper.find('.header-top').css({
9419									height: ''
9420								});
9421							}
9422
9423							self.deactivateStickyHeader();
9424						} else {
9425							self.checkStickyHeader();
9426						}
9427					});
9428				} else {
9429					self.activateStickyHeader();
9430				}
9431
9432				$(window).on('load resize', () => {
9433					self.checkSideHeader();
9434				});
9435
9436				$(window).on('layout.boxed', () => {
9437					self.boxedLayout();
9438				});
9439
9440				return this;
9441			},
9442
9443			boxedLayout() {
9444				const self = this, $window = $(window);
9445
9446				if($('html').hasClass('boxed') && self.options.stickyEffect == 'shrink') {
9447					if( (parseInt(self.options.stickyStartAt) == 0) && $window.width() > 991) {
9448						self.options.stickyStartAt = 30;
9449					}
9450
9451					// Set Header Body Position Absolute
9452					self.options.headerBody.css({
9453						position: 'absolute',
9454						top: 0
9455					});
9456
9457					// Set position absolute because top margin from boxed layout
9458					$window.on('scroll', () => {
9459						if( $window.scrollTop() > $('.body').offset().top ) {
9460							self.options.headerBody.css({
9461								'position' : 'fixed',
9462								'top' : 0
9463							});								
9464						} else {
9465							self.options.headerBody.css({
9466								'position' : 'absolute',
9467								'top' : 0
9468							});
9469						}
9470					});
9471				}
9472
9473				return this;
9474			}
9475
9476		}
9477
9478	});
9479})).apply(this, [window.theme, 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.