
//======================================
// STEPRA ENGINE LITE — VERSION 1.1.0
// Lightweight Multi-Step Forms for WordPress
//======================================

(function($) {
    if (!$) { return; }

    // ==========================================
    // 0. SECURITY HELPER (XSS PROTECTION)
    // ==========================================
    function escapeHtml(str) {
        return String(str)
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#039;');
    }


    // ==========================================
    // 0A. DOM HELPER LAYER (VANILLA-FIRST FOUNDATION)
    // Internal only. These helpers normalize DOM access without replacing
    // the existing jQuery bridge used by supported builders.
    // ==========================================
    function stepraToElement(target) {
        if (!target) return null;
        if (target.jquery) return target[0] || null;
        if (target.nodeType === 1 || target.nodeType === 9) return target;
        return null;
    }

    function stepraToElementArray(target) {
        if (!target) return [];

        if (target.jquery) {
            return target.toArray();
        }

        if (target.nodeType === 1 || target.nodeType === 9) {
            return [target];
        }

        if (typeof target.length === 'number') {
            var list = [];
            for (var i = 0; i < target.length; i++) {
                if (target[i] && (target[i].nodeType === 1 || target[i].nodeType === 9)) {
                    list.push(target[i]);
                }
            }
            return list;
        }

        return [];
    }

    function stepraMatches(element, selector) {
        if (!element || element.nodeType !== 1 || !selector) return false;

        var matches = element.matches ||
            element.webkitMatchesSelector ||
            element.msMatchesSelector ||
            element.mozMatchesSelector;

        if (!matches) return false;

        try {
            return matches.call(element, selector);
        } catch(e) {
            return false;
        }
    }

    function stepraClosest(element, selector) {
        if (!element || element.nodeType !== 1 || !selector) return null;

        if (element.closest) {
            try {
                return element.closest(selector);
            } catch(e) {}
        }

        var current = element;
        while (current && current.nodeType === 1) {
            if (stepraMatches(current, selector)) return current;
            current = current.parentElement;
        }

        return null;
    }

    function stepraQueryAll(scope, selector) {
        if (!selector) return [];

        var root = stepraToElement(scope) || document;
        if (!root.querySelectorAll) root = document;

        try {
            return Array.prototype.slice.call(root.querySelectorAll(selector));
        } catch(e) {
            return [];
        }
    }

    function stepraUniqueElements(elements) {
        var unique = [];

        $.each(elements || [], function(index, element) {
            if (element && $.inArray(element, unique) === -1) {
                unique.push(element);
            }
        });

        return unique;
    }

    function stepraFindSupportedFormElements(scope) {
        if (scope && scope.jquery && scope.length === 0) return [];
        if (scope && !scope.nodeType && typeof scope.length === 'number' && scope.length === 0) return [];

        var roots = stepraToElementArray(scope);
        var forms = [];

        if (!roots.length) {
            roots = [document];
        }

        $.each(roots, function(index, root) {
            if (root.nodeType === 1 && stepraMatches(root, STEPRA_SUPPORTED_FORM_SELECTOR)) {
                forms.push(root);
            }

            forms = forms.concat(stepraQueryAll(root, STEPRA_SUPPORTED_FORM_SELECTOR));
        });

        return stepraUniqueElements(forms);
    }

    // ==========================================
    // 1. SETTINGS LOAD 
    // ==========================================
    var primaryColor = (typeof stepra_settings !== 'undefined') ? stepra_settings.primaryColor  : '#0061e0';
    var nextLabel    = (typeof stepra_settings !== 'undefined') ? stepra_settings.nextText      : 'Next step';
    var prevLabel    = (typeof stepra_settings !== 'undefined') ? stepra_settings.prevText      : 'Previous';
    var progTextCol  = (typeof stepra_settings !== 'undefined') ? stepra_settings.progTextColor : '#ffffff';
    var btnTextCol   = (typeof stepra_settings !== 'undefined') ? stepra_settings.btnTextColor  : '#ffffff';
    var progressStyle = (typeof stepra_settings !== 'undefined' && stepra_settings.progressStyle === 'numbered') ? 'numbered' : 'bar';

    var strictHeading = (typeof stepra_settings !== 'undefined' && stepra_settings.strictHeading === '1');
    var hTags = strictHeading ? 'h3' : 'h3, h4';

    var stepraBuilderTargets = (typeof stepra_settings !== 'undefined' && stepra_settings.builderTargets) ? stepra_settings.builderTargets : {};

    function stepraIsTargetEnabled(targetKey) {
        if (!targetKey) return true;
        if (!Object.prototype.hasOwnProperty.call(stepraBuilderTargets, targetKey)) return true;
        var value = stepraBuilderTargets[targetKey];
        return value === true || value === 1 || value === '1';
    }

    function stepraIsAdapterEnabled(adapter) {
        if (!adapter) return false;
        return stepraIsTargetEnabled(adapter.targetKey || adapter.id);
    }

    // ==========================================
    // 2. INTERNAL SUPPORTED BUILDER REGISTRY
    // Internal only. Do not expose this as a public adapter API in 1.1.0.
    // ==========================================
    var stepraInternalAdapters = [
        {
            id: 'elementor-forms',
            targetKey: 'elementor',
            label: 'Elementor Forms',
            formSelector: '.elementor-form',
            visualRootSelector: '.elementor-form',
            primaryRowSelector: '.elementor-field-group',
            fallbackRowSelector: '.elementor-field-group',
            submitSelector: '.elementor-field-type-submit, button[type="submit"], input[type="submit"]',
            conflictChecks: [
                { name: 'Elementor Native Steps', selector: '.elementor-field-type-step' }
            ],
            splitHandler: handleElementor
        },
        {
            id: 'wpforms',
            targetKey: 'wpforms',
            label: 'WPForms',
            formSelector: '.wpforms-form',
            visualRootSelector: '.wpforms-form',
            primaryRowSelector: '.wpforms-field',
            fallbackRowSelector: '.wpforms-field',
            submitSelector: '.wpforms-submit, button[type="submit"], input[type="submit"]',
            conflictChecks: [
                { name: 'WPForms Multi-page', selector: '.wpforms-page-indicator, .wpforms-page' }
            ],
            splitHandler: handleWPForms
        },
        {
            id: 'forminator',
            targetKey: 'forminator',
            label: 'Forminator',
            formSelector: 'form.forminator-ui, .forminator-custom-form',
            visualRootSelector: 'form.forminator-ui, .forminator-custom-form',
            primaryRowSelector: '.forminator-row',
            fallbackRowSelector: '.forminator-row',
            submitSelector: '.forminator-button-submit, button[type="submit"], input[type="submit"]',
            conflictChecks: [
                { name: 'Forminator Native Pagination', selector: '.forminator-pagination' }
            ],
            splitHandler: handleForminator
        },
        {
            id: 'contact-form-7',
            targetKey: 'cf7',
            label: 'Contact Form 7',
            formSelector: '.wpcf7-form',
            visualRootSelector: '.wpcf7-form',
            primaryRowSelector: '.wpcf7-form-control-wrap',
            fallbackRowSelector: 'p, fieldset, div',
            submitSelector: '.wpcf7-submit, button[type="submit"], input[type="submit"]',
            conflictChecks: [
                { name: 'Contact Form 7 Multi-Step Addon', selector: '.wpcf7-multistep', formClass: 'wpcf7-multistep' }
            ],
            splitHandler: handleCF7
        }
    ];

    function stepraBuildSupportedFormSelector() {
        return $.map(stepraInternalAdapters, function(adapter) {
            return stepraIsAdapterEnabled(adapter) ? adapter.formSelector : null;
        }).filter(function(selector) {
            return !!selector;
        }).join(', ') || 'form.__stepra-no-enabled-builders__';
    }

    var STEPRA_SUPPORTED_FORM_SELECTOR = stepraBuildSupportedFormSelector();
    var STEPRA_OWN_NODE_SELECTOR = '.stepra-progress, .stepra-nav, .stepra-summary-wrapper, .stepra-admin-warning';
    var STEPRA_OBSERVER_DEBOUNCE_MS = 50;
    var STEPRA_RETRY_INTERVAL_MS = 250;
    var STEPRA_MAX_INIT_ATTEMPTS = 25;


    // ==========================================
    // 2B-READY. READY CONTRACT + PRELOAD-SAFE FIELD DETECTION
    // Phase 12D: prevent false-ready states caused by Stepra's own anti-flash preload.
    // A form is not allowed to stay ready when it still needs Stepra UI.
    // ==========================================

    // ==========================================
    // 2B-VISUAL. NORMAL-FORM STAGING REVEAL
    // Phase 12H: visual shield is normal-form only and layout-safe.
    // ==========================================
    function stepraIsNormalVisualShieldForm($form) {
        if (!$form || !$form.length) return false;
        return $form.is('form.wpcf7-form, form.forminator-ui, form.forminator-custom-form, form.elementor-form, form.wpforms-form');
    }

    var STEPRA_VISUAL_PRELOAD_TIMEOUT_MS = 4500;
    var stepraVisualPreloadStartedAt = Date.now();
    var stepraGlobalPreloadReleaseTimer = null;

    function stepraScheduleVisualReveal($form) {
        if (!stepraIsNormalVisualShieldForm($form)) return;

        var reveal = function() {
            var adapter = stepraGetAdapter($form);

            if (adapter && !stepraBuilderVisualContractValid($form, adapter)) {
                if (($form.hasClass('stepra-ready') || stepraGetState($form) === 'ready') && !stepraReadyContractValid($form, adapter)) {
                    $form.removeClass('stepra-visual-ready');
                    stepraRepairInvalidReadyContract($form, adapter);
                }

                setTimeout(function() {
                    stepraScheduleVisualReveal($form);
                }, 60);
                return;
            }

            $form.addClass('stepra-visual-ready');
            stepraReleaseGlobalPreload(false);
        };

        if (window.requestAnimationFrame) {
            window.requestAnimationFrame(function() {
                window.requestAnimationFrame(reveal);
            });
        } else {
            setTimeout(reveal, 32);
        }
    }

    function stepraGetNormalVisualShieldForms() {
        return $('form.wpcf7-form, form.forminator-ui, form.forminator-custom-form, form.elementor-form, form.wpforms-form');
    }

    function stepraIsNormalVisualFormResolved($form) {
        if (!$form || !$form.length || !stepraIsNormalVisualShieldForm($form)) return true;

        if ($form.hasClass('stepra-visual-ready') || $form.hasClass('stepra-visual-failsafe') || $form.hasClass('stepra-aborted') || $form.hasClass('stepra-failed')) return true;

        var state = stepraGetState($form);
        if (state === 'aborted' || state === 'failed') return true;

        return false;
    }

    function stepraGetUnresolvedVisualFormCount() {
        var count = 0;

        stepraGetNormalVisualShieldForms().each(function() {
            if (!stepraIsNormalVisualFormResolved($(this))) {
                count++;
            }
        });

        return count;
    }

    function stepraForceResolveVisualForms() {
        stepraGetNormalVisualShieldForms().each(function() {
            var $form = $(this);
            if (!stepraIsNormalVisualFormResolved($form)) {
                $form.addClass('stepra-visual-ready stepra-visual-failsafe');
            }
        });
    }

    function stepraReleaseGlobalPreload(force) {
        force = force === true;

        if (!force) {
            var unresolved = stepraGetUnresolvedVisualFormCount();

            if (unresolved > 0) {
                if ((Date.now() - stepraVisualPreloadStartedAt) >= STEPRA_VISUAL_PRELOAD_TIMEOUT_MS) {
                    stepraForceResolveVisualForms();
                    force = true;
                } else {
                    clearTimeout(stepraGlobalPreloadReleaseTimer);
                    stepraGlobalPreloadReleaseTimer = setTimeout(function() {
                        stepraReleaseGlobalPreload(false);
                    }, 60);
                    return;
                }
            }
        }

        clearTimeout(stepraGlobalPreloadReleaseTimer);

        var release = function() {
            $('html').removeClass('stepra-preload').addClass('stepra-ready-global');
            $('body').removeClass('stepra-preload').addClass('stepra-loaded');
        };

        if (window.requestAnimationFrame) {
            window.requestAnimationFrame(function() {
                window.requestAnimationFrame(release);
            });
        } else {
            setTimeout(release, 32);
        }
    }

    function stepraIsHiddenByStepraPreload($el) {
        if (!$el || !$el.length) return false;
        if (!$('body').hasClass('stepra-preload') && !$('html').hasClass('stepra-preload')) return false;

        var $form = $el.closest(STEPRA_SUPPORTED_FORM_SELECTOR);
        if (!$form.length || !stepraIsNormalVisualShieldForm($form)) return false;

        if ($form.hasClass('stepra-visual-ready') || $form.hasClass('stepra-aborted') || $form.hasClass('stepra-failed')) {
            return false;
        }

        return true;
    }

    // Phase 12J: per-builder visual locks are Stepra-owned hiding.
    // Field detection must treat this as visually hidden only, not as a real hidden field.
    function stepraIsHiddenByStepraVisualLock($el) {
        if (!$el || !$el.length) return false;

        var $form = $el.is(STEPRA_SUPPORTED_FORM_SELECTOR) ? $el : $el.closest(STEPRA_SUPPORTED_FORM_SELECTOR);
        if (!$form.length || !stepraIsNormalVisualShieldForm($form)) return false;

        if ($form.hasClass('stepra-visual-ready') ||
            $form.hasClass('stepra-visual-failsafe') ||
            $form.hasClass('stepra-aborted') ||
            $form.hasClass('stepra-failed')) {
            return false;
        }

        return true;
    }

    function stepraIsRealVisibilityHidden($el) {
        if (!$el || !$el.length) return false;
        if ($el.css('visibility') !== 'hidden') return false;
        return !stepraIsHiddenByStepraPreload($el) && !stepraIsHiddenByStepraVisualLock($el);
    }

    function stepraIsElementActuallyVisible(element) {
        if (!element || element.nodeType !== 1) return false;

        var $el = $(element);
        var style = window.getComputedStyle ? window.getComputedStyle(element) : null;
        var preloadHidden = stepraIsHiddenByStepraPreload($el);
        var visualLockHidden = stepraIsHiddenByStepraVisualLock($el);
        var stepraOwnedHidden = preloadHidden || visualLockHidden;

        if (style) {
            if (style.display === 'none') return false;
            if (style.visibility === 'hidden' && !stepraOwnedHidden) return false;
            if (style.opacity === '0' && !stepraOwnedHidden) return false;
        }

        return element.offsetParent !== null || stepraOwnedHidden;
    }

    function stepraGetSplitInputCount($form, adapter) {
        if (!$form || !$form.length) return 0;

        return $form.find('input:not([type="hidden"]), select, textarea')
            .not('[type="submit"], [type="button"], [type="reset"], [type="image"], [type="password"]')
            .filter(function() {
                var $field = $(this);

                if (adapter && adapter.id === 'contact-form-7' && stepraIsCF7InternalHiddenField($field)) return false;
                if (adapter && adapter.id === 'forminator' && stepraIsForminatorSystemHiddenField($field)) return false;
                if (adapter && adapter.id === 'elementor-forms' && stepraIsElementorSystemField($field)) return false;
                if (adapter && adapter.id === 'wpforms' && stepraIsWPFormsValidationExcludedField($field)) return false;

                return true;
            }).length;
    }

    function stepraGetPolicyCandidateRowCount($form, adapter) {
        if (!$form || !$form.length || !adapter) return 0;

        if (adapter.id === 'contact-form-7') {
            return stepraGetCF7CandidateRows($form).length;
        }

        if (adapter.id === 'forminator') {
            return stepraGetForminatorCandidateRows($form).length;
        }

        if (adapter.id === 'elementor-forms') {
            return stepraGetElementorCandidateGroups($form).length;
        }

        if (adapter.id === 'wpforms') {
            return $form.find('.wpforms-field').filter(function() {
                var $row = $(this);
                if ($row.parent().closest('.wpforms-field').length > 0) return false;
                return stepraWPFormsFieldHasStepContent($row);
            }).length;
        }


        return $form.find('input:not([type="hidden"]), select, textarea').length;
    }

    function stepraGetAssignedStepRowCount($form) {
        if (!$form || !$form.length) return 0;
        return $form.find('.stepra-step-el[data-step]').length;
    }

    function stepraGetAssignedRealTotalSteps($form) {
        var total = 0;
        if (!$form || !$form.length) return total;

        $form.find('.stepra-step-el[data-step]').each(function() {
            var step = parseInt($(this).attr('data-step'), 10) || 0;
            if (step > total) total = step;
        });

        var progressTotal = parseInt($form.find('.stepra-progress').first().attr('data-total-steps'), 10) || 0;
        if (progressTotal > total) total = progressTotal;

        return total;
    }

    function stepraReadyRequiresUI($form, adapter) {
        if (!$form || !$form.length || !adapter) return false;
        var inputCount = stepraGetSplitInputCount($form, adapter);
        var rowCount = stepraGetPolicyCandidateRowCount($form, adapter);

        return inputCount >= 6 && rowCount > 1;
    }

    function stepraReadyContractValid($form, adapter) {
        if (!$form || !$form.length) return true;
        if (!$form.hasClass('stepra-ready') && stepraGetState($form) !== 'ready') return true;
        if (!adapter) adapter = stepraGetAdapter($form);
        if (!adapter) return true;

        if (!stepraReadyRequiresUI($form, adapter)) return true;

        var progressBars = $form.find('.stepra-progress').length;
        var navBlocks = $form.find('.stepra-nav').length;
        var stepRows = stepraGetAssignedStepRowCount($form);
        var totalSteps = stepraGetAssignedRealTotalSteps($form);
        var currentStep = parseInt($form.attr('data-current-step'), 10) || 0;

        return progressBars === 1 &&
            navBlocks === 1 &&
            stepRows > 0 &&
            totalSteps > 1 &&
            currentStep >= 1 &&
            currentStep <= totalSteps;
    }


    // Phase 12J: builder-specific visual contracts.
    // The visual lock may only release when that builder's own split policy agrees
    // that visible fields are assigned and builder-native system areas are preserved.

    function stepraGetWPFormsFieldRows($form) {
        if (!$form || !$form.length || !$form.hasClass('wpforms-form')) return $();

        return $form.find('.wpforms-field').filter(function() {
            var $row = $(this);

            if ($row.parent().closest('.wpforms-field').length > 0) return false;
            if (typeof stepraWPFormsFieldHasStepContent === 'function') {
                return stepraWPFormsFieldHasStepContent($row);
            }

            if ($row.hasClass('wpforms-field-hidden') || $row.hasClass('wpforms-field-hp') || $row.hasClass('wpforms-field-honeypot') || $row.hasClass('wpforms-field-pagebreak')) return false;
            if ($row.find('input:not([type="hidden"]):not([type="submit"]):not([type="button"]), select, textarea').length > 0) return true;

            return $.trim($row.text()) !== '';
        });
    }


    function stepraBuilderVisualContractValid($form, adapter) {
        try {
            return stepraBuilderVisualContractValidUnsafe($form, adapter);
        } catch(e) {
            if (typeof window !== 'undefined') {
                window.stepraLastVisualContractError = {
                    message: e && e.message ? e.message : String(e),
                    adapterId: adapter && adapter.id ? adapter.id : 'unknown',
                    time: Date.now()
                };
            }
            return false;
        }
    }

    function stepraBuilderVisualContractValidUnsafe($form, adapter) {
        if (!$form || !$form.length) return true;
        if (!adapter) adapter = stepraGetAdapter($form);
        if (!adapter) return true;

        if (!stepraIsNormalVisualShieldForm($form)) return true;
        if (stepraGetState($form) === 'aborted' || stepraGetState($form) === 'failed') return true;

        if (!stepraReadyContractValid($form, adapter)) return false;

        if (adapter.id === 'contact-form-7') {
            if (stepraGetCF7CandidateRows($form).length > 1 && stepraGetUnassignedCF7Rows($form).length > 0) return false;
            if ($form.find('.wpcf7-response-output').closest('.stepra-step-el').length > 0) return false;
            if ($form.find('input[type="hidden"], .wpcf7-hidden').filter(function() {
                return $(this).closest('.stepra-step-el').length > 0 && !$(this).closest('.wpcf7-form-control-wrap').length;
            }).length > 0) return false;
            return true;
        }

        if (adapter.id === 'forminator') {
            if (stepraGetForminatorCandidateRows($form).length > 1 && stepraGetUnassignedForminatorRows($form).length > 0) return false;
            if ($form.find('.forminator-response-message').closest('.stepra-step-el').length > 0) return false;
            if ($form.find('.forminator-row-last.stepra-step-el').length > 0) return false;
            return true;
        }

        if (adapter.id === 'elementor-forms') {
            if (stepraGetElementorCandidateGroups($form).length > 1 && stepraGetUnassignedElementorRows($form).length > 0) return false;
            if ($form.find('.elementor-field-type-hidden.stepra-step-el, .elementor-field-type-honeypot.stepra-step-el').length > 0) return false;
            if ($form.find('.elementor-field-type-submit.stepra-step-el').length > 0) return false;
            return true;
        }

        if (adapter.id === 'wpforms') {
            if (stepraGetWPFormsFieldRows($form).length > 1 && stepraGetUnassignedWPFormsRows($form).length > 0) return false;
            if ($form.find('.wpforms-submit-container').closest('.stepra-step-el').length > 0) return false;
            if ($form.find('.wpforms-field-hidden.stepra-step-el, .wpforms-field-hp.stepra-step-el, .wpforms-field-honeypot.stepra-step-el').length > 0) return false;
            return true;
        }

        return true;
    }

    function stepraResetFormForReadyRepair($form, adapter) {
        if (!$form || !$form.length || !adapter) return;

        if (adapter.id === 'contact-form-7') {
            stepraResetCF7ForRebuild($form);
            return;
        }

        if (adapter.id === 'forminator') {
            stepraResetForminatorForRebuild($form);
            return;
        }

        if (adapter.id === 'elementor-forms') {
            stepraResetElementorForRebuild($form);
            return;
        }

        if (adapter.id === 'wpforms') {
            stepraResetWPFormsForRebuild($form);
            return;
        }

        $form
            .removeClass('stepra-ready stepra-visual-ready stepra-initializing stepra-aborted stepra-failed')
            .removeAttr('data-stepra-state data-stepra-initialized data-stepra-init-lock data-current-step data-last-step data-first-step data-stepra-nav-direction');

        $form.find('.stepra-progress, .stepra-nav, .stepra-summary-wrapper').remove();
        $form.find('.stepra-step-el').removeClass('stepra-step-el stepra-hidden').removeAttr('data-step');
    }

    function stepraRepairInvalidReadyContract($form, adapter) {
        if (!$form || !$form.length || !adapter) return false;

        if (($form.hasClass('stepra-ready') || stepraGetState($form) === 'ready') && !stepraReadyContractValid($form, adapter)) {
            stepraDispatchInternalEvent('ready-contract-repair', $form, {
                adapterId: adapter.id,
                inputCount: stepraGetSplitInputCount($form, adapter),
                candidateRows: stepraGetPolicyCandidateRowCount($form, adapter),
                progressBars: $form.find('.stepra-progress').length,
                navBlocks: $form.find('.stepra-nav').length,
                stepRows: stepraGetAssignedStepRowCount($form)
            });

            stepraResetFormForReadyRepair($form, adapter);
            return true;
        }

        return false;
    }

    function stepraGetPendingOrInvalidFormCount() {
        var count = 0;

        stepraGetSupportedForms().each(function() {
            var $form = $(this);
            var adapter = stepraGetAdapter($form);
            var state = stepraGetState($form);

            if (state === 'aborted' || state === 'failed') return true;

            if (!$form.hasClass('stepra-ready') || state !== 'ready') {
                count++;
                return true;
            }

            if (!stepraReadyContractValid($form, adapter)) {
                count++;
            }
        });

        return count;
    }

    // ==========================================
    // 2A. INTERNAL HOOKS, EVENTS, AND DEBUG FOUNDATION
    // Internal only. This is not public adapter registration.
    // ==========================================
    var stepraInternalHooks = {
        actions: {},
        filters: {}
    };
    var stepraDebugHistory = [];
    var STEPRA_DEBUG_HISTORY_LIMIT = 50;

    function stepraIsDebugEnabled() {
        var enabled = (typeof window !== 'undefined' && window.stepraDebug === true);

        if (!enabled && typeof stepra_settings !== 'undefined') {
            enabled = stepra_settings.debug === true || stepra_settings.debug === '1';
        }

        return !!enabled;
    }

    function stepraAddInternalAction(name, callback) {
        if (!name || !$.isFunction(callback)) return;
        if (!stepraInternalHooks.actions[name]) stepraInternalHooks.actions[name] = [];
        stepraInternalHooks.actions[name].push(callback);
    }

    function stepraDoInternalAction(name, detail) {
        var callbacks = stepraInternalHooks.actions[name] || [];

        $.each(callbacks, function(index, callback) {
            try {
                callback(detail || {});
            } catch(e) {
                stepraDebugLog('Internal action error', {
                    hook: name,
                    message: e && e.message ? e.message : String(e)
                });
            }
        });
    }

    function stepraAddInternalFilter(name, callback) {
        if (!name || !$.isFunction(callback)) return;
        if (!stepraInternalHooks.filters[name]) stepraInternalHooks.filters[name] = [];
        stepraInternalHooks.filters[name].push(callback);
    }

    function stepraApplyInternalFilters(name, value, detail) {
        var callbacks = stepraInternalHooks.filters[name] || [];
        var filtered = value;

        $.each(callbacks, function(index, callback) {
            try {
                filtered = callback(filtered, detail || {});
            } catch(e) {
                stepraDebugLog('Internal filter error', {
                    hook: name,
                    message: e && e.message ? e.message : String(e)
                });
            }
        });

        return filtered;
    }

    function stepraRememberDebug(entry) {
        stepraDebugHistory.push(entry);

        if (stepraDebugHistory.length > STEPRA_DEBUG_HISTORY_LIMIT) {
            stepraDebugHistory.shift();
        }
    }

    function stepraGetDebugForms() {
        return $.map(stepraGetSupportedForms(), function(form, index) {
            var $form = $(form);
            var adapter = stepraGetAdapter($form);

            return {
                index: index + 1,
                adapterId: adapter ? adapter.id : '',
                adapterLabel: adapter ? adapter.label : '',
                state: stepraGetState($form),
                initialized: String($form.attr('data-stepra-initialized') || ''),
                initLock: String($form.attr('data-stepra-init-lock') || ''),
                currentStep: String($form.attr('data-current-step') || ''),
                progressBars: $form.find('.stepra-progress').length,
                navBlocks: $form.find('.stepra-nav').length
            };
        });
    }

    function stepraMaybeExposeDebugApi() {
        if (typeof window === 'undefined' || !stepraIsDebugEnabled()) return;

        window.stepraInternalDebug = {
            getForms: stepraGetDebugForms,
            getHistory: function() {
                return stepraDebugHistory.slice();
            }
        };
    }

    function stepraDebugLog(message, data) {
        if (!stepraIsDebugEnabled()) return;

        var entry = {
            message: String(message || ''),
            data: data || {},
            timestamp: Date.now()
        };

        stepraRememberDebug(entry);
        stepraMaybeExposeDebugApi();

        if (typeof window !== 'undefined' && window.console && window.console.log) {
            window.console.log('[StepraEngine]', message, data || {});
        }
    }

    function stepraDispatchInternalEvent(name, $form, detail) {
        if (!name) return;

        var form = stepraToElement($form);
        var adapter = $form && $form.length ? stepraGetAdapter($form) : null;
        var eventDetail = $.extend({
            form: form || null,
            adapterId: adapter ? adapter.id : '',
            adapterLabel: adapter ? adapter.label : '',
            state: $form && $form.length ? stepraGetState($form) : '',
            timestamp: Date.now()
        }, detail || {});

        eventDetail = stepraApplyInternalFilters('event.detail', eventDetail, {
            name: name,
            form: form || null
        });

        stepraDoInternalAction(name, eventDetail);
        stepraDebugLog('event:' + name, eventDetail);

        try {
            if (typeof document !== 'undefined' && typeof window !== 'undefined' && typeof window.CustomEvent === 'function') {
                document.dispatchEvent(new window.CustomEvent('stepra:' + name, {
                    detail: eventDetail
                }));
            }
        } catch(e) {
            stepraDebugLog('Internal event dispatch failed', {
                event: name,
                message: e && e.message ? e.message : String(e)
            });
        }
    }

    function stepraGetAdapter($form) {
        var form = stepraToElement($form);
        if (!form) return null;

        for (var i = 0; i < stepraInternalAdapters.length; i++) {
            var adapter = stepraInternalAdapters[i];
            if (stepraIsAdapterEnabled(adapter) && stepraMatches(form, adapter.formSelector)) {
                return adapter;
            }
        }

        return null;
    }

    function stepraFindBuilderConflict($form, adapter) {
        if (!$form || !$form.length || !adapter || !adapter.conflictChecks) return null;

        for (var i = 0; i < adapter.conflictChecks.length; i++) {
            var check = adapter.conflictChecks[i];

            if (check.selector && $form.find(check.selector).length > 0) {
                return check;
            }

            if (check.formClass && $form.hasClass(check.formClass)) {
                return check;
            }
        }

        return null;
    }

    function stepraRunAdapterSplit($form, adapter) {
        if (!adapter || !$.isFunction(adapter.splitHandler)) return 0;
        return adapter.splitHandler($form);
    }

    function stepraGetSupportedForms($scope) {
        return $(stepraFindSupportedFormElements($scope));
    }

    function stepraIsOwnInsertedNode(node) {
        if (!node || node.nodeType !== 1) return false;

        return stepraMatches(node, STEPRA_OWN_NODE_SELECTOR) ||
            stepraClosest(node, STEPRA_OWN_NODE_SELECTOR) !== null;
    }

    function stepraNodeHasSupportedForm(node) {
        if (!node || node.nodeType !== 1 || stepraIsOwnInsertedNode(node)) return false;

        return stepraMatches(node, STEPRA_SUPPORTED_FORM_SELECTOR) ||
            stepraQueryAll(node, STEPRA_SUPPORTED_FORM_SELECTOR).length > 0;
    }

    function stepraBuildProgressMarkup(totalSteps) {
        if (progressStyle === 'numbered') {
            var html = '<div class="stepra-progress stepra-progress-numbered" style="--stepra-progress-color:' + escapeHtml(primaryColor) + ';">';
            html += '<div class="stepra-numbered-steps" role="list" aria-label="Form steps">';

            for (var i = 1; i <= totalSteps; i++) {
                html += '<button type="button" class="stepra-progress-number" data-stepra-target-step="' + i + '" aria-label="Step ' + i + '" aria-disabled="true">' + i + '</button>';

                if (i < totalSteps) {
                    html += '<span class="stepra-progress-segment" data-stepra-segment="' + i + '" aria-hidden="true"></span>';
                }
            }

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

        return '<div class="stepra-progress stepra-progress-bar-mode">' +
            '<div class="stepra-progress-bar" style="background:' + escapeHtml(primaryColor) + ';"></div>' +
            '<div class="stepra-progress-text" style="color:' + escapeHtml(progTextCol) + ' !important;">Step 1 of ' + totalSteps + '</div>' +
            '</div>';
    }


    function stepraGetCurrentStep($form, totalSteps) {
        var currentStep = parseInt($form.attr('data-current-step'), 10) || 1;
        totalSteps = parseInt(totalSteps, 10) || 1;

        if (currentStep < 1) currentStep = 1;
        if (currentStep > totalSteps) currentStep = totalSteps;

        $form.attr('data-current-step', currentStep);
        return currentStep;
    }

    function stepraSetCurrentStep($form, targetStep, totalSteps) {
        var previousStep = parseInt($form.attr('data-current-step'), 10) || 0;

        targetStep = parseInt(targetStep, 10) || 1;
        totalSteps = parseInt(totalSteps, 10) || 1;

        if (targetStep < 1) targetStep = 1;
        if (targetStep > totalSteps) targetStep = totalSteps;

        $form.attr('data-current-step', targetStep);

        if (previousStep !== targetStep) {
            stepraDispatchInternalEvent('step-change', $form, {
                previousStep: previousStep || null,
                currentStep: targetStep,
                totalSteps: totalSteps
            });
        }

        return targetStep;
    }

    function stepraBuildNavigationMarkup() {
        return '<div class="stepra-nav" style="display:flex; width:100%; align-items:center; --stepra-primary:' + escapeHtml(primaryColor) + '; --stepra-btn-text:' + escapeHtml(btnTextCol) + ';">' +
            '<button type="button" class="stepra-prev" style="color:#334155 !important;">' + escapeHtml(prevLabel) + '</button>' +
            '<button type="button" class="stepra-next" style="margin-left:auto;">' + escapeHtml(nextLabel) + '</button>' +
            '</div>';
    }

    function stepraUpdateProgressUI($form, currentStep, totalSteps) {
        if (progressStyle === 'numbered') {
            $form.find('.stepra-progress-segment').each(function() {
                var $segment = $(this);
                var segmentStep = parseInt($segment.attr('data-stepra-segment'), 10) || 1;
                $segment.css('--stepra-segment-fill', currentStep > segmentStep ? 1 : 0);
            });

            $form.find('.stepra-progress-number').each(function() {
                var $num = $(this);
                var targetStep = parseInt($num.attr('data-stepra-target-step'), 10) || 1;

                $num.removeClass('is-active is-completed is-locked');

                if (targetStep === currentStep) {
                    $num.addClass('is-active').attr('aria-current', 'step').attr('aria-disabled', 'true');
                } else if (targetStep < currentStep) {
                    $num.addClass('is-completed').removeAttr('aria-current').attr('aria-disabled', 'false');
                } else {
                    $num.addClass('is-locked').removeAttr('aria-current').attr('aria-disabled', 'true');
                }
            });

            return;
        }

        $form.find('.stepra-progress-bar').css('width', (currentStep / totalSteps * 100) + '%');
        $form.find('.stepra-progress-text')
            .text('Step ' + currentStep + ' of ' + totalSteps)
            .css('cssText', 'color:' + escapeHtml(progTextCol) + ' !important;');
    }


    function stepraMarkLoaded(force) {
        force = force === true;

        var wasLoaded = $('body').hasClass('stepra-loaded');

        stepraReleaseGlobalPreload(force);

        if (!wasLoaded && (force || stepraGetUnresolvedVisualFormCount() === 0)) {
            stepraDispatchInternalEvent('loaded', null, {
                pendingForms: stepraGetPendingOrInvalidFormCount(),
                unresolvedVisualForms: stepraGetUnresolvedVisualFormCount()
            });
        }
    }

    // ==========================================
    // 1A/1B. STEPRA LIFECYCLE STATE + INIT LOCK HELPERS
    // State and lock foundation only. This does not change splitting,
    // validation, progress rendering, navigation, or submit behavior.
    // ==========================================
    function stepraReleaseInitLock($form) {
        if (!$form || !$form.length) return;
        $form.removeAttr('data-stepra-init-lock');
    }

    function stepraAcquireInitLock($form) {
        if (!$form || !$form.length) return false;
        if ($form.attr('data-stepra-init-lock') === '1') return false;

        $form.attr('data-stepra-init-lock', '1');
        return true;
    }

    function stepraSetState($form, state) {
        if (!$form || !$form.length || !state) return;

        var allowed = ['pending', 'initializing', 'ready', 'aborted', 'failed'];
        if ($.inArray(state, allowed) === -1) return;

        var previousState = stepraGetState($form);

        $form
            .removeClass('stepra-pending stepra-initializing stepra-aborted stepra-failed')
            .attr('data-stepra-state', state);

        if (state === 'initializing') {
            $form.attr('data-stepra-init-lock', '1');
        } else if (state === 'ready' || state === 'aborted' || state === 'failed') {
            stepraReleaseInitLock($form);
        }

        if (state === 'ready') {
            $form.addClass('stepra-ready').attr('data-stepra-initialized', '1');
            stepraScheduleVisualReveal($form);
        } else {
            $form.removeClass('stepra-ready stepra-visual-ready').addClass('stepra-' + state);
        }

        if (previousState !== state) {
            stepraDispatchInternalEvent('state-change', $form, {
                previousState: previousState || null,
                currentState: state
            });

            if (state === 'ready' || state === 'aborted' || state === 'failed') {
                stepraDispatchInternalEvent(state, $form, {
                    previousState: previousState || null,
                    currentState: state
                });
            }
        }
    }

    function stepraGetState($form) {
        if (!$form || !$form.length) return '';
        return String($form.attr('data-stepra-state') || '');
    }

    function stepraDeferInit($form) {
        stepraReleaseInitLock($form);
        stepraSetState($form, 'pending');
        stepraDispatchInternalEvent('init-deferred', $form, {
            reason: 'document-loading'
        });
    }


    // ==========================================
    // 2. SURGICAL GHOST FILTER (Select2 Safe)
    // ==========================================


    function stepraIsCF7SystemArea($el) {
        if (!$el || !$el.length) return false;

        return $el.closest(
            '.hidden-fields-container, ' +
            '.wpcf7-response-output, ' +
            '.screen-reader-response, ' +
            '.wpcf7-spinner'
        ).length > 0;
    }

    function stepraIsCF7InternalHiddenField($el) {
        if (!$el || !$el.length) return false;

        var type = String($el.attr('type') || '').toLowerCase();
        var name = String($el.attr('name') || '');

        return type === 'hidden' ||
            $el.hasClass('wpcf7-hidden') ||
            name.indexOf('_wpcf7') === 0 ||
            name.indexOf('_wpcf7_quiz_answer_') === 0 ||
            stepraIsCF7SystemArea($el);
    }



    // ==========================================
    // 2A. CF7 EXTENDED FIELD-POLICY HELPERS
    // Adapter-scoped safety layer. These helpers make CF7 behave like the
    // hardened WPForms policy: every real visible row is either assigned to a
    // Stepra step, or explicitly ignored as CF7/system markup. They do not
    // clone, move, or rewrite CF7 controls.
    // ==========================================
    function stepraIsCF7SubmitArea($el) {
        if (!$el || !$el.length) return false;

        return $el.is('.wpcf7-submit, button[type="submit"], input[type="submit"]') ||
            $el.closest('p, div, label').find('.wpcf7-submit, button[type="submit"], input[type="submit"]').length > 0;
    }

    function stepraIsCF7SystemRow($row) {
        if (!$row || !$row.length) return true;

        if ($row.is(
            'input[type="hidden"], ' +
            'input.wpcf7-hidden, ' +
            'style, script, noscript, ' +
            '.stepra-progress, ' +
            '.stepra-nav, ' +
            '.stepra-summary-wrapper, ' +
            '.stepra-admin-warning, ' +
            '.wpcf7-response-output, ' +
            '.screen-reader-response, ' +
            '.wpcf7-spinner, ' +
            '.hidden-fields-container'
        )) {
            return true;
        }

        if (stepraIsCF7SystemArea($row)) return true;

        var $controls = $row.find('input, select, textarea').addBack('input, select, textarea');
        if ($controls.length > 0) {
            var usableControls = $controls.filter(function() {
                return stepraCF7HasUsableControl($(this));
            }).length;

            if (usableControls === 0 && $.trim($row.text()) === '') {
                return true;
            }
        }

        return false;
    }

    function stepraCF7HasUsableControl($control) {
        if (!$control || !$control.length) return false;
        if (stepraIsCF7InternalHiddenField($control)) return false;

        var type = String($control.attr('type') || '').toLowerCase();
        if (type === 'hidden' || type === 'submit' || type === 'button' || type === 'reset' || type === 'image') return false;
        if ($control.is('[disabled]')) return false;
        if ($control.attr('aria-hidden') === 'true') return false;
        if (stepraIsRealVisibilityHidden($control)) return false;

        return true;
    }

    function stepraCF7RowHasUsableControl($row) {
        if (!$row || !$row.length) return false;

        return $row.find('input, select, textarea').addBack('input, select, textarea').filter(function() {
            return stepraCF7HasUsableControl($(this));
        }).length > 0;
    }

    function stepraCF7RowHasVisibleTextContent($row) {
        if (!$row || !$row.length) return false;

        var $clone = $row.clone();
        $clone.find(
            'input[type="hidden"], input[type="submit"], button[type="submit"], script, style, ' +
            '.wpcf7-response-output, .screen-reader-response, .wpcf7-spinner, .hidden-fields-container, ' +
            '.stepra-progress, .stepra-nav, .stepra-summary-wrapper, .stepra-admin-warning'
        ).remove();

        return $.trim($clone.text()).length > 0;
    }

    function stepraCF7RowHasStepContent($row) {
        if (!$row || !$row.length) return false;

        // Do not treat Stepra's own inactive-step class as real hidden CF7 state.
        var hiddenOnlyByStepra = $row.hasClass('stepra-hidden') && !stepraHasInlineHiddenStyle($row[0]);
        if (!hiddenOnlyByStepra && ($row.css('display') === 'none' || stepraHasInlineHiddenStyle($row[0]))) return false;
        if (stepraIsRealVisibilityHidden($row)) return false;
        if (stepraIsCF7SystemRow($row)) return false;
        if (stepraIsCF7SubmitArea($row) && !stepraCF7RowHasUsableControl($row) && !stepraCF7RowHasVisibleTextContent($row)) return false;

        var hasHeading = $row.is(hTags) || $row.find(hTags).length > 0;
        return stepraCF7RowHasUsableControl($row) || hasHeading || stepraCF7RowHasVisibleTextContent($row);
    }

    function stepraAddCF7CandidateRow(rows, row) {
        if (!row) return rows;

        var $row = $(row);
        if (!$row.length) return rows;
        if (!stepraCF7RowHasStepContent($row)) return rows;
        if ($.inArray(row, rows) !== -1) return rows;

        var shouldSkip = false;
        rows = $.grep(rows, function(existing) {
            if (existing === row) {
                shouldSkip = true;
                return true;
            }

            if ($.contains(existing, row)) {
                shouldSkip = true;
                return true;
            }

            if ($.contains(row, existing)) {
                return false;
            }

            return true;
        });

        if (!shouldSkip) rows.push(row);
        return rows;
    }

    function stepraGetCF7CandidateRows($form) {
        var rows = [];
        if (!$form || !$form.length || !$form.hasClass('wpcf7-form')) return $();

        $form.children().each(function() {
            rows = stepraAddCF7CandidateRow(rows, this);
        });

        $form.find('.wpcf7-form-control-wrap, label, p, fieldset, li, div').each(function() {
            var $candidate = $(this);
            if ($candidate.closest('.stepra-progress, .stepra-nav, .stepra-summary-wrapper, .stepra-admin-warning').length) return true;
            if ($candidate.closest('.wpcf7-response-output, .screen-reader-response, .wpcf7-spinner, .hidden-fields-container').length) return true;
            rows = stepraAddCF7CandidateRow(rows, this);
        });

        return $(rows);
    }

    function stepraCleanupCF7SystemRows($form) {
        if (!$form || !$form.length || !$form.hasClass('wpcf7-form')) return;

        $form.find('.hidden-fields-container, .wpcf7-response-output, .screen-reader-response, .wpcf7-spinner, input[type="hidden"], .wpcf7-hidden').each(function() {
            $(this).removeClass('stepra-step-el stepra-hidden').removeAttr('data-step');
        });
    }

    function stepraInferCF7Step($form, $row, totalSteps) {
        totalSteps = parseInt(totalSteps, 10) || 1;

        var assigned = [];
        $form.find('.stepra-step-el[data-step]').each(function() {
            assigned.push(this);
        });

        var node = $row && $row.length ? $row[0] : null;
        if (!node || assigned.length === 0) return totalSteps;

        var prevStep = 0;
        var nextStep = 0;

        $.each(assigned, function(index, existing) {
            if (existing === node) return true;

            var position = existing.compareDocumentPosition(node);
            var step = parseInt($(existing).attr('data-step'), 10) || 0;

            if (position & Node.DOCUMENT_POSITION_FOLLOWING) {
                if (step > 0) prevStep = step;
            } else if (!nextStep && (position & Node.DOCUMENT_POSITION_PRECEDING)) {
                if (step > 0) nextStep = step;
            }
        });

        if (prevStep) return Math.min(prevStep, totalSteps);
        if (nextStep) return Math.min(nextStep, totalSteps);
        return totalSteps;
    }

    function stepraNormalizeCF7Rows($form, totalSteps) {
        if (!$form || !$form.length || !$form.hasClass('wpcf7-form')) return;

        totalSteps = parseInt(totalSteps, 10) || 1;
        stepraCleanupCF7SystemRows($form);

        stepraGetCF7CandidateRows($form).each(function() {
            var $row = $(this);

            if ($row.closest('.stepra-step-el').length && !$row.hasClass('stepra-step-el')) return true;
            if (!stepraCF7RowHasStepContent($row)) return true;

            var assignedStep = parseInt($row.attr('data-step'), 10);
            if (!assignedStep || assignedStep < 1 || assignedStep > totalSteps) {
                assignedStep = stepraInferCF7Step($form, $row, totalSteps);
                $row.attr('data-step', assignedStep);
            }

            $row.addClass('stepra-step-el');
        });
    }

    function stepraGetCF7RealTotalSteps($form, fallbackTotal) {
        if (!$form || !$form.length || !$form.hasClass('wpcf7-form')) return parseInt(fallbackTotal, 10) || 1;

        stepraNormalizeCF7Rows($form, fallbackTotal);

        var realTotal = 0;
        $form.find('.stepra-step-el[data-step]').each(function() {
            var $row = $(this);
            if (!stepraCF7RowHasStepContent($row)) return true;

            var step = parseInt($row.attr('data-step'), 10) || 0;
            if (step > realTotal) realTotal = step;
        });

        fallbackTotal = parseInt(fallbackTotal, 10) || 1;
        return Math.max(1, realTotal || fallbackTotal);
    }

    function stepraSyncCF7NavSubmitState($form, currentStep, totalSteps) {
        if (!$form || !$form.length || !$form.hasClass('wpcf7-form')) return totalSteps;

        currentStep = parseInt(currentStep, 10) || 1;
        totalSteps = stepraGetCF7RealTotalSteps($form, totalSteps);

        if (currentStep < 1) currentStep = 1;
        if (currentStep > totalSteps) currentStep = totalSteps;

        var isFinalStep = currentStep === totalSteps;

        $form.attr('data-current-step', currentStep);
        $form.attr('data-first-step', currentStep === 1 ? 'true' : 'false');
        $form.attr('data-last-step', isFinalStep ? 'true' : 'false');

        var $nextButton = $form.find('.stepra-next').first();
        var $prevButton = $form.find('.stepra-prev').first();

        if ($prevButton.length) {
            if (currentStep === 1) {
                $prevButton.attr('hidden', 'hidden').addClass('stepra-button-hidden')
                    .css('cssText', 'display: none !important;');
            } else {
                $prevButton.removeAttr('hidden').removeClass('stepra-button-hidden')
                    .css('cssText', 'display: inline-block !important; color:#334155 !important;');
            }
        }

        if ($nextButton.length) {
            if (isFinalStep) {
                $nextButton.attr('hidden', 'hidden').addClass('stepra-button-hidden')
                    .css('cssText', 'display: none !important;');
            } else {
                $nextButton.removeAttr('hidden').removeClass('stepra-button-hidden')
                    .css('cssText', 'display: inline-block !important; margin-left: auto !important;');
            }
        }

        var $submit = $form.find('.wpcf7-submit, button[type="submit"], input[type="submit"]')
            .not('.stepra-prev, .stepra-next');

        var $submitContainer = $submit.closest(
            '.stepra-cf7-submit-wrapper, .wpcf7-submit-wrapper, .form-row, .field, .field-wrapper, p, div'
        );

        $submitContainer = $submitContainer.filter(function() {
            var $candidate = $(this);

            if ($candidate.is($form)) return false;
            if ($candidate.closest('.stepra-nav, .stepra-progress').length) return false;
            if ($candidate.hasClass('wpcf7-response-output') || $candidate.hasClass('screen-reader-response')) return false;
            if ($candidate.hasClass('wpcf7-spinner')) return false;

            return $candidate.find('.wpcf7-submit, button[type="submit"], input[type="submit"]').not('.stepra-prev, .stepra-next').length > 0;
        }).first();

        if (!$submitContainer.length && $submit.length) {
            $submitContainer = $submit.parent();
        }

        if (isFinalStep) {
            $submitContainer.css('display', '');
            $submit.css('display', '');
        } else {
            $submitContainer.css('display', 'none');
            $submit.css('display', 'none');
        }

        var $nav = $form.find('.stepra-nav').first();
        var $activeContainer = $form.find('.stepra-step-el[data-step="' + currentStep + '"]').last();

        if ($nav.length) {
            if (isFinalStep && $submitContainer.length) {
                $nav.insertBefore($submitContainer);
                $nav.css('margin-bottom', '20px');
            } else if ($activeContainer.length) {
                $nav.insertAfter($activeContainer);
                $nav.css('margin-bottom', '0');
            }
        }

        return totalSteps;
    }


    function stepraGetUnassignedCF7Rows($form) {
        if (!$form || !$form.length || !$form.hasClass('wpcf7-form')) return $();

        return stepraGetCF7CandidateRows($form).filter(function() {
            var $row = $(this);
            if ($row.closest('.stepra-step-el').length && !$row.hasClass('stepra-step-el')) return false;
            if (!stepraCF7RowHasStepContent($row)) return false;

            return !$row.hasClass('stepra-step-el') || !$row.attr('data-step');
        });
    }

    function stepraShouldRebuildCF7($form) {
        if (!$form || !$form.length || !$form.hasClass('wpcf7-form')) return false;

        if (stepraGetCF7CandidateRows($form).length < 2) return false;

        if ($form.find('.stepra-progress').length !== 1 || $form.find('.stepra-nav').length !== 1) {
            return true;
        }

        return stepraGetUnassignedCF7Rows($form).length > 0;
    }

    function stepraResetCF7ForRebuild($form) {
        if (!$form || !$form.length || !$form.hasClass('wpcf7-form')) return;

        $form
            .removeClass('stepra-ready stepra-visual-ready stepra-initializing stepra-aborted stepra-failed')
            .removeAttr('data-stepra-state data-stepra-initialized data-stepra-init-lock data-current-step data-last-step data-first-step data-stepra-nav-direction');

        $form.find('.stepra-progress, .stepra-nav, .stepra-summary-wrapper').remove();
        $form.find('.stepra-step-el').removeClass('stepra-step-el stepra-hidden').removeAttr('data-step');
        stepraCleanupCF7SystemRows($form);
    }



    // ==========================================
    // 2D-E. ELEMENTOR FORMS FIELD POLICY FOUNDATION
    // Phase 12B-C: source/rendered-DOM aware Elementor field handling.
    // ==========================================
    var STEPRA_ELEMENTOR_SYSTEM_FIELD_TYPES = [
        'hidden',
        'honeypot',
        'submit',
        'step'
    ];

    var STEPRA_ELEMENTOR_SENSITIVE_FIELD_TYPES = [
        'recaptcha',
        'recaptcha_v3',
        'captcha',
        'hcaptcha',
        'turnstile'
    ];

    var STEPRA_ELEMENTOR_KNOWN_STEP_FIELD_TYPES = [
        'text',
        'email',
        'textarea',
        'url',
        'tel',
        'number',
        'select',
        'radio',
        'checkbox',
        'acceptance',
        'date',
        'time',
        'upload',
        'password',
        'html',
        'recaptcha',
        'recaptcha_v3',
        'captcha',
        'hcaptcha',
        'turnstile'
    ];

    function stepraGetElementorGroupType($el) {
        if (!$el || !$el.length) return '';

        var $group = $el.hasClass('elementor-field-group') ? $el : $el.closest('.elementor-field-group');
        if (!$group.length) return '';

        var classes = String($group.attr('class') || '').split(/\s+/);
        var prefix = 'elementor-field-type-';

        for (var i = 0; i < classes.length; i++) {
            if (classes[i].indexOf(prefix) === 0) {
                return classes[i].replace(prefix, '');
            }
        }

        return '';
    }

    function stepraIsElementorActuallyVisible($el) {
        if (!$el || !$el.length) return false;
        return stepraIsElementActuallyVisible($el[0]);
    }

    function stepraIsElementorSystemHiddenGroup($el) {
        if (!$el || !$el.length) return false;

        var type = stepraGetElementorGroupType($el);

        return type === 'hidden' ||
            type === 'honeypot' ||
            $el.closest('.elementor-field-type-hidden, .elementor-field-type-honeypot').length > 0;
    }

    function stepraIsElementorCaptchaGroup($el) {
        if (!$el || !$el.length) return false;

        var type = stepraGetElementorGroupType($el);

        return $.inArray(type, STEPRA_ELEMENTOR_SENSITIVE_FIELD_TYPES) !== -1 ||
            $el.closest(
                '.elementor-field-type-recaptcha, ' +
                '.elementor-field-type-recaptcha_v3, ' +
                '.elementor-field-type-captcha, ' +
                '.elementor-field-type-hcaptcha, ' +
                '.elementor-field-type-turnstile'
            ).length > 0;
    }

    function stepraIsElementorSystemField($el) {
        if (!$el || !$el.length) return false;

        var type = String($el.attr('type') || '').toLowerCase();
        var name = String($el.attr('name') || '');

        return type === 'hidden' ||
            name === 'post_id' ||
            name === 'form_id' ||
            name === 'referer_title' ||
            name === 'queried_id' ||
            stepraIsElementorSystemHiddenGroup($el) ||
            stepraIsElementorCaptchaGroup($el);
    }

    function stepraIsElementorUsableControl($input) {
        if (!$input || !$input.length) return false;

        var type = String($input.attr('type') || '').toLowerCase();

        if (type === 'hidden' || type === 'submit' || type === 'button' || type === 'reset' || type === 'image') return false;
        if ($input.is('[disabled]')) return false;
        if ($input.attr('aria-hidden') === 'true' && !$input.is('select')) return false;
        if (stepraIsElementorSystemField($input)) return false;

        return true;
    }

    function stepraElementorGroupHasStepContent($group) {
        if (!$group || !$group.length) return false;

        var type = stepraGetElementorGroupType($group);

        if ($group.hasClass('elementor-field-type-submit') || type === 'submit') return false;
        if (stepraIsElementorSystemHiddenGroup($group)) return false;

        if (stepraIsElementorCaptchaGroup($group)) {
            // CAPTCHA/anti-spam areas must be controlled by step visibility,
            // but Stepra must not validate or rewrite their internals.
            return true;
        }

        if ($.inArray(type, STEPRA_ELEMENTOR_KNOWN_STEP_FIELD_TYPES) !== -1 && $.inArray(type, STEPRA_ELEMENTOR_SYSTEM_FIELD_TYPES) === -1) {
            return true;
        }

        var hasInput = $group.find('input, select, textarea').filter(function() {
            return stepraIsElementorUsableControl($(this));
        }).length > 0;

        var hasHeading = $group.is(hTags) || $group.find(hTags + ', .elementor-heading-title').length > 0;
        var hasHtmlField = $group.hasClass('elementor-field-type-html') && $.trim($group.text()).length > 0;
        var hasVisibleTextOnlyContent = $.trim($group.text()).length > 0 &&
            $group.find('input, select, textarea, button').length === 0;

        return hasInput || hasHeading || hasHtmlField || hasVisibleTextOnlyContent;
    }

    function stepraGetElementorCandidateGroups($form) {
        if (!$form || !$form.length) return $();

        return $form.find('.elementor-field-group').filter(function() {
            var $group = $(this);
            if ($group.parent().closest('.elementor-field-group').length > 0) return false;
            return stepraElementorGroupHasStepContent($group);
        });
    }

    function stepraCleanupElementorSystemRows($form) {
        if (!$form || !$form.length) return;

        $form.find('.elementor-field-type-hidden, .elementor-field-type-honeypot, .elementor-field-type-submit').each(function() {
            var $group = $(this);
            $group.removeClass('stepra-step-el stepra-hidden').removeAttr('data-step');

            if (stepraIsElementorSystemHiddenGroup($group)) {
                $group.css('display', 'none');
            }
        });
    }

    function stepraInferElementorStep($form, $group, totalSteps) {
        var fallbackStep = parseInt(totalSteps, 10) || 1;
        var previousStep = 0;
        var nextStep = 0;

        $group.prevAll('.stepra-step-el[data-step]').each(function() {
            previousStep = parseInt($(this).attr('data-step'), 10) || 0;
            if (previousStep > 0) return false;
        });

        if (previousStep > 0) return previousStep;

        $group.nextAll('.stepra-step-el[data-step]').each(function() {
            nextStep = parseInt($(this).attr('data-step'), 10) || 0;
            if (nextStep > 0) return false;
        });

        if (nextStep > 0) return nextStep;

        $form.find('.stepra-step-el[data-step]').each(function() {
            var step = parseInt($(this).attr('data-step'), 10) || 0;
            if (step > fallbackStep) fallbackStep = step;
        });

        return Math.max(1, fallbackStep);
    }

    function stepraNormalizeElementorRows($form, totalSteps) {
        if (!$form || !$form.length || !$form.hasClass('elementor-form')) return;

        stepraCleanupElementorSystemRows($form);

        stepraGetElementorCandidateGroups($form).each(function() {
            var $group = $(this);
            var assignedStep;

            if (!stepraElementorGroupHasStepContent($group)) return true;

            if (!$group.hasClass('stepra-step-el') || !$group.attr('data-step')) {
                assignedStep = stepraInferElementorStep($form, $group, totalSteps);
                $group.addClass('stepra-step-el').attr('data-step', assignedStep);
            }
        });
    }

    function stepraGetElementorRealTotalSteps($form, fallbackTotal) {
        var maxStep = parseInt(fallbackTotal, 10) || 1;

        stepraNormalizeElementorRows($form, maxStep);

        $form.find('.elementor-field-group.stepra-step-el[data-step]').each(function() {
            if (!stepraElementorGroupHasStepContent($(this))) return true;
            var step = parseInt($(this).attr('data-step'), 10) || 0;
            if (step > maxStep) maxStep = step;
        });

        return Math.max(1, maxStep);
    }


    function stepraSyncElementorNavSubmitState($form, currentStep, totalSteps) {
        if (!$form || !$form.length || !$form.hasClass('elementor-form')) return totalSteps;

        currentStep = parseInt(currentStep, 10) || 1;
        totalSteps = stepraGetElementorRealTotalSteps($form, totalSteps);

        if (currentStep < 1) currentStep = 1;
        if (currentStep > totalSteps) currentStep = totalSteps;

        var isFinalStep = currentStep === totalSteps;

        $form.attr('data-current-step', currentStep);
        $form.attr('data-first-step', currentStep === 1 ? 'true' : 'false');
        $form.attr('data-last-step', isFinalStep ? 'true' : 'false');

        var $nextButton = $form.find('.stepra-next').first();
        var $prevButton = $form.find('.stepra-prev').first();

        if ($prevButton.length) {
            if (currentStep === 1) {
                $prevButton.attr('hidden', 'hidden').addClass('stepra-button-hidden')
                    .css('cssText', 'display: none !important;');
            } else {
                $prevButton.removeAttr('hidden').removeClass('stepra-button-hidden')
                    .css('cssText', 'display: inline-block !important; color:#334155 !important;');
            }
        }

        if ($nextButton.length) {
            if (isFinalStep) {
                $nextButton.attr('hidden', 'hidden').addClass('stepra-button-hidden')
                    .css('cssText', 'display: none !important;');
            } else {
                $nextButton.removeAttr('hidden').removeClass('stepra-button-hidden')
                    .css('cssText', 'display: inline-block !important; margin-left: auto !important;');
            }
        }

        var $submit = $form.find('.elementor-field-type-submit button[type="submit"], .elementor-field-type-submit input[type="submit"], button[type="submit"], input[type="submit"]')
            .not('.stepra-prev, .stepra-next');

        var $submitContainer = $form.find('.elementor-field-type-submit').filter(function() {
            var $candidate = $(this);

            if ($candidate.is($form)) return false;
            if ($candidate.closest('.stepra-nav, .stepra-progress').length) return false;
            if ($candidate.hasClass('elementor-message') || $candidate.hasClass('elementor-error')) return false;

            return $candidate.find('button[type="submit"], input[type="submit"]')
                .not('.stepra-prev, .stepra-next').length > 0;
        }).first();

        if (!$submitContainer.length && $submit.length) {
            $submitContainer = $submit.closest('.elementor-field-type-submit');
        }

        if (!$submitContainer.length && $submit.length) {
            $submitContainer = $submit.parent();
        }

        if (isFinalStep) {
            $submitContainer.css('display', '');
            $submit.css('display', '');
        } else {
            $submitContainer.css('display', 'none');
            $submit.css('display', 'none');
        }

        var $nav = $form.find('.stepra-nav').first();
        var $activeContainer = $form.find('.stepra-step-el[data-step="' + currentStep + '"]').last();

        if ($nav.length) {
            if (isFinalStep && $submitContainer.length) {
                $nav.insertBefore($submitContainer);
                $nav.css('margin-bottom', '20px');
            } else if ($activeContainer.length) {
                $nav.insertAfter($activeContainer);
                $nav.css('margin-bottom', '0');
            }
        }

        return totalSteps;
    }

    function stepraGetUnassignedElementorRows($form) {
        if (!$form || !$form.length) return $();

        return stepraGetElementorCandidateGroups($form).filter(function() {
            var $group = $(this);
            if (!stepraElementorGroupHasStepContent($group)) return false;
            if ($group.hasClass('stepra-step-el') && $group.attr('data-step')) return false;
            return stepraIsElementorActuallyVisible($group) || $group.css('display') !== 'none';
        });
    }

    function stepraShouldRebuildElementor($form) {
        if (!$form || !$form.length || !$form.hasClass('elementor-form')) return false;

        if ($form.find('.stepra-progress').length !== 1 || $form.find('.stepra-nav').length !== 1) return true;
        if (stepraGetElementorCandidateGroups($form).length < 2) return false;

        return stepraGetUnassignedElementorRows($form).length > 0;
    }

    function stepraResetElementorForRebuild($form) {
        if (!$form || !$form.length || !$form.hasClass('elementor-form')) return;

        $form
            .removeClass('stepra-ready stepra-visual-ready stepra-initializing stepra-aborted stepra-failed')
            .removeAttr('data-stepra-state data-stepra-initialized data-stepra-init-lock data-current-step data-last-step data-first-step data-stepra-nav-direction');

        $form.find('.stepra-progress, .stepra-nav, .stepra-summary-wrapper').remove();
        $form.find('.stepra-step-el').removeClass('stepra-step-el stepra-hidden').removeAttr('data-step');
        stepraCleanupElementorSystemRows($form);
    }

    function stepraIsForminatorSelect2OriginalField($el) {
        if (!$el || !$el.length) return false;

        return $el.is('select') && (
            $el.hasClass('select2-hidden-accessible') ||
            $el.hasClass('forminator-select2') ||
            $el.hasClass('forminator-select2-multiple')
        );
    }

    function stepraIsForminatorSystemArea($el) {
        if (!$el || !$el.length) return false;

        return $el.closest(
            '.forminator-response-message, ' +
            '.forminator-row-last, ' +
            '.forminator-pagination, ' +
            '.forminator-edit-module'
        ).length > 0;
    }

    function stepraIsForminatorSystemHiddenField($el) {
        if (!$el || !$el.length) return false;

        var type = String($el.attr('type') || '').toLowerCase();
        var name = String($el.attr('name') || '');

        if (type !== 'hidden') return false;

        return $el.closest('.forminator-ui, .forminator-custom-form').length > 0 && (
            name === 'forminator_nonce' ||
            name === '_wp_http_referer' ||
            name === 'referer_url' ||
            name === 'form_id' ||
            name === 'page_id' ||
            name === 'form_type' ||
            name === 'current_url' ||
            name === 'render_id' ||
            name === 'action' ||
            $el.closest('.forminator-hidden').length > 0
        );
    }


    // 2B. FORMINATOR EXTENDED FIELD-POLICY HELPERS
    // Source-aware adapter layer based on Forminator field modules:
    // address, calculation, captcha, consent, currency, custom, date, email,
    // gdprcheckbox, group, hidden, html, multivalue, name, number, page-break,
    // password, paypal, phone, postdata, radio, rating, section, select, slider,
    // stripe, stripe-payment-element, text, textarea, time, upload, website.
    function stepraIsForminatorSubmitArea($el) {
        if (!$el || !$el.length) return false;

        return $el.closest(
            '.forminator-row-last, ' +
            '.forminator-pagination-footer, ' +
            '.forminator-pagination-submit'
        ).length > 0;
    }

    function stepraIsForminatorHiddenSystemRow($row) {
        if (!$row || !$row.length) return false;

        return $row.hasClass('forminator-hidden') ||
            $row.hasClass('forminator-page-hidden') ||
            $row.closest('.forminator-hidden, .forminator-page-hidden').length > 0 ||
            stepraIsForminatorSystemArea($row) ||
            stepraIsForminatorSubmitArea($row) ||
            $row.is('.stepra-progress, .stepra-nav, .stepra-summary-wrapper, style, script');
    }

    function stepraForminatorHasKnownFieldMarkup($row) {
        if (!$row || !$row.length) return false;

        return $row.find(
            '.forminator-field-address, ' +
            '.forminator-field-name, ' +
            '.forminator-field-email, ' +
            '.forminator-field-phone, ' +
            '.forminator-field-textarea, ' +
            '.forminator-field-select, ' +
            '.forminator-field-radio, ' +
            '.forminator-field-checkbox, ' +
            '.forminator-field-upload, ' +
            '.forminator-field-consent, ' +
            '.forminator-field-time, ' +
            '.forminator-field-postdata, ' +
            '.forminator-field-stripe, ' +
            '.forminator-field-stripe-ocs, ' +
            '.forminator-field-signature, ' +
            '.forminator-field-section, ' +
            '.forminator-field-html, ' +
            '.forminator-field-group, ' +
            '.forminator-input, ' +
            '.forminator-textarea, ' +
            '.forminator-select, ' +
            '.forminator-radio, ' +
            '.forminator-checkbox, ' +
            '.forminator-consent, ' +
            '.forminator-date, ' +
            '.forminator-time, ' +
            '.forminator-upload, ' +
            '.forminator-file-upload, ' +
            '.forminator-calculation, ' +
            '.forminator-currency, ' +
            '.forminator-slider, ' +
            '.forminator-rating, ' +
            '.forminator-payment, ' +
            '.forminator-paypal-row, ' +
            '.forminator-button-paypal, ' +
            '.forminator-stripe-element, ' +
            '.forminator-stripe-payment-element, ' +
            '.forminator-g-recaptcha, ' +
            '.forminator-google-recaptcha, ' +
            '.forminator-hcaptcha, ' +
            '.forminator-turnstile, ' +
            '.forminator-signature, ' +
            '.forminator-wp-editor-required, ' +
            '.forminator-repeater-field, ' +
            '.forminator-grouped-fields'
        ).length > 0;
    }

    function stepraIsForminatorSensitiveBuilderArea($el) {
        if (!$el || !$el.length) return false;

        return $el.closest(
            '.forminator-field-stripe, ' +
            '.forminator-field-stripe-ocs, ' +
            '.forminator-stripe-element, ' +
            '.forminator-stripe-payment-element, ' +
            '.forminator-paypal-row, ' +
            '.forminator-payment, ' +
            '.forminator-g-recaptcha, ' +
            '.forminator-google-recaptcha, ' +
            '.forminator-hcaptcha, ' +
            '.forminator-turnstile, ' +
            '.forminator-field-signature, ' +
            '.forminator-signature'
        ).length > 0 || $el.find('iframe').length > 0;
    }

    function stepraForminatorHasUsableControl($row) {
        if (!$row || !$row.length) return false;

        return $row.find('input, select, textarea').filter(function() {
            var $input = $(this);
            var type = String($input.attr('type') || '').toLowerCase();
            var name = String($input.attr('name') || '');
            var id = String($input.attr('id') || '');

            if (stepraIsForminatorSystemHiddenField($input)) return false;
            if ($input.closest('.forminator-hidden, .forminator-page-hidden').length > 0) return false;
            if (type === 'hidden' || type === 'submit' || type === 'button' || type === 'reset' || type === 'image') return false;

            // Password fields are visible Forminator fields and must be split into a step.
            // They remain excluded from Stepra value summary/validation elsewhere.
            if (type === 'password') return true;

            // Calculation/currency/slider fields may be readonly/disabled but visible.
            if (
                $input.hasClass('forminator-calculation') ||
                $input.hasClass('forminator-currency') ||
                $input.hasClass('forminator-slider-hidden') ||
                name.indexOf('calculation') !== -1 ||
                name.indexOf('currency') !== -1 ||
                name.indexOf('slider') !== -1 ||
                id.indexOf('calculation') !== -1 ||
                id.indexOf('currency') !== -1 ||
                id.indexOf('slider') !== -1
            ) {
                return true;
            }

            if (stepraIsForminatorSelect2OriginalField($input)) return true;
            if ($input.is('[disabled]')) return false;
            if ($input.attr('aria-hidden') === 'true' && !$input.is('select, :radio, :checkbox')) return false;

            return true;
        }).length > 0;
    }

    function stepraForminatorRowHasVisibleTextContent($row) {
        if (!$row || !$row.length) return false;

        if ($.trim($row.text()).length === 0) return false;

        return $row.find(
            '.forminator-label, ' +
            '.forminator-title, ' +
            '.forminator-subtitle, ' +
            '.forminator-description, ' +
            '.forminator-field, ' +
            '.forminator-field-html, ' +
            '.forminator-field-section, ' +
            '.forminator-payment, ' +
            '.forminator-card-message, ' +
            '.forminator-repeater-label, ' +
            '.forminator-repeater-description'
        ).length > 0;
    }

    function stepraForminatorRowHasStepContent($row) {
        if (!$row || !$row.length) return false;

        // Do not treat Stepra's inactive-step class as a real Forminator hidden state.
        var hadStepraHidden = $row.hasClass('stepra-hidden');
        if (hadStepraHidden) $row.removeClass('stepra-hidden');

        var isSystem = stepraIsForminatorHiddenSystemRow($row);
        var hasKnownMarkup = stepraForminatorHasKnownFieldMarkup($row);
        var hasUsableControl = stepraForminatorHasUsableControl($row);
        var hasText = stepraForminatorRowHasVisibleTextContent($row);
        var hasSensitive = stepraIsForminatorSensitiveBuilderArea($row);

        if (hadStepraHidden) $row.addClass('stepra-hidden');
        if (isSystem) return false;

        return hasKnownMarkup || hasUsableControl || hasText || hasSensitive;
    }

    function stepraGetForminatorCandidateRows($form) {
        if (!$form || !$form.length) return $();

        return $form.find('.forminator-row').filter(function() {
            var $row = $(this);
            if ($row.parent().closest('.forminator-row').length > 0) return false;
            return stepraForminatorRowHasStepContent($row);
        });
    }

    function stepraCleanupForminatorSystemRows($form) {
        if (!$form || !$form.length) return;

        $form.find('.forminator-row-last, .forminator-pagination, .forminator-response-message, .forminator-hidden, .forminator-page-hidden').each(function() {
            $(this).removeClass('stepra-step-el stepra-hidden').removeAttr('data-step');
        });
    }

    function stepraInferForminatorStep($form, $row, totalSteps) {
        var fallbackStep = parseInt(totalSteps, 10) || 1;
        var previousStep = 0;
        var nextStep = 0;

        $row.prevAll('.stepra-step-el[data-step]').each(function() {
            previousStep = parseInt($(this).attr('data-step'), 10) || 0;
            if (previousStep > 0) return false;
        });

        if (previousStep > 0) return previousStep;

        $row.nextAll('.stepra-step-el[data-step]').each(function() {
            nextStep = parseInt($(this).attr('data-step'), 10) || 0;
            if (nextStep > 0) return false;
        });

        if (nextStep > 0) return nextStep;

        $form.find('.stepra-step-el[data-step]').each(function() {
            var step = parseInt($(this).attr('data-step'), 10) || 0;
            if (step > fallbackStep) fallbackStep = step;
        });

        return Math.max(1, fallbackStep);
    }

    function stepraNormalizeForminatorRows($form, totalSteps) {
        if (!$form || !$form.length || !$form.is('form.forminator-ui, form.forminator-custom-form')) return;

        stepraCleanupForminatorSystemRows($form);

        stepraGetForminatorCandidateRows($form).each(function() {
            var $row = $(this);
            var assignedStep;

            if (!stepraForminatorRowHasStepContent($row)) return true;

            if (!$row.hasClass('stepra-step-el') || !$row.attr('data-step')) {
                assignedStep = stepraInferForminatorStep($form, $row, totalSteps);
                $row.addClass('stepra-step-el').attr('data-step', assignedStep);
            }
        });
    }

    function stepraGetForminatorRealTotalSteps($form, fallbackTotal) {
        var maxStep = parseInt(fallbackTotal, 10) || 1;

        stepraNormalizeForminatorRows($form, maxStep);

        $form.find('.forminator-row.stepra-step-el[data-step]').each(function() {
            if (!stepraForminatorRowHasStepContent($(this))) return true;
            var step = parseInt($(this).attr('data-step'), 10) || 0;
            if (step > maxStep) maxStep = step;
        });

        return Math.max(1, maxStep);
    }



    function stepraSyncForminatorNavSubmitState($form, currentStep, totalSteps) {
        if (!$form || !$form.length || !$form.is('form.forminator-ui, form.forminator-custom-form')) return totalSteps;

        currentStep = parseInt(currentStep, 10) || 1;
        totalSteps = stepraGetForminatorRealTotalSteps($form, totalSteps);

        if (currentStep < 1) currentStep = 1;
        if (currentStep > totalSteps) currentStep = totalSteps;

        var isFinalStep = currentStep === totalSteps;

        $form.attr('data-current-step', currentStep);
        $form.attr('data-first-step', currentStep === 1 ? 'true' : 'false');
        $form.attr('data-last-step', isFinalStep ? 'true' : 'false');

        var $nextButton = $form.find('.stepra-next').first();
        var $prevButton = $form.find('.stepra-prev').first();

        if ($prevButton.length) {
            if (currentStep === 1) {
                $prevButton.attr('hidden', 'hidden').addClass('stepra-button-hidden')
                    .css('cssText', 'display: none !important;');
            } else {
                $prevButton.removeAttr('hidden').removeClass('stepra-button-hidden')
                    .css('cssText', 'display: inline-block !important; color:#334155 !important;');
            }
        }

        if ($nextButton.length) {
            if (isFinalStep) {
                $nextButton.attr('hidden', 'hidden').addClass('stepra-button-hidden')
                    .css('cssText', 'display: none !important;');
            } else {
                $nextButton.removeAttr('hidden').removeClass('stepra-button-hidden')
                    .css('cssText', 'display: inline-block !important; margin-left: auto !important;');
            }
        }

        var $submit = $form.find('.forminator-button-submit, button[type="submit"], input[type="submit"]')
            .not('.stepra-prev, .stepra-next');

        var $submitContainer = $form.find('.forminator-row-last, .forminator-pagination-footer, .forminator-pagination-submit').filter(function() {
            var $candidate = $(this);

            if ($candidate.is($form)) return false;
            if ($candidate.closest('.stepra-nav, .stepra-progress').length) return false;
            if ($candidate.hasClass('forminator-response-message')) return false;

            return $candidate.find('.forminator-button-submit, button[type="submit"], input[type="submit"]')
                .not('.stepra-prev, .stepra-next').length > 0;
        }).first();

        if (!$submitContainer.length && $submit.length) {
            $submitContainer = $submit.closest('.forminator-row-last, .forminator-pagination-footer, .forminator-pagination-submit');
        }

        if (!$submitContainer.length && $submit.length) {
            $submitContainer = $submit.parent();
        }

        if (isFinalStep) {
            $submitContainer.css('display', '');
            $submit.css('display', '');
        } else {
            $submitContainer.css('display', 'none');
            $submit.css('display', 'none');
        }

        var $nav = $form.find('.stepra-nav').first();
        var $activeContainer = $form.find('.stepra-step-el[data-step="' + currentStep + '"]').last();

        if ($nav.length) {
            if (isFinalStep && $submitContainer.length) {
                $nav.insertBefore($submitContainer);
                $nav.css('margin-bottom', '20px');
            } else if ($activeContainer.length) {
                $nav.insertAfter($activeContainer);
                $nav.css('margin-bottom', '0');
            }
        }

        return totalSteps;
    }

    function stepraGetUnassignedForminatorRows($form) {
        if (!$form || !$form.length) return $();

        return stepraGetForminatorCandidateRows($form).filter(function() {
            var $row = $(this);
            if (!stepraForminatorRowHasStepContent($row)) return false;
            if ($row.hasClass('stepra-step-el') && $row.attr('data-step')) return false;
            return stepraIsElementActuallyVisible($row[0]) || $row.css('display') !== 'none';
        });
    }

    function stepraShouldRebuildForminator($form) {
        if (!$form || !$form.length || !$form.is('form.forminator-ui, form.forminator-custom-form')) return false;

        if ($form.find('.stepra-progress').length !== 1 || $form.find('.stepra-nav').length !== 1) return true;
        if (stepraGetForminatorCandidateRows($form).length < 2) return false;

        return stepraGetUnassignedForminatorRows($form).length > 0;
    }

    function stepraResetForminatorForRebuild($form) {
        if (!$form || !$form.length || !$form.is('form.forminator-ui, form.forminator-custom-form')) return;

        $form
            .removeClass('stepra-ready stepra-visual-ready stepra-initializing stepra-aborted stepra-failed')
            .removeAttr('data-stepra-state data-stepra-initialized data-stepra-init-lock data-current-step data-last-step data-first-step data-stepra-nav-direction');

        $form.find('.stepra-progress, .stepra-nav, .stepra-summary-wrapper').remove();
        $form.find('.stepra-step-el').removeClass('stepra-step-el stepra-hidden').removeAttr('data-step');
        stepraCleanupForminatorSystemRows($form);
    }



    // ==========================================
    // 2E. WPFORMS FIELD POLICY FOUNDATION
    // Phase 10: strict WPForms row classification.
    // ==========================================
    var STEPRA_WPFORMS_SYSTEM_FIELD_TYPES = [
        'hidden',
        'pagebreak',
        'internal-information'
    ];

    var STEPRA_WPFORMS_STEP_FIELD_TYPES = [
        'text',
        'textarea',
        'name',
        'email',
        'phone',
        'address',
        'url',
        'number',
        'number-slider',
        'select',
        'radio',
        'checkbox',
        'date-time',
        'file-upload',
        'password',
        'rating',
        'richtext',
        'content',
        'html',
        'divider',
        'gdpr-checkbox',
        'payment-single',
        'payment-multiple',
        'payment-checkbox',
        'payment-select',
        'payment-total',
        'credit-card',
        'stripe-credit-card',
        'paypal-commerce',
        'square',
        'coupon',
        'captcha',
        'custom-captcha',
        'signature',
        'likert-scale',
        'net-promoter-score',
        'entry-preview',
        'map',
        'camera'
    ];

    var STEPRA_WPFORMS_VALIDATION_EXCLUDED_FIELD_TYPES = [
        'hidden',
        'pagebreak',
        'internal-information',
        'payment-single',
        'payment-total',
        'credit-card',
        'stripe-credit-card',
        'paypal-commerce',
        'square',
        'coupon',
        'captcha',
        'custom-captcha',
        'signature',
        'entry-preview',
        'map',
        'camera'
    ];

    function stepraArrayHasValue(list, value) {
        if (!value) return false;
        return $.inArray(value, list) !== -1;
    }

    function stepraGetWPFormsFieldType($row) {
        if (!$row || !$row.length) return '';

        var attrType = String($row.attr('data-field-type') || '').toLowerCase();
        if (attrType) return attrType;

        var classes = String($row.attr('class') || '').split(/\s+/);
        var best = '';

        $.each(classes, function(index, className) {
            if (!className || className === 'wpforms-field') return;
            if (className.indexOf('wpforms-field-') !== 0) return;

            var type = className.replace('wpforms-field-', '');

            if (type === 'medium' || type === 'large' || type === 'small' || type === 'required') return;
            if (type.indexOf('select-style-') === 0) return;

            if (!best || stepraArrayHasValue(STEPRA_WPFORMS_STEP_FIELD_TYPES, type) || stepraArrayHasValue(STEPRA_WPFORMS_SYSTEM_FIELD_TYPES, type)) {
                best = type;
            }
        });

        return best;
    }

    function stepraIsWPFormsSubmitArea($el) {
        if (!$el || !$el.length) return false;

        return $el.closest(
            '.wpforms-submit-container, ' +
            '.wpforms-submit-spinner, ' +
            '.wpforms-confirmation-container, ' +
            '.wpforms-error-container, ' +
            '.wpforms-error-noscript'
        ).length > 0;
    }

    function stepraIsWPFormsHoneypotField($row) {
        if (!$row || !$row.length) return false;

        if ($row.hasClass('wpforms-field-hp') || $row.hasClass('wpforms-field-honeypot')) return true;

        var style = String($row.attr('style') || '').replace(/\s+/g, '').toLowerCase();
        if (
            style.indexOf('position:absolute') !== -1 &&
            style.indexOf('z-index:-1000') !== -1
        ) {
            return true;
        }

        var $controls = $row.find('input, select, textarea');
        if ($controls.length === 0) return false;

        var hiddenLike = 0;
        $controls.each(function() {
            var $control = $(this);
            var type = String($control.attr('type') || '').toLowerCase();

            if (
                type === 'hidden' ||
                $control.attr('aria-hidden') === 'true' ||
                String($control.attr('tabindex') || '') === '-1' ||
                stepraIsRealVisibilityHidden($control)
            ) {
                hiddenLike++;
            }
        });

        return hiddenLike === $controls.length && $row.find('label[aria-hidden="true"]').length > 0;
    }

    function stepraIsWPFormsSystemField($row) {
        if (!$row || !$row.length) return false;
        if (!$row.hasClass('wpforms-field')) return false;

        var fieldType = stepraGetWPFormsFieldType($row);

        if (stepraArrayHasValue(STEPRA_WPFORMS_SYSTEM_FIELD_TYPES, fieldType)) return true;
        if (stepraIsWPFormsHoneypotField($row)) return true;
        if ($row.hasClass('wpforms-field-hidden') || $row.hasClass('wpforms-hidden')) return true;
        if ($row.closest('.wpforms-field-hidden, .wpforms-hidden').length > 0) return true;
        if (stepraIsWPFormsSubmitArea($row)) return true;

        var $controls = $row.find('input, select, textarea');
        if ($controls.length > 0) {
            var $nonHiddenControls = $controls.filter(function() {
                var $control = $(this);
                var type = String($control.attr('type') || '').toLowerCase();

                return type !== 'hidden' &&
                    type !== 'submit' &&
                    type !== 'button' &&
                    type !== 'reset' &&
                    type !== 'image' &&
                    $control.attr('aria-hidden') !== 'true' &&
                    !stepraIsRealVisibilityHidden($control);
            });

            if ($nonHiddenControls.length === 0 && !stepraArrayHasValue(STEPRA_WPFORMS_STEP_FIELD_TYPES, fieldType)) {
                return true;
            }
        }

        return false;
    }

    function stepraIsWPFormsValidationExcludedField($el) {
        if (!$el || !$el.length) return false;

        var $row = $el.closest('.wpforms-field');
        if (!$row.length) return false;

        var fieldType = stepraGetWPFormsFieldType($row);

        return stepraIsWPFormsSystemField($row) ||
            stepraArrayHasValue(STEPRA_WPFORMS_VALIDATION_EXCLUDED_FIELD_TYPES, fieldType);
    }

    function stepraWPFormsHasUsableControl($row) {
        if (!$row || !$row.length) return false;

        return $row.find('input, select, textarea').filter(function() {
            var $control = $(this);
            var type = String($control.attr('type') || '').toLowerCase();

            if (type === 'hidden' || type === 'submit' || type === 'button' || type === 'reset' || type === 'image') return false;
            if ($control.is('[disabled]')) return false;
            if ($control.attr('aria-hidden') === 'true') return false;
            if (stepraIsRealVisibilityHidden($control)) return false;

            return true;
        }).length > 0;
    }

    function stepraWPFormsHasVisibleTextContent($row) {
        if (!$row || !$row.length) return false;

        var text = $.trim($row.clone().children('input[type="hidden"], script, style').remove().end().text());
        if (!text) return false;

        var fieldType = stepraGetWPFormsFieldType($row);

        return stepraArrayHasValue(STEPRA_WPFORMS_STEP_FIELD_TYPES, fieldType) ||
            $row.find('.wpforms-payment-price, .wpforms-payment-total, .wpforms-field-label, .wpforms-field-description').length > 0;
    }

    function stepraWPFormsFieldHasStepContent($row) {
        if (!$row || !$row.length) return false;
        if (!$row.hasClass('wpforms-field')) return false;
        // Do not treat Stepra's own inactive-step class as a real WPForms hidden field.
        // Otherwise inactive future steps can be excluded from step/nav state during updates.
        var hiddenOnlyByStepra = $row.hasClass('stepra-hidden') && !stepraHasInlineHiddenStyle($row[0]);
        if (!hiddenOnlyByStepra && ($row.css('display') === 'none' || stepraHasInlineHiddenStyle($row[0]))) return false;
        if (stepraIsWPFormsSystemField($row)) return false;

        var fieldType = stepraGetWPFormsFieldType($row);

        if (stepraArrayHasValue(STEPRA_WPFORMS_STEP_FIELD_TYPES, fieldType)) return true;
        if (stepraWPFormsHasUsableControl($row)) return true;
        if (stepraWPFormsHasVisibleTextContent($row)) return true;

        return false;
    }

    function stepraInferWPFormsStep($row, totalSteps) {
        if (!$row || !$row.length) return totalSteps;

        totalSteps = parseInt(totalSteps, 10) || 1;

        var $prev = $row.prevAll('.wpforms-field.stepra-step-el[data-step]').first();
        var prevStep = parseInt($prev.attr('data-step'), 10);
        if (prevStep && prevStep >= 1) return Math.min(prevStep, totalSteps);

        var $next = $row.nextAll('.wpforms-field.stepra-step-el[data-step]').first();
        var nextStep = parseInt($next.attr('data-step'), 10);
        if (nextStep && nextStep >= 1) return Math.min(nextStep, totalSteps);

        return totalSteps;
    }

    function stepraNormalizeWPFormsRows($form, totalSteps) {
        if (!$form || !$form.length || !$form.hasClass('wpforms-form')) return;

        totalSteps = parseInt(totalSteps, 10) || 1;

        $form.find('.wpforms-field').filter(function() {
            return $(this).parent().closest('.wpforms-field').length === 0;
        }).each(function() {
            var $row = $(this);

            if (stepraIsWPFormsSystemField($row)) {
                $row.removeClass('stepra-step-el stepra-hidden').removeAttr('data-step');

                if (
                    $row.hasClass('wpforms-field-hidden') ||
                    stepraGetWPFormsFieldType($row) === 'hidden' ||
                    stepraIsWPFormsHoneypotField($row)
                ) {
                    $row.css('display', 'none');
                }
                return;
            }

            if (!stepraWPFormsFieldHasStepContent($row)) return;

            var assignedStep = parseInt($row.attr('data-step'), 10);
            if (!assignedStep || assignedStep < 1 || assignedStep > totalSteps) {
                assignedStep = stepraInferWPFormsStep($row, totalSteps);
                $row.attr('data-step', assignedStep);
            }

            $row.addClass('stepra-step-el');
        });
    }


    function stepraCleanupWPFormsSystemRows($form) {
        if (!$form || !$form.length || !$form.hasClass('wpforms-form')) return;

        $form.find('.wpforms-field').filter(function() {
            return $(this).parent().closest('.wpforms-field').length === 0;
        }).each(function() {
            var $row = $(this);

            if (!stepraIsWPFormsSystemField($row)) return;

            $row.removeClass('stepra-step-el stepra-hidden').removeAttr('data-step');

            if (
                $row.hasClass('wpforms-field-hidden') ||
                $row.hasClass('wpforms-hidden') ||
                stepraGetWPFormsFieldType($row) === 'hidden' ||
                stepraIsWPFormsHoneypotField($row)
            ) {
                $row.css('display', 'none');
            }
        });
    }

    function stepraGetWPFormsRealTotalSteps($form, fallbackTotal) {
        if (!$form || !$form.length || !$form.hasClass('wpforms-form')) {
            return parseInt(fallbackTotal, 10) || 1;
        }

        stepraCleanupWPFormsSystemRows($form);

        var realTotal = 0;

        $form.find('.wpforms-field.stepra-step-el[data-step]').filter(function() {
            var $row = $(this);

            if ($row.parent().closest('.wpforms-field').length > 0) return false;
            if (stepraIsWPFormsSystemField($row)) return false;
            if (!stepraWPFormsFieldHasStepContent($row)) return false;

            return true;
        }).each(function() {
            var step = parseInt($(this).attr('data-step'), 10) || 0;
            if (step > realTotal) realTotal = step;
        });

        fallbackTotal = parseInt(fallbackTotal, 10) || 1;

        return Math.max(1, realTotal || fallbackTotal);
    }


    function stepraSyncWPFormsNavSubmitState($form, currentStep, totalSteps) {
        if (!$form || !$form.length || !$form.hasClass('wpforms-form')) return totalSteps;

        currentStep = parseInt(currentStep, 10) || 1;
        totalSteps = stepraGetWPFormsRealTotalSteps($form, totalSteps);

        if (currentStep < 1) currentStep = 1;
        if (currentStep > totalSteps) currentStep = totalSteps;

        var isFinalStep = currentStep === totalSteps;

        $form.attr('data-current-step', currentStep);
        $form.attr('data-first-step', currentStep === 1 ? 'true' : 'false');
        $form.attr('data-last-step', isFinalStep ? 'true' : 'false');

        var $nextButton = $form.find('.stepra-next').first();
        var $prevButton = $form.find('.stepra-prev').first();

        if ($prevButton.length) {
            if (currentStep === 1) {
                $prevButton.attr('hidden', 'hidden').addClass('stepra-button-hidden')
                    .css('cssText', 'display: none !important;');
            } else {
                $prevButton.removeAttr('hidden').removeClass('stepra-button-hidden')
                    .css('cssText', 'display: inline-block !important; color:#334155 !important;');
            }
        }

        if ($nextButton.length) {
            if (isFinalStep) {
                $nextButton.attr('hidden', 'hidden').addClass('stepra-button-hidden')
                    .css('cssText', 'display: none !important;');
            } else {
                $nextButton.removeAttr('hidden').removeClass('stepra-button-hidden')
                    .css('cssText', 'display: inline-block !important; margin-left: auto !important;');
            }
        }

        var $submit = $form.find('.wpforms-submit, button[type="submit"], input[type="submit"]')
            .not('.stepra-prev, .stepra-next');

        var $submitContainer = $form.find('.wpforms-submit-container');
        if (!$submitContainer.length && $submit.length) {
            $submitContainer = $submit.closest('.wpforms-submit-container');
        }
        if (!$submitContainer.length && $submit.length) {
            $submitContainer = $submit.parent();
        }

        if (isFinalStep) {
            $submitContainer.css('display', '');
            $submit.css('display', '');
        } else {
            $submitContainer.css('display', 'none');
            $submit.css('display', 'none');
        }

        return totalSteps;
    }


    function stepraGetUnassignedWPFormsRows($form) {
        if (!$form || !$form.length || !$form.hasClass('wpforms-form')) return $();

        return $form.find('.wpforms-field').filter(function() {
            var $row = $(this);

            if ($row.parent().closest('.wpforms-field').length > 0) return false;
            if (!stepraWPFormsFieldHasStepContent($row)) return false;

            return !$row.hasClass('stepra-step-el') || !$row.attr('data-step');
        });
    }

    function stepraShouldRebuildWPForms($form) {
        if (!$form || !$form.length || !$form.hasClass('wpforms-form')) return false;

        var hasEnoughRows = $form.find('.wpforms-field').filter(function() {
            return stepraWPFormsFieldHasStepContent($(this));
        }).length >= 2;

        if (!hasEnoughRows) return false;

        if ($form.find('.stepra-progress').length !== 1 || $form.find('.stepra-nav').length !== 1) {
            return true;
        }

        return stepraGetUnassignedWPFormsRows($form).length > 0;
    }

    function stepraResetWPFormsForRebuild($form) {
        if (!$form || !$form.length || !$form.hasClass('wpforms-form')) return;

        $form
            .removeClass('stepra-ready stepra-visual-ready stepra-initializing stepra-aborted stepra-failed')
            .removeAttr('data-stepra-state data-stepra-initialized data-stepra-init-lock data-current-step data-last-step data-first-step data-stepra-nav-direction');

        $form.find('.stepra-progress, .stepra-nav, .stepra-summary-wrapper').remove();
        $form.find('.stepra-step-el').removeClass('stepra-step-el stepra-hidden').removeAttr('data-step');
    }

    function isGhostField($el) {
        if ($el.is('select') && $el.hasClass('select2-hidden-accessible')) return false;

        if ($el.closest('.wpforms-field-hp, .forminator-hidden').length > 0) return true;
        if ($el.attr('aria-hidden') === 'true') return true;
        if (stepraIsRealVisibilityHidden($el)) return true;
        
        var hasGhostInput = false;
        $el.find('input, select, textarea').not('.select2-hidden-accessible').each(function() {
            if ($(this).attr('aria-hidden') === 'true' || stepraIsRealVisibilityHidden($(this))) {
                hasGhostInput = true;
            }
        });
        if (hasGhostInput) return true;

        return false;
    }

    // ==========================================
    // 2B. CONDITIONAL VISIBILITY CORE
    // Shared core only. Builder-specific hardening stays in later phases.
    // ==========================================
    var STEPRA_CONDITIONAL_HIDDEN_SELECTOR = [
        '.forminator-hidden',
        '.wpforms-conditional-hide',
        '.wpforms-field-hidden',
        '.wpforms-hidden',
        '.elementor-hidden',
        '.elementor-field-type-hidden',
        '.elementor-field-type-honeypot',
        '.elementor-field-type-recaptcha',
        '.elementor-field-type-recaptcha_v3',
        '.hidden-fields-container',
        '.hidden',
        '.hide',
        '.d-none',
        '[hidden]',
        '[aria-hidden="true"]',
        '[data-conditional-hidden="true"]',
        '[data-stepra-condition-hidden="true"]'
    ].join(', ');

    function stepraHasInlineHiddenStyle(element) {
        if (!element || !element.getAttribute) return false;

        var style = String(element.getAttribute('style') || '').replace(/\s+/g, '').toLowerCase();

        return style.indexOf('display:none') !== -1 ||
            style.indexOf('visibility:hidden') !== -1;
    }

    function stepraIsConditionallyHidden(row, adapter) {
        var element = stepraToElement(row);
        if (!element || element.nodeType !== 1) return false;

        var form = stepraClosest(element, STEPRA_SUPPORTED_FORM_SELECTOR);
        var current = element;

        while (current && current.nodeType === 1 && current !== form) {
            if (current === element && stepraIsForminatorSelect2OriginalField($(current))) {
                current = current.parentElement;
                continue;
            }

            if (stepraMatches(current, STEPRA_CONDITIONAL_HIDDEN_SELECTOR)) {
                return true;
            }

            if (stepraHasInlineHiddenStyle(current)) {
                return true;
            }

            current = current.parentElement;
        }

        return false;
    }

    function stepraGetFieldVisibilityRoot(field, adapter) {
        var $field = field && field.jquery ? field : $(field);
        if (!$field.length) return $();

        var selectors = [];

        if (adapter && adapter.primaryRowSelector) selectors.push(adapter.primaryRowSelector);
        if (adapter && adapter.fallbackRowSelector) selectors.push(adapter.fallbackRowSelector);

        selectors.push(
            '.form-row',
            '.wpforms-field',
            '.forminator-row',
            '.forminator-field',
            '.elementor-field-group',
            '.elementor-field',
            '.wpcf7-form-control-wrap',
            '.stepra-step-el'
        );

        try {
            return $field.closest(stepraUniqueElements(selectors).join(', '));
        } catch(e) {
            return $field.closest('.stepra-step-el');
        }
    }

    function stepraIsFieldVisibleForStep(field, adapter) {
        var $field = field && field.jquery ? field : $(field);
        if (!$field.length) return false;

        var $root = stepraGetFieldVisibilityRoot($field, adapter);

        if (stepraIsConditionallyHidden($field[0], adapter)) return false;
        if ($root.length && stepraIsConditionallyHidden($root[0], adapter)) return false;

        return true;
    }

    function stepraGetVisibleRowsForStep(form, step, adapter) {
        var $form = form && form.jquery ? form : $(form);
        if (!$form.length) return $();

        step = parseInt(step, 10) || 1;

        return $form.find('.stepra-step-el[data-step="' + step + '"]').filter(function() {
            var $row = $(this);

            if (stepraIsConditionallyHidden(this, adapter)) return false;
            if (isGhostField($row)) return false;
            if ($row.hasClass('wpforms-field') && stepraIsWPFormsSystemField($row)) return false;
            if ($row.hasClass('forminator-row') && !stepraForminatorRowHasStepContent($row)) return false;

            var hasVisibleField = $row.find('input, select, textarea').filter(function() {
                var $field = $(this);
                var type = String($field.attr('type') || '').toLowerCase();

                if (type === 'hidden' || type === 'submit' || type === 'button' || type === 'reset' || type === 'image') return false;
                if ($field.is('[disabled]')) return false;
                if (stepraIsCF7InternalHiddenField($field)) return false;
                if (stepraIsForminatorSystemHiddenField($field)) return false;
                if (stepraIsForminatorSensitiveBuilderArea($field)) return false;
                if (stepraIsElementorSystemField($field)) return false;
                if (stepraIsWPFormsValidationExcludedField($field)) return false;

                return stepraIsFieldVisibleForStep($field, adapter);
            }).length > 0;

            var hasVisibleText = $.trim($row.text()).length > 0 &&
                $row.find('input, select, textarea, button').length === 0;

            var hasWPFormsTextField = $row.hasClass('wpforms-field') && stepraWPFormsHasVisibleTextContent($row);

            return hasVisibleField || hasVisibleText || hasWPFormsTextField;
        });
    }

    function stepraSkipEmptyConditionalSteps(form, state) {
        var $form = form && form.jquery ? form : $(form);
        if (!$form.length) return 1;

        state = state || {};

        var adapter = state.adapter || stepraGetAdapter($form);
        var currentStep = parseInt(state.currentStep || $form.attr('data-current-step') || '1', 10) || 1;
        var totalSteps = parseInt(state.totalSteps || '1', 10) || 1;
        var direction = state.direction === 'backward' ? -1 : 1;

        function hasVisibleRows(step) {
            return stepraGetVisibleRowsForStep($form, step, adapter).length > 0;
        }

        if (hasVisibleRows(currentStep)) {
            return currentStep;
        }

        var candidate = currentStep + direction;
        while (candidate >= 1 && candidate <= totalSteps) {
            if (hasVisibleRows(candidate)) return candidate;
            candidate += direction;
        }

        candidate = currentStep - direction;
        while (candidate >= 1 && candidate <= totalSteps) {
            if (hasVisibleRows(candidate)) return candidate;
            candidate -= direction;
        }

        return currentStep;
    }


    // ==========================================
    // 3. SCROLL AND FOCUS HELPERS
    // ==========================================
    function stepraGetStickyHeaderHeight() {
        return $(
            '.elementor-sticky, header.site-header, .navbar-fixed-top, #masthead, #site-header, ' +
            '.site-header, #header, .main-header, .header-main, [data-sticky="on"], .is-sticky, ' +
            '.sticky-header, .fixed-header'
        ).first().outerHeight() || 0;
    }

    function stepraScrollToFormTop($form) {
        if (!$form || !$form.length) return;

        var headerHeight = stepraGetStickyHeaderHeight();
        var targetTop = Math.max(0, $form.offset().top - headerHeight - 16);

        $('html, body').stop(true).animate({
            scrollTop: targetTop
        }, 360);
    }

    function stepraGetFirstFieldInStep($form, stepNumber) {
        return $form.find('.stepra-step-el[data-step="' + stepNumber + '"]')
            .find('input, select, textarea')
            .filter(function() {
                var $el = $(this);
                var type = ($el.attr('type') || '').toLowerCase();

                if (type === 'hidden' || type === 'submit' || type === 'button' || type === 'password') return false;
                if ($el.is('[disabled]')) return false;
                if (stepraIsCF7InternalHiddenField($el)) return false;
                if (stepraIsWPFormsValidationExcludedField($el)) return false;
                if ($el.closest('.forminator-hidden, .elementor-field-type-hidden, .elementor-field-type-honeypot, .elementor-field-type-recaptcha, .elementor-field-type-recaptcha_v3, .hidden-fields-container').length > 0) return false;
                if ($el.is(':hidden') && !$el.is('select, :radio, :checkbox')) return false;

                return !isGhostField($el);
            })
            .first();
    }

    function stepraFocusFieldWithoutScroll($field) {
        if (!$field || !$field.length || !$field[0] || typeof $field[0].focus !== 'function') return;

        try {
            $field[0].focus({ preventScroll: true });
        } catch(e) {
            try {
                $field[0].focus();
            } catch(ignore) {}
        }
    }

    function stepraScrollAndFocusStep($form, stepNumber) {
        stepraScrollToFormTop($form);

        setTimeout(function() {
            stepraFocusFieldWithoutScroll(stepraGetFirstFieldInStep($form, stepNumber));
        }, 390);
    }

    function smoothScrollToForm($form) {
        stepraScrollToFormTop($form);
    }

    // ==========================================
    // 4. CHUNK SPLITTING LOGIC
    // ==========================================
    function applyChunkSplitting($fields, targetStepCount) {
        var $validFields = $fields.filter(function() {
            var $container = $(this);
            
            if (isGhostField($container)) return false;

            var isHidden   = $container.css('display') === 'none' || $container.hasClass('stepra-hidden');
            var isMetadata = $container.find('input[type="hidden"]').length > 0 && $container.find('input:not([type="hidden"])').length === 0;
            var hasSubmit  = $container.find('button[type="submit"], input[type="submit"], .forminator-button-submit, .wpcf7-submit, .wpforms-submit').length > 0;
            var hasInputs  = $container.find('input:not([type="hidden"]), select, textarea').length > 0;
            if (isHidden || isMetadata || (hasSubmit && !hasInputs)) return false;
            return true;
        });

        var total = $validFields.length;
        if (total < 1) return 1;
        var steps = Math.max(targetStepCount, Math.ceil(total / 4));
        
        // Limit math-generated steps to 3
        steps = Math.min(steps, 3);
        
        var b = Math.floor(total / steps), r = total % steps, s = 1, c = 0, t = b + (r > 0 ? 1 : 0);

        $validFields.each(function() {
            $(this).addClass('stepra-step-el').attr('data-step', s);
            if (++c >= t && s < steps) { s++; c = 0; r--; t = b + (r > 0 ? 1 : 0); }
        });
        return steps;
    }

    // ==========================================
    // 5. MODULAR ROUTERS
    // ==========================================
    function handleElementor($form) {
        if ($form.find('.elementor-field-type-step').length > 0) {
            return 1;
        }

        var $groups = $form.find('.elementor-field-group').filter(function() {
            return $(this).parent().closest('.elementor-field-group').length === 0;
        });

        function isUsableElementorGroup($group) {
            if ($group.css('display') === 'none') return false;
            if ($group.hasClass('stepra-hidden')) return false;
            if ($group.is('.stepra-progress, .stepra-nav, style, script')) return false;

            return stepraElementorGroupHasStepContent($group);
        }

        function splitElementorGroups($items, targetStepCount) {
            var $validGroups = $items.filter(function() {
                return isUsableElementorGroup($(this));
            });

            var total = $validGroups.length;
            if (total < 1) return 1;

            var steps = Math.max(targetStepCount, Math.ceil(total / 4));

            // Limit steps to 3
            steps = Math.min(steps, 3);
            steps = Math.min(steps, total);

            var b = Math.floor(total / steps);
            var r = total % steps;
            var s = 1;
            var c = 0;
            var t = b + (r > 0 ? 1 : 0);

            $validGroups.each(function() {
                $(this).addClass('stepra-step-el').attr('data-step', s);

                if (++c >= t && s < steps) {
                    s++;
                    c = 0;
                    r--;
                    t = b + (r > 0 ? 1 : 0);
                }
            });

            return steps;
        }

        var hasHeadings = $groups.filter(function() {
            return $(this).is(hTags) || $(this).find(hTags + ', .elementor-heading-title').length > 0;
        }).length > 0;

        if (hasHeadings) {
            var currentStep = 1;

            $groups.each(function(index) {
                var $group = $(this);

                if ($group.is(hTags) || $group.find(hTags + ', .elementor-heading-title').length > 0) {
                    if (index > 0) currentStep++;
                }

                if (isUsableElementorGroup($group)) {
                    $group.addClass('stepra-step-el').attr('data-step', currentStep);
                }
            });

            if (currentStep > 1) {
                return currentStep;
            }

            $groups.removeClass('stepra-step-el').removeAttr('data-step');
        }

        return splitElementorGroups($groups, 3);
    }

    function handleWPForms($form) {
        var $fields = $form.find('.wpforms-field').filter(function() {
            return $(this).parent().closest('.wpforms-field').length === 0;
        });

        var $validFields = $fields.filter(function() {
            return stepraWPFormsFieldHasStepContent($(this));
        });

        var total = $validFields.length;
        if (total < 1) return 1;

        var steps = Math.max(3, Math.ceil(total / 4));

        if (typeof stepraFeatureEnabled === 'function' && typeof stepraFeatureMaxSteps === 'function') {
            if (!stepraFeatureEnabled('unlimited_steps')) {
                steps = Math.min(steps, stepraFeatureMaxSteps());
            }
        } else {
            steps = Math.min(steps, 3);
        }

        steps = Math.max(1, Math.min(steps, total));

        var b = Math.floor(total / steps);
        var r = total % steps;
        var s = 1;
        var c = 0;
        var t = b + (r > 0 ? 1 : 0);

        $validFields.each(function() {
            $(this).addClass('stepra-step-el').attr('data-step', s);

            if (++c >= t && s < steps) {
                s++;
                c = 0;
                r--;
                t = b + (r > 0 ? 1 : 0);
            }
        });

        stepraNormalizeWPFormsRows($form, steps);

        return steps;
    }

    function handleForminator($form) {
        var $elements = $form.find('.forminator-row').filter(function() {
            return $(this).parent().closest('.forminator-row').length === 0;
        });

        function hasUsableForminatorInput($row) {
            return $row.find('input, select, textarea').filter(function() {
                var $input = $(this);
                var type = ($input.attr('type') || '').toLowerCase();

                if (stepraIsForminatorSystemHiddenField($input)) return false;
                if (type === 'hidden' || type === 'submit' || type === 'button' || type === 'reset' || type === 'image') return false;
                if ($input.closest('.forminator-hidden, .forminator-page-hidden').length > 0) return false;
                if (type === 'password') return true;

                /*
                 * Forminator calculation fields are disabled/readonly by design,
                 * but they are still real visible fields and must be assigned to a Stepra step.
                 */
                if (
                    $input.hasClass('forminator-calculation') ||
                    ($input.attr('name') || '').indexOf('calculation') !== -1 ||
                    ($input.attr('id') || '').indexOf('calculation') !== -1
                ) {
                    return true;
                }

                /*
                 * Forminator Select2 hides the original select with aria-hidden/tabindex.
                 * The original select is still the submitted field and must remain usable.
                 */
                if (stepraIsForminatorSelect2OriginalField($input)) return true;

                if ($input.is('[disabled]')) return false;
                if ($input.attr('aria-hidden') === 'true') return false;

                return true;
            }).length > 0;
        }

        function isUsableForminatorRow($row) {
            if (!$row || !$row.length) return false;
            if (!stepraForminatorRowHasStepContent($row)) return false;
            if ($row.css('display') === 'none' || stepraHasInlineHiddenStyle($row[0])) return false;

            var hasSection = $row.find('.forminator-field-section').length > 0;
            var hasSubmit = $row.find('button[type="submit"], input[type="submit"], .forminator-button-submit').length > 0;
            var hasInput = hasUsableForminatorInput($row);

            var hasTimeField = $row.text().replace(/\s+/g, '').indexOf('HoursMinutesAM/PM') !== -1 ||
                               $row.find('[id^="time-"], [class*="time"], [name*="hour"], [name*="minute"], [name*="ampm"]').length > 0;

            var hasHtmlField = $row.find(
                '.forminator-field-html, .forminator-html, [class*="field-html"], [id*="html-"]'
            ).length > 0;

            var hasVisibleTextOnlyContent = $.trim($row.text()).length > 0 &&
                                            $row.find('input, select, textarea, button').length === 0;

            if (hasSubmit && !hasInput && !hasSection && !hasTimeField && !hasHtmlField && !hasVisibleTextOnlyContent) return false;

            return hasInput || hasSection || hasTimeField || hasHtmlField || hasVisibleTextOnlyContent;
        }

        function stepraGetForminatorMaxSteps(calculatedSteps, totalRows) {
            var steps = calculatedSteps;

            if (typeof stepraFeatureEnabled === 'function' && typeof stepraFeatureMaxSteps === 'function') {
                if (!stepraFeatureEnabled('unlimited_steps')) {
                    steps = Math.min(steps, stepraFeatureMaxSteps());
                }
            } else {
                steps = Math.min(steps, 3);
            }

            return Math.max(1, Math.min(steps, totalRows));
        }

        function splitForminatorRows($rows, targetStepCount) {
            var $validRows = $rows.filter(function() {
                return isUsableForminatorRow($(this));
            });

            var total = $validRows.length;
            if (total < 1) return 1;

            var steps = Math.max(targetStepCount, Math.ceil(total / 4));
            steps = stepraGetForminatorMaxSteps(steps, total);

            var b = Math.floor(total / steps);
            var r = total % steps;
            var s = 1;
            var c = 0;
            var t = b + (r > 0 ? 1 : 0);

            $validRows.each(function() {
                $(this).addClass('stepra-step-el').attr('data-step', s);

                if (++c >= t && s < steps) {
                    s++;
                    c = 0;
                    r--;
                    t = b + (r > 0 ? 1 : 0);
                }
            });

            return steps;
        }

        var hasSections = false;

        $elements.each(function() {
            if ($(this).find('.forminator-field-section').length > 0) {
                hasSections = true;
            }
        });

        if (hasSections) {
            var currentStep = 1;

            $elements.each(function(index) {
                var $row = $(this);

                if ($row.find('.forminator-field-section').length > 0) {
                    if (index > 0) currentStep++;
                }

                if (isUsableForminatorRow($row)) {
                    $row.addClass('stepra-step-el').attr('data-step', currentStep);
                }
            });

            if (currentStep > 1) {
                return currentStep;
            }

            $elements.removeClass('stepra-step-el').removeAttr('data-step');
        }

        return splitForminatorRows($elements, 3);
    }

    function handleCF7($form) {
        function isCF7ExcludedArea($el) {
            if (!$el || !$el.length) return false;

            return $el.closest(
                '.hidden-fields-container, ' +
                '.wpcf7-response-output, ' +
                '.screen-reader-response, ' +
                '.wpcf7-spinner, ' +
                '.stepra-progress, ' +
                '.stepra-nav, ' +
                '.stepra-summary-wrapper, ' +
                '.stepra-admin-warning'
            ).length > 0;
        }

        function isCF7HiddenOrSystemInput($input) {
            if (!$input || !$input.length) return true;

            var type = String($input.attr('type') || '').toLowerCase();
            var name = String($input.attr('name') || '');

            return type === 'hidden' ||
                type === 'submit' ||
                type === 'button' ||
                type === 'reset' ||
                type === 'image' ||
                type === 'password' ||
                $input.hasClass('wpcf7-hidden') ||
                name.indexOf('_wpcf7') === 0 ||
                name.indexOf('_wpcf7_quiz_answer_') === 0 ||
                isCF7ExcludedArea($input);
        }

        function isUsableCF7Input($input) {
            if (isCF7HiddenOrSystemInput($input)) return false;
            if ($input.is('[disabled]')) return false;

            return true;
        }

        function isCF7SystemOnlyRow($row) {
            if (!$row || !$row.length) return true;

            if ($row.is(
                'input[type="hidden"], ' +
                'input.wpcf7-hidden, ' +
                'style, script, ' +
                '.stepra-progress, ' +
                '.stepra-nav, ' +
                '.stepra-summary-wrapper, ' +
                '.stepra-admin-warning, ' +
                '.wpcf7-response-output, ' +
                '.screen-reader-response, ' +
                '.wpcf7-spinner, ' +
                '.hidden-fields-container'
            )) {
                return true;
            }

            if (isCF7ExcludedArea($row)) return true;

            return false;
        }

        function isUsableCF7Row($row) {
            if (isCF7SystemOnlyRow($row)) return false;
            var hiddenOnlyByStepra = $row.hasClass('stepra-hidden') && !stepraHasInlineHiddenStyle($row[0]);
            if (!hiddenOnlyByStepra && ($row.css('display') === 'none' || stepraHasInlineHiddenStyle($row[0]))) return false;
            if (stepraIsRealVisibilityHidden($row)) return false;

            var hasSubmit = $row.find('button[type="submit"], input[type="submit"], .wpcf7-submit').length > 0;

            var hasInput = $row.find('input, select, textarea').filter(function() {
                return isUsableCF7Input($(this));
            }).length > 0;

            var hasHeading = $row.is(hTags) || $row.find(hTags).length > 0;

            var hasVisibleTextOnlyContent = $.trim($row.text()).length > 0 &&
                                            $row.find('input, select, textarea, button').length === 0;

            if (hasSubmit && !hasInput && !hasHeading && !hasVisibleTextOnlyContent) return false;

            return hasInput || hasHeading || hasVisibleTextOnlyContent;
        }

        function getCF7Rows() {
            var rows = [];

            $form.children().each(function() {
                var $row = $(this);

                if (isUsableCF7Row($row)) {
                    rows.push($row[0]);
                }
            });

            if (rows.length < 2) {
                $form.find('.wpcf7-form-control-wrap, input, select, textarea').each(function() {
                    var $item = $(this);

                    if (isCF7HiddenOrSystemInput($item)) return true;
                    if (isCF7ExcludedArea($item)) return true;

                    var $container = $item.closest('.stepra-cf7-test-row, .form-row, p, div, label, li');

                    if ($container.length === 0 || $container.is($form) || isCF7SystemOnlyRow($container)) {
                        $container = $item.closest('.wpcf7-form-control-wrap');
                    }

                    if ($container.length > 0 && isUsableCF7Row($container) && $.inArray($container[0], rows) === -1) {
                        rows.push($container[0]);
                    }
                });
            }

            return $(rows);
        }

        function splitCF7Rows($rows, targetStepCount) {
            var $validRows = $rows.filter(function() {
                return isUsableCF7Row($(this));
            });

            var total = $validRows.length;
            if (total < 1) return 1;

            var steps = Math.max(targetStepCount, Math.ceil(total / 4));

            // Limit steps to 3
            steps = Math.min(steps, 3);
            steps = Math.min(steps, total);

            var b = Math.floor(total / steps);
            var r = total % steps;
            var s = 1;
            var c = 0;
            var t = b + (r > 0 ? 1 : 0);

            $validRows.each(function() {
                $(this).addClass('stepra-step-el').attr('data-step', s);

                if (++c >= t && s < steps) {
                    s++;
                    c = 0;
                    r--;
                    t = b + (r > 0 ? 1 : 0);
                }
            });

            return steps;
        }

        var $rows = getCF7Rows();

        var hasHeadings = $rows.filter(function() {
            return $(this).is(hTags) || $(this).find(hTags).length > 0;
        }).length > 0;

        if (hasHeadings) {
            var currentStep = 1;

            $rows.each(function(index) {
                var $row = $(this);

                if ($row.is(hTags) || $row.find(hTags).length > 0) {
                    if (index > 0) currentStep++;
                }

                if (isUsableCF7Row($row)) {
                    $row.addClass('stepra-step-el').attr('data-step', currentStep);
                }
            });

            if (currentStep > 1) {
                return currentStep;
            }

            $rows.removeClass('stepra-step-el').removeAttr('data-step');
        }

        return splitCF7Rows($rows, 3);
    }

    // ==========================================
    // 6. MAIN INIT ENGINE
    // ==========================================
    function initWrapper(scope) {
        var $forms = stepraGetSupportedForms(scope ? $(scope) : null);

        $forms.each(function() {
            var $form = $(this);

            var adapter = stepraGetAdapter($form);
            if (!adapter) return;

            if (adapter.id === 'elementor-forms') {
                $form.attr('novalidate', 'novalidate');
            }

            stepraRepairInvalidReadyContract($form, adapter);

            if ($form.hasClass('processing')) return;

            var stepraState = stepraGetState($form);

            if ($form.attr('data-stepra-init-lock') === '1') {
                if (stepraState === 'ready' || stepraState === 'aborted' || stepraState === 'failed') {
                    stepraReleaseInitLock($form);
                }
                return;
            }

            if (adapter.id === 'wpforms' && (stepraState === 'ready' || $form.hasClass('stepra-ready')) && stepraShouldRebuildWPForms($form)) {
                stepraResetWPFormsForRebuild($form);
                stepraState = stepraGetState($form);
            }

            if (adapter.id === 'contact-form-7' && (stepraState === 'ready' || $form.hasClass('stepra-ready')) && stepraShouldRebuildCF7($form)) {
                stepraResetCF7ForRebuild($form);
                stepraState = stepraGetState($form);
            }

            if (adapter.id === 'forminator' && (stepraState === 'ready' || $form.hasClass('stepra-ready')) && stepraShouldRebuildForminator($form)) {
                stepraResetForminatorForRebuild($form);
                stepraState = stepraGetState($form);
            }

            if (adapter.id === 'elementor-forms' && (stepraState === 'ready' || $form.hasClass('stepra-ready')) && stepraShouldRebuildElementor($form)) {
                stepraResetElementorForRebuild($form);
                stepraState = stepraGetState($form);
            }

            if ((stepraState === 'ready' || $form.hasClass('stepra-ready')) && stepraRepairInvalidReadyContract($form, adapter)) {
                stepraState = stepraGetState($form);
            }

            if (stepraState === 'ready' || stepraState === 'aborted' || stepraState === 'failed') {
                if (stepraState === 'ready' && !stepraBuilderVisualContractValid($form, adapter)) {
                    $form.removeClass('stepra-visual-ready');
                    if (stepraRepairInvalidReadyContract($form, adapter)) {
                        stepraState = stepraGetState($form);
                    } else {
                        stepraScheduleVisualReveal($form);
                    }
                }

                if (stepraState === 'ready' || stepraState === 'aborted' || stepraState === 'failed') {
                    stepraReleaseInitLock($form);
                    return;
                }
            }
            if (stepraState === 'initializing') return;

            if ($form.hasClass('stepra-ready')) {
                stepraSetState($form, 'ready');
                return;
            }

            if (!stepraAcquireInitLock($form)) return;
            stepraSetState($form, 'initializing');
            stepraDispatchInternalEvent('init-start', $form, {
                adapterId: adapter.id,
                adapterLabel: adapter.label
            });

            var conflict = stepraFindBuilderConflict($form, adapter);

            if (conflict) {
                var conflictName = conflict.name || adapter.label || 'Native Multi-Step Feature';
                stepraDispatchInternalEvent('conflict-detected', $form, {
                    conflictName: conflictName,
                    adapterId: adapter.id,
                    adapterLabel: adapter.label
                });
                $form.addClass('stepra-conflict-aborted');
                stepraSetState($form, 'aborted');
                if ($('body').hasClass('admin-bar') && $form.prev('.stepra-admin-warning').length === 0) {
                    $form.before(
                        '<div class="stepra-admin-warning" style="background:#fff3cd; color:#856404; padding:12px 15px; border-left:4px solid #ffeeba; border-radius:4px; margin-bottom:20px; font-family:sans-serif; font-size:14px; line-height:1.5;">' +
                        '<strong>&#9888;&#65039; Stepra Engine Paused:</strong> We detected an active multi-step feature ' +
                        '(<strong>' + escapeHtml(conflictName) + '</strong>) on this form. ' +
                        'To use Stepra, please disable the native pagination in your form builder or deactivate the conflicting plugin. ' +
                        '<em style="display:block; margin-top:5px; font-size:12px; color:#b58105;">' +
                        '(Only logged-in admins can see this message. Your visitors see the normal form.)' +
                        '</em></div>'
                    );
                }
                stepraSetState($form, 'aborted');
                return;
            }

            var inputCount = stepraGetSplitInputCount($form, adapter);
            if (inputCount < 6) {
                if (document.readyState === 'loading') {
                    stepraDeferInit($form);
                    return;
                }
                stepraSetState($form, 'ready');
                return;
            }

            var totalSteps = stepraRunAdapterSplit($form, adapter);

            if (adapter.id === 'elementor-forms') {
                stepraNormalizeElementorRows($form, totalSteps);
                totalSteps = stepraGetElementorRealTotalSteps($form, totalSteps);
            }

            if (adapter.id === 'contact-form-7') {
                stepraNormalizeCF7Rows($form, totalSteps);
                totalSteps = stepraGetCF7RealTotalSteps($form, totalSteps);
            }

            if (adapter.id === 'forminator') {
                stepraNormalizeForminatorRows($form, totalSteps);
                totalSteps = stepraGetForminatorRealTotalSteps($form, totalSteps);
            }

            if (adapter.id === 'wpforms') {
                stepraNormalizeWPFormsRows($form, totalSteps);
                totalSteps = stepraGetWPFormsRealTotalSteps($form, totalSteps);
            }

            // Global step limit
            if (totalSteps > 3) {
                $form.find('.stepra-step-el').each(function() {
                    var s = parseInt($(this).attr('data-step'), 10);
                    if (s > 3) {
                        $(this).attr('data-step', 3);
                    }
                });
                totalSteps = 3;
            }

            if (adapter.id === 'wpforms') {
                stepraNormalizeWPFormsRows($form, totalSteps);
                totalSteps = stepraGetWPFormsRealTotalSteps($form, totalSteps);
            }

            if (adapter.id === 'contact-form-7') {
                stepraNormalizeCF7Rows($form, totalSteps);
                totalSteps = stepraGetCF7RealTotalSteps($form, totalSteps);
            }

            if (adapter.id === 'forminator') {
                stepraNormalizeForminatorRows($form, totalSteps);
                totalSteps = stepraGetForminatorRealTotalSteps($form, totalSteps);
            }

            if (adapter.id === 'elementor-forms') {
                stepraNormalizeElementorRows($form, totalSteps);
                totalSteps = stepraGetElementorRealTotalSteps($form, totalSteps);
            }

            if (totalSteps <= 1) {
                if (document.readyState === 'loading' || stepraReadyRequiresUI($form, adapter)) {
                    stepraDeferInit($form);
                    return;
                }
                stepraSetState($form, 'ready');
                return;
            }

            $form.find('.stepra-progress, .stepra-nav').remove();

            $form.prepend(stepraBuildProgressMarkup(totalSteps));

            $form.append(stepraBuildNavigationMarkup());

            var savedStep = parseInt($form.attr('data-current-step'), 10);
            var initStep  = (savedStep && savedStep <= totalSteps) ? savedStep : 1;
            stepraSetCurrentStep($form, initStep, totalSteps);

            // ==========================================
            // 7. UI UPDATE FUNCTION
            // ==========================================
            function updateUI() {
                var currentStep = stepraGetCurrentStep($form, totalSteps);

                if (adapter.id === 'elementor-forms') {
                    stepraNormalizeElementorRows($form, totalSteps);
                    totalSteps = stepraGetElementorRealTotalSteps($form, totalSteps);
                    currentStep = stepraGetCurrentStep($form, totalSteps);
                }

                if (adapter.id === 'contact-form-7') {
                    stepraNormalizeCF7Rows($form, totalSteps);
                    totalSteps = stepraGetCF7RealTotalSteps($form, totalSteps);
                    currentStep = stepraGetCurrentStep($form, totalSteps);
                }

                if (adapter.id === 'forminator') {
                    stepraNormalizeForminatorRows($form, totalSteps);
                    totalSteps = stepraGetForminatorRealTotalSteps($form, totalSteps);
                    currentStep = stepraGetCurrentStep($form, totalSteps);
                }

                if (adapter.id === 'wpforms') {
                    stepraNormalizeWPFormsRows($form, totalSteps);
                    totalSteps = stepraGetWPFormsRealTotalSteps($form, totalSteps);
                    currentStep = stepraGetCurrentStep($form, totalSteps);
                }

                // Hide/show only with a class so Stepra does not overwrite
                // user/theme/custom CSS display or width rules.
                $form.find('.stepra-step-el').addClass('stepra-hidden');
                $form.find('.stepra-step-el[data-step="' + currentStep + '"]').removeClass('stepra-hidden');

                var visibilityAdapter = stepraGetAdapter($form);
                var navDirection = $form.attr('data-stepra-nav-direction') || 'forward';
                var visibleStep = stepraSkipEmptyConditionalSteps($form, {
                    currentStep: currentStep,
                    totalSteps: totalSteps,
                    direction: navDirection,
                    adapter: visibilityAdapter
                });

                if (visibleStep !== currentStep) {
                    var skippedFromStep = currentStep;

                    currentStep = stepraSetCurrentStep($form, visibleStep, totalSteps);
                    $form.find('.stepra-step-el').addClass('stepra-hidden');
                    $form.find('.stepra-step-el[data-step="' + currentStep + '"]').removeClass('stepra-hidden');

                    stepraDispatchInternalEvent('conditional-step-skipped', $form, {
                        previousStep: skippedFromStep,
                        currentStep: currentStep,
                        totalSteps: totalSteps,
                        direction: navDirection
                    });
                }

                stepraUpdateProgressUI($form, currentStep, totalSteps);

                $form.attr('data-last-step', (currentStep === totalSteps) ? 'true' : 'false');

                if (currentStep === 1) {
                    $form.find('.stepra-prev').css('cssText', 'display: none !important;');
                } else {
                    $form.find('.stepra-prev').css('cssText', 'display: inline-block !important; color:#334155 !important;');
                }

                var $submit = $form.find(
                    'button[type="submit"], ' +
                    'input[type="submit"], ' +
                    '.forminator-button-submit, ' +
                    '.wpcf7-submit, ' +
                    '.wpforms-submit'
                ).not('.stepra-prev, .stepra-next');

                var $submitParentObj = $submit.closest(
                    '.elementor-field-type-submit, .forminator-row-last, .wpforms-submit-container'
                );
                if ($submitParentObj.length === 0) $submitParentObj = $submit.parent();

                var $nextButton = $form.find('.stepra-next');
                $nextButton.removeAttr('hidden').removeClass('stepra-button-hidden');

                if (currentStep === totalSteps) {
                    $nextButton.css('cssText', 'display: none !important;');
                    $submitParentObj.show();
                    $submit.show();
                } else {
                    $nextButton.css('cssText', 'display: inline-block !important; margin-left: auto !important;');
                    $submitParentObj.hide();
                    $submit.hide();
                }

                if (adapter.id === 'wpforms') {
                    totalSteps = stepraSyncWPFormsNavSubmitState($form, currentStep, totalSteps);
                    currentStep = stepraGetCurrentStep($form, totalSteps);
                }

                var stepraDedicatedNavSubmitSyncHandled = false;

                if (adapter.id === 'contact-form-7') {
                    totalSteps = stepraSyncCF7NavSubmitState($form, currentStep, totalSteps);
                    currentStep = stepraGetCurrentStep($form, totalSteps);
                    stepraDedicatedNavSubmitSyncHandled = true;
                }

                if (adapter.id === 'forminator') {
                    totalSteps = stepraSyncForminatorNavSubmitState($form, currentStep, totalSteps);
                    currentStep = stepraGetCurrentStep($form, totalSteps);
                    stepraDedicatedNavSubmitSyncHandled = true;
                }

                if (adapter.id === 'elementor-forms') {
                    totalSteps = stepraSyncElementorNavSubmitState($form, currentStep, totalSteps);
                    currentStep = stepraGetCurrentStep($form, totalSteps);
                    stepraDedicatedNavSubmitSyncHandled = true;
                }

                var $nav = $form.find('.stepra-nav');
                var $activeContainer = $form.find('.stepra-step-el[data-step="' + currentStep + '"]').last();

                if (!stepraDedicatedNavSubmitSyncHandled) {
                    if (currentStep === totalSteps && $submitParentObj.length) {
                        $nav.insertBefore($submitParentObj);
                        $nav.css('margin-bottom', '20px');
                    } else if ($activeContainer.length) {
                        $nav.insertAfter($activeContainer);
                        $nav.css('margin-bottom', '0');
                    }
                }
            }

            function stepraShowFieldError($el, message) {
                if (!$el || !$el.length) return;

                var safeMessage = $.trim(String(message || ''));
                if (safeMessage === '') return;

                var $errorTarget = $el;

                if ($el.is('select') && $el.siblings('.select2-container').length > 0) {
                    $errorTarget = $el.siblings('.select2-container');
                } else if ($el.is(':radio') || $el.is(':checkbox')) {
                    var $groupTarget = $el.closest(
                        '.form-row, .wpforms-field, .forminator-field, .elementor-field-group, .wpcf7-form-control-wrap'
                    );

                    if ($groupTarget.length > 0) {
                        $errorTarget = $groupTarget;
                    }
                }

                $errorTarget.next('.stepra-error-message').remove();

                $errorTarget.after(
                    '<div class="stepra-error-message" style="color:#d63638; font-size:12px; margin-top:6px; line-height:1.4;">' +
                    escapeHtml(safeMessage) +
                    '</div>'
                );
            }

           function stepraGetValidationMessages() {
    var valLang = (typeof stepra_settings !== 'undefined') ? stepra_settings.validationLang : 'en';
    var i18n = {
        en: {
            req: "This field is required.",
            email: "Invalid email address.",
            url: "Invalid URL. Include https://",
            phone: "Invalid phone number (8-15 digits).",
            zip: "Invalid postal code.",
            date: "Invalid year (1900-2100)."
        },
        fr: {
            req: "Champ requis.",
            email: "Email invalide.",
            url: "URL invalide. Ajoutez https://",
            phone: "T\u00e9l\u00e9phone invalide (8-15 chiffres).",
            zip: "Code postal invalide.",
            date: "Ann\u00e9e invalide (1900-2100)."
        },
        es: {
            req: "Este campo es obligatorio.",
            email: "Correo electr\u00f3nico no v\u00e1lido.",
            url: "URL no v\u00e1lida. Incluye https://",
            phone: "Tel\u00e9fono no v\u00e1lido (8-15 d\u00edgitos).",
            zip: "C\u00f3digo postal no v\u00e1lido.",
            date: "A\u00f1o no v\u00e1lido (1900-2100)."
        }
    };

    return i18n[valLang] || i18n['en'];
}

            function stepraClearValidationState($form) {
                $form.find('.stepra-error-border').css('border', '').removeClass('stepra-error-border');
                $form.find('.stepra-error-message').remove();
                $form.find('[aria-invalid="true"]').removeAttr('aria-invalid');
            }

            function stepraGetValidationErrorTarget($el) {
                var $errorTarget = $el;

                if ($el.is('select') && $el.siblings('.select2-container').length > 0) {
                    $errorTarget = $el.siblings('.select2-container');
                } else if ($el.is(':radio') || $el.is(':checkbox')) {
                    var $groupTarget = $el.closest(
                        '.form-row, .wpforms-field, .forminator-field, .elementor-field-group, .elementor-field, .wpcf7-form-control-wrap'
                    );

                    if ($groupTarget.length > 0) {
                        $errorTarget = $groupTarget;
                    }
                }

                return $errorTarget;
            }

            function stepraIsValidationCandidate($el) {
                var type = String($el.attr('type') || '').toLowerCase();

                if (type === 'hidden' || type === 'submit' || type === 'button' || type === 'reset' || type === 'image' || type === 'password') return false;
                if ($el.is('[disabled], [readonly]')) return false;
                if (stepraIsCF7InternalHiddenField($el)) return false;
                if (stepraIsForminatorSystemHiddenField($el)) return false;
                if (stepraIsForminatorSensitiveBuilderArea($el)) return false;
                if (stepraIsElementorSystemField($el)) return false;
                if (stepraIsWPFormsValidationExcludedField($el)) return false;
                if ($el.closest('.stepra-progress, .stepra-nav, .stepra-summary-wrapper, .stepra-admin-warning').length > 0) return false;
                if ($el.closest('.forminator-hidden, .hidden-fields-container').length > 0) return false;

                var $ownerForm = $el.closest(STEPRA_SUPPORTED_FORM_SELECTOR);
                var visibilityAdapter = $ownerForm.length ? stepraGetAdapter($ownerForm) : null;
                if (!stepraIsFieldVisibleForStep($el, visibilityAdapter)) return false;

                var $wrapper = $el.closest('.form-row, .wpforms-field, .forminator-field, .elementor-field, .elementor-field-group, .wpcf7-form-control-wrap');
                if ($wrapper.length > 0) {
                    if ($wrapper.hasClass('stepra-hidden')) return false;
                    if ($wrapper.css('display') === 'none' || stepraIsRealVisibilityHidden($wrapper)) return false;
                }

                if ($el.is(':hidden') && !$el.is('select, :radio, :checkbox')) return false;

                return !isGhostField($el);
            }

            function stepraGetCurrentStepValidationFields($form, currentStep) {
                return $form.find('.stepra-step-el[data-step="' + currentStep + '"]')
                    .find('input, select, textarea')
                    .filter(function() {
                        return stepraIsValidationCandidate($(this));
                    });
            }

            function stepraIsRequiredValidationField($el) {
                return $el.prop('required') ||
                    $el.attr('required') !== undefined ||
                    $el.attr('aria-required') === 'true' ||
                    $el.attr('data-required') === 'true' ||
                    $el.attr('data-required') === '1' ||
                    $el.attr('data-required') === 'required' ||
                    $el.closest(
                        '.validate-required, ' +
                        '.wpforms-field-required, ' +
                        '.forminator-is_required, ' +
                        '.forminator-field-required, ' +
                        '.elementor-mark-required, ' +
                        '.elementor-field-required, ' +
                        '.wpcf7-validates-as-required'
                    ).length > 0 ||
                    $el.closest('.forminator-field').find(
                        '.forminator-required, .forminator-label .forminator-required'
                    ).length > 0 ||
                    $el.closest('.elementor-field').find(
                        '.elementor-required, .elementor-field-label .elementor-required'
                    ).length > 0;
            }

            function stepraGetFieldValue($el) {
                if ($el.is('select')) {
                    var selectValue = $el.val();
                    if ($.isArray(selectValue)) {
                        return $.map(selectValue, function(item) {
                            return $.trim(String(item || ''));
                        }).filter(function(item) {
                            return item !== '';
                        }).join(',');
                    }
                    return selectValue === null ? '' : $.trim(String(selectValue));
                }

                return $.trim(String($el.val() || ''));
            }

            function stepraIsChoiceGroupChecked($form, $el) {
                var groupName = $el.attr('name') || '';

                if (!groupName) {
                    return $el.is(':checked');
                }

                return $form.find('input').filter(function() {
                    return this.name === groupName;
                }).filter(':checked').length > 0;
            }

            function stepraValidateField($form, $el, msgs) {
                var type = String($el.attr('type') || '').toLowerCase();
                var name = String($el.attr('name') || '').toLowerCase();
                var value = stepraGetFieldValue($el);
                var required = stepraIsRequiredValidationField($el);
                var valid = true;
                var invalidMessage = '';

                try {
                    $el[0].setCustomValidity('');
                } catch(e) {}

                if (required) {
                    if (type === 'checkbox' || type === 'radio') {
                        valid = stepraIsChoiceGroupChecked($form, $el);
                    } else if (type === 'file') {
                        valid = !!($el[0].files && $el[0].files.length > 0);
                    } else {
                        valid = value !== '';
                    }

                    if (!valid) {
                        invalidMessage = msgs.req;
                    }
                }

                if (valid && value !== '') {
                    if ((type === 'email' || name.indexOf('email') !== -1) && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
                        valid = false;
                        invalidMessage = msgs.email;
                    }

                    if (($el.is('input') && (type === 'url' || $el.hasClass('wpcf7-url') || $el.hasClass('wpcf7-validates-as-url'))) && !/^https?:\/\/[^\s]+\.[^\s]+/i.test(value)) {
                        valid = false;
                        invalidMessage = msgs.url;
                    }

                    if (type === 'tel' || name.indexOf('phone') !== -1 || name.indexOf('tel') !== -1) {
                        var cleanPhone = value.replace(/[\s\-()]/g, '');
                        if (!/^\+?[0-9]{8,15}$/.test(cleanPhone)) {
                            valid = false;
                            invalidMessage = msgs.phone;
                        }
                    }

                    if (name.indexOf('zip') !== -1 || name.indexOf('postcode') !== -1 || name.indexOf('postal') !== -1) {
                        if (!/^[a-zA-Z0-9\s\-]{3,10}$/.test(value)) {
                            valid = false;
                            invalidMessage = msgs.zip;
                        }
                    }

                    if (type === 'date' || name.indexOf('date') !== -1) {
                        var year = new Date(value).getFullYear();
                        if (isNaN(year) || year < 1900 || year > 2100) {
                            valid = false;
                            invalidMessage = msgs.date;
                        }
                    }
                }

                if (!valid) {
                    try {
                        $el[0].setCustomValidity(invalidMessage || msgs.req);
                    } catch(e) {}
                }

                return {
                    valid: valid,
                    message: invalidMessage || msgs.req
                };
            }

            function stepraMarkInvalidField($el, message) {
                var $target = stepraGetValidationErrorTarget($el);

                $el.attr('aria-invalid', 'true');

                if ($el.is('select') && $el.siblings('.select2-container').length > 0) {
                    $el.siblings('.select2-container').find('.select2-selection')
                        .css('border', '2px solid #d63638')
                        .addClass('stepra-error-border');
                } else {
                    $target.css('border', '2px solid #d63638').addClass('stepra-error-border');
                }

                stepraShowFieldError($el, message);
            }

            function stepraClearFieldValidationState($el) {
                var $target = stepraGetValidationErrorTarget($el);

                $el.removeAttr('aria-invalid');
                $target.css('border', '').removeClass('stepra-error-border');

                if ($el.is('select') && $el.siblings('.select2-container').length > 0) {
                    $el.siblings('.select2-container').find('.select2-selection')
                        .css('border', '')
                        .removeClass('stepra-error-border');
                }
            }

            function stepraFocusInvalidField($el) {
                if (!$el || !$el.length || !$el[0]) return;

                try {
                    if (typeof $el[0].reportValidity === 'function') {
                        $el[0].reportValidity();
                    }
                } catch(e) {}

                stepraFocusFieldWithoutScroll($el);
            }

            function stepraValidateCurrentStep($form, currentStep, msgs) {
                var $invalid = $();

                stepraClearValidationState($form);

                stepraGetCurrentStepValidationFields($form, currentStep).each(function() {
                    var $el = $(this);
                    var result = stepraValidateField($form, $el, msgs);

                    if (!result.valid) {
                        stepraMarkInvalidField($el, result.message || msgs.req);
                        $invalid = $el;
                        return false;
                    }

                    stepraClearFieldValidationState($el);
                    return true;
                });

                return {
                    valid: $invalid.length === 0,
                    $invalid: $invalid
                };
            }


            function stepraFindInvalidElementorField($form, msgs) {
                msgs = msgs || stepraGetValidationMessages();
                var $invalid = $();
                var elementorAdapter = stepraGetAdapter($form);

                $form.find('.stepra-step-el input, .stepra-step-el select, .stepra-step-el textarea').each(function() {
                    var $el = $(this);
                    var type = String($el.attr('type') || '').toLowerCase();

                    // Elementor submit snap-back must scan every Stepra step, including
                    // hidden future/previous steps. Keep only Elementor-specific skip
                    // rules here, then delegate real validation to stepraValidateField()
                    // so zip/postal/email/phone/date/choice rules cannot diverge.
                    if (type === 'hidden' || type === 'submit' || type === 'button' || type === 'password') return true;
                    if ($el.is('[disabled]')) return true;
                    if (stepraIsElementorSystemField($el)) return true;
                    if (!stepraIsFieldVisibleForStep($el, elementorAdapter)) return true;

                    var result = stepraValidateField($form, $el, msgs);

                    if (!result.valid) {
                        $invalid = $el;
                        return false;
                    }

                    stepraClearFieldValidationState($el);
                    return true;
                });

                return $invalid;
            }


            $form.off('stepra_update_ui').on('stepra_update_ui', function(e, stepraOptions) {
                updateUI();

                if (stepraOptions && stepraOptions.scroll) {
                    stepraScrollToFormTop($form);
                }
            });

            // ==========================================
            // 8. VALIDATION & DELEGATED NAVIGATION
            // ==========================================
            if (!$form.data('stepra-events-bound')) {

                var stepraConditionalRefreshTimer = null;

                $form.on('change.stepraConditional input.stepraConditional', 'input, select, textarea', function() {
                    clearTimeout(stepraConditionalRefreshTimer);

                    stepraConditionalRefreshTimer = setTimeout(function() {
                        if (stepraGetState($form) !== 'ready') return;

                        updateUI();

                        stepraDispatchInternalEvent('conditional-visibility-refresh', $form, {
                            currentStep: stepraGetCurrentStep($form, totalSteps),
                            totalSteps: totalSteps
                        });
                    }, 120);
                });

                $form.on('click', '.stepra-progress-number', function(e) {
                    e.preventDefault();

                    var currentStep = parseInt($form.attr('data-current-step')) || 1;
                    var targetStep = parseInt($(this).attr('data-stepra-target-step'), 10) || currentStep;

                    // Allow safe backward navigation from numbered progress.
                    // Future steps are locked so visitors cannot skip validation.
                    if (targetStep >= currentStep || targetStep < 1) {
                        return;
                    }

                    $form.attr('data-stepra-nav-direction', 'backward');
                    targetStep = stepraSetCurrentStep($form, targetStep, totalSteps);
                    updateUI();
                    stepraScrollAndFocusStep($form, targetStep);
                });

                $form.on('click', '.stepra-next', function(e) {
                    e.preventDefault();

                    if (adapter.id === 'contact-form-7') {
                        stepraNormalizeCF7Rows($form, totalSteps);
                        totalSteps = stepraGetCF7RealTotalSteps($form, totalSteps);
                    }

                    if (adapter.id === 'contact-form-7') {
                        stepraNormalizeCF7Rows($form, totalSteps);
                        totalSteps = stepraGetCF7RealTotalSteps($form, totalSteps);
                    }

                    if (adapter.id === 'forminator') {
                        stepraNormalizeForminatorRows($form, totalSteps);
                        totalSteps = stepraGetForminatorRealTotalSteps($form, totalSteps);
                    }

                    if (adapter.id === 'forminator') {
                        stepraNormalizeForminatorRows($form, totalSteps);
                        totalSteps = stepraGetForminatorRealTotalSteps($form, totalSteps);
                    }

                    if (adapter.id === 'wpforms') {
                        stepraNormalizeWPFormsRows($form, totalSteps);
                        totalSteps = stepraGetWPFormsRealTotalSteps($form, totalSteps);
                    }

                    var currentStep = stepraGetCurrentStep($form, totalSteps);
                    var msgs = stepraGetValidationMessages();
                    var validation = stepraValidateCurrentStep($form, currentStep, msgs);

                    if (!validation.valid) {
                        stepraDispatchInternalEvent('validation-failed', $form, {
                            currentStep: currentStep,
                            totalSteps: totalSteps,
                            invalidField: validation.$invalid && validation.$invalid.length ? validation.$invalid[0] : null
                        });
                        stepraFocusInvalidField(validation.$invalid);
                        return;
                    }

                    stepraDispatchInternalEvent('validation-passed', $form, {
                        currentStep: currentStep,
                        totalSteps: totalSteps
                    });

                    if (currentStep < totalSteps) {
                        $form.attr('data-stepra-nav-direction', 'forward');
                        currentStep = stepraSetCurrentStep($form, currentStep + 1, totalSteps);
                        updateUI();
                        stepraScrollAndFocusStep($form, currentStep);
                    }
                });

                $form.on('click', '.stepra-prev', function(e) {
                    e.preventDefault();
                    if (adapter.id === 'wpforms') {
                        stepraNormalizeWPFormsRows($form, totalSteps);
                        totalSteps = stepraGetWPFormsRealTotalSteps($form, totalSteps);
                    }

                    var currentStep = stepraGetCurrentStep($form, totalSteps);
                    if (currentStep > 1) {
                        $form.attr('data-stepra-nav-direction', 'backward');
                        currentStep = stepraSetCurrentStep($form, currentStep - 1, totalSteps);
                        updateUI();
                        stepraScrollAndFocusStep($form, currentStep);
                    }
                });

                $form.off('click.stepraElementorSubmit').on('click.stepraElementorSubmit', 'button[type="submit"], input[type="submit"]', function(e) {
                    if (!$form.hasClass('elementor-form')) return;

                    var msgs = stepraGetValidationMessages();
                    var $invalid = stepraFindInvalidElementorField($form, msgs);

                    if (!$invalid.length) return;

                    var $invalidStep = $invalid.closest('.stepra-step-el');

                    if (!$invalidStep.length) return;

                    var targetStep = parseInt($invalidStep.attr('data-step'), 10) || 1;

                    e.preventDefault();
                    e.stopImmediatePropagation();

                    targetStep = stepraSetCurrentStep($form, targetStep, totalSteps);

                    updateUI();

                    setTimeout(function() {
                        if ($invalid.is(':visible')) {
                            try {
                                $invalid.trigger('focus');
                            } catch(e) {}
                        }

                        if ($invalid.is('select') && $invalid.siblings('.select2-container').length > 0) {
                            $invalid.siblings('.select2-container').find('.select2-selection')
                                .css('border', '2px solid #d63638').addClass('stepra-error-border');
                        } else if ($invalid.is(':radio') || $invalid.is(':checkbox')) {
                            $invalid.closest('.form-row, .wpforms-field, .forminator-field, .elementor-field-group, .elementor-field, .wpcf7-form-control-wrap')
                                .css('border', '2px solid #d63638').addClass('stepra-error-border');
                        } else {
                            $invalid.css('border', '2px solid #d63638').addClass('stepra-error-border');
                        }

                        stepraShowFieldError($invalid, $invalid[0].validationMessage || msgs.req);

                        stepraScrollToFormTop($form);
                    }, 80);

                    return false;
                });


                $form.data('stepra-events-bound', true);
            }

            updateUI();
            stepraSetState($form, 'ready');
        });

        var pendingInitialForms = stepraGetPendingOrInvalidFormCount();

        if (pendingInitialForms === 0 || document.readyState !== 'loading') {
            stepraMarkLoaded();
        }
    }

    // ==========================================
    // 9. BACKGROUND LOADERS & PERFORMANCE
    // ==========================================

    var debounceTimer;
    var $pendingInitScope = $();
    var pendingFullInit = false;

    function debouncedInit(scope) {
        if (scope) {
            $pendingInitScope = $pendingInitScope.add(scope);
        } else {
            pendingFullInit = true;
            $pendingInitScope = $();
        }

        clearTimeout(debounceTimer);
        debounceTimer = setTimeout(function() {
            var scopeToInit = pendingFullInit ? null : $pendingInitScope;

            pendingFullInit = false;
            $pendingInitScope = $();

            initWrapper(scopeToInit);
        }, STEPRA_OBSERVER_DEBOUNCE_MS);
    }

    var domObserver = new MutationObserver(function(mutations) {
        var addedScopes = [];

        mutations.forEach(function(mutation) {
            if (!mutation.addedNodes || !mutation.addedNodes.length) return;

            Array.prototype.forEach.call(mutation.addedNodes, function(node) {
                if (stepraNodeHasSupportedForm(node)) {
                    addedScopes.push(node);
                }
            });
        });

        if (addedScopes.length) {
            debouncedInit($(addedScopes));
        }
    });
    domObserver.observe(document.documentElement, { childList: true, subtree: true });

    $(window).on('elementor/frontend/init', function() {
        if (typeof elementorFrontend !== 'undefined' && elementorFrontend.hooks) {
            elementorFrontend.hooks.addAction('frontend/element_ready/form.default', function() {
                debouncedInit();
            });
        }
    });

    $(document).on('wpformsReady wpformsAjaxSubmitSuccess after.load.forminator', function() {
        debouncedInit();
    });

    // Run immediately, then in short early passes. This reduces the time
    // supported forms spend in preload on both fast and slow devices.
    initWrapper();
    setTimeout(initWrapper, 0);
    setTimeout(initWrapper, 25);
    setTimeout(initWrapper, 75);
    setTimeout(initWrapper, 150);
    setTimeout(initWrapper, 300);
    setTimeout(initWrapper, 600);
    setTimeout(initWrapper, 1000);

    var initAttempts = 0;
    var initInterval = setInterval(function() {
        initWrapper();
        initAttempts++;

        var pendingForms = stepraGetPendingOrInvalidFormCount();

        if (pendingForms === 0 || initAttempts >= STEPRA_MAX_INIT_ATTEMPTS) {
            stepraDebugLog('Init retry stopped', {
                reason: pendingForms === 0 ? 'all-supported-forms-ready' : 'max-init-attempts-reached',
                attempts: initAttempts,
                pendingForms: pendingForms
            });

            clearInterval(initInterval);
            stepraMarkLoaded(initAttempts >= STEPRA_MAX_INIT_ATTEMPTS);
        }
    }, STEPRA_RETRY_INTERVAL_MS);

    // ==========================================
    // 10. AJAX ERROR AUTO-SNAPBACK
    // ==========================================

    document.addEventListener('wpcf7invalid', function(event) {
        var $form = $(event.target);
        setTimeout(function() {
            var $errorEl = $form.find('.wpcf7-not-valid').first();
            if ($errorEl.length === 0) $errorEl = $form.find('.wpcf7-not-valid-tip').first();
            if ($errorEl.length > 0) {
                var $step = $errorEl.closest('.stepra-step-el');
                if ($step.length > 0) {
                    var targetStep = parseInt($step.attr('data-step'), 10) || 1;
                    var previousStep = parseInt($form.attr('data-current-step'), 10) || null;

                    $form.attr('data-current-step', targetStep);
                    stepraDispatchInternalEvent('builder-validation-error', $form, {
                        builderEvent: 'wpcf7invalid',
                        previousStep: previousStep,
                        currentStep: targetStep
                    });
                    $form.trigger('stepra_update_ui', [{ scroll: true }]);
                }
            }
        }, 150);
    }, false);

    // ==========================================
    // 11. STRICT NUMERIC / PHONE ENFORCEMENT
    // ==========================================

    $(document).on('input', 'input[type="tel"], input[type="number"], input[name*="phone"], input[name*="tel"], input[name*="number"]', function() {
        var $el      = $(this);
        var type     = $el.attr('type');
        var val      = $el.val();
        var nameAttr = $el.attr('name') ? $el.attr('name').toLowerCase() : '';

        if (type === 'number' || nameAttr.indexOf('number') !== -1) {
            $el.val(val.replace(/[^\d\.\-]/g, ''));
        } else {
            $el.val(val.replace(/[^\d\+\-\s\(\)]/g, ''));
        }
    });

})(jQuery);