/******/ (() => { // webpackBootstrap
/******/ 	var __webpack_modules__ = ({

/***/ "./assets/js/ach-handler.js"
/*!**********************************!*\
  !*** ./assets/js/ach-handler.js ***!
  \**********************************/
() {

/**
 * FunnelKit Square - ACH Bank Transfer Handler
 *
 * Handles ACH bank transfer payments using Square's Web SDK.
 * ACH uses Plaid for bank account verification.
 *
 * Flow: User clicks Place Order -> Plaid modal opens -> On success, order processes
 *
 * @package FunnelKit_Square
 */

/* global Square, fkwcsq_ach_params */

(function($) {
    'use strict';

    let payments = null;
    let ach = null;
    let isProcessing = false;
    let isInitialized = false;
    let paymentRequestData = null;

    /**
     * Get the current cart total from payment request data
     *
     * @returns {string} Cart total amount
     */
    function getCartTotal() {
        if (paymentRequestData && paymentRequestData.total && paymentRequestData.total.amount) {
            return paymentRequestData.total.amount;
        }

        if (fkwcsq_ach_params.payment_request && fkwcsq_ach_params.payment_request.total) {
            return fkwcsq_ach_params.payment_request.total.amount;
        }

        return '0.00';
    }

    /**
     * Initialize ACH payment method
     */
    async function initializeACH() {
        const container = document.getElementById('fkwcsq-ach-container');

        if (!container) {
            return;
        }

        if (isInitialized && ach) {
            return;
        }

        if (typeof Square === 'undefined') {
            showError(fkwcsq_ach_params.i18n.error_generic);
            return;
        }

        try {
            if (!payments) {
                payments = await Square.payments(
                    fkwcsq_ach_params.application_id,
                    fkwcsq_ach_params.location_id
                );
            }

            ach = await payments.ach({
                redirectURI: fkwcsq_ach_params.redirect_url,
                transactionId: fkwcsq_ach_params.transaction_id
            });

            isInitialized = true;
            hideError();
            ach.addEventListener('ontokenization', handleTokenization);

        } catch (error) {
            if (error.message && error.message.includes('not supported')) {
                showError(fkwcsq_ach_params.i18n.not_supported);
            } else {
                showError(fkwcsq_ach_params.i18n.error_generic);
            }
        }
    }

    /**
     * Start ACH tokenization process (opens Plaid modal)
     *
     * @returns {Promise<boolean>} Whether tokenization was initiated
     */
    async function startACHTokenization() {
        if (isProcessing || !ach) {
            return false;
        }

        const accountHolderName = $('#fkwcsq_ach_account_holder').val().trim();

        if (!accountHolderName) {
            showError(fkwcsq_ach_params.i18n.account_holder + ' is required');
            $('#fkwcsq_ach_account_holder').focus();
            return false;
        }

        isProcessing = true;
        hideError();

        try {
            const result = await ach.tokenize({
                accountHolderName,
                intent: 'CHARGE',
                amount: getCartTotal(),
                currency: fkwcsq_ach_params.currency
            });

            if (!result) {
                return true;
            }

            if (result.status === 'OK') {
                $('#fkwcsq_ach_nonce').val(result.token);

                if (result.details && result.details.ach) {
                    const details = result.details.ach;
                    const accountInfo = details.bankName + ' ****' + details.accountNumberSuffix;
                    $('#fkwcsq_ach_account_details').val(accountInfo);
                    showSuccess('Bank account connected: ' + accountInfo);
                }

                isProcessing = false;

                setTimeout(function() {
                    $('form.checkout #place_order').trigger('click');
                }, 100);

                return true;

            } else if (result.status === 'Cancel') {
                isProcessing = false;
                return false;
            } else {
                const errorMessage = result.errors && result.errors[0]
                    ? result.errors[0].message
                    : fkwcsq_ach_params.i18n.error_generic;
                showError(errorMessage);
                isProcessing = false;
                return false;
            }

        } catch (error) {
            showError(error.message || fkwcsq_ach_params.i18n.error_generic);
            isProcessing = false;
            return false;
        }
    }

    /**
     * Handle tokenization event from Plaid
     *
     * @param {Object} event Tokenization event
     */
    function handleTokenization(event) {
        const { tokenResult, error } = event.detail;

        isProcessing = false;

        if (error) {
            showError(error.message || fkwcsq_ach_params.i18n.error_generic);
            return;
        }

        if (tokenResult && tokenResult.status === 'OK') {
            $('#fkwcsq_ach_nonce').val(tokenResult.token);

            if (tokenResult.details && tokenResult.details.ach) {
                const details = tokenResult.details.ach;
                const accountInfo = details.bankName + ' ****' + details.accountNumberSuffix;
                $('#fkwcsq_ach_account_details').val(accountInfo);
                showSuccess('Bank account connected: ' + accountInfo);
            }

            setTimeout(function() {
                $('form.checkout #place_order').trigger('click');
            }, 100);

        } else if (tokenResult && tokenResult.status !== 'Cancel') {
            const errorMessage = tokenResult?.errors?.[0]?.message || fkwcsq_ach_params.i18n.error_generic;
            showError(errorMessage);
        }
    }

    /**
     * Handle form submission - intercept to open Plaid modal
     *
     * @returns {boolean} Whether to proceed with form submission
     */
    function handleFormSubmit() {
        const selectedPayment = $('input[name="payment_method"]:checked').val();

        if (selectedPayment !== 'fkwcsq_ach') {
            return true;
        }

        const nonce = $('#fkwcsq_ach_nonce').val();
        if (nonce) {
            return true;
        }

        startACHTokenization();
        return false;
    }

    /**
     * Show error message
     *
     * @param {string} message Error message
     */
    function showError(message) {
        $('#fkwcsq-ach-error')
            .text(message)
            .css('display', 'block')
            .css('color', '#dc3545');
    }

    /**
     * Show success message
     *
     * @param {string} message Success message
     */
    function showSuccess(message) {
        $('#fkwcsq-ach-error')
            .text(message)
            .css('display', 'block')
            .css('color', '#28a745');
    }

    /**
     * Hide error message
     */
    function hideError() {
        $('#fkwcsq-ach-error').hide();
    }

    /**
     * Destroy ACH instance
     */
    async function destroyACH() {
        if (ach) {
            try {
                await ach.destroy();
            } catch (e) {
                // Silently handle
            }
            ach = null;
            isInitialized = false;
        }
    }

    /**
     * Handle payment method change
     */
    async function handlePaymentMethodChange() {
        const selectedPayment = $('input[name="payment_method"]:checked').val();

        if (selectedPayment === 'fkwcsq_ach') {
            if (ach) {
                await destroyACH();
            }
            initializeACH();
        }
    }

    /**
     * Initialize when document is ready
     */
    $(document).ready(function() {
        if (typeof fkwcsq_ach_params === 'undefined') {
            return;
        }

        const selectedPayment = $('input[name="payment_method"]:checked').val();
        if (selectedPayment === 'fkwcsq_ach') {
            initializeACH();
        }

        $(document.body).on('change', 'input[name="payment_method"]', handlePaymentMethodChange);
        $('form.checkout').on('checkout_place_order_fkwcsq_ach', handleFormSubmit);

        // Handle FunnelKit checkout initialization
        $(document.body).on('init_checkout', async function() {
            const selectedPayment = $('input[name="payment_method"]:checked').val();
            if (selectedPayment === 'fkwcsq_ach') {
                initializeACH();
            }
        });

        $(document.body).on('updated_checkout', async function(_e, data) {
            if (data && data.fragments && data.fragments.fkwcsq_payment_request) {
                paymentRequestData = data.fragments.fkwcsq_payment_request;
            }

            const selectedPayment = $('input[name="payment_method"]:checked').val();
            if (selectedPayment === 'fkwcsq_ach') {
                await destroyACH();
                initializeACH();
            }
        });
    });

    $(window).on('unload', destroyACH);

})(jQuery);


/***/ },

/***/ "./assets/js/afterpay-handler.js"
/*!***************************************!*\
  !*** ./assets/js/afterpay-handler.js ***!
  \***************************************/
() {

/* global Square, fkwcsq_afterpay_params */

/**
 * FunnelKit Square Afterpay/Clearpay Handler
 *
 * Handles Square Afterpay/Clearpay initialization and tokenization.
 * Uses CSS body class approach for button visibility toggle.
 *
 * @package FunnelKit_Square
 */

(function ($) {
    'use strict';

    // State management
    let afterpay = null;
    let payments = null;
    let isProcessing = false;
    let isInitialized = false;
    let isInitializing = false;
    let paymentRequestData = null;

    /**
     * Toggle button visibility based on payment method selection.
     * Uses CSS body class for reliable visibility control.
     */
    function toggleButtons() {
        const selectedPayment = $('input[name="payment_method"]:checked').val();

        if (selectedPayment === 'fkwcsq_afterpay') {
            $('body').addClass('fkwcsq-afterpay-selected');
        } else {
            $('body').removeClass('fkwcsq-afterpay-selected');
        }
    }

    /**
     * Get the current cart total from payment request data
     *
     * @returns {string} Cart total amount
     */
    function getCartTotal() {
        // Use payment request data from checkout fragments (preferred)
        if (paymentRequestData && paymentRequestData.total && paymentRequestData.total.amount) {
            return paymentRequestData.total.amount;
        }

        // Fallback to localized params if available
        if (fkwcsq_afterpay_params.payment_request && fkwcsq_afterpay_params.payment_request.total) {
            return fkwcsq_afterpay_params.payment_request.total.amount;
        }

        return '0.00';
    }

    /**
     * Build payment request for Afterpay
     *
     * @param {Object} paymentsInstance Square payments instance
     * @returns {Object} Payment request
     */
    function buildPaymentRequest(paymentsInstance) {
        const total = getCartTotal();

        const paymentRequest = paymentsInstance.paymentRequest({
            countryCode: fkwcsq_afterpay_params.country_code,
            currencyCode: fkwcsq_afterpay_params.currency_code,
            total: {
                amount: total,
                label: 'Total'
            },
            requestShippingContact: true
        });

        // Add Afterpay-specific event listeners (required for proper initialization)
        paymentRequest.addEventListener('afterpay_shippingaddresschanged', function () {
            return {
                shippingOptions: [{
                    amount: '0.00',
                    id: 'shipping-option-1',
                    label: 'Shipping',
                    taxLineItems: [],
                    total: {
                        amount: total,
                        label: 'Total'
                    }
                }]
            };
        });

        paymentRequest.addEventListener('afterpay_shippingoptionchanged', function () {
            // Event listener for shipping option changes (informational only)
        });

        return paymentRequest;
    }

    /**
     * Initialize Afterpay payment method
     */
    async function initializeAfterpay() {
        const buttonWrapper = document.getElementById('fkwcsq-afterpay-button-wrapper');
        const buttonContainer = document.getElementById('fkwcsq-afterpay-button-container');

        // Check if containers exist
        if (!buttonWrapper || !buttonContainer) {
            return;
        }

        // Prevent concurrent initializations
        if (isInitializing) {
            return;
        }

        // Clear any previous errors
        hideError();

        // Check if already initialized
        if (isInitialized && afterpay) {
            return;
        }

        isInitializing = true;

        // Check if Square SDK is loaded
        if (typeof Square === 'undefined') {
            console.error('Square SDK not loaded');
            showError(fkwcsq_afterpay_params.i18n.error_generic);
            return;
        }

        // Check amount limits
        const total = parseFloat(getCartTotal());
        if (total < fkwcsq_afterpay_params.min_amount) {
            showError(fkwcsq_afterpay_params.i18n.amount_too_low);
            return;
        }
        if (total > fkwcsq_afterpay_params.max_amount) {
            showError(fkwcsq_afterpay_params.i18n.amount_too_high);
            return;
        }

        try {
            // Initialize Square payments
            if (!payments) {
                payments = await Square.payments(
                    fkwcsq_afterpay_params.application_id,
                    fkwcsq_afterpay_params.location_id
                );
            }

            // Build payment request
            const paymentRequest = buildPaymentRequest(payments);

            // Create Afterpay instance
            afterpay = await payments.afterpayClearpay(paymentRequest);

            // Attach button to the wrapper container
            await afterpay.attach('#fkwcsq-afterpay-button-container', {
                buttonColor: getButtonColor(),
                buttonType: getButtonType()
            });

            // Attach messaging if enabled (wrap in separate try-catch to not break button)
            if (fkwcsq_afterpay_params.show_messaging) {
                const messagingContainer = document.getElementById('fkwcsq-afterpay-messaging-container');
                if (messagingContainer) {
                    try {
                        await afterpay.attachMessaging('#fkwcsq-afterpay-messaging-container', {
                            amount: getCartTotal(),
                            currency: fkwcsq_afterpay_params.currency_code
                        });
                    } catch (messagingError) {
                        // Messaging may not be available in sandbox or for certain accounts
                        console.warn('Afterpay messaging not available:', messagingError.message);
                    }
                }
            }

            // Mark as initialized
            isInitialized = true;
            isInitializing = false;
            hideError();

        } catch (error) {


            if (error.name === 'AfterpayMerchantError') {
                showError(fkwcsq_afterpay_params.i18n.not_supported);
            } else if (error.name === 'AfterpayAmountOutsideLimitsError') {
                const total = parseFloat(getCartTotal());
                if (total < fkwcsq_afterpay_params.min_amount) {
                    showError(fkwcsq_afterpay_params.i18n.amount_too_low);
                } else {
                    showError(fkwcsq_afterpay_params.i18n.amount_too_high);
                }
            } else if (error.name === 'UnexpectedError') {
                // UnexpectedError usually means Afterpay is not available at this location
                // or the Square account is not properly configured for Afterpay
                console.error('Afterpay UnexpectedError - This usually indicates Afterpay is not enabled for this Square location');
                showError('Afterpay is not available. Please ensure your Square account has Afterpay enabled.');
            } else {
                showError(fkwcsq_afterpay_params.i18n.error_generic);
            }

            isInitializing = false;
        }
    }

    /**
     * Get button color based on theme setting
     *
     * @returns {string} Button color
     */
    function getButtonColor() {
        const themeMap = {
            black_on_mint: 'black',
            white_on_black: 'white',
            black_on_white: 'black',
            mint_on_black: 'mint'
        };
        return themeMap[fkwcsq_afterpay_params.button_theme] || 'black';
    }

    /**
     * Get button type based on setting
     *
     * @returns {string} Button type
     */
    function getButtonType() {
        return fkwcsq_afterpay_params.button_type || 'buy_now_with_afterpay';
    }

    /**
     * Handle Afterpay button click - triggers tokenization
     *
     * @param {Event} e Click event
     */
    async function handleAfterpayButtonClick(e) {
        e.preventDefault();
        e.stopPropagation();

        if (isProcessing || !afterpay) {
            return;
        }

        // Check if we already have a nonce
        if ($('#fkwcsq_afterpay_nonce').val()) {
            // Already have token, trigger place order
            $('body').removeClass('fkwcsq-afterpay-selected');
            $('form.checkout #place_order').trigger('click');
            return;
        }

        isProcessing = true;
        hideError();

        try {
            // Tokenize - payment request was set during initialization
            const result = await afterpay.tokenize();

            if (result.status === 'OK') {
                // Store the token
                $('#fkwcsq_afterpay_nonce').val(result.token);
                isProcessing = false;

                // Remove body class to show Place Order button
                $('body').removeClass('fkwcsq-afterpay-selected');

                // Trigger Place Order button click to run WooCommerce checkout AJAX
                $('form.checkout #place_order').trigger('click');
            } else if (result.status === 'Cancel') {
                // User cancelled - don't show error
                isProcessing = false;
            } else {
                // Error occurred
                const errorMessage = result.errors && result.errors[0]
                    ? result.errors[0].message
                    : fkwcsq_afterpay_params.i18n.error_generic;
                showError(errorMessage);
                isProcessing = false;
            }

        } catch (error) {
            console.error('Afterpay payment error:', error);
            showError(error.message || fkwcsq_afterpay_params.i18n.error_generic);
            isProcessing = false;
        }
    }

    /**
     * Handle form submission - validate Afterpay payment was completed
     *
     * When Afterpay is selected, user must click the Afterpay button to complete payment.
     * After successful tokenization, this handler allows form submission.
     *
     * @returns {boolean} Whether to proceed with submission
     */
    function handleFormSubmit() {
        // If we already have a nonce, proceed with form submission
        if ($('#fkwcsq_afterpay_nonce').val()) {
            return true;
        }

        // User must click Afterpay button to complete payment
        const brand = fkwcsq_afterpay_params.is_clearpay ? 'Clearpay' : 'Afterpay';
        showError('Please click the ' + brand + ' button to complete your payment.');
        return false;
    }

    /**
     * Show error message
     *
     * @param {string} message Error message
     */
    function showError(message) {
        $('#fkwcsq-afterpay-error')
            .text(message)
            .show();
    }

    /**
     * Hide error message
     */
    function hideError() {
        $('#fkwcsq-afterpay-error').hide();
    }

    /**
     * Destroy Afterpay instance and clear containers
     */
    async function destroyAfterpay() {
        if (afterpay) {
            try {
                await afterpay.destroy();
            } catch (error) {
                // Silently handle - instance may already be destroyed
            }
            afterpay = null;
        }

        // Always reset state
        isInitialized = false;
        isInitializing = false;

        // Clear containers to prevent duplicates on reinit
        $('#fkwcsq-afterpay-messaging-container').empty();
        $('#fkwcsq-afterpay-button-container').empty();

        // Remove any stray afterpay-placement elements (SDK adds them as siblings, not children)
        $('#fkwcsq-afterpay-container afterpay-placement').remove();
        $('#fkwcsq-afterpay-button-wrapper afterpay-placement').remove();
    }

    /**
     * Handle payment method change
     */
    async function handlePaymentMethodChange() {
        // Toggle button visibility based on selection
        toggleButtons();

        const selectedPayment = $('input[name="payment_method"]:checked').val();

        if (selectedPayment === 'fkwcsq_afterpay') {
            // Always destroy and clear before reinitializing (handles null case internally)
            await destroyAfterpay();
            initializeAfterpay();
        } else if (afterpay) {
            // Destroy when switching away from Afterpay to clean up
            await destroyAfterpay();
        }
    }

    /**
     * Initialize when document is ready
     */
    $(document).ready(function () {
        // Check if Afterpay params are available
        if (typeof fkwcsq_afterpay_params === 'undefined') {
            return;
        }

        // Initial button visibility toggle
        toggleButtons();

        // Initialize if Afterpay is the selected payment method
        const selectedPayment = $('input[name="payment_method"]:checked').val();
        if (selectedPayment === 'fkwcsq_afterpay') {
            initializeAfterpay();
        }

        // Handle payment method change
        $(document.body).on('change', 'input[name="payment_method"]', handlePaymentMethodChange);

        // Validate before form submission
        $('form.checkout').on('checkout_place_order_fkwcsq_afterpay', handleFormSubmit);

        // Handle Afterpay button click - triggers tokenization
        $(document.body).on('click', '#fkwcsq-afterpay-button-container', handleAfterpayButtonClick);

        // Handle FunnelKit checkout initialization
        $(document.body).on('init_checkout', async function () {
            // Toggle button visibility after checkout init
            toggleButtons();

            const selectedPayment = $('input[name="payment_method"]:checked').val();
            if (selectedPayment === 'fkwcsq_afterpay') {
                initializeAfterpay();
            }
        });
        // Reinitialize on checkout update
        $(document.body).on('updated_checkout', async function (_e, data) {
            // Capture payment request data from fragments
            if (data && data.fragments && data.fragments.fkwcsq_payment_request) {
                paymentRequestData = data.fragments.fkwcsq_payment_request;
            }

            // Toggle button visibility after checkout update
            toggleButtons();

            const selectedPayment = $('input[name="payment_method"]:checked').val();
            if (selectedPayment === 'fkwcsq_afterpay') {
                // Properly destroy previous instance before reinitializing
                await destroyAfterpay();
                initializeAfterpay();
            }
        });
    });

    // Cleanup on page unload
    $(window).on('unload', destroyAfterpay);

})(jQuery);


/***/ },

/***/ "./assets/js/card-payment-form.js"
/*!****************************************!*\
  !*** ./assets/js/card-payment-form.js ***!
  \****************************************/
() {

/* global Square, fkwcsq_card_payment_params */

(function ($) {
    'use strict';

    // Keep track of card instance
    let card = null;
    let payments = null;
    let isInitialized = false;
    let isProcessing = false;
    let initializationInProgress = false; // New flag to prevent race conditions
    let previousBillingCountry = '';
    let isPaymentMethodChanging = false;
    let updateCheckoutInProgress = false; // Flag to track if update_checkout is running

    // Cleanup function to destroy existing card instance
    async function destroyCard() {
        if (card) {
            try {
                await card.destroy();
                card = null;
                isInitialized = false;
            } catch (error) {
                // Silently handle destroy errors
            }
        }
    }

    // Add this function to verify the payment form container
    function verifyPaymentFormContainer() {
        const container = $('#square-card-container');
        if (!container.length) {
            return false;
        }

        if (container.is(':visible')) {
            return true;
        }

        return false;
    }

    // Check if card is already functional to prevent unnecessary reinitializations
    function isCardFunctional() {
        // Check if card is initialized and has an iframe
        const hasIframe = $('#square-card-container iframe').length > 0;
        const isVisible = $('#square-card-container').is(':visible');

        // If container is empty but card is initialized, we need to reinitialize
        if (isInitialized && card && !hasIframe && isVisible) {
            return false;
        }

        return isInitialized && card && hasIframe && isVisible;
    }

    // Check if container is empty (needs initialization)
    function isContainerEmpty() {
        const container = $('#square-card-container');
        return container.length > 0 && container.is(':visible') && container.children().length === 0;
    }

    // Initialize Square payment form
    async function initializeSquarePayment() {

        if (!verifyPaymentFormContainer()) {
            return;
        }
        const selector = '.fkwcsq-square-payment-form .sq-card-iframe-container iframe';
        if ($(selector).length > 0) {
            isInitialized = true;
            return;
        }

        // Check if already initialized or initialization in progress
        if (isInitialized && !isContainerEmpty()) {
            return;
        }

        if (initializationInProgress) {
            return;
        }

        // Check if we're on order pay page
        const isOrderPayPage = $('body').hasClass('woocommerce-order-pay');

        // Shimmer is already loaded by PHP, no need to show it

        // Set flag to prevent concurrent initialization
        initializationInProgress = true;

        try {

            // Initialize Square payments
            payments = await Square.payments(fkwcsq_card_payment_params.application_id, fkwcsq_card_payment_params.location_id);
            card = await payments.card();

            const cardContainer = document.getElementById('square-card-container');
            if (!cardContainer) {
                initializationInProgress = false;
                return;
            }

            // Clear container and attach card (this will replace shimmer)
            $('#square-card-container').empty();
            await card.attach('#square-card-container');

            // Remove shimmer class immediately after attach (card.attach() replaces the content)
            $('#square-card-container').removeClass('square-shimmer-container').addClass('square-card-loaded');

            // For order pay page, use more aggressive shimmer removal
            if (isOrderPayPage) {
                // Immediately remove shimmer elements if they still exist
                $('#square-card-container .square-shimmer-line').remove();

                // Force remove shimmer class multiple times to ensure it's gone
                const removeShimmer = () => {
                    const container = $('#square-card-container');
                    container.removeClass('square-shimmer-container').addClass('square-card-loaded');
                    container.find('.square-shimmer-line').remove();
                };

                // Remove shimmer immediately and on multiple intervals
                removeShimmer();
                setTimeout(removeShimmer, 50);
                setTimeout(removeShimmer, 150);
                setTimeout(removeShimmer, 300);
            }

            // Add event listener to detect when card is fully loaded
            card.addEventListener('focusClassRemoved', (event) => {
                const { currentState } = event.detail;
                if (currentState.isCompletelyValid) {
                    // Ensure shimmer is removed and loaded class is added
                    $('#square-card-container').removeClass('square-shimmer-container').addClass('square-card-loaded');
                    $('#square-card-container .square-shimmer-line').remove();
                }
            });

            // Also listen for the card to be ready (alternative approach)
            card.addEventListener('cardBrandChanged', () => {
                // Ensure shimmer is removed and loaded class is added
                $('#square-card-container').removeClass('square-shimmer-container').addClass('square-card-loaded');
                $('#square-card-container .square-shimmer-line').remove();
            });

            // Fallback: Check for iframe presence after a short delay and ensure shimmer is removed
            setTimeout(() => {
                const container = $('#square-card-container');
                const iframe = container.find('iframe');
                if (iframe.length > 0 && iframe.is(':visible')) {
                    // Remove shimmer class and add loaded class
                    container.removeClass('square-shimmer-container').addClass('square-card-loaded');
                    container.find('.square-shimmer-line').remove();
                } else if (container.hasClass('square-shimmer-container')) {
                    // If iframe is not present but shimmer is still showing, something went wrong
                    // Remove shimmer class anyway to prevent indefinite display
                    container.removeClass('square-shimmer-container');
                    container.find('.square-shimmer-line').remove();
                }
            }, 100);

            // Safety timeout: Remove shimmer after 3 seconds regardless of state to prevent indefinite display
            setTimeout(() => {
                const container = $('#square-card-container');
                if (container.hasClass('square-shimmer-container')) {
                    container.removeClass('square-shimmer-container');
                    container.find('.square-shimmer-line').remove();
                    // Only add loaded class if iframe is present
                    if (container.find('iframe').length > 0) {
                        container.addClass('square-card-loaded');
                    }
                }
            }, 3000);

            isInitialized = true;

            // Shimmer is automatically replaced by card.attach(), so no need to hide it manually

        } catch (error) {
            console.error('Failed to initialize Square payment form:', error);
            $('#square-card-error')
                .text(`Failed to initialize Square payment form: ${error.message}`)
                .show();
        } finally {
            initializationInProgress = false;
        }
    }

    // Get billing contact details from form fields
    function getBillingContactDetails() {
        const billingContact = {};

        // Get billing details from form fields
        const firstName = $('#billing_first_name').val() || '';
        const lastName = $('#billing_last_name').val() || '';
        const email = $('#billing_email').val() || '';
        const country = $('#billing_country').val() || '';
        const city = $('#billing_city').val() || '';
        const address1 = $('#billing_address_1').val() || '';
        const address2 = $('#billing_address_2').val() || '';
        const state = $('#billing_state').val() || '';
        const postcode = $('#billing_postcode').val() || '';

        // Only add fields that have values
        if (firstName) billingContact.givenName = firstName;
        if (lastName) billingContact.familyName = lastName;
        if (email) billingContact.email = email;
        if (country) billingContact.countryCode = country.toUpperCase();
        if (city) billingContact.city = city;
        if (address1) billingContact.addressLines = [address1];
        if (address2 && billingContact.addressLines) {
            billingContact.addressLines.push(address2);
        }
        if (state) billingContact.region = state;
        if (postcode) billingContact.postalCode = postcode;

        return billingContact;
    }

    // Build buyer verification details for tokenization
    function buildBuyerVerificationDetails() {
        // Format amount as integer (cents)
        const amount = Math.round(parseFloat(fkwcsq_card_payment_params.amount) * 100);

        // Determine intent based on save card checkbox
        const intent = 'CHARGE_AND_STORE';

        // Get billing contact details from form
        const billingContact = getBillingContactDetails();

        // Build verification details object
        const verificationDetails = {
            amount: amount.toString(),
            currencyCode: fkwcsq_card_payment_params.currency.toUpperCase(),
            intent,
            customerInitiated: true,
            sellerKeyedIn: false,
            billingContact
        };

        return verificationDetails;
    }

    // Enhanced tokenization with buyer verification
    async function tokenizeWithBuyerVerification() {
        try {
            const verificationDetails = buildBuyerVerificationDetails();

            // Tokenize with buyer verification details included
            const result = await card.tokenize(verificationDetails);

            if (result.status === 'OK') {
                return {
                    token: result.token,
                    verifiedBuyer: result.verifiedBuyer || null
                };
            } else {
                // Handle specific error cases
                const errorMessage = result.errors[0].message;
                if (errorMessage.includes('card') || errorMessage.includes('invalid') || errorMessage.includes('required')) {
                    throw new Error('Please fill in all required card details.');
                }
                throw new Error(errorMessage);
            }
        } catch (error) {
            const errorMessage = error.message || '';
            const isCardValidationError = errorMessage.includes('card') || errorMessage.includes('invalid') || errorMessage.includes('required') || errorMessage.includes('Please fill in all required card details.');

            if (isCardValidationError) {
                // If it's a known card validation error, throw a user-friendly message without logging to console
                throw new Error('Please fill in all required card details.');
            } else {
                // For other errors, log to console and re-throw
                console.error('Tokenization with buyer verification failed:', error);
                throw error;
            }
        }
    }

    // Add this function to help with debugging
    function logPaymentError(_error, _context) {
        // Error logging function - can be used for debugging if needed
    }

    // Handle the checkout button click
    async function handleCheckoutButtonClick(event) {
        // Only process if Square is selected
        if (!$('#payment_method_fkwcsq_square').is(':checked')) {
            return true;
        }

        // Prevent default form submission
        event.preventDefault();

        if (isProcessing) {
            return false;
        }

        // Clear any previous error messages when user tries to submit again
        $('#square-card-error').hide();

        isProcessing = true;

        // Get the correct form based on page type
        const isOrderPayPage = $('body').hasClass('woocommerce-order-pay');
        const $form = isOrderPayPage ? $('form#order_review') : $('form.checkout');

        // Block the form UI
        $form.block({
            message: null,
            overlayCSS: {
                background: '#fff',
                opacity: 0.6
            }
        });

        try {
            // Clear any previous tokens and errors
            $('#square-card-error').hide();
            $('input[name="fkwcsq_square_nonce"]').remove();
            $('input[name="fkwcsq_verification_token"]').remove();

            // Ensure card is initialized
            if (!isInitialized) {
                logPaymentError('Card not initialized', 'handleCheckoutButtonClick');
                await initializeSquarePayment();
            }

            // Use enhanced tokenization with buyer verification
            const tokenizationResult = await tokenizeWithBuyerVerification();

            // Add payment nonce to form
            const nonceInput = $('<input>').attr({
                type: 'hidden',
                name: 'fkwcsq_square_nonce',
                value: tokenizationResult.token
            });

            // Add verified buyer token if available
            if (tokenizationResult.verifiedBuyer) {
                const verificationInput = $('<input>').attr({
                    type: 'hidden',
                    name: 'fkwcsq_verification_token',
                    value: tokenizationResult.verifiedBuyer
                });
                $form.append(verificationInput);
            }

            // Add save card flag if checkbox is checked
            if ($('#fkwcsq_square_save_card').is(':checked')) {
                const saveCardInput = $('<input>').attr({
                    type: 'hidden',
                    name: 'fkwcsq_square_save_card',
                    value: 'true'
                });
                $form.append(saveCardInput);
            }

            $form.append(nonceInput);

            // Verify nonce was added
            const addedNonce = $('input[name="fkwcsq_square_nonce"]').val();

            if (!addedNonce) {
                isProcessing = false;
                $form.unblock();
                $('#square-card-error').html('Payment Error: Failed to add payment information.').show();
                return false;
            }

            // Reset processing flag
            isProcessing = false;

            // Unblock the form
            $form.unblock();

            // Submit the form
            if (isOrderPayPage) {
                // For order pay page, use the specific submit button
                $('#place_order').trigger('click');
            } else {
                // For checkout page, submit the form
                $form.submit();
            }
            return true;
        } catch (error) {
            isProcessing = false;
            // Unblock the form on error
            $form.unblock();

            const errorMessage = error.message || '';
            const isCardValidationError = errorMessage.includes('Please fill in all required card details.');

            if (isCardValidationError) {
                // For card validation errors, just show the message without console logging
                $('#square-card-error')
                    .text(`Payment Error: ${error.message}`)
                    .show();
            } else {
                // For other errors, log to console and show error
                logPaymentError(error, 'handleCheckoutButtonClick');
                console.error('Payment error:', error);
                $('#square-card-error')
                    .text(`Payment Error: ${error.message}`)
                    .show();
            }
            return false;
        }
    }
    // Function to check if Square source exists
    function hasSquareSource() {
        return $('input[name="fkwcsq_square_nonce"]').length > 0 ? $('input[name="fkwcsq_square_nonce"]').val() : '';
    }
    function getDynamicSavedToken() {
        return new Promise((resolve, reject) => {
            const $selectedInput = $('input[name="wc-fkwcsq_square-payment-token"]:checked');
            const tokenId = $selectedInput.val();

            if (!tokenId || tokenId === 'new') {
                reject(new Error('No saved card selected'));
                return;
            }

            // Get token from data-token attribute
            const token = $selectedInput.attr('data-token');

            if (!token) {
                reject(new Error('Token not found in input element'));
                return;
            }

            resolve(token);
        });
    }
    // Process form submission
    function processCheckoutSubmit(e) {
        if (!$('#payment_method_fkwcsq_square').is(':checked')) {
            return true;
        }

        const savedCardValue = $('input[name="wc-fkwcsq_square-payment-token"]:checked').val();

        // If a saved card is selected and it's not 'new'
        if (savedCardValue && savedCardValue !== 'new') {
            if ($('input[name="fkwcsq_verification_token"]').length > 0) {
                return true;
            }
            getDynamicSavedToken()
                .then(savedToken => {
                    processSavedCardPayment(e, savedToken);
                })
                .catch(error => {
                    $('#square-card-error')
                        .text(`Payment Error: ${error.message}`)
                        .show();
                });

            return false;
        }

        // Check for existing nonce
        const source = hasSquareSource();
        if ('' === source) {
            // Ensure card is initialized before proceeding
            if (!isInitialized) {
                initializeSquarePayment().then(() => {
                    handleCheckoutButtonClick(e);
                }).catch(_error => {
                    $('#square-card-error')
                        .html('Payment Error: Failed to initialize payment form. Please try again.')
                        .show();
                });
            } else {
                handleCheckoutButtonClick(e);
            }
            return false;
        }

        return true;
    }
    // Build verification details for saved card payment
    function buildSavedCardVerificationDetails() {
        // Format amount as integer (cents)
        const amount = Math.round(parseFloat(fkwcsq_card_payment_params.amount) * 100);

        // Get billing contact details from form
        const billingContact = getBillingContactDetails();

        // Build verification details object for saved cards
        const verificationDetails = {
            amount: amount.toString(),
            currencyCode: fkwcsq_card_payment_params.currency.toUpperCase(),
            intent: 'CHARGE',
            customerInitiated: true,
            sellerKeyedIn: false,
            billingContact
        };

        return verificationDetails;
    }

    async function processSavedCardPayment(event, savedToken) {
        if (isProcessing) {
            return false;
        }

        isProcessing = true;

        // Get the correct form based on page type
        const isOrderPayPage = $('body').hasClass('woocommerce-order-pay');
        const $form = isOrderPayPage ? $('form#order_review') : $('form.checkout');

        // Block the form UI
        $form.block({
            message: null,
            overlayCSS: {
                background: '#fff',
                opacity: 0.6
            }
        });

        try {
            // Clear any previous errors
            $('#square-card-error').hide();
            $('input[name="fkwcsq_verification_token"]').remove();

            // Ensure payments object is initialized
            if (!payments) {
                payments = await Square.payments(fkwcsq_card_payment_params.application_id, fkwcsq_card_payment_params.location_id);
            }

            // For saved cards, we need to verify using the token directly
            let verificationToken = '';
            try {
                const verificationDetails = buildSavedCardVerificationDetails();
                const verificationResults = await payments.verifyBuyer(savedToken, verificationDetails);

                if (!verificationResults || !verificationResults.token) {
                    throw new Error('Invalid verification results received');
                }

                verificationToken = verificationResults.token;

                // If verification is successful, add token to form
                if (verificationToken) {
                    const verificationInput = $('<input>').attr({
                        type: 'hidden',
                        name: 'fkwcsq_verification_token',
                        value: verificationToken
                    });
                    $form.append(verificationInput);

                    // Only now reset flags and submit
                    isProcessing = false;
                    $form.unblock();

                    // For order pay page, submit the form directly instead of triggering the button
                    if (isOrderPayPage) {
                        $form.submit();
                    } else {
                        $form.submit();
                    }
                    return true;
                } else {
                    throw new Error('Verification failed: No verification token received.');
                }
            } catch (verificationError) {
                isProcessing = false;
                $form.unblock();
                $('#square-card-error').html(`Payment Error: ${verificationError.message}`).show();
                return false;
            }
        } catch (error) {
            isProcessing = false;
            $form.unblock();
            $('#square-card-error')
                .html(`Payment Error: ${error.message}`)
                .show();
            return false;
        }
    }

    // Flag to track if events have been attached
    let eventsAttached = false;

    // Initialize when document is ready
    $(document).ready(function () {
        // Prevent multiple event attachments
        if (eventsAttached) {
            return;
        }
        eventsAttached = true;

        // Initial check with debounce
        // Skip on order pay page - it has its own initialization logic
        const isOrderPayPage = $('body').hasClass('woocommerce-order-pay');
        if (!isOrderPayPage && $('#payment_method_fkwcsq_square').is(':checked')) {
            setTimeout(() => initializeSquarePayment(), 100);
        }

        // Handle payment method changes - using a debounced approach
        let paymentMethodChangeTimeout;

        // Track update_checkout events to detect when AJAX is running
        $('body').on('update_checkout', function () {
            updateCheckoutInProgress = true;
        });

        $('body').on('updated_checkout', function () {
            updateCheckoutInProgress = false;
        });

        $('body').on('payment_method_selected', function () {
            clearTimeout(paymentMethodChangeTimeout);
            isPaymentMethodChanging = true;
            paymentMethodChangeTimeout = setTimeout(function () {
                if ($('#payment_method_fkwcsq_square').is(':checked')) {
                    // Check if update_checkout is in progress
                    if (updateCheckoutInProgress) {
                        isPaymentMethodChanging = false;
                        return;
                    }

                    if (!isCardFunctional() && !initializationInProgress) {
                        // Only initialize if card is not functional and not in progress
                        initializeSquarePayment();
                    }
                } else {
                    destroyCard();
                }
                isPaymentMethodChanging = false;
            }, 100); // Reduced debounce for faster response
        });

        // Handle checkout updates separately to avoid conflicts
        // Skip this on order pay page as it doesn't use update_checkout AJAX
        $('body').on('updated_checkout', function () {
            // Skip on order pay page - it doesn't use update_checkout AJAX
            if ($('body').hasClass('woocommerce-order-pay')) {
                return;
            }

            // Initialize saved card handling
            initializeSavedCardHandling();

            // Only handle if not currently changing payment method
            if (!isPaymentMethodChanging) {
                clearTimeout(paymentMethodChangeTimeout);
                paymentMethodChangeTimeout = setTimeout(function () {
                    if ($('#payment_method_fkwcsq_square').is(':checked')) {
                        // After AJAX update, container might be replaced with shimmer HTML
                        // If container is empty (only has shimmer lines) or card is not functional, reset state and reinitialize
                        const container = $('#square-card-container');
                        const hasShimmerOnly = container.hasClass('square-shimmer-container') &&
                                               container.find('.square-shimmer-line').length > 0 &&
                                               container.find('iframe').length === 0;

                        if (hasShimmerOnly || (!isCardFunctional() || isContainerEmpty())) {
                            // Reset initialization state when container is replaced by AJAX
                            if (hasShimmerOnly || isContainerEmpty()) {
                                isInitialized = false;
                                card = null;
                            }

                            if (!initializationInProgress && container.is(':visible')) {
                                initializeSquarePayment();
                            }
                        }
                    } else {
                        destroyCard();
                    }
                }, 200); // Slightly longer debounce for checkout updates
            }
        });

        // Handle FunnelKit multi-step checkout step switching.
        // The payment container is hidden until the user navigates to the payment step,
        // so the initial init is silently skipped by verifyPaymentFormContainer().
        // This listener triggers init when the payment step becomes visible.
        $('body').on('wfacp_step_switching', function () {
            clearTimeout(paymentMethodChangeTimeout);
            paymentMethodChangeTimeout = setTimeout(function () {
                if ($('#payment_method_fkwcsq_square').is(':checked') && !isCardFunctional() && !initializationInProgress) {
                    initializeSquarePayment();
                }
            }, 500);
        });

        // Listen for payment errors from server-side
        $('body').on('checkout_error', function () {
            if ($('#payment_method_fkwcsq_square').is(':checked')) {
                // Just clear the tokens and errors, no need to reset the form
                $('#square-card-error').hide();
                $('input[name="fkwcsq_square_nonce"]').remove();
                $('input[name="fkwcsq_verification_token"]').remove();
                isProcessing = false;
            }
        });

        // Hook into the main WooCommerce checkout submission
        $('form.checkout').on('checkout_place_order', function (e) {
            if ($('#payment_method_fkwcsq_square').is(':checked')) {
                return processCheckoutSubmit(e);
            }
            return true;
        });

        // Additionally, keep the specific gateway hook as well
        $('form.checkout').on('checkout_place_order_fkwcsq_square', function (e) {
            return processCheckoutSubmit(e);
        });
        $('form.checkout')
            .off('checkout_place_order checkout_place_order_fkwcsq_square')
            .on('checkout_place_order checkout_place_order_fkwcsq_square', function (e) {
                if ($('#payment_method_fkwcsq_square').is(':checked')) {
                    return processCheckoutSubmit(e);
                }
                return true;
            });
        // Cleanup on page unload
        $(window).on('unload', function () {
            destroyCard();
        });

        // Handle saved card selection
        $('.funnelkit-square-saved-card').on('change', function () {
            const savedCardId = $(this).val();
            if (savedCardId) {
                $('#square-card-container').hide();
                $('.funnelkit-square-save-card-checkbox').hide();
            } else {
                $('#square-card-container').show();
                $('.funnelkit-square-save-card-checkbox').show();
            }
        });

        // Trigger initial state
        $('.funnelkit-square-saved-card').trigger('change');

        // Store initial billing country
        previousBillingCountry = $('#billing_country').val();

        // Listen for billing country changes
        $(document.body).on('change', '#billing_country', function() {
            const newCountry = $(this).val();
            if (newCountry !== previousBillingCountry) {
                previousBillingCountry = newCountry;
                if ($('#payment_method_fkwcsq_square').is(':checked')) {
                    reinitializeCardElement();
                }
            }
        });

        // Handle order pay page form submission
        if ($('body').hasClass('woocommerce-order-pay')) {
            // Remove any existing handlers to prevent duplicates
            $('form#order_review').off('submit');
            $('#place_order').off('click');

            // Add new submit handler
            $('form#order_review').on('submit', function(e) {
                if ($('#payment_method_fkwcsq_square').is(':checked')) {
                    return processCheckoutSubmit(e);
                }
                return true;
            });

            // Handle place order button click
            $('#place_order').on('click', function(e) {
                if ($('#payment_method_fkwcsq_square').is(':checked')) {
                    const savedCardValue = $('input[name="wc-fkwcsq_square-payment-token"]:checked').val();
                    if (savedCardValue && savedCardValue !== 'new') {
                        e.preventDefault();
                        e.stopPropagation(); // Prevent event bubbling

                        // Check if we already have a verification token
                        if ($('input[name="fkwcsq_verification_token"]').length > 0) {
                            // If we have a token, submit the form directly
                            $('form#order_review').submit();
                            return false;
                        }

                        // Otherwise, get the token and process payment
                        getDynamicSavedToken()
                            .then(savedToken => {
                                processSavedCardPayment(e, savedToken);
                            })
                            .catch(error => {
                                $('#square-card-error')
                                    .html(`Payment Error: ${  error.message}`)
                                    .show();
                            });
                        return false;
                    }
                }
                return true;
            });
        }

        // Ensure card is initialized on order pay page
        // Order pay page doesn't use update_checkout AJAX, so we need direct initialization
        if ($('body').hasClass('woocommerce-order-pay')) {
            // Initialize immediately if Square is selected
            if ($('#payment_method_fkwcsq_square').is(':checked')) {
                // Small delay to ensure DOM is ready
                setTimeout(() => {
                    initializeSquarePayment();
                }, 100);
            }

            // Also listen for payment method changes on order pay page
            $(document).on('change', 'input[name="payment_method"]', function() {
                if ($('#payment_method_fkwcsq_square').is(':checked')) {
                    setTimeout(() => {
                        initializeSquarePayment();
                    }, 100);
                } else {
                    destroyCard();
                }
            });
        }

        // Clear error message when user interacts with card fields
        $(document).on('input focus', '#square-card-container iframe, #square-card-container input', function() {
            if ($('#square-card-error').is(':visible')) {
                $('#square-card-error').hide();
            }
        });

        // Clear error message when user changes payment method
        $(document).on('change', 'input[name="payment_method"]', function() {
            $('#square-card-error').hide();
        });
    });

    function initializeSavedCardHandling() {
        const $cardContainer = $('#square-card-container');
        const $saveCardContainer = $('.form-row-wide:has(#fkwcsq_square_save_card)');
        const gatewayId = 'fkwcsq_square';
        const isOrderPayPage = $('body').hasClass('woocommerce-order-pay');

        // Handle saved card selection using WooCommerce's structure
        $(document).on('change', `input[name="wc-${gatewayId}-payment-token"]`, function () {
            const selectedValue = $(this).val();
            if (selectedValue && selectedValue !== 'new') {
                // Hide card form and save card option when using saved card
                $cardContainer.hide();
                $saveCardContainer.hide();

                // Destroy card instance if it exists
                if (card) {
                    destroyCard();
                }
            } else {
                // Show card form and save card option when using new card
                $cardContainer.show();
                $saveCardContainer.show();

                // Initialize card if not already initialized
                if (!isInitialized) {
                    initializeSquarePayment();
                }
            }
        });

        // Special handling for order pay page
        if (isOrderPayPage) {
            // Initialize card if no saved card is selected
            const selectedToken = $(`input[name="wc-${gatewayId}-payment-token"]:checked`).val();
            if (!selectedToken || selectedToken === 'new') {
                setTimeout(() => {
                    initializeSquarePayment();
                }, 500);
            }
        }

        // Trigger initial state
        $(`input[name="wc-${gatewayId}-payment-token"]:checked`).trigger('change');
    }

    // Initialize saved card handling when document is ready
    $(document).ready(function () {
        initializeSavedCardHandling();
    });

    async function reinitializeCardElement() {
        try {
            // Destroy existing card instance
            await destroyCard();

            // Clear initialization flags
            isInitialized = false;
            initializationInProgress = false;

            // Reinitialize card
            await initializeSquarePayment();

        } catch (error) {
            // Silently handle reinitialization errors
        }
    }

})(jQuery);


/***/ },

/***/ "./assets/js/cash-app-handler.js"
/*!***************************************!*\
  !*** ./assets/js/cash-app-handler.js ***!
  \***************************************/
() {

/* global Square, fkwcsq_cash_app_params */

/**
 * FunnelKit Square Cash App Handler
 *
 * Handles Square Cash App Pay initialization and tokenization.
 *
 * Note: Cash App Pay does NOT support programmatic tokenization like Afterpay.
 * Users must click the Cash App button to initiate payment. The token is
 * received via the 'ontokenization' event listener after user completes
 * the Cash App flow.
 *
 * @package FunnelKit_Square
 */

(function ($) {
    'use strict';

    // State management
    let cashAppPay = null;
    let payments = null;
    let isInitialized = false;
    let isProcessing = false;
    let paymentRequestData = null;

    /**
     * Initialize the Cash App handler
     */
    function init() {
        // Handle checkout update
        $(document.body).on('updated_checkout', handleCheckoutUpdate);

        // Handle FunnelKit checkout initialization
        $(document.body).on('init_checkout', function () {
            toggleButtons();
            maybeInitializeCashApp();
        });

        // Handle payment method change - use immediate toggle
        $(document.body).on('change', 'input[name="payment_method"]', function () {
            toggleButtons();
            maybeInitializeCashApp();
        });

        // Handle form submission
        $('form.checkout').on('checkout_place_order_fkwcsq_cash_app', handleFormSubmit);

        // Initial setup
        toggleButtons();
        maybeInitializeCashApp();
    }

    /**
     * Toggle Place Order / Cash App button visibility using body class
     */
    function toggleButtons() {
        const selectedPayment = $('input[name="payment_method"]:checked').val();

        if (selectedPayment === 'fkwcsq_cash_app') {
            // Add body class to hide Place Order and show Cash App button via CSS
            $('body').addClass('fkwcsq-cash-app-selected');
        } else {
            // Remove body class to show Place Order and hide Cash App button
            $('body').removeClass('fkwcsq-cash-app-selected');
        }
    }

    /**
     * Initialize Cash App if selected and not already initialized
     */
    async function maybeInitializeCashApp() {
        const selectedPayment = $('input[name="payment_method"]:checked').val();

        if (selectedPayment === 'fkwcsq_cash_app' && !isInitialized) {
            await initializeCashApp();
        }
    }

    /**
     * Handle checkout update - capture payment request data and reinitialize
     *
     * @param {Event} _e Event object
     * @param {Object} data Checkout update data containing fragments
     */
    async function handleCheckoutUpdate(_e, data) {
        // Capture payment request data from fragments
        if (data && data.fragments && data.fragments.fkwcsq_payment_request) {
            paymentRequestData = data.fragments.fkwcsq_payment_request;
        }

        // Toggle buttons immediately after checkout update (DOM may have changed)
        toggleButtons();

        const selectedPayment = $('input[name="payment_method"]:checked').val();
        if (selectedPayment === 'fkwcsq_cash_app') {
            // Properly destroy previous instance before reinitializing
            await destroyCashApp();
            await initializeCashApp();

            // Toggle again after initialization in case DOM changed
            toggleButtons();
        }
    }

    /**
     * Get cart total from payment request data
     *
     * @returns {string} Cart total
     */
    function getCartTotal() {
        // Use payment request data from checkout fragments (preferred)
        if (paymentRequestData && paymentRequestData.total && paymentRequestData.total.amount) {
            return paymentRequestData.total.amount;
        }

        // Fallback to localized params if available
        if (fkwcsq_cash_app_params.payment_request && fkwcsq_cash_app_params.payment_request.total) {
            return fkwcsq_cash_app_params.payment_request.total.amount;
        }

        return '0.00';
    }

    /**
     * Initialize Square Cash App Pay
     */
    async function initializeCashApp() {
        const container = document.getElementById('fkwcsq-cash-app-container');

        // Check if container exists
        if (!container) {
            return;
        }

        // Check if already initialized
        if (isInitialized && cashAppPay) {
            return;
        }

        // Check if Square SDK is loaded
        if (typeof Square === 'undefined') {
            console.error('Square SDK not loaded');
            showError(fkwcsq_cash_app_params.i18n.error_generic);
            return;
        }

        try {
            // Initialize Square payments
            if (!payments) {
                payments = await Square.payments(
                    fkwcsq_cash_app_params.application_id,
                    fkwcsq_cash_app_params.location_id
                );
            }

            // Build payment request
            const paymentRequest = payments.paymentRequest({
                countryCode: fkwcsq_cash_app_params.country_code,
                currencyCode: fkwcsq_cash_app_params.currency_code,
                total: {
                    amount: getCartTotal(),
                    label: 'Total'
                }
            });

            // Create Cash App Pay instance
            cashAppPay = await payments.cashAppPay(paymentRequest, {
                redirectURL: fkwcsq_cash_app_params.checkout_url
            });

            // Attach to container
            await cashAppPay.attach('#fkwcsq-cash-app-container', {
                size: 'medium',
                width: 'full'
            });

            // Mark as initialized
            isInitialized = true;

            // Clear any previous error messages
            hideError();

            // Listen for tokenization events (fires when user completes Cash App flow)
            cashAppPay.addEventListener('ontokenization', handleTokenization);

        } catch (error) {
            console.error('Cash App initialization error:', error);

            // Cash App may not be available in this region/browser
            if (error.message && error.message.includes('not supported')) {
                showError(fkwcsq_cash_app_params.i18n.not_supported);
            } else {
                showError(fkwcsq_cash_app_params.i18n.error_generic);
            }
        }
    }

    /**
     * Handle tokenization event from Cash App
     *
     * This fires when user clicks Cash App button and completes the flow.
     *
     * @param {Object} event Tokenization event
     */
    function handleTokenization(event) {
        const { tokenResult } = event.detail;

        if (tokenResult.status === 'OK') {
            // Set the nonce value
            $('#fkwcsq_cash_app_nonce').val(tokenResult.token);
            isProcessing = false;

            // Remove body class to show Place Order button, then trigger click
            $('body').removeClass('fkwcsq-cash-app-selected');
            $('#place_order').trigger('click');
        } else if (tokenResult.status === 'Cancel') {
            // User cancelled - don't show error
            isProcessing = false;
        } else {
            const errorMessage = tokenResult.errors && tokenResult.errors[0]
                ? tokenResult.errors[0].message
                : fkwcsq_cash_app_params.i18n.error_generic;

            showError(errorMessage);
            isProcessing = false;
        }
    }

    /**
     * Handle form submission
     *
     * Cash App does not support programmatic tokenization. User must click
     * the Cash App button first. If they click "Place Order" without a token,
     * we show an error message.
     *
     * @returns {boolean} Whether to proceed with submission
     */
    function handleFormSubmit() {
        // If we already have a nonce, proceed with form submission
        if ($('#fkwcsq_cash_app_nonce').val()) {
            return true;
        }

        // Cash App requires user to click the Cash App button
        // We cannot programmatically trigger tokenization
        showError('Please click the Cash App button to complete your payment.');
        return false;
    }

    /**
     * Show error message
     *
     * @param {string} message Error message
     */
    function showError(message) {
        $('#fkwcsq-cash-app-error')
            .text(message)
            .show();
    }

    /**
     * Hide error message
     */
    function hideError() {
        $('#fkwcsq-cash-app-error').hide();
    }

    /**
     * Destroy Cash App instance and clear containers
     */
    async function destroyCashApp() {
        if (cashAppPay) {
            try {
                await cashAppPay.destroy();
            } catch (error) {
                // Silently handle - instance may already be destroyed
            }
            cashAppPay = null;
            isInitialized = false;
        }
    }

    // Initialize on document ready
    $(document).ready(init);

    // Cleanup on page unload (use pagehide to avoid "Leave site?" dialog on Place Order)
    $(window).on('pagehide', destroyCashApp);

})(jQuery);


/***/ },

/***/ "./assets/js/gift-card-handler.js"
/*!****************************************!*\
  !*** ./assets/js/gift-card-handler.js ***!
  \****************************************/
() {

/* global Square, fkwcsq_gift_card_params */

/**
 * FunnelKit Square Gift Card Handler
 *
 * Handles Square Gift Card payment method initialization and tokenization.
 *
 * Architecture note (mirrors WooCommerce Square):
 * - "Apply" tokenizes the card and POSTs the nonce to the server, which stores
 *   it in session (no API call, no pre-authorization).
 * - A checkout review refresh (update_checkout) is then triggered, which calls
 *   add_gift_card_fragments() server-side: that does the read-only balance check
 *   (retrieve_gift_card), updates the session, and returns HTML fragments with
 *   the applied state and balance info.
 * - "Remove" just clears the session — no API call needed.
 *
 * @package FunnelKit_Square
 */

(function ($) {
    'use strict';

    // State management
    let giftCard = null;
    let payments = null;
    let isInitialized = false;
    let isInitializing = false;
    let isProcessing = false;
    let submitAfterApply = false;

    /**
     * Check whether the Square gift card iframe is attached.
     *
     * @returns {boolean}
     */
    function hasAttachedIframe() {
        return $('#fkwcsq-gift-card-container iframe').length > 0;
    }

    /**
     * Initialize the gift card handler.
     */
    function init() {
        $(document.body).on('updated_checkout', initializeGiftCard);
        $(document.body).on('updated_checkout', handleUpdatedCheckout);
        $(document.body).on('payment_method_selected', handlePaymentMethodChange);

        if ($('#fkwcsq-gift-card-container').length) {
            initializeGiftCard();
        }

        $('form.checkout, form#order_review').on('checkout_place_order_fkwcsq_gift_card', handlePlaceOrderGiftCard);

        $(document).on('click', '.fkwcsq-remove-gift-card', handleRemoveGiftCard);
    }

    /**
     * Handle payment method change.
     */
    function handlePaymentMethodChange() {
        const selectedPayment = $('input[name="payment_method"]:checked').val();

        if (selectedPayment === 'fkwcsq_gift_card' && !isInitialized) {
            initializeGiftCard();
        }
    }

    /**
     * Initialize Square Gift Card SDK.
     */
    async function initializeGiftCard() {
        const container = document.getElementById('fkwcsq-gift-card-container');

        if (!container || !$(container).is(':visible')) {
            return;
        }

        if (isInitializing) {
            return;
        }

        if (isInitialized && giftCard && hasAttachedIframe()) {
            return;
        }

        if (typeof Square === 'undefined') {
            console.error('Square SDK not loaded');
            showError(fkwcsq_gift_card_params.i18n.error_generic);
            return;
        }

        if (!fkwcsq_gift_card_params.application_id || !fkwcsq_gift_card_params.location_id) {
            showError('Square Gift Card is not configured correctly. Missing application or location ID.');
            return;
        }

        isInitializing = true;

        try {
            if (!payments) {
                payments = await Square.payments(
                    fkwcsq_gift_card_params.application_id,
                    fkwcsq_gift_card_params.location_id
                );
            }

            if (giftCard) {
                await destroyGiftCard();
            }

            $('#fkwcsq-gift-card-container').empty();

            giftCard = await payments.giftCard();
            await giftCard.attach('#fkwcsq-gift-card-container');

            isInitialized = true;
            $('#fkwcsq-gift-card-container').addClass('fkwcsq-initialized');

            giftCard.addEventListener('inputEvent', handleInputEvent);

        } catch (error) {
            console.error('Gift card initialization error:', error);
            showError(error && error.message ? error.message : fkwcsq_gift_card_params.i18n.error_generic);
        } finally {
            isInitializing = false;
        }
    }

    /**
     * Handle input events from Square gift card field.
     *
     * @param {Object} event Input event
     */
    function handleInputEvent(event) {
        if (event.eventType === 'focusClassAdded') {
            hideError();
        }
    }

    /**
     * Check if a gift card has been applied.
     *
     * The server renders .fkwcsq-gift-card-applied (via payment_fields or fragment)
     * when a gift card token is in session and the balance has been confirmed.
     *
     * @returns {boolean}
     */
    function isGiftCardApplied() {
        return $('.fkwcsq-gift-card-applied').length > 0;
    }

    /**
     * Handle Place Order when gift card payment is selected.
     * Applies gift card first if not yet applied, then allows checkout to proceed.
     *
     * @param {Object} e Event object
     * @returns {boolean|undefined}
     */
    function handlePlaceOrderGiftCard(e) {
        if (isGiftCardApplied()) {
            return true;
        }

        if (!giftCard || isProcessing) {
            if (!giftCard) {
                showError(fkwcsq_gift_card_params.i18n.error_generic);
            }
            return false;
        }

        const $placeOrderBtn = $('#place_order');
        if (!$placeOrderBtn.length) {
            return true;
        }

        submitAfterApply = true;
        isProcessing = true;
        const originalText = $placeOrderBtn.attr('data-value') || $placeOrderBtn.val() || $placeOrderBtn.text();
        $placeOrderBtn.prop('disabled', true).val(fkwcsq_gift_card_params.i18n.applying);
        hideError();

        applyGiftCardForCheckout()
            .then(() => {
                // update_checkout will refresh fragments (balance check) and
                // handleUpdatedCheckout() will then submit the form.
                $(document.body).trigger('update_checkout');
            })
            .catch((error) => {
                console.error('Gift card apply error:', error);
                showError(error.message || fkwcsq_gift_card_params.i18n.error_generic);
                $placeOrderBtn.prop('disabled', false).val(originalText);
                submitAfterApply = false;
            })
            .finally(() => {
                isProcessing = false;
            });

        return false;
    }

    /**
     * After a checkout refresh: if we stored a token and the fragment has confirmed
     * the gift card applied state, submit the form. If the balance was insufficient
     * the server clears the session and returns a "not-applied" fragment — in that
     * case re-enable the Place Order button and reinitialize the gift card field.
     */
    function handleUpdatedCheckout() {
        if (!submitAfterApply) {
            return;
        }

        if (isGiftCardApplied()) {
            submitAfterApply = false;
            const $form = $('form.checkout, form#order_review');
            if ($form.length) {
                $form.submit();
            }
        } else {
            // Balance was insufficient — fragment returned the "not-applied" state.
            // Reset state and restore the Place Order button so the user can act.
            submitAfterApply = false;
            $('#place_order').prop('disabled', false);

            // Re-initialize the gift card field into the refreshed container.
            isInitialized = false;
            giftCard = null;
            initializeGiftCard();
        }
    }

    /**
     * Tokenize the gift card and send the nonce to the server.
     *
     * @returns {Promise}
     */
    async function applyGiftCardForCheckout() {
        const result = await giftCard.tokenize();

        if (result.status !== 'OK') {
            throw new Error(result.errors ? result.errors[0].message : fkwcsq_gift_card_params.i18n.error_invalid);
        }

        const response = await applyGiftCardToServer(result.token);

        if (!response.success) {
            throw new Error(response.data.message || fkwcsq_gift_card_params.i18n.error_generic);
        }

        // Server just stored the token. Balance check happens in the subsequent
        // update_checkout → add_gift_card_fragments() call.
        return response.data;
    }

    /**
     * POST gift card token to server for session storage.
     *
     * @param {string} token Gift card nonce
     * @returns {Promise} AJAX response
     */
    function applyGiftCardToServer(token) {
        return $.ajax({
            url: fkwcsq_gift_card_params.ajax_url,
            type: 'POST',
            data: {
                action: 'fkwcsq_apply_gift_card',
                nonce: fkwcsq_gift_card_params.apply_nonce,
                token
            }
        });
    }

    /**
     * Handle remove gift card button click.
     *
     * Clears the session server-side. No API call needed — with autocomplete=true
     * there is no pre-authorization to cancel.
     *
     * @param {Event} e Click event
     */
    function handleRemoveGiftCard(e) {
        e.preventDefault();

        if (isProcessing) {
            return;
        }

        isProcessing = true;

        $.ajax({
            url: fkwcsq_gift_card_params.ajax_url,
            type: 'POST',
            data: {
                action: 'fkwcsq_remove_gift_card',
                nonce: fkwcsq_gift_card_params.remove_nonce
            },
            success () {
                $(document.body).trigger('update_checkout');
            },
            complete () {
                isProcessing = false;
            }
        });
    }

    /**
     * Show error message.
     *
     * @param {string} message Error message
     */
    function showError(message) {
        $('#fkwcsq-gift-card-error')
            .text(message)
            .show();
    }

    /**
     * Hide error message.
     */
    function hideError() {
        $('#fkwcsq-gift-card-error').hide();
    }

    /**
     * Destroy gift card instance.
     */
    async function destroyGiftCard() {
        if (giftCard) {
            try {
                await giftCard.destroy();
            } catch (error) {
                // Silently handle
            }
            giftCard = null;
            isInitialized = false;
        }
    }

    // Initialize on document ready
    $(document).ready(init);

    $(document).on('change', 'input[name="payment_method"]', handlePaymentMethodChange);

    $(window).on('pagehide', destroyGiftCard);

})(jQuery);


/***/ }

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		if (!(moduleId in __webpack_modules__)) {
/******/ 			delete __webpack_module_cache__[moduleId];
/******/ 			var e = new Error("Cannot find module '" + moduleId + "'");
/******/ 			e.code = 'MODULE_NOT_FOUND';
/******/ 			throw e;
/******/ 		}
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/compat get default export */
/******/ 	(() => {
/******/ 		// getDefaultExport function for compatibility with non-harmony modules
/******/ 		__webpack_require__.n = (module) => {
/******/ 			var getter = module && module.__esModule ?
/******/ 				() => (module['default']) :
/******/ 				() => (module);
/******/ 			__webpack_require__.d(getter, { a: getter });
/******/ 			return getter;
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/define property getters */
/******/ 	(() => {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = (exports, definition) => {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	(() => {
/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/make namespace object */
/******/ 	(() => {
/******/ 		// define __esModule on exports
/******/ 		__webpack_require__.r = (exports) => {
/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 			}
/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
/******/ 		};
/******/ 	})();
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};
// This entry needs to be wrapped in an IIFE because it needs to be in strict mode.
(() => {
"use strict";
/*!**************************************!*\
  !*** ./assets/js/checkout-bundle.js ***!
  \**************************************/
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _card_payment_form_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./card-payment-form.js */ "./assets/js/card-payment-form.js");
/* harmony import */ var _card_payment_form_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_card_payment_form_js__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _cash_app_handler_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./cash-app-handler.js */ "./assets/js/cash-app-handler.js");
/* harmony import */ var _cash_app_handler_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_cash_app_handler_js__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _ach_handler_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ach-handler.js */ "./assets/js/ach-handler.js");
/* harmony import */ var _ach_handler_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_ach_handler_js__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var _afterpay_handler_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./afterpay-handler.js */ "./assets/js/afterpay-handler.js");
/* harmony import */ var _afterpay_handler_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_afterpay_handler_js__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var _gift_card_handler_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./gift-card-handler.js */ "./assets/js/gift-card-handler.js");
/* harmony import */ var _gift_card_handler_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_gift_card_handler_js__WEBPACK_IMPORTED_MODULE_4__);
/**
 * FunnelKit Square - Checkout Bundle
 *
 * This file bundles all payment gateway handlers for classic checkout.
 * Individual handlers check for their own params before initializing.
 *
 * @package FunnelKit_Square
 */

// Import all payment handlers
// Each handler self-initializes based on its localized params

// Card payment form


// Cash App handler


// ACH handler


// Afterpay handler


// Gift Card handler


})();

/******/ })()
;