(function ($) {
    'use strict';

    var stateMap = new WeakMap();

    function decodePayload(encoded) {
        var json;

        if (!encoded) {
            return null;
        }

        try {
            json = window.atob(String(encoded));
            return JSON.parse(json);
        } catch (e) {
            return null;
        }
    }

    function getWidgetData($widget, name) {
        var attrValue = $widget.attr('data-' + name);

        if (typeof attrValue !== 'undefined') {
            return attrValue;
        }

        return $widget.data(name);
    }

    function getAjaxConfig($widget) {
        var globalConfig = window.sitselFilterableGallery || {};

        return {
            ajaxUrl: globalConfig.ajaxUrl || getWidgetData($widget, 'ajax-url') || '',
            nonce: globalConfig.nonce || getWidgetData($widget, 'ajax-nonce') || '',
            labels: globalConfig.labels || {}
        };
    }

    function normalizePaginationType(value) {
        var type = String(value || '').trim().toLowerCase();

        if ('load-more' === type || 'numbers' === type) {
            return type;
        }

        return 'none';
    }

    function getEditorContext() {
        var editorWindow = (window.parent && window.parent !== window) ? window.parent : window;
        var editor$ = editorWindow.jQuery || null;
        var editorDoc = editorWindow.document || null;

        if (!editor$ || !editorDoc) {
            return null;
        }

        return {
            $: editor$,
            doc: editorDoc
        };
    }

    function readEditorControlValue(setting, options) {
        var ctx = getEditorContext();
        var opts = options || {};
        var $control;
        var $field;
        var value;
        var missingValue = typeof opts.missingValue !== 'undefined'
            ? opts.missingValue
            : (opts.multiple ? [] : '');

        if (!ctx) {
            return missingValue;
        }

        $control = ctx.$(ctx.doc).find('.elementor-control[data-setting="' + setting + '"]').first();
        if (!$control.length) {
            return missingValue;
        }

        $field = $control.find('select, textarea, input[type="number"], input[type="text"], input[type="hidden"]').first();
        if (!$field.length) {
            return missingValue;
        }

        value = $field.val();

        if (opts.multiple) {
            if (Array.isArray(value)) {
                return value.filter(function (item) {
                    return String(item || '').trim() !== '';
                }).map(function (item) {
                    return String(item);
                });
            }

            if (typeof value === 'string' && value.trim() !== '') {
                return [value.trim()];
            }

            return [];
        }

        return String(value || '').trim();
    }

    function normalizePerPageValue(rawValue, fallbackValue) {
        var parsed = parseInt(rawValue, 10);
        var fallback = (typeof fallbackValue === 'number' && !isNaN(fallbackValue)) ? fallbackValue : 6;

        if (isNaN(parsed)) {
            return fallback;
        }

        if (parsed === -1) {
            return -1;
        }

        return parsed < 1 ? fallback : parsed;
    }

    function getEditorQuerySnapshot(defaultPerPage) {
        var source = readEditorControlValue('source', { missingValue: null });
        var postType = readEditorControlValue('post_type', { missingValue: null });
        var selection = readEditorControlValue('selection', { missingValue: null });
        var order = readEditorControlValue('order', { missingValue: null });
        var postsPerPageRaw = readEditorControlValue('posts_per_page', { missingValue: null });
        var offsetRaw = readEditorControlValue('offset', { missingValue: null });
        var postsPerPage = postsPerPageRaw === null ? null : normalizePerPageValue(postsPerPageRaw, defaultPerPage);
        var offset = offsetRaw === null ? null : parseInt(offsetRaw, 10);

        if (source === null && postType === null && selection === null) {
            return null;
        }

        return {
            source: source,
            post_type: postType,
            selection: selection,
            manual_posts: readEditorControlValue('manual_posts', { multiple: true, missingValue: null }),
            categories: readEditorControlValue('categories', { multiple: true, missingValue: null }),
            exclude_categories: readEditorControlValue('exclude_categories', { multiple: true, missingValue: null }),
            manual_tags: readEditorControlValue('manual_tags', { multiple: true, missingValue: null }),
            orderby: readEditorControlValue('orderby', { missingValue: null }),
            order: (order === 'ASC' || order === 'DESC') ? order : null,
            offset: (offset === null || isNaN(offset)) ? null : Math.max(0, offset),
            posts_per_page: (postsPerPage === null || isNaN(postsPerPage)) ? null : postsPerPage,
            dynamic_filter_taxonomy: readEditorControlValue('dynamic_filter_taxonomy', { missingValue: null }),
            meta_query_relation: readEditorControlValue('meta_query_relation', { missingValue: null })
        };
    }

    function buildFallbackPayload($widget, baseSettings) {
        var imagesPerPage = normalizePerPageValue(getWidgetData($widget, 'images-per-page'), 6);
        var source = getWidgetData($widget, 'source') || 'dynamic';
        var base = $.isPlainObject(baseSettings) ? baseSettings : {};
        var editorSnapshot = isEditorPreview() ? getEditorQuerySnapshot(imagesPerPage) : null;
        var effectiveSource = (
            editorSnapshot && editorSnapshot.source !== null && editorSnapshot.source !== ''
        ) ? editorSnapshot.source : (base.source || source);

        function pickScalar(editorValue, baseValue, fallbackValue) {
            if (editorValue !== null && editorValue !== '') {
                return editorValue;
            }
            if (typeof baseValue !== 'undefined' && baseValue !== null && baseValue !== '') {
                return baseValue;
            }
            return fallbackValue;
        }

        function pickArray(editorValue, baseValue, fallbackValue) {
            if (editorValue !== null && Array.isArray(editorValue)) {
                return editorValue;
            }
            if (Array.isArray(baseValue)) {
                return baseValue;
            }
            return fallbackValue;
        }

        var payload = {
            widgetId: String(getWidgetData($widget, 'widget-id') || 'sitsel-filterable-gallery-fallback'),
            settings: {
                source: effectiveSource,
                image_size: pickScalar(null, base.image_size, 'large'),
                show_title: pickScalar(null, base.show_title, 'yes'),
                show_description: pickScalar(null, base.show_description, ''),
                show_filter_bar: pickScalar(null, base.show_filter_bar, getWidgetData($widget, 'filter-enabled') === 'yes' ? 'yes' : ''),
                show_all_tab: pickScalar(null, base.show_all_tab, 'yes'),
                limited_items: pickScalar(null, base.limited_items, ''),
                dynamic_filter_taxonomy: pickScalar(editorSnapshot ? editorSnapshot.dynamic_filter_taxonomy : null, base.dynamic_filter_taxonomy, 'category'),
                dynamic_item_image: $.isPlainObject(base.dynamic_item_image) ? base.dynamic_item_image : {},
                dynamic_item_title: pickScalar(null, base.dynamic_item_title, ''),
                dynamic_item_description: pickScalar(null, base.dynamic_item_description, ''),
                dynamic_item_link: $.isPlainObject(base.dynamic_item_link) ? base.dynamic_item_link : { url: '', is_external: '' },
                enable_lightbox: pickScalar(null, base.enable_lightbox, getWidgetData($widget, 'enable-lightbox') === 'yes' ? 'yes' : ''),
                enable_pagination: ('yes' !== pickScalar(null, base.limited_items, '') || 'dynamic' === effectiveSource) ? 'yes' : '',
                images_per_page: pickScalar(null, base.images_per_page, imagesPerPage),
                pagination_type: normalizePaginationType(pickScalar(null, base.pagination_type, getWidgetData($widget, 'pagination-type') || 'none')),
                load_more_text: pickScalar(null, base.load_more_text, 'Load More'),
                all_label: pickScalar(null, base.all_label, 'All'),
                on_image_click: pickScalar(null, base.on_image_click, getWidgetData($widget, 'click-mode') || 'lightbox'),
                on_image_click_basic: pickScalar(null, base.on_image_click_basic, 'lightbox'),
                lightbox_caption: effectiveSource === 'basic_gallery' ? 'none' : pickScalar(null, base.lightbox_caption, 'title'),
                lightbox_title_position: pickScalar(null, base.lightbox_title_position, getWidgetData($widget, 'lightbox-title-position') || 'above'),
                show_lightbox_navigation: pickScalar(null, base.show_lightbox_navigation, getWidgetData($widget, 'show-navigation') === 'yes' ? 'yes' : ''),
                show_lightbox_counter: pickScalar(null, base.show_lightbox_counter, getWidgetData($widget, 'show-counter') === 'yes' ? 'yes' : ''),
                show_lightbox_thumbnails: pickScalar(null, base.show_lightbox_thumbnails, getWidgetData($widget, 'show-thumbnails') === 'yes' ? 'yes' : ''),
                show_lightbox_post_link: pickScalar(null, base.show_lightbox_post_link, getWidgetData($widget, 'show-post-link') === 'yes' ? 'yes' : ''),
                lightbox_post_link_label: pickScalar(null, base.lightbox_post_link_label, getWidgetData($widget, 'post-link-label') || 'Open Post'),
                lightbox_post_link_target: pickScalar(null, base.lightbox_post_link_target, getWidgetData($widget, 'post-link-target') || '_self'),
                close_on_backdrop_click: pickScalar(null, base.close_on_backdrop_click, getWidgetData($widget, 'close-backdrop') === 'yes' ? 'yes' : ''),
                gallery_animation: pickScalar(null, base.gallery_animation, getWidgetData($widget, 'sitsel-animation') || 'fade'),
                gallery_animation_speed: pickScalar(null, base.gallery_animation_speed, parseInt(getWidgetData($widget, 'sitsel-animation-speed'), 10) || 400),
                post_type: pickScalar(editorSnapshot ? editorSnapshot.post_type : null, base.post_type, 'post'),
                selection: pickScalar(editorSnapshot ? editorSnapshot.selection : null, base.selection, 'dynamic'),
                manual_posts: pickArray(editorSnapshot ? editorSnapshot.manual_posts : null, base.manual_posts, []),
                categories: pickArray(editorSnapshot ? editorSnapshot.categories : null, base.categories, []),
                exclude_categories: pickArray(editorSnapshot ? editorSnapshot.exclude_categories : null, base.exclude_categories, []),
                manual_tags: pickArray(editorSnapshot ? editorSnapshot.manual_tags : null, base.manual_tags, []),
                orderby: pickScalar(editorSnapshot ? editorSnapshot.orderby : null, base.orderby, 'date'),
                order: pickScalar(editorSnapshot ? editorSnapshot.order : null, base.order, 'DESC'),
                offset: pickScalar(editorSnapshot ? editorSnapshot.offset : null, base.offset, 0),
                posts_per_page: pickScalar(editorSnapshot ? editorSnapshot.posts_per_page : null, base.posts_per_page, imagesPerPage),
                meta_query_relation: pickScalar(editorSnapshot ? editorSnapshot.meta_query_relation : null, base.meta_query_relation, 'AND'),
                meta_query_rows: Array.isArray(base.meta_query_rows) ? base.meta_query_rows : []
            },
            items: []
        };

        try {
            return window.btoa(unescape(encodeURIComponent(JSON.stringify(payload))));
        } catch (e) {
            return '';
        }
    }

    function getConfig($widget) {
        var payload = decodePayload(getWidgetData($widget, 'gallery-payload'));
        var settings = (payload && payload.settings) ? payload.settings : {};
        var source = getWidgetData($widget, 'source') || settings.source || 'static';

        return {
            source: source,
            showAllItems: 'yes' === settings.limited_items,
            animation: getWidgetData($widget, 'sitsel-animation') || 'fade',
            speed: parseInt(getWidgetData($widget, 'sitsel-animation-speed'), 10) || 400,
            filterEnabled: getWidgetData($widget, 'filter-enabled') === 'yes',
            paginationEnabled: getWidgetData($widget, 'pagination-enabled') === 'yes',
            paginationType: normalizePaginationType(getWidgetData($widget, 'pagination-type') || settings.pagination_type || 'none'),
            enableLightbox: getWidgetData($widget, 'enable-lightbox') === 'yes',
            lightboxTitlePosition: getWidgetData($widget, 'lightbox-title-position') || settings.lightbox_title_position || 'above',
            showNavigation: getWidgetData($widget, 'show-navigation') === 'yes',
            showCounter: getWidgetData($widget, 'show-counter') === 'yes',
            showThumbnails: getWidgetData($widget, 'show-thumbnails') === 'yes',
            showPostLink: getWidgetData($widget, 'show-post-link') === 'yes',
            postLinkLabel: getWidgetData($widget, 'post-link-label') || settings.lightbox_post_link_label || 'Open Post',
            postLinkTarget: getWidgetData($widget, 'post-link-target') || settings.lightbox_post_link_target || '_self',
            closeBackdrop: getWidgetData($widget, 'close-backdrop') === 'yes'
        };
    }

    function normalizeWidgetVisibility($widget) {
        $widget.removeClass('elementor-invisible');
        $widget.find('.elementor-invisible').removeClass('elementor-invisible');
        $widget.css({
            opacity: '',
            visibility: ''
        });
    }

    function getState($widget) {
        var node = $widget.get(0);
        var payloadKey = String(getWidgetData($widget, 'gallery-payload') || '');
        var payload = decodePayload(payloadKey) || { items: [], settings: {} };
        var state;

        if (!stateMap.has(node)) {
            stateMap.set(node, {
                payload: payload,
                payloadKey: payloadKey,
                currentFilter: getWidgetData($widget, 'current-filter') || 'all',
                currentPage: parseInt(getWidgetData($widget, 'current-page'), 10) || 1,
                totalPages: parseInt(getWidgetData($widget, 'total-pages'), 10) || 1,
                activeIndex: 0,
                items: $()
            });
        }

        state = stateMap.get(node);

        if (state.payloadKey !== payloadKey) {
            state.payload = payload;
            state.payloadKey = payloadKey;
            state.currentFilter = getWidgetData($widget, 'current-filter') || 'all';
            state.currentPage = parseInt(getWidgetData($widget, 'current-page'), 10) || 1;
            state.totalPages = parseInt(getWidgetData($widget, 'total-pages'), 10) || 1;
            state.activeIndex = 0;
            state.items = $();
        }

        return state;
    }

    function getItems(state) {
        return (state.payload && state.payload.items) ? state.payload.items : [];
    }

    function getSettings(state) {
        return (state.payload && state.payload.settings) ? state.payload.settings : {};
    }

    function isEditorPreview() {
        if ($('body').hasClass('elementor-editor-active')) {
            return true;
        }

        if (window.elementorFrontend && typeof window.elementorFrontend.isEditMode === 'function') {
            return window.elementorFrontend.isEditMode();
        }

        return typeof window.elementor !== 'undefined' && !!window.elementor.channels;
    }

    function markGalleryPageReady() {
        $('body').addClass('sitsel-gallery-page-ready');
    }

    function getPayloadData($widget) {
        var node = $widget.get(0);
        var state = node ? stateMap.get(node) : null;

        if (state && state.payload) {
            return state.payload;
        }

        return decodePayload(getWidgetData($widget, 'gallery-payload')) || { items: [], settings: {} };
    }

    function shouldUseAjax($widget) {
        var config = getConfig($widget);
        var ajaxConfig = getAjaxConfig($widget);
        var payload = getPayloadData($widget);
        var hasLocalItems = !!(payload && Array.isArray(payload.items) && payload.items.length);

        if (isEditorPreview()) {
            return false;
        }

        return 'dynamic' === config.source && !hasLocalItems && !!ajaxConfig.ajaxUrl && !!ajaxConfig.nonce;
    }

    function getCategories(state) {
        var categories = [];
        var items = getItems(state);
        var i;
        var j;
        var cat;
        var categoriesMap = {};

        for (i = 0; i < items.length; i += 1) {
            for (j = 0; j < (items[i].categories ? items[i].categories.length || 0 : 0); j += 1) {
                cat = items[i].categories[j];
                if (cat && cat.slug) {
                    categoriesMap[String(cat.slug)] = String(cat.label || cat.slug);
                }
            }

            if (items[i].categories && !Array.isArray(items[i].categories)) {
                Object.keys(items[i].categories).forEach(function (slug) {
                    categoriesMap[String(slug)] = String(items[i].categories[slug] || slug);
                });
            }
        }

        Object.keys(categoriesMap).forEach(function (slug) {
            categories.push({ slug: slug, label: categoriesMap[slug] });
        });

        return categories;
    }

    function itemMatchesCategory(item, category) {
        var cats = item.categories || {};

        if ('all' === category) {
            return true;
        }

        if (Array.isArray(cats)) {
            return cats.some(function (cat) {
                return cat && String(cat.slug || '') === category;
            });
        }

        return Object.prototype.hasOwnProperty.call(cats, category);
    }

    function filterItems(state, category) {
        return getItems(state).filter(function (item) {
            return itemMatchesCategory(item, category);
        });
    }

    function paginateItems(items, page, perPage, paginationType) {
        var currentPage = Math.max(1, parseInt(page, 10) || 1);
        var totalPages = Math.max(1, Math.ceil(items.length / perPage));
        var start = 0;
        var end = items.length;

        if ('none' === paginationType) {
            return {
                pageItems: items.slice(0, perPage),
                currentPage: 1,
                totalPages: totalPages,
                hasMore: false,
                visible: false
            };
        }

        if ('numbers' === paginationType) {
            currentPage = Math.min(currentPage, totalPages);
            start = (currentPage - 1) * perPage;
            end = start + perPage;
            return {
                pageItems: items.slice(start, end),
                currentPage: currentPage,
                totalPages: totalPages,
                hasMore: currentPage < totalPages,
                visible: items.length > perPage
            };
        }

        currentPage = Math.min(currentPage, totalPages);
        start = (currentPage - 1) * perPage;
        end = start + perPage;

        return {
            pageItems: items.slice(start, end),
            currentPage: currentPage,
            totalPages: totalPages,
            hasMore: currentPage < totalPages,
            visible: items.length > perPage
        };
    }

    function escapeHtml(text) {
        return String(text || '')
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#039;');
    }

    function normalizeLinkData(linkValue, linkTarget) {
        var link = $.isPlainObject(linkValue) ? linkValue : { url: linkValue };
        var target = String(linkTarget || '').trim();

        if (!target && link && link.is_external) {
            target = '_blank';
        }

        return {
            url: link && link.url ? String(link.url) : '',
            target: '_blank' === target ? '_blank' : '_self'
        };
    }

    function renderCard(item, settings, index) {
        var title = item.title || '';
        var description = item.description || '';
        var image = item.image || {};
        var imageUrl = image.display_url || image.url || image.full_url || '';
        var lightboxUrl = image.full_url || image.url || image.display_url || '';
        var imageAlt = title;
        var clickMode = settings.on_image_click || 'lightbox';
        var lightboxEligible = ('lightbox' === clickMode && lightboxUrl && 'yes' === settings.enable_lightbox) ? '1' : '0';
        var categories = item.categories || {};
        var categorySlugs = Array.isArray(categories) ? categories.map(function (cat) { return cat.slug; }).filter(Boolean).join(',') : Object.keys(categories).join(',');
        var html = '';
        var linkData = normalizeLinkData(item.link, item.link_target);
        var linkUrl = linkData.url;
        var rel = ('_blank' === linkData.target) ? 'noopener noreferrer' : 'nofollow';
        var lightboxTitle = '';
        var lightboxDescription = '';
        var caption = '';

        if ('title' === settings.lightbox_caption || 'both' === settings.lightbox_caption) {
            lightboxTitle = title;
        }

        if ('description' === settings.lightbox_caption || 'both' === settings.lightbox_caption) {
            lightboxDescription = description;
        }

        caption = [lightboxTitle, lightboxDescription].join(' ').trim();

        html += '<article class="sitsel-filterable-gallery-item"';
        html += ' id="sitsel-filterable-gallery-item-' + escapeHtml(item.uid != null ? item.uid : index) + '"';
        html += ' data-item-index="' + escapeHtml(item.uid != null ? item.uid : index) + '"';
        html += ' data-item-id="sitsel-filterable-gallery-item-' + escapeHtml(item.uid != null ? item.uid : index) + '"';
        html += ' data-category-slugs="' + escapeHtml(categorySlugs) + '"';
        html += ' data-lightbox-eligible="' + escapeHtml(lightboxEligible) + '"';
        html += ' data-lightbox-src="' + escapeHtml(lightboxUrl) + '"';
        html += ' data-lightbox-alt="' + escapeHtml(imageAlt) + '"';
        html += ' data-lightbox-title="' + escapeHtml(lightboxTitle) + '"';
        html += ' data-lightbox-description="' + escapeHtml(lightboxDescription) + '"';
        html += ' data-lightbox-caption="' + escapeHtml(caption) + '"';
        html += ' data-post-link="' + escapeHtml(linkUrl) + '"';
        html += ' data-post-target="' + escapeHtml(linkData.target) + '">';
        html += '<div class="sitsel-filterable-gallery-card">';

        if ('custom-link' === clickMode && linkUrl) {
            html += '<a class="sitsel-filterable-gallery-action" href="' + escapeHtml(linkUrl) + '" target="' + escapeHtml(linkData.target) + '" rel="' + escapeHtml(rel) + '" data-click-mode="custom-link">';
        } else if ('lightbox' === clickMode && lightboxUrl) {
            html += '<button class="sitsel-filterable-gallery-action" type="button" data-click-mode="lightbox">';
        } else {
            html += '<div class="sitsel-filterable-gallery-action" data-click-mode="none">';
        }

        html += '<img class="sitsel-filterable-gallery-image" src="' + escapeHtml(imageUrl) + '" alt="' + escapeHtml(imageAlt) + '" loading="lazy" decoding="async" />';
        html += '<div class="sitsel-filterable-gallery-overlay"><div class="sitsel-filterable-gallery-overlay-inner">';

        if ('yes' === settings.show_title && title) {
            html += '<h3 class="sitsel-filterable-gallery-title">' + escapeHtml(title) + '</h3>';
        }

        if ('yes' === settings.show_description && description) {
            html += '<div class="sitsel-filterable-gallery-description">' + escapeHtml(description) + '</div>';
        }

        html += '</div></div>';

        if ('custom-link' === clickMode && linkUrl) {
            html += '</a>';
        } else if ('lightbox' === clickMode && lightboxUrl) {
            html += '</button>';
        } else {
            html += '</div>';
        }

        html += '</div></article>';
        return html;
    }

    function renderItemsHtml(items, settings) {
        var html = '';

        items.forEach(function (item, index) {
            html += renderCard(item, settings, index);
        });

        return html;
    }

    function renderPaginationHtml(result, settings) {
        var html = '';
        var source = String(settings.source || 'static');
        var type = normalizePaginationType(settings.pagination_type || 'none');
        var showAllItems = 'yes' === String(settings.limited_items || '');
        var visible = result.visible;

        if (('dynamic' !== source && showAllItems) || 'none' === type || !visible) {
            return '';
        }

        if ('load-more' === type && !result.hasMore) {
            return '';
        }

        html += '<div class="sitsel-filterable-gallery-pagination-inner sitsel-filterable-gallery-page-links sitsel-pagination-type-' + escapeHtml(type) + '">';

        if ('numbers' === type) {
            html += '<button class="sitsel-filterable-gallery-page-btn' + (1 === result.currentPage ? ' is-disabled' : '') + '" type="button" data-page="' + Math.max(1, result.currentPage - 1) + '"' + (1 === result.currentPage ? ' disabled' : '') + '>Prev</button>';

            for (var page = 1; page <= result.totalPages; page += 1) {
                html += '<button class="sitsel-filterable-gallery-page-btn' + (page === result.currentPage ? ' is-active' : '') + '" type="button" data-page="' + page + '">' + page + '</button>';
            }

            html += '<button class="sitsel-filterable-gallery-page-btn' + (result.currentPage === result.totalPages ? ' is-disabled' : '') + '" type="button" data-page="' + Math.min(result.totalPages, result.currentPage + 1) + '"' + (result.currentPage === result.totalPages ? ' disabled' : '') + '>Next</button>';
        } else {
            html += '<button class="sitsel-filterable-gallery-load-more" type="button" data-next-page="' + (result.currentPage + 1) + '"' + (!result.hasMore ? ' disabled' : '') + '>';
            html += '<span class="sitsel-filterable-gallery-button-label">' + escapeHtml(settings.load_more_text || 'Load More') + '</span>';
            html += '<span class="sitsel-filterable-gallery-button-loader" aria-hidden="true"></span>';
            html += '</button>';
        }

        html += '</div>';
        return html;
    }

    function collectLightboxItems($widget) {
        return $widget.find('.sitsel-filterable-gallery-item[data-lightbox-eligible="1"]')
            .filter(function () {
                return $(this).is(':visible');
            });
    }

    function getLightboxItemIndex(state, itemRef) {
        var $target = itemRef && itemRef.jquery ? itemRef.first() : $(itemRef).first();

        if ($target.length) {
            return state.items.index($target);
        }

        if (typeof itemRef !== 'undefined') {
            return state.items.index(state.items.filter('[data-item-index="' + itemRef + '"]').first());
        }

        return -1;
    }

    function getLoadingMessage($widget, isLoadMore) {
        var labels = getAjaxConfig($widget).labels || {};

        return isLoadMore ? (labels.loadingMore || 'Loading more items...') : (labels.loading || 'Loading gallery items...');
    }

    function isWidgetBusy($widget) {
        return !!$widget.data('sitselGalleryLoading') || $widget.hasClass('is-loading') || $widget.hasClass('is-loading-more');
    }

    function scheduleAjaxRetry($widget, category, page, mode) {
        var currentRetry = parseInt($widget.data('sitselGalleryAjaxRetry') || 0, 10);
        var maxRetries = 4;

        if (currentRetry >= maxRetries) {
            return;
        }

        $widget.data('sitselGalleryAjaxRetry', currentRetry + 1);

        window.setTimeout(function () {
            if (!isWidgetBusy($widget) && shouldUseAjax($widget)) {
                refreshWidgetWithLoading($widget, category, page, mode, null, mode);
            }
        }, 260 * (currentRetry + 1));
    }

    function setLoadingState($widget, isLoading, triggerType, $trigger) {
        var config = getConfig($widget);
        var isLoadMore = 'load-more' === triggerType && 'load-more' === config.paginationType;
        var isPaginationAction = isLoadMore || 'pagination' === triggerType;

        $widget.toggleClass('is-loading', isLoading && !isPaginationAction);
        $widget.toggleClass('is-loading-more', isLoading && isPaginationAction);
        $widget.attr('aria-busy', isLoading ? 'true' : 'false');
        $widget.data('sitselGalleryLoading', isLoading);

        if (isLoading) {
            $widget.find('.sitsel-filterable-gallery-pagination button').prop('disabled', true);
            if ($trigger && $trigger.length) {
                if (!$trigger.data('sitselOriginalLabel')) {
                    $trigger.data('sitselOriginalLabel', $trigger.find('.sitsel-filterable-gallery-button-label').text());
                }

                if (isLoadMore) {
                    $trigger.css('width', $trigger.outerWidth() + 'px');
                }

                $trigger.addClass('is-loading');
                if (isLoadMore) {
                    $trigger.find('.sitsel-filterable-gallery-button-label').text(getLoadingMessage($widget, true));
                }
            }
            updateStatus($widget, getLoadingMessage($widget, 'load-more' === triggerType));
            return;
        }

        $widget.find('.sitsel-filterable-gallery-pagination button').each(function () {
            var $button = $(this);
            $button.prop('disabled', $button.is('[disabled]') || $button.hasClass('is-disabled'));
            $button.removeClass('is-loading');
        });

        if ($trigger && $trigger.length) {
            if ($trigger.data('sitselOriginalLabel')) {
                $trigger.find('.sitsel-filterable-gallery-button-label').text($trigger.data('sitselOriginalLabel'));
            }

            $trigger.css('width', '');
            $trigger.removeClass('is-loading');
        }

        updateStatus($widget, '');
    }

    function applyEntryAnimation($widget, $targetItems) {
        var config = getConfig($widget);
        var $items = $targetItems && $targetItems.length ? $targetItems : $widget.find('.sitsel-filterable-gallery-item');

        $widget[0].style.setProperty('--sitsel-animation-speed', config.speed + 'ms');
        $items.removeClass('is-entering');

        if ('none' === config.animation) {
            return;
        }

        requestAnimationFrame(function () {
            $items.each(function (index) {
                $(this).css('--sitsel-animation-delay', (index * 45) + 'ms').addClass('is-entering');
            });
            window.setTimeout(function () {
                $items.removeClass('is-entering').css('--sitsel-animation-delay', '');
            }, config.speed + 80);
        });
    }

    function syncEmptyState($widget) {
        var deferEmptyState = shouldUseAjax($widget) && !$widget.data('sitselGalleryLoaded');
        var hasItems = $widget.find('.sitsel-filterable-gallery-item').length > 0;
        $widget.find('.sitsel-filterable-gallery-empty').toggleClass('is-visible', !deferEmptyState && !hasItems);
    }

    function updateStatus($widget, message) {
        $widget.find('.sitsel-filterable-gallery-status').text(message || '');
    }

    function setActiveFilterButton($widget, category) {
        var activeCategory = category || 'all';

        $widget.find('.sitsel-filterable-gallery-filter')
            .removeClass('is-active')
            .attr('aria-pressed', 'false');

        $widget.find('.sitsel-filterable-gallery-filter[data-category="' + activeCategory + '"]')
            .addClass('is-active')
            .attr('aria-pressed', 'true');
    }

    function replaceToolbar($widget, toolbarHtml, activeCategory) {
        var $existing = $widget.children('.sitsel-filterable-gallery-toolbar');
        var $status = $widget.children('.sitsel-filterable-gallery-status').first();

        if (toolbarHtml) {
            if ($existing.length) {
                $existing.replaceWith(toolbarHtml);
            } else if ($status.length) {
                $(toolbarHtml).insertBefore($status);
            } else {
                $widget.prepend(toolbarHtml);
            }

            setActiveFilterButton($widget, activeCategory);
            return;
        }

        $existing.remove();
    }

    function closeLightbox($widget) {
        var parts = ensureThumbnailElements($widget);

        $widget.find('.sitsel-filterable-gallery-lightbox').prop('hidden', true).removeClass('is-open');
        $widget.find('.sitsel-filterable-gallery-lightbox-post-link').prop('hidden', true).attr('href', '#');
        parts.wrap.addClass('is-hidden');
        parts.strip.addClass('is-hidden');
        $('body').removeClass('sitsel-filterable-gallery-lock');
    }

    function ensureThumbnailElements($widget) {
        var $wrap = $widget.find('.sitsel-filterable-gallery-lightbox-thumbnails-wrap').first();
        var $strip;

        if ($wrap.length) {
            $strip = $wrap.find('.sitsel-filterable-gallery-lightbox-thumbnails').first();

            return {
                wrap: $wrap,
                strip: $strip
            };
        }

        $strip = $widget.find('.sitsel-filterable-gallery-lightbox-thumbnails').first();

        if (!$strip.length) {
            return {
                wrap: $(),
                strip: $()
            };
        }

        $strip.wrap('<div class="sitsel-filterable-gallery-lightbox-thumbnails-wrap"></div>');
        $wrap = $strip.parent();

        if (!$wrap.find('.sitsel-filterable-gallery-lightbox-thumbnails-nav.is-prev').length) {
            $wrap.prepend('<button class="sitsel-filterable-gallery-lightbox-thumbnails-nav is-prev" type="button" aria-label="Previous thumbnails">&#10094;</button>');
        }

        if (!$wrap.find('.sitsel-filterable-gallery-lightbox-thumbnails-nav.is-next').length) {
            $wrap.append('<button class="sitsel-filterable-gallery-lightbox-thumbnails-nav is-next" type="button" aria-label="Next thumbnails">&#10095;</button>');
        }

        return {
            wrap: $wrap,
            strip: $strip
        };
    }

    function getThumbnailScrollAmount($strip) {
        var amount = 0;

        $strip.find('.sitsel-filterable-gallery-lightbox-thumb').slice(0, 3).each(function () {
            amount += $(this).outerWidth(true) || 0;
        });

        return amount || Math.max($strip.innerWidth() * 0.75, 120);
    }

    function syncThumbnailNavState($widget) {
        var parts = ensureThumbnailElements($widget);
        var $wrap = parts.wrap;
        var $strip = parts.strip;
        var strip = $strip.get(0);
        var hasOverflow;
        var maxScroll;

        if (!$wrap.length || !$strip.length || !strip) {
            return;
        }

        hasOverflow = strip.scrollWidth > (strip.clientWidth + 1);
        maxScroll = Math.max(0, strip.scrollWidth - strip.clientWidth - 1);

        $wrap.toggleClass('has-overflow', hasOverflow);
        $wrap.find('.sitsel-filterable-gallery-lightbox-thumbnails-nav')
            .toggleClass('is-hidden', !hasOverflow);

        if (!hasOverflow) {
            $wrap.find('.sitsel-filterable-gallery-lightbox-thumbnails-nav').prop('disabled', true);
            return;
        }

        $wrap.find('.sitsel-filterable-gallery-lightbox-thumbnails-nav.is-prev').prop('disabled', strip.scrollLeft <= 1);
        $wrap.find('.sitsel-filterable-gallery-lightbox-thumbnails-nav.is-next').prop('disabled', strip.scrollLeft >= maxScroll);
    }

    function scrollThumbnailStrip($widget, direction) {
        var $strip = ensureThumbnailElements($widget).strip;
        var strip = $strip.get(0);
        var distance;
        var nextLeft;

        if (!$strip.length || !strip) {
            return;
        }

        distance = getThumbnailScrollAmount($strip);
        nextLeft = Math.max(0, strip.scrollLeft + (direction * distance));

        $strip.stop(true).animate({ scrollLeft: nextLeft }, 220, function () {
            syncThumbnailNavState($widget);
        });
    }

    function syncLightboxThumbnails($widget, state, config) {
        var parts = ensureThumbnailElements($widget);
        var $wrap = parts.wrap;
        var $strip = parts.strip;
        var html = '';

        if (!$strip.length) {
            return;
        }

        if (!config.showThumbnails || state.items.length < 2) {
            $wrap.addClass('is-hidden').removeClass('has-overflow');
            $strip.addClass('is-hidden').empty();
            $wrap.find('.sitsel-filterable-gallery-lightbox-thumbnails-nav').prop('disabled', true);
            return;
        }

        state.items.each(function (index) {
            var $item = $(this);
            var src = $item.data('lightbox-src') || '';
            var alt = $item.data('lightbox-alt') || '';
            var activeClass = index === state.activeIndex ? ' is-active' : '';

            if (!src) {
                return;
            }

            html += '<button class="sitsel-filterable-gallery-lightbox-thumb' + activeClass + '" type="button" data-thumb-index="' + index + '" aria-label="Go to image ' + (index + 1) + '">';
            html += '<img src="' + escapeHtml(src) + '" alt="' + escapeHtml(alt) + '" loading="lazy" decoding="async" />';
            html += '</button>';
        });

        $wrap.removeClass('is-hidden');
        $strip.html(html).removeClass('is-hidden');

        window.requestAnimationFrame(function () {
            var activeThumb = $strip.find('.sitsel-filterable-gallery-lightbox-thumb.is-active').get(0);

            if (activeThumb && typeof activeThumb.scrollIntoView === 'function') {
                activeThumb.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' });
            }

            syncThumbnailNavState($widget);
            window.setTimeout(function () {
                syncThumbnailNavState($widget);
            }, 220);
        });
    }

    function setLightboxImageLoading($lightbox, isLoading) {
        $lightbox.find('.sitsel-filterable-gallery-lightbox-content').toggleClass('is-loading', !!isLoading);
    }

    function getLightboxZoomLevel($lightbox) {
        var $image = $lightbox.find('.sitsel-filterable-gallery-lightbox-image');
        var transform = $image.css('transform');
        
        if (!transform || transform === 'none') {
            return 1;
        }
        
        var matrix = transform.match(/matrix\(([^)]+)\)/);
        if (matrix) {
            var values = matrix[1].split(',').map(function(v) { return parseFloat(v.trim()); });
            return values[0] || 1; // scaleX value
        }
        
        return 1;
    }

    function setLightboxZoom($lightbox, scale) {
        var $image = $lightbox.find('.sitsel-filterable-gallery-lightbox-image');
        var $wrapper = $lightbox.find('.sitsel-filterable-gallery-lightbox-image-wrapper');
        var clampedScale = Math.max(1, Math.min(3, scale));
        
        $image.css('transform', clampedScale === 1 ? 'none' : 'scale(' + clampedScale + ')');
        $wrapper.toggleClass('is-zoomed', clampedScale > 1);
        
        // Update button states
        $lightbox.find('.sitsel-filterable-gallery-lightbox-zoom-in').prop('disabled', clampedScale >= 3);
        $lightbox.find('.sitsel-filterable-gallery-lightbox-zoom-out').prop('disabled', clampedScale <= 1);
        $lightbox.find('.sitsel-filterable-gallery-lightbox-zoom-reset').prop('disabled', clampedScale === 1);
    }

    function resetLightboxZoom($lightbox) {
        setLightboxZoom($lightbox, 1);
    }

    function zoomInLightbox($lightbox) {
        var currentZoom = getLightboxZoomLevel($lightbox);
        setLightboxZoom($lightbox, currentZoom + 0.25);
    }

    function zoomOutLightbox($lightbox) {
        var currentZoom = getLightboxZoomLevel($lightbox);
        setLightboxZoom($lightbox, currentZoom - 0.25);
    }

    function shareLightboxImage($widget) {
        var state = getState($widget);
        var $item = state.items.eq(state.activeIndex);
        var title = $item.data('lightbox-title') || 'Image';
        var imageUrl = $item.data('lightbox-src') || '';
        
        if (!imageUrl) {
            return;
        }

        // Try native Web Share API first
        if (navigator.share) {
            navigator.share({
                title: title,
                text: title,
                url: imageUrl
            }).catch(function() {
                // User cancelled or error - fail silently
            });
        } else {
            // Fallback: copy URL to clipboard
            var $temp = $('<textarea>').val(imageUrl).appendTo('body').select();
            
            try {
                document.execCommand('copy');
                // Could show a toast notification here
                alert('Image URL copied to clipboard!');
            } catch (err) {
                alert('Unable to share. URL: ' + imageUrl);
            }
            
            $temp.remove();
        }
    }

    function updateLightbox($widget) {
        var config = getConfig($widget);
        var state = getState($widget);
        var $lightbox = $widget.find('.sitsel-filterable-gallery-lightbox');

        if (!state.items.length) {
            closeLightbox($widget);
            return;
        }

        if (state.activeIndex < 0) {
            state.activeIndex = state.items.length - 1;
        }

        if (state.activeIndex >= state.items.length) {
            state.activeIndex = 0;
        }

        var $item = state.items.eq(state.activeIndex);
        var title = $item.data('lightbox-title') || '';
        var description = $item.data('lightbox-description') || '';
        var src = $item.data('lightbox-src') || '';
        var alt = $item.data('lightbox-alt') || '';
        var postLink = $item.data('post-link') || $item.data('link') || '';
        var postTarget = String($item.data('post-target') || config.postLinkTarget || '_self');
        var $image = $lightbox.find('.sitsel-filterable-gallery-lightbox-image');
        var $postLink = $lightbox.find('.sitsel-filterable-gallery-lightbox-post-link');
        var showTitleInFooter = config.lightboxTitlePosition === 'below';
        var showHeaderTitle = !!title && !showTitleInFooter;
        var showFooterTitle = !!title && showTitleInFooter;

        setLightboxImageLoading($lightbox, !!src);

        $image
            .off('.sitselLightboxLoader')
            .one('load.sitselLightboxLoader error.sitselLightboxLoader', function () {
                setLightboxImageLoading($lightbox, false);
            })
            .attr('src', src)
            .attr('alt', alt);

        if ($image.get(0) && $image.get(0).complete) {
            setLightboxImageLoading($lightbox, false);
        }

        // Update title placement
        $lightbox.find('.sitsel-filterable-gallery-lightbox-header')
            .toggleClass('is-title-hidden', !showHeaderTitle);

        $lightbox.find('.sitsel-filterable-gallery-lightbox-caption-title')
            .text(title)
            .attr('title', title || '')
            .toggleClass('is-hidden', !showHeaderTitle);

        $lightbox.find('.sitsel-filterable-gallery-lightbox-caption-title-footer')
            .text(title)
            .attr('title', title || '')
            .toggleClass('is-hidden', !showFooterTitle);
        
        // Update description in footer
        $lightbox.find('.sitsel-filterable-gallery-lightbox-caption-description')
            .text(description)
            .toggleClass('is-hidden', !description);
        
        // Update counter
        $lightbox.find('.sitsel-filterable-gallery-lightbox-counter')
            .toggleClass('is-hidden', !config.showCounter)
            .text((state.activeIndex + 1) + ' / ' + state.items.length);
        
        // Update navigation
        $lightbox.find('.sitsel-filterable-gallery-lightbox-nav')
            .toggleClass('is-hidden', !config.showNavigation || state.items.length < 2);

        if ($postLink.length) {
            if (config.showPostLink && 'dynamic' === config.source && postLink) {
                $postLink
                    .prop('hidden', false)
                    .attr('href', postLink)
                    .attr('target', '_blank' === postTarget ? '_blank' : '_self')
                    .attr('rel', '_blank' === postTarget ? 'noopener noreferrer' : 'nofollow')
                    .find('.sitsel-filterable-gallery-lightbox-post-link-label')
                    .text(config.postLinkLabel || 'Open Post');
            } else {
                $postLink.prop('hidden', true).attr('href', '#');
            }
        }
        
        syncLightboxThumbnails($widget, state, config);
        
        // Reset zoom when changing images
        resetLightboxZoom($lightbox);
    }

    function openLightbox($widget, itemRef) {
        var state = getState($widget);

        if (!getConfig($widget).enableLightbox) {
            return;
        }

        state.items = collectLightboxItems($widget);
        state.activeIndex = getLightboxItemIndex(state, itemRef);

        if (state.activeIndex < 0) {
            state.activeIndex = 0;
        }

        $widget.find('.sitsel-filterable-gallery-lightbox').prop('hidden', false).addClass('is-open');
        $('body').addClass('sitsel-filterable-gallery-lock');
        updateLightbox($widget);
    }

    function getVisibleItems(state, category, page) {
        var settings = getSettings(state);
        var filtered = filterItems(state, category);
        var source = String(settings.source || 'static');
        var showAllItems = 'yes' === String(settings.limited_items || '');
        var perPage = 'dynamic' === source
            ? normalizePerPageValue(settings.posts_per_page, 6)
            : Math.max(1, parseInt(settings.images_per_page, 10) || 10);
        var paginationType = normalizePaginationType(settings.pagination_type || 'none');
        var paginationEnabled = ('dynamic' === source) ? perPage > 0 : (!showAllItems && perPage > 0);

        if (!paginationEnabled) {
            return {
                pageItems: filtered,
                filteredItems: filtered,
                currentPage: 1,
                totalPages: 1,
                hasMore: false,
                visible: false,
                totalItems: filtered.length,
                perPage: perPage,
                paginationType: paginationType,
                settings: settings
            };
        }

        var paginated = paginateItems(filtered, page, perPage, paginationType);

        return {
            pageItems: paginated.pageItems,
            filteredItems: filtered,
            currentPage: paginated.currentPage,
            totalPages: paginated.totalPages,
            hasMore: paginated.hasMore,
            visible: paginated.visible,
            totalItems: filtered.length,
            perPage: perPage,
            paginationType: paginationType,
            settings: settings
        };
    }

    function refreshWidgetViaAjax($widget, category, page, mode) {
        var state = getState($widget);
        var config = getConfig($widget);
        var ajaxConfig = getAjaxConfig($widget);
        var payload = String(getWidgetData($widget, 'gallery-payload') || '');
        var decoded = decodePayload(payload);
        var decodedSettings = decoded && decoded.settings ? decoded.settings : null;
        var decodedSource = decodedSettings && decodedSettings.source ? String(decodedSettings.source) : '';
        var decodedPostType = decodedSettings && typeof decodedSettings.post_type !== 'undefined' ? String(decodedSettings.post_type || '').trim() : '';
        var $items = $widget.find('.sitsel-filterable-gallery-items');
        var previousCount = $items.children('.sitsel-filterable-gallery-item').length;

        if (
            isEditorPreview() &&
            'dynamic' === config.source
        ) {
            payload = buildFallbackPayload($widget, decodedSettings || {});
        } else if (
            !decodedSettings ||
            ('dynamic' === config.source && ('dynamic' !== decodedSource || '' === decodedPostType))
        ) {
            payload = buildFallbackPayload($widget, decodedSettings || {});
        }

        return $.ajax({
            url: ajaxConfig.ajaxUrl,
            type: 'POST',
            dataType: 'json',
            data: {
                action: 'sitsel_filterable_gallery_filter',
                nonce: ajaxConfig.nonce,
                category: category,
                page: page,
                payload: payload
            }
        }).done(function (response) {
            var data = response && response.success && response.data ? response.data : null;
            var $targetItems;

            if (!data) {
                $widget.data('sitselGalleryLoaded', true);
                updateStatus($widget, 'Unable to load gallery items.');
                syncEmptyState($widget);

                if (isEditorPreview()) {
                    scheduleAjaxRetry($widget, category, page, mode);
                }

                return;
            }

            $widget.data('sitselGalleryAjaxRetry', 0);
            state.currentFilter = data.activeFilter || category;
            state.currentPage = parseInt(data.currentPage, 10) || 1;
            state.totalPages = parseInt(data.totalPages, 10) || 1;

            if ('append' === mode) {
                $items.append(data.html || '');
                $targetItems = $items.children('.sitsel-filterable-gallery-item').slice(previousCount);
            } else {
                $items.html(data.html || '');
                $targetItems = $items.children('.sitsel-filterable-gallery-item');
            }

            $widget.attr('data-current-filter', state.currentFilter);
            $widget.attr('data-current-page', state.currentPage);
            $widget.attr('data-total-pages', state.totalPages);
            $widget.data('sitselGalleryLoaded', true);
            replaceToolbar($widget, data.toolbar || '', state.currentFilter);
            $widget.find('.sitsel-filterable-gallery-pagination').html(data.pagination || '');
            if ('none' === normalizePaginationType(getConfig($widget).paginationType)) {
                $widget.find('.sitsel-filterable-gallery-pagination').empty();
            }
            syncEmptyState($widget);
            applyEntryAnimation($widget, $targetItems);
            closeLightbox($widget);

            if ('replace' === mode && 'numbers' === config.paginationType) {
                $('html, body').stop(true).animate({ scrollTop: Math.max($widget.offset().top - 24, 0) }, 250);
            }

            updateStatus($widget, '');
        }).fail(function () {
            $widget.data('sitselGalleryLoaded', true);
            updateStatus($widget, 'Unable to load gallery items.');
            syncEmptyState($widget);

            if (isEditorPreview()) {
                scheduleAjaxRetry($widget, category, page, mode);
            }
        });
    }

    function refreshWidget($widget, category, page, mode) {
        var state = getState($widget);
        var config = getConfig($widget);
        var result = getVisibleItems(state, category, page);
        var $items = $widget.find('.sitsel-filterable-gallery-items');
        var paginationHtml = renderPaginationHtml(result, result.settings);
        var previousCount = $items.children('.sitsel-filterable-gallery-item').length;
        var $targetItems;

        state.currentFilter = category;
        state.currentPage = result.currentPage;
        state.totalPages = result.totalPages;

        if ('append' === mode) {
            $items.append(renderItemsHtml(result.pageItems, result.settings));
            $targetItems = $items.children('.sitsel-filterable-gallery-item').slice(previousCount);
        } else {
            $items.html(renderItemsHtml(result.pageItems, result.settings));
            $targetItems = $items.children('.sitsel-filterable-gallery-item');
        }

        $widget.attr('data-current-filter', category);
        $widget.attr('data-current-page', result.currentPage);
        $widget.attr('data-total-pages', result.totalPages);
        $widget.data('sitselGalleryLoaded', true);

        if (config.filterEnabled) {
            setActiveFilterButton($widget, category);
        }

        $widget.find('.sitsel-filterable-gallery-pagination').html(paginationHtml);
        if ('none' === normalizePaginationType(result.settings.pagination_type || 'none')) {
            $widget.find('.sitsel-filterable-gallery-pagination').empty();
        }
        syncEmptyState($widget);
        applyEntryAnimation($widget, $targetItems);
        closeLightbox($widget);

        if ('replace' === mode && 'numbers' === config.paginationType) {
            $('html, body').stop(true).animate({ scrollTop: Math.max($widget.offset().top - 24, 0) }, 250);
        }

        updateStatus($widget, '');

        return result;
    }

    function refreshWidgetWithLoading($widget, category, page, mode, $trigger, triggerType) {
        if (isWidgetBusy($widget)) {
            return;
        }

        setLoadingState($widget, true, triggerType || mode, $trigger);

        if (shouldUseAjax($widget)) {
            refreshWidgetViaAjax($widget, category, page, mode).always(function () {
                setLoadingState($widget, false, triggerType || mode, $trigger);
            });
            return;
        }

        window.requestAnimationFrame(function () {
            window.setTimeout(function () {
                refreshWidget($widget, category, page, mode);
                setLoadingState($widget, false, triggerType || mode, $trigger);
            }, 160);
        });
    }

    function bindWidget($widget) {
        var state = getState($widget);
        var config = getConfig($widget);
        var initialFilter = state.currentFilter || 'all';
        var payloadKey = String(getWidgetData($widget, 'gallery-payload') || '');
        var lastPayloadKey = String($widget.data('sitselGalleryPayloadKey') || '');

        normalizeWidgetVisibility($widget);

        if ($widget.data('sitselGalleryInit')) {
            if (lastPayloadKey !== payloadKey) {
                $widget.data('sitselGalleryPayloadKey', payloadKey);

                if (shouldUseAjax($widget)) {
                    $widget.data('sitselGalleryLoaded', false);
                    $widget.find('.sitsel-filterable-gallery-empty').removeClass('is-visible');
                    refreshWidgetWithLoading($widget, initialFilter, state.currentPage || 1, 'replace', null, 'replace');
                } else {
                    refreshWidget($widget, initialFilter, state.currentPage || 1, 'replace');
                }
            } else {
                applyEntryAnimation($widget);
                syncEmptyState($widget);
            }
            return;
        }

        $widget.data('sitselGalleryInit', true);
        $widget.data('sitselGalleryPayloadKey', payloadKey);
        $widget.data('sitselGalleryLoaded', !shouldUseAjax($widget));

        $widget.off('.sitselGallery');

        if (shouldUseAjax($widget)) {
            $widget.find('.sitsel-filterable-gallery-empty').removeClass('is-visible');
        }

        if (shouldUseAjax($widget)) {
            refreshWidgetWithLoading($widget, initialFilter, state.currentPage || 1, 'replace', null, 'replace');
        } else {
            refreshWidget($widget, initialFilter, state.currentPage || 1, 'replace');
        }

        $widget.on('click.sitselGallery', '.sitsel-filterable-gallery-filter', function () {
            var $button = $(this);
            var category = $button.data('category') || 'all';

            if ($button.hasClass('is-active') || isWidgetBusy($widget)) {
                return;
            }

            setActiveFilterButton($widget, category);
            refreshWidgetWithLoading($widget, category, 1, 'replace', $button, 'replace');
        });

        $widget.on('click.sitselGallery', '.sitsel-filterable-gallery-load-more', function () {
            var stateNow = getState($widget);
            var $button = $(this);
            var nextPage = parseInt($(this).data('next-page'), 10) || (stateNow.currentPage + 1);

            if (isWidgetBusy($widget)) {
                return;
            }

            refreshWidgetWithLoading($widget, stateNow.currentFilter || 'all', nextPage, 'append', $button, 'load-more');
        });

        $widget.on('click.sitselGallery', '.sitsel-filterable-gallery-page-btn', function () {
            var stateNow = getState($widget);
            var $button = $(this);
            var page = parseInt($(this).data('page'), 10) || 1;

            if ($(this).prop('disabled') || $(this).hasClass('is-active') || isWidgetBusy($widget)) {
                return;
            }

            refreshWidgetWithLoading($widget, stateNow.currentFilter || 'all', page, 'replace', $button, 'pagination');
        });

        $widget.on('click.sitselGallery', '.sitsel-filterable-gallery-action[data-click-mode="lightbox"]', function (event) {
            event.preventDefault();
            openLightbox($widget, $(this).closest('.sitsel-filterable-gallery-item'));
        });

        $widget.on('click.sitselGallery', '.sitsel-filterable-gallery-lightbox-close', function () {
            closeLightbox($widget);
        });

        $widget.on('click.sitselGallery', '[data-lightbox-close="backdrop"]', function () {
            if (getConfig($widget).closeBackdrop) {
                closeLightbox($widget);
            }
        });

        $widget.on('click.sitselGallery', '.sitsel-filterable-gallery-lightbox-nav.is-prev', function () {
            var stateNow = getState($widget);
            stateNow.activeIndex -= 1;
            updateLightbox($widget);
        });

        $widget.on('click.sitselGallery', '.sitsel-filterable-gallery-lightbox-nav.is-next', function () {
            var stateNow = getState($widget);
            stateNow.activeIndex += 1;
            updateLightbox($widget);
        });

        $widget.on('click.sitselGallery', '.sitsel-filterable-gallery-lightbox-thumb', function () {
            var stateNow = getState($widget);
            stateNow.activeIndex = parseInt($(this).data('thumb-index'), 10) || 0;
            updateLightbox($widget);
        });

        $widget.on('click.sitselGallery', '.sitsel-filterable-gallery-lightbox-thumbnails-nav.is-prev', function () {
            scrollThumbnailStrip($widget, -1);
        });

        $widget.on('click.sitselGallery', '.sitsel-filterable-gallery-lightbox-thumbnails-nav.is-next', function () {
            scrollThumbnailStrip($widget, 1);
        });

        $widget.on('scroll.sitselGallery', '.sitsel-filterable-gallery-lightbox-thumbnails', function () {
            syncThumbnailNavState($widget);
        });

        $widget.on('click.sitselGallery', '.sitsel-filterable-gallery-lightbox-zoom-in', function () {
            zoomInLightbox($widget.find('.sitsel-filterable-gallery-lightbox'));
        });

        $widget.on('click.sitselGallery', '.sitsel-filterable-gallery-lightbox-zoom-out', function () {
            zoomOutLightbox($widget.find('.sitsel-filterable-gallery-lightbox'));
        });

        $widget.on('click.sitselGallery', '.sitsel-filterable-gallery-lightbox-zoom-reset', function () {
            resetLightboxZoom($widget.find('.sitsel-filterable-gallery-lightbox'));
        });

        $widget.on('click.sitselGallery', '.sitsel-filterable-gallery-lightbox-share', function () {
            shareLightboxImage($widget);
        });
    }

    function initScope($scope, forceRebind) {
        $scope.find('.sitsel-filterable-gallery-wrapper').each(function () {
            var $widget = $(this);

            if (forceRebind) {
                $widget.removeData('sitselGalleryInit');
                $widget.removeData('sitselGalleryPayloadKey');
            }

            bindWidget($widget);
        });
    }

    $(document).on('keydown', function (event) {
        if ('Escape' !== event.key) {
            return;
        }

        $('.sitsel-filterable-gallery-wrapper').each(function () {
            closeLightbox($(this));
        });
    });

    window.SitselFilterableGallery = {
        initScope: initScope,
        refreshAll: function (forceRebind) {
            initScope($(document), !!forceRebind);
        }
    };

    $(function () {
        if (isEditorPreview() || document.readyState === 'complete') {
            markGalleryPageReady();
        }

        initScope($(document));
    });

    $(window).on('elementor/frontend/init', function () {
        if (!window.elementorFrontend || !window.elementorFrontend.hooks) {
            return;
        }

        window.elementorFrontend.hooks.addAction('frontend/element_ready/sitsel_filterable_gallery.default', initScope);
    });

    $(window).on('load.sitselGalleryReady', function () {
        markGalleryPageReady();
    });

    window.setTimeout(function () {
        markGalleryPageReady();
    }, 5000);
})(jQuery);
