! function( $ ) {
	"use strict";

	if ( typeof Codevz_Plus != 'object' ) {
		var Codevz_Plus = {};
	}

	Codevz_Plus.woocommerce = function() {

		var body 		= $( document.body ),
			adminBar 	= document.getElementById('wpadminbar') ? 32 : 0;

		// Fix WC message button.
		document.querySelectorAll( '.button.wc-forward' ).forEach( function( el ) {
			el.classList.remove( 'wc-forward' );
		});

		// AJAX Filters.
		if ( document.querySelector( '.codevz-plus-shop-ajax-filters' ) ) {

			function filterByPrice( page = 1 ) {
				const filtersDiv = $('.codevz-plus-shop-ajax-filters');
				const nonce = filtersDiv.data('nonce');
				const [min, max] = [parseInt($('#min_price').val(), 10), parseInt($('#max_price').val(), 10)];
				const rangeMin = $('.price_slider').slider('option', 'min');
				const rangeMax = $('.price_slider').slider('option', 'max');

				$('ul.products').addClass('codevz-plus-loading-products');

				$.post(body.data('ajax'), { action: 'filter_products_by_price', min_price: min, max_price: max, page, nonce }, (res) => {
					if (res.error) {
						alert(res.data.message || 'Security check failed.');
						return;
					}

					$('ul.products').removeClass('codevz-plus-loading-products').html(res.products);
					$('.woocommerce-pagination').replaceWith(res.pagination);

					// Show selected price filter if range changed
					const filterHtml = (min > rangeMin || max < rangeMax) ? `
						<div data-filter="price">
							<span>Price: $${min} - $${max}</span>
							<i class="fa czico-close-bold codevz-plus-shop-ajax-remove-filter"></i>
						</div>` : '';
					filtersDiv.find('> div').html(filterHtml);
				});
			}

			// Debounce and optimize slider event
			let debounceTimer;
			body.on('slidechange', '.widget .price_slider', function() {
				clearTimeout(debounceTimer);
				debounceTimer = setTimeout(function() { filterByPrice() }, 200 );
			});

			// Remove filter
			body.on('click', '.codevz-plus-shop-ajax-remove-filter', function() {
				$(this).parent().remove();
				$('.widget .price_slider').slider('values', [0, $('.price_slider').slider('option', 'max')]);
				filterByPrice();
			});

			// Pagination
			body.on('click', '.woocommerce-pagination a', function(e) {
				e.preventDefault();
				filterByPrice($(this).data('page') || 1);
			});
		}

		// Product quantity field.
		document.addEventListener( 'click', function (e) {

			const btn = e.target.closest('.quantity-up, .quantity-down');
			if (!btn) { return; }

			const wrap = btn.closest('.quantity');
			if (!wrap) { return; }

			const i = wrap.querySelector('input.qty');
			if (!i || i.disabled || i.readOnly) { return; }

			const max = parseFloat(i.max) || Infinity;

			let current = parseFloat(i.value);
			if (isNaN(current)) { current = 0; }

			const next = btn.classList.contains('quantity-up')
				? Math.min(current + 1, max)
				: Math.max(current - 1, 1);

			if (next === current) { return; }

			i.value = next;
			i.dispatchEvent(new Event('change', { bubbles: true }));

			if ( ! i.closest( '.product-type-grouped, .cz_popup_in, .woocommerce-cart-form' ) ) {
				document.querySelectorAll('.page_content input.qty').forEach(function (other) {
					if (
						other === i ||
						other.closest('.product-type-grouped') ||
						parseFloat(other.value) === next
					) {
						return;
					}

					other.value = next;
					other.dispatchEvent(new Event('change', { bubbles: true }));
				});
			}
		});

		// Cart page.
		if ( document.querySelector( '.woocommerce-cart-form' ) ) {

			// When cart page is empty, refresh
			body.on( 'updated_wc_div', function() {
				if ( ! document.querySelector( '.cart_item' ) ) {
					window.location.reload();
				}
			});

			// Auto update cart on quantity change
			let timeout;
			document.body.addEventListener( 'change', function(e) {
				const input = e.target.closest( '.woocommerce-cart-form input.qty' );
				if (!input) {return;}

				clearTimeout(timeout);

				timeout = setTimeout(function() {
					const updateBtn = document.querySelector( '[name="update_cart"]' );
					if (updateBtn) {updateBtn.click();}
				}, 1000);
			});

		}

		// Custom variations.
		document.addEventListener('click', function(e) {
		    const label = e.target.closest('.codevz-variations label');
		    if (!label) {return;}

		    const radio = label.previousElementSibling;
		    if (radio && radio.type === 'radio') {
		        radio.checked = true;

		        const val = radio.value;
		        const form = label.closest('.variations_form');
		        const container = label.closest('.value');

		        if (container) {
		            const select = container.querySelector('select');
		            if (select) {
		                select.value = val;
		                select.dispatchEvent(new Event('change', { bubbles: true }));

		                if (form) {
		                    const jqueryForm = window.jQuery && window.jQuery(form);
		                    if (jqueryForm) {
		                        jqueryForm.trigger('check_variations');
		                    }
		                }
		            }
		        }
		    }
		});

		// Single add to cart fake loading.
		let clickedButton = null;
		body.on( 'click', '.single_add_to_cart_button', function() {
		    clickedButton = $( this );
		    sessionStorage.wooclicked = '1';
		});
		$(window).on( 'beforeunload', function() {
		    if ( clickedButton && sessionStorage.wooclicked ) {
		        clickedButton.addClass( 'loading' );
		        sessionStorage.removeItem( 'wooclicked' );
		    }
		});

		// Single AJAX add to cart.
		document.addEventListener( 'submit', function(e) {
		    const form = e.target.closest('form.cart');
		    if (!form || form.closest('.product-type-external') || ! form.closest( '.codevz-woo-ajax-add-to-cart' ) ) {
		    	return;
		    }

			if ( typeof wc_add_to_cart_params !== 'undefined' && wc_add_to_cart_params.cart_redirect_after_add === 'yes' ) {
			    return;
			}

		    e.preventDefault();

		    const button = form.querySelector('.single_add_to_cart_button');
		    const qty = form.querySelector('input.qty');
		    const formData = new FormData(form);

		    if (!formData.has('product_id')) {
		        const idInput = form.querySelector('input[name="add-to-cart"]') || form.querySelector('button[name="add-to-cart"]');
		        if (idInput) formData.append('product_id', idInput.value);
		    }
		    
		    formData.append('action', 'single_add_to_cart');
		    formData.append('nonce', xtra_strings.nonce);

		    button.classList.add('loading');
		    if (qty) {
		        qty.disabled = true;
		        qty.parentNode.style.opacity = '0.3';
		    }

		    fetch(wc_add_to_cart_params.ajax_url, {
		        method: 'POST',
		        body: formData
		    })
		    .then(response => response.json())
		    .then(data => {
		        if (data.error) {
		            window.location = data.product_url;
		            return;
		        }

		        if (data.fragments) {
		            Object.entries(data.fragments).forEach(([selector, html]) => {
		                const target = document.querySelector(selector);
		                if (target) {
		                    if (selector === '.cz_cart_items' || target.classList.contains('cz_cart_items')) {
		                        const temp = document.createElement('div');
		                        temp.innerHTML = html;
		                        const newContent = temp.querySelector(selector) ? temp.querySelector(selector).innerHTML : temp.innerHTML;
		                        target.innerHTML = newContent;
		                    } else {
		                        target.outerHTML = html;
		                    }
		                }
		            });
		        }

		        if (typeof jQuery !== 'undefined') {
		            jQuery(document.body).trigger('added_to_cart', [data.fragments, data.cart_hash, jQuery(button)]);
		        }

		        button.classList.remove('loading');
		        button.classList.add('added');

		        // Show shopping mini cart after added.
				setTimeout(() => {
					const elmsCart = document.querySelector('.elms_shop_cart');
					if ( elmsCart && ! form.closest( '.cz_popup_in' ) ) {
					    document.querySelector('.elms_shop_cart').dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));

					    window.scrollTo({
					        top: 0,
					        behavior: 'smooth'
					    });
					}
				}, 10);

			    if (qty) {
			        qty.disabled = true;
			        qty.parentNode.style.opacity = '0.3';
			    }
		    })
		    .catch(() => {
		        button.classList.remove('loading');
		        if (qty) {
		            qty.disabled = false;
		            qty.parentNode.style.opacity = '1';
		        }
		    });
		});

		// AJAX remove from mini cart.
		document.addEventListener('click', function(e) {
		    const removeLink = e.target.closest('a.remove');
		    if (!removeLink) {return;}

		    removeLink.classList.add( 'codevz-remove' );

		    e.preventDefault();

		    const cartContainer = removeLink.closest('.cz_cart_items');
		    const itemRow = removeLink.closest('.item_small');
		    const url = new URL(removeLink.getAttribute('href'));
		    const removeKey = url.searchParams.get('remove_item');

		    if (!removeKey) {return;}
		    if (itemRow) {itemRow.style.opacity = '0.3';}

		    function update_cart() {
				const updateBtn = document.querySelector('[name="update_cart"]');
				if (updateBtn) {
				    updateBtn.disabled = false;
				    updateBtn.click();
				}
			    setTimeout(() => document.querySelector( '.elms_shop_cart' ).dispatchEvent(new MouseEvent('mouseover', { bubbles: true })), 10 );
		    }

			fetch(wc_add_to_cart_params.ajax_url, {
			    method: 'POST',
			    body: new URLSearchParams({
			        action: 'single_add_to_cart_remove', 
			        remove_item: removeKey, 
			        nonce: xtra_strings.nonce
			    })
			})
			.then(response => response.json())
			.then(data => {
			    if (data.fragments) {
			        Object.entries(data.fragments).forEach(([selector, html]) => {
			            const target = document.querySelector(selector);
			            if (!target) {return;}

			            if (selector === '.cz_cart_items' || target.classList.contains('cz_cart_items')) {
			                const temp = document.createElement('div');
			                temp.innerHTML = html;
			                const newContent = temp.querySelector(selector) ? temp.querySelector(selector).innerHTML : temp.innerHTML;
			                target.innerHTML = newContent;
			            } else {
			                target.outerHTML = html;
			            }
			            update_cart();
			        });
			    }

			    if (typeof jQuery !== 'undefined') {
			        jQuery(document.body).trigger('removed_from_cart', [data.fragments, data.cart_hash, jQuery(removeLink)]);
			    }
			})
			.catch(() => {
			    if (itemRow) {itemRow.style.opacity = '1';}
			    update_cart();
			});
		});

		// Widgets accordion.
		document.querySelectorAll( '.codevz-widgets-toggle .page_content .sidebar_inner' ).forEach( c => c.addEventListener( 'click', e => {
			const t = e.target.closest('.codevz-widget-title');
			if (!t) {return;}
			const n = t.nextElementSibling;
			if (!n) {return;}
			n.hidden = !n.hidden;
		}));

		// Auto x-position shop cart in header.
		if ( document.querySelector( '.elms_shop_cart' ) ) {

			if ( document.querySelector( '.elms_shop_cart_offcanvas' ) ) {

				// v6.0 - Custom cart offcanvas.
				body.off( 'click.elms_shop_cart_offcanvas' ).on( 'click.elms_shop_cart_offcanvas', '.elms_shop_cart_offcanvas', function( e ) {

					Codevz.offCanvas( $( this ).addClass( 'done' ), 1, $( '[data-offcanvas="cart"]' ) );
					e.preventDefault();
				});

			} else {

				const overlay = document.querySelector('.codevz-plus-dropdown-overlay .inner_layout > .cz_overlay');
				let hoverTimeout;
				let isCartActive = false;

				document.body.addEventListener('click', (e) => {
				    const dropdown = document.querySelector('.cz_cart_items');
				    
				    if (dropdown && !dropdown.contains(e.target) && !e.target.closest('.elms_shop_cart') && !e.target.closest('.cz')) {
				        dropdown.style.opacity = '0';
				        dropdown.style.visibility = 'hidden';
				        dropdown.style.pointerEvents = 'none';
				        if (overlay) {
				            overlay.style.display = 'none';
				        }
				        isCartActive = false;
				    }
				});

				document.body.addEventListener('mouseover', (e) => {
				    const cartX = e.target.closest('.elms_shop_cart');
				    if (!cartX) {
				        return;
				    }

				    isCartActive = true;
				    clearTimeout(hoverTimeout);

				    const dropdown = cartX.querySelector('.cz_cart_items');
				    const icon = cartX.querySelector('.shop_icon i');
				    const isRtl = document.body.classList.contains('rtl');

				    if (!dropdown) {
				        return;
				    }

				    dropdown.style.pointerEvents = 'auto';

				    if ((window.innerWidth / 2) > (cartX.getBoundingClientRect().left + window.scrollX + 300)) {
				        cartX.classList.add('inview_right');
				        const iconMl = parseFloat(getComputedStyle(icon).marginLeft) || 0;
				        const leftVal = (icon.offsetWidth / 2) + (isRtl ? -38 : 36) + iconMl;
				        dropdown.style.left = isRtl ? `${leftVal}px` : `-${leftVal}px`;
				    } else {
				        const iconMr = parseFloat(getComputedStyle(icon).marginRight) || 0;
				        dropdown.style.right = `${(icon.offsetWidth / 2) - 36 + iconMr}px`;
				    }

				    setTimeout(() => {
				        dropdown.style.opacity = '1';
				        dropdown.style.visibility = 'visible';
				        if (overlay) {
				            overlay.style.zIndex = '99';
				            overlay.style.display = 'block';
				        }
				    }, 100);
				});

				document.body.addEventListener('mouseout', (e) => {
				    if (!isCartActive) {
				        return;
				    }

				    const cartX = e.target.closest('.elms_shop_cart');
				    if (!cartX) {
				        return;
				    }

				    const dropdown = cartX.querySelector('.cz_cart_items');
				    const relatedTarget = e.relatedTarget;

				    if (!dropdown) {
				        return;
				    }

				    if (relatedTarget && cartX.contains(relatedTarget)) {
				        return;
				    }

				    isCartActive = false;

				    hoverTimeout = setTimeout(() => {
				        dropdown.style.opacity = '0';
				        dropdown.style.visibility = 'hidden';
				        dropdown.style.pointerEvents = 'none';
				        if (overlay) {
				            overlay.style.display = 'none';
				        }
				    }, 250);
				});

			}

		}

		// Move cart count to icon data.
		const cartBox = document.querySelector( '.elms_shop_cart' );
		if ( cartBox ) {
			let mutationTimeout;
			const observer = new MutationObserver(() => {
				clearTimeout(mutationTimeout);
				mutationTimeout = setTimeout(() => {
					cartBox.querySelector( '.shop_icon > i' ).setAttribute( 'data-count', cartBox.querySelector( '.cz_cart_count' ).innerHTML );
				}, 100 );
			});
			observer.observe( cartBox, { childList: true, subtree: true });
		}

		// Wishlist & Compare popup.
		var wishComPopup = $( '#xtra_wish_compare' );
		wishComPopup.appendTo( 'body' );

		// Fix wishComPopup link issue.
		wishComPopup.on( 'click', 'a', function() {
			window.location = $( this ).attr( 'href' );
		});

		// Current wishlist items
		if ( document.querySelector( '.xtra-add-to-wishlist, .xtra-wishlist, .wishlist_icon' ) ) {

			var wishlist = localStorage.getItem( 'xtraWishlist' ),
				wishlistDiv = $( '.xtra-wishlist' ),
				noWishlist = '<h2 class="xtra-wish-compare-empty xtra-wishlist-empty tac"><i class="fa fa-heart-o"></i>' + wishlistDiv.attr( 'data-empty' ) + '<small>' + xtra_strings.wishlist_desc + '</small></h2><a href="' + xtra_strings.shop_url + '" class="button" style="margin:40px auto;display:table;"><span><strong>' + xtra_strings.back_to_shop + '</strong></span></a>';

			// Wishlist shortcode
			wishlistDiv.length && wishlistDiv.each( function() {

				var en 		= $( this ),
					nonce 	= en.data( 'nonce' ),
					col 	= en.data( 'col' );

				if ( wishlist ) {

					// Check ID's.
					$.post( body.data( 'ajax' ), 'action=xtra_wishlist_content&check=1&ids=' + wishlist + '&nonce=' + nonce, function( msg ) {

						localStorage.setItem( 'xtraWishlist', msg );

						wishlist = msg;

						// Get wishlist products.
						$.post( body.data( 'ajax' ), 'action=xtra_wishlist_content&ids=' + wishlist + '&nonce=' + nonce + '&col=' + col, function( msg ) {

							en.removeClass( 'xtra-icon-loading' ).html( msg );

							$( '.woocommerce-loop-product__link' ).prepend( '<i class="xtra-remove-from-wishlist fas fa-times"></i>' );

							var count = localStorage.getItem( 'xtraWishlist' ).replace( /\d+/g,'' ).length;

							$( '.wishlist_icon > i' ).attr( 'data-count', count || 0 );

							if ( ! count ) {
								en.removeClass( 'xtra-icon-loading' ).html( noWishlist );
							}

							if ( ! en.find( 'li' ).length ) {
								en.removeClass( 'xtra-icon-loading' ).html( noWishlist );
							}

						});

					});

				} else {

					en.removeClass( 'xtra-icon-loading' ).html( noWishlist );

				}

			});

			// Set wishlist products
			if ( wishlist ) {
				wishlist = wishlist.split( ',' );

				$.each( wishlist, function( index, id ) {
					var product = $( '[data-id="' + id + '"] .xtra-add-to-wishlist' );

					if ( product.length ) {
						product.removeClass( 'fa-heart-o' ).addClass( 'fa-heart' ).attr( 'data-title', xtra_strings.added_wishlist );
					}
				});

				var count = localStorage.getItem( 'xtraWishlist' ).replace( /\d+/g,'' ).length;

				$( '.wishlist_icon > i' ).attr( 'data-count', count || 0 );

				if ( ! count ) {
					wishlistDiv.removeClass( 'xtra-icon-loading' ).html( noWishlist );
				}
			}

			// Wishlist icon.
			body.on( 'click', '.xtra-add-to-wishlist,.xtra-remove-from-wishlist', function(e) {

				var en = $( this ),
					id = en.closest( '.product' ).find( '[data-id]' ).data( 'id' ) + ',',
					ls = localStorage.getItem( 'xtraWishlist' ) || '',
					tt = en.attr( 'data-title' );

				if ( en.hasClass( 'fa-heart' ) && ! en.closest( '.xtra-wishlist' ).length ) {

					window.location.replace( xtra_strings.wishlist_url );

				} else {

					en.addClass( 'xtra-icon-loading' ).removeAttr( 'data-title' );

					setTimeout(function() {

						if ( en.hasClass( 'fa-heart' ) || en.hasClass( 'fa-times' ) ) {

							ls = ls.replace( id, '' );

							localStorage.setItem( 'xtraWishlist', ls );

							tt = xtra_strings.add_wishlist;

							en.removeClass( 'fa-heart' ).addClass( 'fa-heart-o' );

						} else if ( ls.indexOf( id ) < 0 ) {

							localStorage.setItem( 'xtraWishlist', ls + id );

							tt = xtra_strings.added_wishlist;

							setTimeout( function() {

								$( '[data-id="' + id.replace( ',', '' ) + '"] .xtra-add-to-wishlist' ).removeClass( 'fa-heart-o' ).addClass( 'fa-heart' ).attr( 'data-title', xtra_strings.added_wishlist );

							}, 500 );

							$( '.cz_close_popup' ).trigger( 'click' );

							setTimeout( function() {

								wishComPopup.find( 'h3' ).html( en.closest( '.product' ).find( '.woocommerce-loop-product__title, .product_title' ).html() );
								wishComPopup.find( 'a' ).attr( 'href', xtra_strings.wishlist_url ).find( 'strong' ).html( xtra_strings.view_wishlist );
								wishComPopup.fadeIn( 'fast' ).delay( 1000 ).addClass( 'cz_show_popup' );

							}, $( '.cz_popup_modal' ).is( ':visible' ) ? 50 : 0 );
						}

						en.removeClass( 'xtra-icon-loading' );

						setTimeout( function() {

							en.attr( 'data-title', tt );

						}, 250 );

						// Wishlist page.
						if ( en.closest( '.xtra-wishlist' ).length ) {

							en.closest( 'li' ).fadeOut(function() {

								$( this ).remove();

								if ( ! wishlistDiv.find( 'li' ).length ) {
									wishlistDiv.removeClass( 'xtra-icon-loading' ).html( noWishlist );
								}

							});

						}

						var count = localStorage.getItem( 'xtraWishlist' ).replace( /\d+/g,'' ).length;

						$( '.wishlist_icon > i' ).attr( 'data-count', count || 0 );

						if ( ! count ) {
							wishlistDiv.removeClass( 'xtra-icon-loading' ).html( noWishlist );
						}

					}, 1000 );

				}

				e.preventDefault();
			});

		}

		// Current compare items
		if ( document.querySelector( '.xtra-add-to-compare, .xtra-compare, .compare_icon' ) ) {

			// Compare icon.
			body.on( 'click', '.xtra-add-to-compare,.xtra-remove-from-compare', function(e) {

				var en = $( this ),
					id = en.closest( '.product' ).find( '[data-id]' ).data( 'id' ) + ',',
					ls = localStorage.getItem( 'xtraCompare' ) || '',
					tt = en.attr( 'data-title' );

				// Remove from compare.
				if ( en.attr( 'class' ).indexOf( 'remove' ) > 0 ) {

					id = en.closest( 'td' ).find( '[data-id]' ).data( 'id' ) + ',';

					en.addClass( 'xtra-icon-loading' );

					ls = ls.replace( id, '' );

					localStorage.setItem( 'xtraCompare', ls );

					window.location.replace( xtra_strings.compare_url );

					e.preventDefault();

					return false;

				}

				// ...
				if ( en.hasClass( 'fa-check' ) && ! en.closest( '.xtra-compare' ).length ) {

					window.location.replace( xtra_strings.compare_url );

				} else {

					en.addClass( 'xtra-icon-loading' ).removeAttr( 'data-title' );

					setTimeout( function() {

						if ( en.hasClass( 'fa-check' ) || en.hasClass( 'fa-times' ) ) {

							ls = ls.replace( id, '' );

							localStorage.setItem( 'xtraCompare', ls );

							tt = xtra_strings.add_compare;

							en.removeClass( 'fa-check' ).addClass( 'czico-shuffle' ).attr( 'data-title', xtra_strings.add_compare );

						} else if ( ls.indexOf( id ) < 0 ) {

							localStorage.setItem( 'xtraCompare', ls + id );

							tt = xtra_strings.added_compare;

							setTimeout( function() {

								$( '[data-id="' + id.replace( ',', '' ) + '"] .xtra-add-to-compare' ).removeClass( 'czico-shuffle' ).addClass( 'fa-check' ).attr( 'data-title', xtra_strings.added_compare );

							}, 500 );

							$( '.cz_close_popup' ).trigger( 'click' );

							setTimeout( function() {

								wishComPopup.find( 'h3' ).html( en.closest( '.product' ).find( '.woocommerce-loop-product__title, .product_title' ).html() );
								wishComPopup.find( 'a' ).attr( 'href', xtra_strings.compare_url ).find( 'strong' ).html( xtra_strings.view_compare );
								wishComPopup.fadeIn( 'fast' ).delay( 1000 ).addClass( 'cz_show_popup' );

							}, $( '.cz_popup_modal' ).is( ':visible' ) ? 50 : 0 );

						}

						en.removeClass( 'xtra-icon-loading' );

						setTimeout( function() {

							en.attr( 'data-title', tt );

						}, 250 );

						var compareDiv = null;

						// Compare page.
						if ( en.closest( '.xtra-compare' ).length ) {

							en.closest( 'li' ).fadeOut(function() {

								$( this ).remove();

								if ( ! compareDiv.find( 'li' ).length ) {
									compareDiv.removeClass( 'xtra-icon-loading' ).html( noCompare );
								}

							});

						}

						var count = localStorage.getItem( 'xtraCompare' ).replace( /\d+/g,'' ).length;

						$( '.compare_icon > i' ).attr( 'data-count', count || 0 );

						if ( ! count ) {
							compareDiv.removeClass( 'xtra-icon-loading' ).html( noCompare );
						}

					}, 1000 );

				}

				e.preventDefault();
			});

			var compare = localStorage.getItem( 'xtraCompare' ),
				compareDiv = $( '.xtra-compare' ),
				noCompare = '<h2 class="xtra-wish-compare-empty xtra-compare-empty tac"><i class="fa-solid fa-list-check"></i>' + compareDiv.attr( 'data-empty' ) + '<small>' + xtra_strings.wishlist_desc + '</small></h2><a href="' + xtra_strings.shop_url + '" class="button" style="margin:40px auto;display:table;"><span><strong>' + xtra_strings.back_to_shop + '</strong></span></a>';

			// Compare shortcode
			compareDiv.length && compareDiv.each( function() {

				var en = $( this ),
					nonce = en.data( 'nonce' );

				if ( compare ) {

					// Check ID's.
					$.post( body.data( 'ajax' ), 'action=xtra_compare_content&check=1&ids=' + compare + '&nonce=' + nonce, function( msg ) {

						localStorage.setItem( 'xtraCompare', msg );

						compare = msg;

						// Get compare products.
						$.post( body.data( 'ajax' ), 'action=xtra_compare_content&ids=' + compare + '&nonce=' + nonce, function( msg ) {

							en.removeClass( 'xtra-icon-loading' ).html( msg );

							$( '.cz-compare-tr-general td' ).prepend( '<i class="xtra-remove-from-compare fas fa-times"></i>' );

							var count = localStorage.getItem( 'xtraCompare' ).replace( /\d+/g,'' ).length;

							$( '.compare_icon > i' ).attr( 'data-count', count || 0 );

							if ( ! count ) {
								en.removeClass( 'xtra-icon-loading' ).html( noCompare );
							}

							if ( ! en.find( 'li' ).length ) {
								en.removeClass( 'xtra-icon-loading' ).html( noCompare );
							}

						});

					});

				} else {

					en.removeClass( 'xtra-icon-loading' ).html( noCompare );

				}

			});

			// Set compare products
			if ( compare ) {
				compare = compare.split( ',' );

				$.each( compare, function( index, id ) {
					var product = id ? $( '[data-id="' + id + '"] .xtra-add-to-compare' ) : 0;

					if ( product.length ) {
						product.removeClass( 'czico-shuffle' ).addClass( 'fa-check' ).attr( 'data-title', xtra_strings.added_compare );
					}
				});

				var count = localStorage.getItem( 'xtraCompare' ).replace( /\d+/g,'' ).length;

				$( '.compare_icon > i' ).attr( 'data-count', count || 0 );

				if ( ! count ) {
					compareDiv.removeClass( 'xtra-icon-loading' ).html( noCompare );
				}
			}

		}

		// Product quick view.
		if ( document.querySelector( '.xtra-product-quick-view' ) ) {

			body.on( 'click', '.xtra-product-quick-view', function( e ) {

				e.preventDefault();

				var x 		= $( this ),
					id 		= x.parent().data( 'id' ),
					nonce 	= x.data( 'nonce' ),
					link  	= x.closest( 'a' ).attr( 'href' ),
					popup 	= $( '#xtra_quick_view' ),
					content = popup.find( '.cz_popup_in > div' ),
					tt 		= x.attr( 'data-title' );

				popup.appendTo( 'body' );

				x.addClass( 'xtra-icon-loading' ).removeAttr( 'data-title' );

				content.html( '' );
				content.addClass( 'xtra-qv-loading' );

				popup.fadeIn( 'fast' ).delay( 1000 ).addClass( 'cz_show_popup' );

				$( 'html, body' ).addClass( 'no-scroll' );

				$.post( body.data( 'ajax' ), 'action=xtra_quick_view&id=' + id + '&nonce=' + nonce, function( msg ) {

					x.removeClass( 'xtra-icon-loading' ).attr( 'data-title', tt );
					content.removeClass().html( msg );

					// Add link to full product view.
					content.find( '.product_title' ).append( '<a href="' + link + '"><small>' + xtra_strings.quick_view_full + '</small></a>' );

					// Set wishlist in quickview.
					if ( localStorage.getItem( 'xtraWishlist' ) && localStorage.getItem( 'xtraWishlist' ).indexOf( id ) >= 0 ) {
						$( '[data-id="' + id + '"] .xtra-add-to-wishlist' ).removeClass( 'fa-heart-o' ).addClass( 'fa-heart' ).attr( 'data-title', xtra_strings.added_wishlist );
					}

					// Set compare in quickview.
					if ( localStorage.getItem( 'xtraCompare' ) && localStorage.getItem( 'xtraCompare' ).indexOf( id ) >= 0 ) {
						$( '[data-id="' + id + '"] .xtra-add-to-compare' ).removeClass( 'czico-shuffle' ).addClass( 'fa-check' ).attr( 'data-title', xtra_strings.added_compare );
					}

					// Fix flex slider.
					setTimeout( function() {

						// Init variations
						content.find('.variations_form').each(function () {
							var $form = $( this );
							$form.wc_variation_form();
							$form.trigger('wc_variation_form'); 
							$form.find('.variations select').trigger('change');
						});

						content.find( '.woocommerce-product-gallery' ).each( function() {
							$( this ).wc_product_gallery();
						} );

						$( window ).trigger( 'resize' );

					}, 500 );

					// Fix onsale position.
					content.find( 'div.product, .xtra-single-product' ).find( '> .onsale' ).prependTo( $( '.woocommerce-product-gallery' ) );

					// Add to cart redirect to cart on quick view popup. 
					content.find( '[name="add-to-cart"]' ).closest( 'form' ).attr( 'action', xtra_strings.cart_url );

				});

				return false;

			});

		}

		// Append onsale badge to parent in archive.
		document.querySelectorAll('ul.products .onsale').forEach(badge => {
		    const parentLink = badge.closest('a');
		    if (parentLink) {
		        parentLink.appendChild(badge);
		    }
		});

		// Checkout page functions.
		if ( document.querySelector( '.woocommerce-checkout' ) ) {

			// Fix checkout section title!
			$( 'wc-order-attribution-inputs' ).each( function() {

				var $this = $( this );

				$this.appendTo( $this.parent() );

			});

			// Fix City and state in RTL.
			if ( body.hasClass( 'rtl' ) ) {

				setTimeout( function() {

					$( '#billing_state_field' ).insertBefore( '#billing_city_field' );

				}, 500 );

			}

		}

		// Add button class to restore-item link in message box.
		$( '.woocommerce-message .restore-item' ).addClass( 'button' );

		// Added to cart notification.
		body.on( 'added_to_cart', function( e, fragments, cart_hash, $button ) {

			// Show view cart btn.
			setTimeout( function() {
				$button.hide().next().addClass( 'button product_type_codevz' ).fadeIn();
			}, 100 );

			// Notification.
			var notif = $( '.codevz-added-to-cart-notif' ),
				width = notif.find( 'span' ).outerWidth();

			// Check if its on single page with sticky mode.
			notif[ $( '.cz-sticky-add-to-cart-show' ).length ? 'addClass' : 'removeClass' ]( 'codevz-added-to-cart-notif-above-sticky' );

			setTimeout( function() {

				var parent = $button.closest( 'li.product' ).length ? $button.closest( 'li.product' ) : $button.closest( '.summary' ),
					title  = parent.find( '.woocommerce-loop-product__title' ).html(),
					title  = title ? title : $( '.cz-sticky-add-to-cart' ).attr( 'data-title' ) || '-';

				// Show the notification.
				notif.addClass( 'codevz-added-to-cart-notif-show' ).find( 'strong' ).text( title.replace( /<[^>]*>.*?<\/[^>]*>/g, '' ) );

				setTimeout( function() {

					// Show the added details span.
					notif.addClass( 'codevz-added-to-cart-notif-show-span' );

				}, 1200 );

				setTimeout( function() {

					// Hide the notification after a delay.
					notif.removeClass( 'codevz-added-to-cart-notif-show-span' );

					setTimeout( function() {

						// Hide the span.
						notif.removeClass( 'codevz-added-to-cart-notif-show' );

					}, 500 );

				}, 6000 );

			}, 100 );

		});

		// Single product page.
		if ( body.hasClass( 'single-product' ) ) {

			setTimeout( function() {

				// Sticky product tabs row.
				var woot 	= $( '.codevz-sticky-product-tabs .woocommerce-tabs' ),
					tabs 	= woot.find( 'ul.tabs' ),
					panels 	= woot.find( '.panel' ),
					lastTab = panels.last(),
					scrollTop, isFixed, activeTabId;

				if ( tabs.length ) {

					var tabsOffset  = tabs.offset().top,
						placeholder = $( '<div>' ).css({
							'height': tabs.outerHeight(),
							'margin': tabs.css( 'margin' )
						}).insertBefore( tabs );

					$( window ).on( 'scroll', function() {

						if ( Codevz.inview( woot, 100 ) ) {

							requestAnimationFrame(function() {

								scrollTop 	= $(window).scrollTop() + adminBar;
								isFixed 	= scrollTop > tabsOffset;

								tabs.toggleClass( 'fixed-tabs', isFixed );
								placeholder[ isFixed ? 'show' : 'hide' ]();

								// Determine which tab content is currently in view
								panels.each( function() {
									var tabContent 		= $(this);
									var topOffset 		= tabContent.offset().top - 150;
									var bottomOffset 	= topOffset + tabContent.outerHeight();

									// Check if the tab content is within the viewport
									if ( topOffset <= ( scrollTop + tabs.outerHeight()) && bottomOffset >= scrollTop ) {
										activeTabId = tabContent.attr('id');
										return false;
									}
								});

								// Set active class on corresponding tab link
								tabs.find('li').removeClass('active');
								if ( activeTabId ) {
									tabs.find('a[href="#' + activeTabId + '"]').closest('li').addClass('active');
								} else if ( scrollTop <= tabsOffset ) { // If at top of page, set first tab as active
									tabs.find('li:first').addClass('active');
								}

								// Last tab out of viewport, hide sticky.
								tabs.toggle( ( lastTab.offset().top + lastTab.outerHeight() - tabs.outerHeight() ) >= scrollTop );

							});

						}

					});

				}

				// Tabs scroll to.
				body.on( 'click', '.wc-tabs a', function() {

					var $page 		= $( 'html, body' ),
						tabs 		= $( 'body:not(.woo-product-tabs-vertical) .wc-tabs' ),
						tab 		= $( this ).attr( 'href' ).replace( '#', '' ),
						sticky 		= $( '.header_is_sticky' ).not( '.smart_sticky,.header_4' );

					tab && $page.stop( true, true ).animate({

						scrollTop: $( '#' + tab ).offset().top - ( tabs.outerHeight() || 0 ) - ( sticky.outerHeight() || 0 ) - adminBar - ( $( '.xtra-preview-header' ).outerHeight() || 0 ) - 50

					}, 1000, 'easeInOutCodevz', function() {

						$page.stop( true, true );

					});

				}).on( 'click', '.codevz-woo-rating-count', function(e) {

					$( '.reviews_tab a' ).trigger( 'click' );
					e.preventDefault();

				});

			}, 1000 );

			// Disable product page lightbox
			$( '.woo-disable-lightbox .woocommerce-product-gallery__wrapper > div:first-child a' ).removeAttr( 'href' ).css( 'cursor', 'default' );

			// Move single onSale badge to sticky.
			$( 'div.product, .xtra-single-product' ).find( '> .onsale' ).prependTo( $( '.woocommerce-product-gallery' ) );

			// Woo sticky column.
			$( '.woocommerce-product-gallery' ).addClass( 'cz_sticky_col' );

			// Edit reviews count in tab and add span.
			$( '.wc-tabs [href="#tab-reviews"]' ).html( function( i, html ) {
				return html.replace( '(', '<span>' ).replace( ')', '</span>' );
			});

			// Out of stock message.
			var outofstock_p = $( 'p.stock.out-of-stock' );

			// Add error class to outofstock p tag.
			outofstock_p.addClass( 'woocommerce-error' );

			// Sticky add to cart.
			if ( $( '.cz-sticky-add-to-cart' ).length && ! outofstock_p.length ) {

				var sticky 	= $( '.cz-sticky-add-to-cart .row' ),
					product = $( '.xtra-single-product' ),
					cart 	= product.find( '.cart' ),
					footer  = $( '.layout_1,.layout_2' ).length ? $( '.layout_1,.layout_2' ) : $( '#site_footer' );

				// Set product details in sticky bar.
				sticky.append( '<h3>' + sticky.parent().attr( 'data-title' ) + '</h3>' );
				sticky.append( product.find( '.cart' ).clone() );
				sticky.find( 'h3' ).append( product.find( '.price' ).clone() );

				// Change add to cart to select options for variation products.
				if ( sticky.find( '.variations_form' ).length && ! $( '.codevz-select-options' ).length ) {

					sticky.find( '.single_add_to_cart_button' ).hide().after( '<a href="#" class="codevz-select-options button alt">' + xtra_strings.select_options + '</a>' );

					body.on( 'click', '.codevz-select-options', function() {

						var targetOffsetTop = $( '.summary .variations_form' ).offset().top - 800;

						$( 'html, body' ).animate( { scrollTop: targetOffsetTop }, 1200, 'easeInOutCodevz' );

						return false;

					});

				}

				// Product image.
				var image = product.find( '.woocommerce-product-gallery__image a > img' ).attr( 'src' ),
					offset;

				if ( image ) {
					sticky.prepend( '<img src="' + image + '" />' );
				}

				// Show/hide sticky on scroll.
				let timeout;
				$( window ).on( 'scroll.sticky_add_to_cart', function() {

					clearTimeout( timeout );

					timeout = setTimeout( function() {

						offset = $( window ).scrollTop() > cart.offset().top + cart.outerHeight();

						// Show/Hide sticky row.
						sticky.parent()[ offset ? 'addClass' : 'removeClass' ]( 'cz-sticky-add-to-cart-show' );

						// Fix footer margin.
						footer.css( 'margin-bottom', sticky.parent().outerHeight() );

						// Fixed icons.
						$( 'i.backtotop,i.fixed_contact' ).css( 'bottom', ( offset ? ( $( window ).width() > 769 ? $( '.cz-sticky-add-to-cart' ).outerHeight() + 20 : '' ) : '' ) );

					}, 100 );

				});

			} // Sticky add to cart.

			// Add title to product image zoom + new icon.
			Codevz.heightChanged( $( '.woocommerce-product-gallery' ), function() {

				setTimeout( function() {

					const trigger = $( '.woocommerce-product-gallery__trigger' );
					const thumbs  = $( '.flex-control-thumbs' );

					if ( ! $( '.codevz-woo-zoom' ).length ) {
						trigger.html( '<i class="fa czico-010-expand"></i><span class="codevz-woo-zoom">' + xtra_strings.zoom_text + '</span>' );
					}

					if ( thumbs.length ) {
						trigger.css( 'bottom', thumbs.outerHeight() + 30 );
					}

				}, 500 );

			});

		} // Single product page.

	};

	Codevz_Plus.woocommerce();

}( jQuery );