/**
 * Guest table order list for maca Restu Pro (client-side, waiter screen).
 */
(function () {
    'use strict';

    function config() {
        return window.macaMenulistTableOrder || null;
    }

    function isOrderingOpen() {
        var cfg = config();

        if (!cfg || !Object.prototype.hasOwnProperty.call(cfg, 'orderingOpen')) {
            return true;
        }

        return cfg.orderingOpen !== false;
    }

    function t(key) {
        var cfg = config();
        if (!cfg || !cfg.i18n || !cfg.i18n[key]) {
            return key;
        }
        return cfg.i18n[key];
    }

    function storageKey() {
        var cfg = config();
        var base = cfg && cfg.storageKey ? cfg.storageKey : 'maca_menulist_table_order';
        return base + '_' + window.location.pathname;
    }

    function getTableFromUrl() {
        var cfg = config();

        if (cfg && Object.prototype.hasOwnProperty.call(cfg, 'urlTableParam')) {
            return cfg.urlTable ? String(cfg.urlTable) : '';
        }

        if (cfg && cfg.urlTable) {
            return String(cfg.urlTable);
        }

        var params = new URLSearchParams(window.location.search);
        return params.get('bord') || params.get('table') || '';
    }

    function ensureTableOption(select, value) {
        if (!select || !value) {
            return;
        }

        var exists = Array.prototype.some.call(select.options, function (option) {
            return option.value === value;
        });

        if (!exists) {
            var option = document.createElement('option');
            option.value = value;
            option.textContent = t('tableLabel').replace('%s', value).replace('%1$s', value);
            select.appendChild(option);
        }
    }

    function getLockedTableNumber() {
        var session = loadGuestSession();

        if (session && session.orders && session.orders.length) {
            var sessionTable = typeof session.tableNumber === 'string' ? session.tableNumber.trim() : '';

            if (sessionTable) {
                return sessionTable;
            }
        }

        var state = loadState();

        if (state.sentOrders && state.sentOrders.length) {
            return typeof state.tableNumber === 'string' ? state.tableNumber.trim() : '';
        }

        return '';
    }

    function isTableNumberLocked() {
        return getLockedTableNumber() !== '';
    }

    function applyTableSelectLock(ui) {
        if (!ui.tableSelect) {
            return;
        }

        var locked = getLockedTableNumber();
        var field = ui.tableSelect.closest('.maca-table-order-field');
        var hint = document.getElementById('maca-table-order-table-locked-hint');

        if (!hint && field) {
            hint = document.createElement('p');
            hint.id = 'maca-table-order-table-locked-hint';
            hint.className = 'description maca-table-order-table-locked-hint';
            hint.hidden = true;
            field.appendChild(hint);
        }

        if (locked) {
            ensureTableOption(ui.tableSelect, locked);
            ui.tableSelect.value = locked;
            ui.tableSelect.disabled = true;
            ui.tableSelect.setAttribute('aria-disabled', 'true');
            ui.tableSelect.classList.add('is-locked');

            if (field) {
                field.classList.add('maca-table-order-field--table-locked');
            }

            if (hint) {
                hint.textContent = t('tableLocked');
                hint.hidden = false;
            }
        } else {
            ui.tableSelect.disabled = false;
            ui.tableSelect.removeAttribute('aria-disabled');
            ui.tableSelect.classList.remove('is-locked');

            if (field) {
                field.classList.remove('maca-table-order-field--table-locked');
            }

            if (hint) {
                hint.hidden = true;
            }
        }
    }

    function syncTableSelectFromState(state, ui) {
        if (!ui.tableSelect) {
            return;
        }

        var locked = getLockedTableNumber();

        if (locked) {
            state.tableNumber = locked;
        } else {
            var urlTable = getTableFromUrl();

            if (urlTable) {
                state.tableNumber = urlTable;
            }
        }

        if (state.tableNumber) {
            ensureTableOption(ui.tableSelect, state.tableNumber);
            ui.tableSelect.value = state.tableNumber;
        }

        applyTableSelectLock(ui);
    }

    function readTableNumberFromUi(ui) {
        var locked = getLockedTableNumber();

        if (locked) {
            return locked;
        }

        if (!ui.tableSelect) {
            return '';
        }

        return ui.tableSelect.value.trim();
    }

    function tableSelectionRequired() {
        var cfg = config();
        if (!cfg || cfg.orderChannel === 'takeaway') {
            return false;
        }
        if (typeof cfg.requiresTable === 'boolean') {
            return cfg.requiresTable;
        }
        return !!(Array.isArray(cfg.activeTables) && cfg.activeTables.length > 0);
    }

    function isTakeawayChannel() {
        var cfg = config();
        return !!(cfg && cfg.orderChannel === 'takeaway');
    }

    function defaultState() {
        return {
            items: [],
            orderNote: '',
            tableNumber: getTableFromUrl(),
            pickupName: '',
            pickupPhone: '',
            sentOrders: [],
        };
    }

    function loadState() {
        try {
            var raw = window.localStorage.getItem(storageKey());
            if (!raw) {
                return defaultState();
            }
            var parsed = JSON.parse(raw);
            if (!parsed || !Array.isArray(parsed.items)) {
                return defaultState();
            }
            return {
                items: parsed.items,
                orderNote: typeof parsed.orderNote === 'string' ? parsed.orderNote : '',
                tableNumber: typeof parsed.tableNumber === 'string' ? parsed.tableNumber : getTableFromUrl(),
                pickupName: typeof parsed.pickupName === 'string' ? parsed.pickupName : '',
                pickupPhone: typeof parsed.pickupPhone === 'string' ? parsed.pickupPhone : '',
                sentOrders: Array.isArray(parsed.sentOrders) ? parsed.sentOrders : [],
            };
        } catch (error) {
            return defaultState();
        }
    }

    function saveState(state) {
        try {
            window.localStorage.setItem(storageKey(), JSON.stringify(state));
        } catch (error) {
            // Ignore quota errors.
        }
    }

    function itemCount(state) {
        return state.items.reduce(function (sum, item) {
            return sum + (item.qty || 0);
        }, 0);
    }

    function formatPrice(amount) {
        var cfg = config();
        var value = Number(amount);
        if (Number.isNaN(value)) {
            return '';
        }
        var decimals = Math.floor(value) === value ? 0 : 2;
        return value.toFixed(decimals).replace('.', ',') + (cfg.currency ? ' ' + cfg.currency : '');
    }

    function calcTotal(state) {
        return state.items.reduce(function (sum, item) {
            if (typeof item.price !== 'number') {
                return sum;
            }
            return sum + item.price * item.qty;
        }, 0);
    }

    function findItemIndex(state, dishId) {
        return state.items.findIndex(function (item) {
            return String(item.id) === String(dishId);
        });
    }

    function getRoot() {
        return document.getElementById('maca-table-order-root');
    }

    function setBodyClass(active) {
        document.body.classList.toggle('maca-table-order-active', active);
    }

    function setWaiterClass(active) {
        document.body.classList.toggle('maca-table-order-waiter-open', active);
    }

    function escapeHtml(text) {
        var div = document.createElement('div');
        div.textContent = text;
        return div.innerHTML;
    }

    function usesServer() {
        var cfg = config();
        return cfg && (cfg.usesServer === true || (cfg.deliveryMode && cfg.deliveryMode !== 'guest_screen'));
    }

    function guestStatusEnabled() {
        var cfg = config();
        return cfg && cfg.guestStatus === true;
    }

    function paymentsConfig() {
        var cfg = config();
        return cfg && cfg.payments ? cfg.payments : null;
    }

    function paymentsFlowEnabled() {
        var pay = paymentsConfig();
        return !!(pay && pay.flowEnabled);
    }

    function paymentPageUrl() {
        var pay = paymentsConfig();
        return pay && pay.pageUrl ? pay.pageUrl : window.location.href.split('?')[0] + window.location.search.replace(/[?&]maca_payment=[^&]*/g, '').replace(/[?&]maca_order=[^&]*/g, '').replace(/[?&]maca_orders=[^&]*/g, '');
    }

    function guestOrderStorageKey() {
        var cfg = config();
        var base = cfg && cfg.guestOrderStorageKey ? cfg.guestOrderStorageKey : 'maca_menulist_guest_order';
        return base + '_' + window.location.pathname;
    }

    var guestPollTimer = null;
    var guestPaymentEmailDrafts = {};
    var guestBillSplitDrafts = {};

    function loadGuestSession() {
        try {
            var raw = window.localStorage.getItem(guestOrderStorageKey());
            if (!raw) {
                return null;
            }
            var parsed = JSON.parse(raw);
            if (parsed && parsed.orderId && parsed.guestToken) {
                return {
                    tableNumber: '',
                    orders: [{
                        orderId: parsed.orderId,
                        guestToken: parsed.guestToken,
                    }],
                };
            }
            if (!parsed || !Array.isArray(parsed.orders) || !parsed.orders.length) {
                return null;
            }
            return {
                tableNumber: typeof parsed.tableNumber === 'string' ? parsed.tableNumber : '',
                orders: parsed.orders.filter(function (entry) {
                    return entry && entry.orderId && entry.guestToken;
                }),
            };
        } catch (error) {
            return null;
        }
    }

    function saveGuestSession(session) {
        try {
            if (!session || !session.orders || !session.orders.length) {
                window.localStorage.removeItem(guestOrderStorageKey());
                return;
            }
            window.localStorage.setItem(guestOrderStorageKey(), JSON.stringify(session));
        } catch (error) {
            // Ignore storage errors.
        }
    }

    function hasActiveGuestSession() {
        var session = loadGuestSession();
        return !!(session && session.orders && session.orders.length);
    }

    function getAppendableGuestToken(session) {
        if (!session || !session.orders || !session.orders.length) {
            return '';
        }
        for (var i = session.orders.length - 1; i >= 0; i -= 1) {
            if (session.orders[i].appendable) {
                return session.orders[i].guestToken;
            }
        }
        return '';
    }

    function addOrderToGuestSession(orderId, guestToken, tableNumber, appended) {
        var session = loadGuestSession() || { tableNumber: tableNumber || '', orders: [] };

        if (tableNumber) {
            session.tableNumber = tableNumber;
        }

        if (appended) {
            for (var i = session.orders.length - 1; i >= 0; i -= 1) {
                if (String(session.orders[i].guestToken) === String(guestToken)) {
                    session.orders[i].appendable = true;
                    saveGuestSession(session);
                    return session;
                }
            }
        }

        session.orders.push({
            orderId: orderId,
            guestToken: guestToken,
            appendable: true,
        });
        saveGuestSession(session);
        return session;
    }

    function clearGuestSession() {
        try {
            window.localStorage.removeItem(guestOrderStorageKey());
        } catch (error) {
            // Ignore storage errors.
        }
        if (guestPollTimer) {
            window.clearTimeout(guestPollTimer);
            guestPollTimer = null;
        }
    }

    function guestOrderAwaitingKitchenUpdate(data) {
        if (!data || data.complete || data.closed) {
            return false;
        }

        return data.status === 'new'
            || data.status === 'accepted'
            || data.status === 'preparing'
            || data.status === 'ready';
    }

    function guestOrderPaymentSignature(payment) {
        if (!payment) {
            return '';
        }

        return [
            payment.is_paid ? '1' : '0',
            payment.status || '',
            payment.method || '',
            payment.tip_amount || 0,
            payment.show_checkout_ui ? '1' : '0',
            payment.amount_remaining || 0,
            payment.bill_split && payment.bill_split.active ? '1' : '0',
        ].join('|');
    }

    function guestOrderEtaMinutes(data) {
        if (!data || data.eta_minutes === undefined || data.eta_minutes === null || data.eta_minutes === '') {
            return 0;
        }

        var eta = parseInt(String(data.eta_minutes), 10);
        return Number.isNaN(eta) ? 0 : Math.max(0, eta);
    }

    function guestShouldShowReadyIn(data) {
        return !!(data && data.status === 'preparing' && guestOrderEtaMinutes(data) > 0 && !data.complete);
    }

    function guestReadyInLabel(data) {
        return t('readyIn').replace('%d', String(guestOrderEtaMinutes(data)));
    }

    function guestOrderKitchenSnapshot(data) {
        if (!data) {
            return '';
        }

        return [
            data.status || '',
            data.status_index || 0,
            guestOrderEtaMinutes(data),
            data.complete ? '1' : '0',
            data.status_label || '',
        ].join(':');
    }

    function guestOrderStableSnapshot(data) {
        if (!data) {
            return '';
        }

        return [
            (data.lines || []).length,
            guestOrderPaymentSignature(data.payment),
        ].join(':');
    }

    function guestPollIntervalMs(statuses, ui) {
        var cfg = config() || {};
        var statusOpen = ui.guestStatus && !ui.guestStatus.hidden;
        var awaitingKitchen = false;
        var preparing = false;

        if (statuses && statuses.length) {
            statuses.forEach(function (entry) {
                if (!entry || !entry.data) {
                    return;
                }
                if (guestOrderAwaitingKitchenUpdate(entry.data)) {
                    awaitingKitchen = true;
                }
                if (entry.data.status === 'preparing' && !entry.data.complete) {
                    preparing = true;
                }
            });
        } else {
            var session = loadGuestSession();
            if (session && session.orders.length) {
                session.orders.forEach(function (order) {
                    if (order.closed) {
                        return;
                    }
                    if (order.status === 'preparing') {
                        preparing = true;
                        awaitingKitchen = true;
                    } else if (
                        order.status === 'new'
                        || order.status === 'accepted'
                        || order.status === 'ready'
                    ) {
                        awaitingKitchen = true;
                    }
                });
            }
        }

        if (preparing && statusOpen) {
            return cfg.pollIntervalPreparing || 3000;
        }
        if (awaitingKitchen) {
            return statusOpen
                ? (cfg.pollIntervalPreparing || 3000)
                : (cfg.pollIntervalActive || 5000);
        }
        if (statusOpen || (statuses && statuses.length)) {
            return cfg.pollIntervalActive || 5000;
        }
        return cfg.pollInterval || 15000;
    }

    function scheduleGuestPoll(ui, statuses) {
        if (guestPollTimer) {
            window.clearTimeout(guestPollTimer);
        }

        guestPollTimer = window.setTimeout(function () {
            pollGuestSession(ui);
        }, guestPollIntervalMs(statuses, ui));
    }

    function renderGuestOrderCardStepsHtml(data) {
        var html = '';
        var steps = data.steps || (config() && config().statusSteps) || [];
        var currentIndex = typeof data.status_index === 'number' ? data.status_index : 0;

        steps.forEach(function (step, stepIndex) {
            var className = '';
            if (stepIndex < currentIndex) {
                className = ' is-done';
            } else if (stepIndex === currentIndex && !data.complete) {
                className = ' is-current';
            } else if (data.complete && stepIndex === steps.length - 1) {
                className = ' is-done is-current';
            } else if (stepIndex <= currentIndex) {
                className = ' is-done';
            }
            html += '<li class="' + className.trim() + '">' + escapeHtml(step.label) + '</li>';
        });

        return html;
    }

    function patchGuestOrderCardKitchenState(card, data) {
        if (!card || !data) {
            return;
        }

        var nextKitchen = guestOrderKitchenSnapshot(data);
        if (card.getAttribute('data-guest-kitchen') === nextKitchen) {
            return;
        }

        var statusEl = card.querySelector('.maca-guest-order-card-status');
        if (statusEl && data.status_label) {
            statusEl.textContent = data.status_label;
        }

        var stepsEl = card.querySelector('.maca-guest-order-status-steps');
        if (stepsEl) {
            stepsEl.innerHTML = renderGuestOrderCardStepsHtml(data);
        }

        var etaEl = card.querySelector('.maca-guest-order-status-eta');
        var messageEl = card.querySelector('.maca-guest-order-card-message');
        var showEta = guestShouldShowReadyIn(data);

        if (showEta) {
            if (messageEl) {
                messageEl.remove();
            }
            var etaText = guestReadyInLabel(data);
            if (etaEl) {
                etaEl.textContent = etaText;
            } else if (stepsEl) {
                stepsEl.insertAdjacentHTML(
                    'afterend',
                    '<p class="maca-guest-order-status-eta">' + escapeHtml(etaText) + '</p>'
                );
            }
        } else {
            if (etaEl) {
                etaEl.remove();
            }
            if (data.complete) {
                if (messageEl) {
                    messageEl.textContent = t('orderComplete');
                } else if (stepsEl) {
                    stepsEl.insertAdjacentHTML(
                        'afterend',
                        '<p class="maca-guest-order-card-message">' + escapeHtml(t('orderComplete')) + '</p>'
                    );
                }
            } else if (data.status === 'ready') {
                if (messageEl) {
                    messageEl.textContent = t('readyNow');
                } else if (stepsEl) {
                    stepsEl.insertAdjacentHTML(
                        'afterend',
                        '<p class="maca-guest-order-card-message">' + escapeHtml(t('readyNow')) + '</p>'
                    );
                }
            } else if (messageEl) {
                messageEl.remove();
            }
        }

        card.setAttribute('data-guest-kitchen', guestOrderKitchenSnapshot(data));
        card.setAttribute('data-guest-stable', guestOrderStableSnapshot(data));
    }

    function canPatchGuestOrderCards(container, statuses) {
        if (!container || !statuses || !statuses.length) {
            return false;
        }

        var cards = container.querySelectorAll('.maca-guest-order-card');
        if (cards.length !== statuses.length) {
            return false;
        }

        for (var index = 0; index < statuses.length; index += 1) {
            var entry = statuses[index];
            var card = cards[index];
            if (!entry || !entry.data || !card) {
                return false;
            }
            if (String(entry.data.order_id) !== card.getAttribute('data-order-id')) {
                return false;
            }
            if (card.getAttribute('data-guest-stable') !== guestOrderStableSnapshot(entry.data)) {
                return false;
            }
        }

        return true;
    }

    function loadGuestOrder() {
        var session = loadGuestSession();
        if (!session || !session.orders.length) {
            return null;
        }
        return session.orders[session.orders.length - 1];
    }

    function saveGuestOrder(orderId, guestToken) {
        addOrderToGuestSession(orderId, guestToken, '', false);
    }

    function clearGuestOrder() {
        clearGuestSession();
    }

    function fetchGuestOrderStatus(guestToken) {
        var cfg = config();
        var formData = new FormData();
        formData.append('action', 'maca_get_guest_order_status');
        formData.append('guest_token', guestToken);

        return fetch(cfg.ajaxUrl, {
            method: 'POST',
            credentials: 'same-origin',
            body: formData,
        }).then(function (response) {
            return response.json();
        });
    }

    function getGuestOrderTokensFromUrl() {
        try {
            var params = new URLSearchParams(window.location.search);
            var multi = params.get('maca_orders');
            if (multi) {
                return multi.split(',').map(function (token) {
                    return String(token || '').trim();
                }).filter(Boolean);
            }

            var single = params.get('maca_order');
            return single ? [String(single).trim()] : [];
        } catch (error) {
            return [];
        }
    }

    function getGuestOrderTokenFromUrl() {
        var tokens = getGuestOrderTokensFromUrl();
        return tokens.length ? tokens[0] : '';
    }

    function stripGuestOrderTokenFromUrl() {
        try {
            var url = new URL(window.location.href);
            if (!url.searchParams.has('maca_order') && !url.searchParams.has('maca_orders')) {
                return;
            }
            url.searchParams.delete('maca_order');
            url.searchParams.delete('maca_orders');
            var next = url.pathname + url.search + url.hash;
            window.history.replaceState({}, '', next);
        } catch (error) {
            // Ignore URL API errors.
        }
    }

    function mergeGuestSessionFromStatuses(statuses) {
        if (!statuses || !statuses.length) {
            return null;
        }

        var session = loadGuestSession() || { tableNumber: '', orders: [] };

        statuses.forEach(function (entry) {
            if (!entry || !entry.token || !entry.data || entry.data.closed) {
                return;
            }

            if (entry.data.table_number) {
                session.tableNumber = String(entry.data.table_number);
            }

            var exists = session.orders.some(function (order) {
                return String(order.guestToken) === String(entry.token);
            });

            if (!exists) {
                session.orders.push({
                    orderId: entry.data.order_id,
                    guestToken: entry.token,
                    appendable: !!entry.data.appendable,
                });
            }
        });

        if (!session.orders.length) {
            return null;
        }

        saveGuestSession(session);
        return session;
    }

    function buildGuestSessionShareUrl() {
        var session = loadGuestSession();
        if (!session || !session.orders.length) {
            return '';
        }

        var tokens = session.orders.map(function (order) {
            return order.guestToken;
        }).filter(Boolean);

        if (!tokens.length) {
            return '';
        }

        try {
            var url = new URL(paymentPageUrl(), window.location.origin);
            url.searchParams.delete('maca_payment');
            url.searchParams.delete('maca_order');
            url.searchParams.delete('maca_orders');

            if (tokens.length === 1) {
                url.searchParams.set('maca_order', tokens[0]);
            } else {
                url.searchParams.set('maca_orders', tokens.join(','));
            }

            return url.toString();
        } catch (error) {
            return '';
        }
    }

    function openGuestShareQrModal() {
        var modal = document.getElementById('maca-guest-share-qr-modal');
        if (!modal) {
            return;
        }

        var shareUrl = buildGuestSessionShareUrl();
        if (!shareUrl) {
            return;
        }

        var cfg = config();
        var img = modal.querySelector('.maca-guest-share-qr-image');
        var apiBase = cfg && cfg.guestQrImageApi
            ? cfg.guestQrImageApi
            : 'https://api.qrserver.com/v1/create-qr-code/?size=220x220&data=';

        if (img) {
            img.src = apiBase + encodeURIComponent(shareUrl);
            img.alt = t('shareOrderQrTitle');
        }

        modal.hidden = false;
        document.body.classList.add('maca-guest-share-qr-open');
    }

    function closeGuestShareQrModal() {
        var modal = document.getElementById('maca-guest-share-qr-modal');
        if (!modal) {
            return;
        }

        modal.hidden = true;
        document.body.classList.remove('maca-guest-share-qr-open');
    }

    function guestSessionShouldShowShareQr(statuses) {
        if (!guestStatusEnabled() || !statuses || !statuses.length) {
            return false;
        }

        if (!paymentsFlowEnabled()) {
            return statuses.length > 1;
        }

        return statuses.some(function (entry) {
            var payment = entry.data && entry.data.payment;
            if (!payment || !payment.enabled || payment.is_paid) {
                return false;
            }

            if (payment.bill_split && payment.bill_split.active && !payment.bill_split.complete) {
                return true;
            }

            return !!(payment.show_checkout_ui && (payment.can_choose || payment.can_pay_online));
        }) || statuses.length > 1;
    }

    function updateGuestShareQrButton(statuses, ui) {
        var button = ui.guestShareQrBtn;
        if (!button) {
            return;
        }

        var visible = guestSessionShouldShowShareQr(statuses);
        button.hidden = !visible;
    }

    function restoreGuestSessionFromToken(guestToken, ui) {
        if (!guestToken || !guestStatusEnabled()) {
            return Promise.resolve(false);
        }

        return fetchGuestOrderStatus(guestToken)
            .then(function (payload) {
                if (!payload || !payload.success || !payload.data) {
                    return false;
                }

                var data = payload.data;
                if (data.closed) {
                    return false;
                }

                addOrderToGuestSession(
                    data.order_id,
                    guestToken,
                    data.table_number || '',
                    !!data.appendable
                );
                updateGuestSessionBar(ui);
                openGuestStatus(ui);
                startGuestStatusPolling(ui);
                return true;
            })
            .catch(function () {
                return false;
            });
    }

    function restoreGuestSessionFromUrl(ui) {
        var tokens = getGuestOrderTokensFromUrl();
        if (!tokens.length || !guestStatusEnabled()) {
            return Promise.resolve(false);
        }

        var requests = tokens.map(function (guestToken) {
            return fetchGuestOrderStatus(guestToken).then(function (payload) {
                if (!payload || !payload.success || !payload.data || payload.data.closed) {
                    return null;
                }

                return {
                    token: guestToken,
                    data: payload.data,
                };
            });
        });

        return Promise.all(requests)
            .then(function (entries) {
                var active = entries.filter(Boolean);
                if (!active.length) {
                    return false;
                }

                mergeGuestSessionFromStatuses(active);
                updateGuestSessionBar(ui);
                openGuestStatus(ui);
                startGuestStatusPolling(ui);
                stripGuestOrderTokenFromUrl();
                return true;
            })
            .catch(function () {
                return false;
            });
    }

    function renderGuestStatusSteps(data, stepsEl) {
        if (!stepsEl) {
            return;
        }

        var steps = data.steps || (config() && config().statusSteps) || [];
        var currentIndex = typeof data.status_index === 'number' ? data.status_index : 0;
        var html = '';

        steps.forEach(function (step, index) {
            var className = '';
            if (index < currentIndex) {
                className = ' is-done';
            } else if (index === currentIndex && !data.complete) {
                className = ' is-current';
            } else if (data.complete && index === steps.length - 1) {
                className = ' is-done is-current';
            } else if (index <= currentIndex) {
                className = ' is-done';
            }

            html += '<li class="' + className.trim() + '">' + escapeHtml(step.label) + '</li>';
        });

        stepsEl.innerHTML = html;
    }

    function guestPaymentShowsCheckout(payment) {
        return !!(payment && payment.show_checkout_ui);
    }

    function guestSessionAllOrdersPaid(statuses) {
        if (!paymentsFlowEnabled() || !statuses || !statuses.length) {
            return false;
        }

        var hasPayableOrder = false;

        for (var i = 0; i < statuses.length; i++) {
            var entry = statuses[i];
            if (!entry || !entry.data) {
                continue;
            }

            var payment = entry.data.payment;
            if (!payment || !payment.enabled) {
                continue;
            }

            hasPayableOrder = true;
            if (!payment.is_paid) {
                return false;
            }
        }

        return hasPayableOrder;
    }

    function updateGuestAllPaidBanner(statuses, ui) {
        ensureGuestStatusUi(ui);

        var allPaid = guestSessionAllOrdersPaid(statuses);
        var banner = ui.guestStatusAllPaid;

        if (banner) {
            if (allPaid) {
                banner.textContent = t('allPaid');
                banner.hidden = false;
            } else {
                banner.textContent = '';
                banner.hidden = true;
            }
        }

        if (ui.guestStatusHint) {
            ui.guestStatusHint.hidden = allPaid;
        }
    }

    function guestPaymentNeedsTipSelection(payment) {
        if (!payment || !payment.tips_enabled || payment.is_paid) {
            return false;
        }
        return payment.tip_choices && payment.tip_choices.length > 0;
    }

    function isGuestTipChoiceSelected(payment, choice) {
        var choiceId = choice.is_custom ? 'custom' : choice.id;

        if (choice.is_custom) {
            return false;
        }
        if (payment.tip_amount > 0 && Math.abs((choice.amount || 0) - payment.tip_amount) < 0.01) {
            return true;
        }
        return payment.tip_amount <= 0 && (choice.preset === 0 || choice.preset === '0');
    }

    function getGuestTipChoiceId(choice) {
        return choice.is_custom ? 'custom' : String(choice.id);
    }

    function formatGuestTipOptionLabel(choice) {
        if (choice.amount_label) {
            return choice.label + ' (' + choice.amount_label + ')';
        }
        return choice.label;
    }

    function guestTipUiLocked(payment) {
        if (!payment) {
            return false;
        }

        if (payment.tip_ui_locked === true || payment.tip_selected === true) {
            return true;
        }

        return payment.is_paid === true
            || payment.status === 'pending'
            || (payment.method && payment.method !== '');
    }

    function guestPaymentRequiresTipChoiceFromBlock(paymentBlock) {
        if (!paymentBlock || paymentBlock.getAttribute('data-tips-required') !== '1') {
            return false;
        }

        syncGuestTipBlockFromSelect(paymentBlock);
        return !paymentBlock.getAttribute('data-tip-choice');
    }

    function syncGuestTipBlockFromSelect(paymentBlock) {
        if (!paymentBlock) {
            return;
        }

        var select = paymentBlock.querySelector('.maca-guest-tip-select');
        if (!select) {
            return;
        }

        var choiceId = select.value;
        var option = select.options[select.selectedIndex];
        var customWrap = paymentBlock.querySelector('.maca-guest-tip-custom');

        if (!choiceId) {
            paymentBlock.removeAttribute('data-tip-choice');
            paymentBlock.removeAttribute('data-tip-amount');
            if (customWrap) {
                customWrap.hidden = true;
            }
            return;
        }

        paymentBlock.setAttribute('data-tip-choice', choiceId);

        if (choiceId === 'custom') {
            paymentBlock.removeAttribute('data-tip-amount');
            if (customWrap) {
                customWrap.hidden = false;
            }
            return;
        }

        if (customWrap) {
            customWrap.hidden = true;
        }

        if (option) {
            var tipAmount = option.getAttribute('data-tip-amount');
            if (tipAmount !== null && tipAmount !== '') {
                paymentBlock.setAttribute('data-tip-amount', tipAmount);
            } else {
                paymentBlock.removeAttribute('data-tip-amount');
            }
        }
    }

    function renderGuestTipSection(payment, guestToken) {
        if (!guestPaymentNeedsTipSelection(payment)) {
            return '';
        }

        var selectedId = '';
        var hasPresetSelected = false;

        payment.tip_choices.forEach(function (choice) {
            if (!choice.is_custom && isGuestTipChoiceSelected(payment, choice)) {
                selectedId = getGuestTipChoiceId(choice);
                hasPresetSelected = true;
            }
        });

        var tipLocked = guestTipUiLocked(payment);
        var html = '<div class="maca-guest-order-tips">';
        html += '<label class="maca-guest-order-tip-field">';
        html += '<span class="maca-guest-order-tips-title">' + escapeHtml(t('tipTitle')) + '</span>';
        html += '<select class="maca-guest-tip-select" data-guest-token="' + escapeHtml(String(guestToken || '')) + '"';
        html += ' aria-label="' + escapeHtml(t('tipTitle')) + '"';
        if (tipLocked) {
            html += ' disabled';
        }
        html += '>';

        if (!hasPresetSelected && !tipLocked) {
            html += '<option value="" disabled' + (selectedId === '' ? ' selected' : '') + '>';
            html += escapeHtml(t('tipSelectPlaceholder'));
            html += '</option>';
        }

        payment.tip_choices.forEach(function (choice) {
            var choiceId = getGuestTipChoiceId(choice);
            var selected = !choice.is_custom && isGuestTipChoiceSelected(payment, choice);

            if (selected) {
                selectedId = choiceId;
            }

            html += '<option value="' + escapeHtml(choiceId) + '"';
            if (selected) {
                html += ' selected';
            }
            if (choice.amount !== null && choice.amount !== undefined) {
                html += ' data-tip-amount="' + escapeHtml(String(choice.amount)) + '"';
            }
            html += '>' + escapeHtml(formatGuestTipOptionLabel(choice)) + '</option>';
        });

        html += '</select>';
        html += '</label>';
        html += '<div class="maca-guest-tip-custom"' + (selectedId === 'custom' ? '' : ' hidden') + '>';
        html += '<label class="maca-guest-tip-custom-label" for="maca-tip-custom-' + escapeHtml(String(guestToken || 'guest')) + '">';
        html += escapeHtml(t('tipCustom'));
        html += '</label>';
        html += '<div class="maca-guest-tip-custom-row">';
        html += '<input type="number" min="0" step="1" id="maca-tip-custom-' + escapeHtml(String(guestToken || 'guest')) + '"';
        html += ' class="maca-guest-tip-custom-input" inputmode="decimal" placeholder="' + escapeHtml(t('tipCustomPlaceholder')) + '"';
        if (tipLocked) {
            html += ' disabled';
        }
        html += ' />';
        html += '<button type="button" class="maca-guest-tip-custom-apply" data-guest-token="' + escapeHtml(String(guestToken || '')) + '"';
        if (tipLocked) {
            html += ' disabled';
        }
        html += '>' + escapeHtml(t('tipApply')) + '</button>';
        html += '</div>';
        html += '</div>';
        html += '</div>';

        return html;
    }

    function guestPaymentBlockDraftKey(block) {
        if (!block) {
            return '';
        }

        if (block.getAttribute('data-combined-payment') === '1') {
            return 'combined';
        }

        return guestPaymentEmailDraftKey(
            block.getAttribute('data-guest-token'),
            block.getAttribute('data-order-id')
        );
    }

    function guestPaymentFormHasFocus(container) {
        if (!container) {
            return false;
        }

        var active = document.activeElement;
        if (!active || !container.contains(active)) {
            return false;
        }

        return active.matches(
            '.maca-guest-bill-split-count, .maca-guest-bill-split-fixed-amount, ' +
            '.maca-guest-confirmation-email-input, .maca-guest-confirmation-email-toggle, ' +
            '.maca-guest-tip-custom-input, .maca-guest-tip-select, ' +
            'input[name="maca-bill-split-mode"], .maca-guest-bill-split-toggle, .maca-guest-bill-split-apply'
        );
    }

    function getGuestBillSplitDraft(guestToken) {
        var key = guestToken ? String(guestToken) : '';
        if (!key || !guestBillSplitDrafts[key]) {
            return null;
        }

        return guestBillSplitDrafts[key];
    }

    function setGuestBillSplitDraft(guestToken, draft) {
        var key = guestToken ? String(guestToken) : '';
        if (!key) {
            return;
        }

        guestBillSplitDrafts[key] = {
            open: !!draft.open,
            mode: draft.mode === 'fixed' ? 'fixed' : 'equal',
            people: draft.people !== undefined && draft.people !== null ? String(draft.people) : '',
            fixed_amount: draft.fixed_amount !== undefined && draft.fixed_amount !== null ? String(draft.fixed_amount) : '',
        };
    }

    function clearGuestBillSplitDraft(guestToken) {
        var key = guestToken ? String(guestToken) : '';
        if (key) {
            delete guestBillSplitDrafts[key];
        }
    }

    function syncGuestBillSplitDraftFromBlock(block) {
        if (!block) {
            return;
        }

        var token = block.getAttribute('data-guest-token');
        if (!token) {
            return;
        }

        var body = block.querySelector('.maca-guest-bill-split-body');
        var countSelect = block.querySelector('.maca-guest-bill-split-count');
        var fixedInput = block.querySelector('.maca-guest-bill-split-fixed-amount');

        setGuestBillSplitDraft(token, {
            open: !!(body && !body.hasAttribute('hidden')),
            mode: getGuestBillSplitModeFromBlock(block),
            people: countSelect ? countSelect.value : '',
            fixed_amount: fixedInput ? fixedInput.value : '',
        });
    }

    function syncAllGuestBillSplitDrafts(container) {
        if (!container) {
            return;
        }

        container.querySelectorAll('.maca-guest-bill-split').forEach(syncGuestBillSplitDraftFromBlock);
    }

    function getGuestBillSplitModeFromBlock(block) {
        if (!block) {
            return 'equal';
        }

        var checked = block.querySelector('input[name="maca-bill-split-mode"]:checked');

        return checked ? String(checked.value) : 'equal';
    }

    function syncGuestBillSplitModePanels(block) {
        if (!block) {
            return;
        }

        var mode = getGuestBillSplitModeFromBlock(block);
        var equalPanel = block.querySelector('.maca-guest-bill-split-panel--equal');
        var fixedPanel = block.querySelector('.maca-guest-bill-split-panel--fixed');

        if (equalPanel) {
            equalPanel.hidden = mode !== 'equal';
        }
        if (fixedPanel) {
            fixedPanel.hidden = mode !== 'fixed';
        }
    }

    function renderGuestShareQrPrompt() {
        if (!paymentsFlowEnabled()) {
            return '';
        }

        var html = '<div class="maca-guest-share-qr-prompt">';
        html += '<p class="maca-guest-share-qr-prompt-text">' + escapeHtml(t('shareOrderQrHint')) + '</p>';
        html += '<button type="button" class="maca-guest-order-share-qr maca-guest-share-qr-inline">' + escapeHtml(t('shareOrderQr')) + '</button>';
        html += '</div>';
        return html;
    }

    function renderGuestBillSplitSection(payment, guestToken) {
        var split = payment && payment.bill_split ? payment.bill_split : null;

        if (!split || !split.feature_enabled || !split.enabled) {
            return '';
        }

        var isActive = !!split.active;
        var canSetup = !isActive && !!split.can_change;
        var canShow = isActive || canSetup;

        if (!canShow) {
            return '';
        }

        var draft = canSetup ? getGuestBillSplitDraft(guestToken) : null;
        var panelOpen = !!(draft && draft.open);
        var draftMode = draft && draft.mode === 'fixed' ? 'fixed' : 'equal';
        var draftPeople = draft && draft.people ? parseInt(String(draft.people), 10) : split.min_people;
        if (Number.isNaN(draftPeople) || draftPeople < split.min_people) {
            draftPeople = split.min_people;
        }
        if (draftPeople > split.max_people) {
            draftPeople = split.max_people;
        }
        var draftFixedAmount = draft && draft.fixed_amount ? String(draft.fixed_amount) : '';

        var html = '<div class="maca-guest-bill-split' + (isActive ? ' maca-guest-bill-split--active' : ' maca-guest-bill-split--inactive');
        if (canSetup && panelOpen) {
            html += ' is-open';
        }
        html += '" data-guest-token="' + escapeHtml(guestToken) + '">';

        if (canSetup) {
            html += '<button type="button" class="maca-guest-bill-split-toggle" aria-expanded="' + (panelOpen ? 'true' : 'false') + '" aria-controls="maca-bill-split-body-' + escapeHtml(guestToken) + '">';
            html += escapeHtml(panelOpen ? t('billSplitHide') : t('billSplitShow'));
            html += '</button>';
        }

        html += '<div class="maca-guest-bill-split-body" id="maca-bill-split-body-' + escapeHtml(guestToken) + '"';
        if (canSetup && !panelOpen) {
            html += ' hidden';
        }
        html += '>';

        html += '<p class="maca-guest-bill-split-title"><strong>' + escapeHtml(t('billSplitTitle')) + '</strong></p>';

        if (isActive) {
            if (split.mode === 'fixed' && split.fixed_amount_label) {
                html += '<p class="maca-guest-bill-split-active">' + escapeHtml(
                    t('billSplitActiveFixed').replace('%s', split.fixed_amount_label)
                ) + '</p>';
            } else {
                html += '<p class="maca-guest-bill-split-active">' + escapeHtml(t('billSplitActive').replace('%d', String(split.count))) + '</p>';
            }

            if (split.next_share_label) {
                html += '<p class="maca-guest-bill-split-share">' + escapeHtml(t('billSplitYourShare').replace('%s', split.next_share_label)) + '</p>';
            }

            if (split.paid_shares > 0) {
                if (split.mode === 'fixed' && split.remaining_label) {
                    html += '<p class="maca-guest-bill-split-progress">' + escapeHtml(
                        t('billSplitProgressFixed')
                            .replace('%1$d', String(split.paid_shares))
                            .replace('%2$s', split.remaining_label)
                    ) + '</p>';
                } else if (split.mode === 'equal') {
                    html += '<p class="maca-guest-bill-split-progress">' + escapeHtml(
                        t('billSplitProgress')
                            .replace('%1$d', String(split.paid_shares))
                            .replace('%2$d', String(split.count))
                    ) + '</p>';
                }
            } else if (split.mode === 'fixed' && split.remaining_label) {
                html += '<p class="maca-guest-bill-split-progress">' + escapeHtml(
                    t('billSplitRemaining').replace('%s', split.remaining_label)
                ) + '</p>';
            }

            if (split.can_change) {
                html += '<button type="button" class="maca-guest-pay-waiter maca-guest-bill-split-clear" data-guest-token="' + escapeHtml(guestToken) + '">' + escapeHtml(t('billSplitClear')) + '</button>';
            }

            if (!split.complete) {
                html += renderGuestShareQrPrompt();
            }
        } else if (canSetup) {
            html += '<p class="maca-guest-bill-split-hint">' + escapeHtml(t('billSplitHint')) + '</p>';

            html += '<fieldset class="maca-guest-bill-split-modes">';
            html += '<label class="maca-guest-bill-split-mode-option">';
            html += '<input type="radio" name="maca-bill-split-mode" value="equal"' + (draftMode === 'equal' ? ' checked' : '') + '> ';
            html += '<span>' + escapeHtml(t('billSplitModeEqual')) + '</span>';
            html += '</label>';
            html += '<label class="maca-guest-bill-split-mode-option">';
            html += '<input type="radio" name="maca-bill-split-mode" value="fixed"' + (draftMode === 'fixed' ? ' checked' : '') + '> ';
            html += '<span>' + escapeHtml(t('billSplitModeFixed')) + '</span>';
            html += '</label>';
            html += '</fieldset>';

            html += '<div class="maca-guest-bill-split-panel maca-guest-bill-split-panel--equal"' + (draftMode !== 'equal' ? ' hidden' : '') + '>';
            html += '<label class="maca-guest-bill-split-field">';
            html += '<span>' + escapeHtml(t('billSplitPeople')) + '</span>';
            html += '<select class="maca-guest-bill-split-count">';
            for (var n = split.min_people; n <= split.max_people; n++) {
                html += '<option value="' + n + '"' + (n === draftPeople ? ' selected' : '') + '>' + n + '</option>';
            }
            html += '</select>';
            html += '</label>';
            html += '</div>';

            html += '<div class="maca-guest-bill-split-panel maca-guest-bill-split-panel--fixed"' + (draftMode !== 'fixed' ? ' hidden' : '') + '>';
            html += '<label class="maca-guest-bill-split-field">';
            html += '<span>' + escapeHtml(t('billSplitFixedAmount')) + '</span>';
            html += '<input type="number" class="maca-guest-bill-split-fixed-amount" min="1" step="1" inputmode="decimal"';
            if (split.order_total > 0) {
                html += ' max="' + escapeHtml(String(split.order_total)) + '"';
            }
            if (draftFixedAmount !== '') {
                html += ' value="' + escapeHtml(draftFixedAmount) + '"';
            }
            html += ' placeholder="200">';
            html += '</label>';
            if (split.order_total_label) {
                html += '<p class="maca-guest-bill-split-total-hint">' + escapeHtml(split.order_total_label) + '</p>';
            }
            html += '</div>';

            html += '<button type="button" class="maca-guest-pay-online maca-guest-bill-split-apply" data-guest-token="' + escapeHtml(guestToken) + '">' + escapeHtml(t('billSplitApply')) + '</button>';
        }

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

    function saveGuestBillSplit(guestToken, payload) {
        var cfg = config();
        var formData = new FormData();
        formData.append('action', 'maca_set_order_bill_split');
        formData.append('nonce', cfg.nonce);
        formData.append('guest_token', guestToken);
        formData.append('mode', payload.mode || '');
        formData.append('people', String(payload.people || 0));
        formData.append('fixed_amount', String(payload.fixed_amount || 0));

        return fetch(cfg.ajaxUrl, {
            method: 'POST',
            credentials: 'same-origin',
            body: formData,
        }).then(function (response) {
            return response.json();
        });
    }

    function saveGuestBillSplitCombined(tokens, payload) {
        var cfg = config();
        var formData = new FormData();
        formData.append('action', 'maca_set_combined_order_bill_split');
        formData.append('nonce', cfg.nonce);
        formData.append('guest_tokens', JSON.stringify(tokens));
        formData.append('mode', payload.mode || '');
        formData.append('people', String(payload.people || 0));
        formData.append('fixed_amount', String(payload.fixed_amount || 0));

        return fetch(cfg.ajaxUrl, {
            method: 'POST',
            credentials: 'same-origin',
            body: formData,
        }).then(function (response) {
            return response.json();
        });
    }

    function splitAmountIntoShares(total, count) {
        var safeTotal = Math.max(0, parseFloat(total) || 0);
        var safeCount = Math.max(0, parseInt(count, 10) || 0);
        if (safeCount <= 0) {
            return [];
        }

        var baseCents = Math.floor((safeTotal * 100) / safeCount);
        var remainder = Math.round(safeTotal * 100) - (baseCents * safeCount);
        var shares = [];

        for (var i = 0; i < safeCount; i += 1) {
            var cents = baseCents + (i < remainder ? 1 : 0);
            shares.push(Math.round(cents) / 100);
        }

        return shares;
    }

    function buildCombinedBillSplitState(entries) {
        var primaryPayment = entries[0] && entries[0].data ? entries[0].data.payment : null;
        var templateSplit = primaryPayment && primaryPayment.bill_split ? primaryPayment.bill_split : null;

        if (!templateSplit || !templateSplit.feature_enabled) {
            return {
                feature_enabled: false,
                enabled: false,
            };
        }

        var combinedTotal = 0;
        var timingOk = true;
        var pending = false;

        entries.forEach(function (entry) {
            var payment = entry && entry.data ? entry.data.payment : null;
            if (!payment) {
                return;
            }
            combinedTotal += payment.total || 0;
            timingOk = timingOk && !!payment.timing_ok;
            if (payment.status === 'pending') {
                pending = true;
            }
        });

        var split = Object.assign({}, templateSplit);
        split.order_total = combinedTotal;
        split.order_total_label = combinedTotal > 0 ? formatPrice(combinedTotal) : '';
        split.enabled = !!templateSplit.feature_enabled
            && timingOk
            && !pending
            && !split.complete
            && combinedTotal > 0;

        if (split.active) {
            var paidAmount = 0;
            if (split.mode === 'equal' && split.count > 0) {
                var shares = splitAmountIntoShares(combinedTotal, split.count);
                for (var i = 0; i < split.paid_shares && i < shares.length; i += 1) {
                    paidAmount += shares[i];
                }
            } else if (split.mode === 'fixed') {
                paidAmount = (split.paid_shares || 0) * (split.fixed_amount || 0);
            }

            var remaining = Math.max(0, combinedTotal - paidAmount);
            var nextAmount = 0;

            if (remaining > 0) {
                if (split.mode === 'fixed' && split.fixed_amount > 0) {
                    nextAmount = Math.min(split.fixed_amount, remaining);
                } else if (split.mode === 'equal' && split.count > 0) {
                    var nextShares = splitAmountIntoShares(combinedTotal, split.count);
                    nextAmount = nextShares[split.paid_shares] || remaining;
                    nextAmount = Math.min(nextAmount, remaining);
                } else {
                    nextAmount = remaining;
                }
            }

            split.remaining = remaining;
            split.remaining_label = remaining > 0 ? formatPrice(remaining) : '';
            split.next_share_amount = nextAmount;
            split.next_share_label = nextAmount > 0 ? formatPrice(nextAmount) : '';
            split.complete = remaining <= 0.009
                || (split.mode === 'equal' && split.paid_shares >= split.count);

            if (split.mode === 'fixed' && split.fixed_amount > 0 && remaining > 0) {
                split.estimated_payments = Math.ceil(remaining / split.fixed_amount);
            }
        }

        return split;
    }

    function renderGuestPaymentTransactions(payment) {
        if (!payment || !payment.payment_transactions || !payment.payment_transactions.length) {
            return '';
        }

        var html = '<div class="maca-guest-order-payment-transactions">';
        if (payment.payment_transactions_label) {
            html += '<p class="maca-guest-order-payment-transactions-summary"><strong>' + escapeHtml(t('paymentTransactions')) + ':</strong> ' + escapeHtml(payment.payment_transactions_label) + '</p>';
        }
        html += '<ul class="maca-guest-order-payment-transactions-list">';
        payment.payment_transactions.forEach(function (tx) {
            html += '<li>';
            html += '<span class="maca-guest-order-payment-tx-title">' + escapeHtml(t('paymentNumber').replace('%d', String(tx.number))) + '</span> ';
            html += '<span class="maca-guest-order-payment-tx-amount">' + escapeHtml(tx.amount_label) + '</span>';
            if (tx.kind_label) {
                html += ' <span class="maca-guest-order-payment-tx-kind">(' + escapeHtml(tx.kind_label) + ')</span>';
            }
            if (tx.paid_at_label) {
                html += '<br><span class="maca-guest-order-payment-tx-time">' + escapeHtml(tx.paid_at_label) + '</span>';
            }
            html += '</li>';
        });
        html += '</ul></div>';
        return html;
    }

    function renderGuestPaymentTotals(payment) {
        var html = '';
        if (payment.subtotal_label) {
            html += '<p class="maca-guest-order-payment-subtotal"><strong>' + escapeHtml(t('subtotal')) + ':</strong> ' + escapeHtml(payment.subtotal_label) + '</p>';
        }
        if (payment.tips_enabled && payment.tip_label) {
            html += '<p class="maca-guest-order-payment-tip"><strong>' + escapeHtml(t('tip')) + ':</strong> ' + escapeHtml(payment.tip_label) + '</p>';
        }
        if (payment.total_label) {
            html += '<p class="maca-guest-order-payment-total"><strong>' + escapeHtml(t('grandTotal')) + ':</strong> ' + escapeHtml(payment.total_label) + '</p>';
        }
        return html;
    }

    function appendTipToFormData(formData, paymentBlock) {
        if (!paymentBlock) {
            return;
        }

        syncGuestTipBlockFromSelect(paymentBlock);

        var choice = paymentBlock.getAttribute('data-tip-choice');
        var amount = paymentBlock.getAttribute('data-tip-amount');

        if (choice) {
            formData.append('tip_choice', choice);
        }
        if (amount !== null && amount !== undefined && amount !== '') {
            formData.append('tip_amount', amount);
        }

        var customInput = paymentBlock.querySelector('.maca-guest-tip-custom-input');
        if (customInput && choice === 'custom') {
            formData.append('tip_custom_amount', customInput.value);
        }
    }

    function guestPaymentEmailDraftKey(guestToken, orderId) {
        if (guestToken) {
            return String(guestToken);
        }
        if (orderId) {
            return 'order:' + String(orderId);
        }
        return '';
    }

    function getGuestPaymentEmailDraft(guestToken, orderId) {
        var key = guestPaymentEmailDraftKey(guestToken, orderId);
        if (!key || !guestPaymentEmailDrafts[key]) {
            return null;
        }
        return guestPaymentEmailDrafts[key];
    }

    function setGuestPaymentEmailDraft(guestToken, orderId, draft) {
        var key = guestPaymentEmailDraftKey(guestToken, orderId);
        if (!key) {
            return;
        }
        guestPaymentEmailDrafts[key] = {
            confirmationChecked: !!draft.confirmationChecked,
            confirmationEmail: draft.confirmationEmail ? String(draft.confirmationEmail) : '',
        };
    }

    function setGuestPaymentEmailDraftByKey(key, draft) {
        if (!key) {
            return;
        }
        guestPaymentEmailDrafts[key] = {
            confirmationChecked: !!draft.confirmationChecked,
            confirmationEmail: draft.confirmationEmail ? String(draft.confirmationEmail) : '',
        };
    }

    function syncGuestPaymentEmailDraftFromBlock(block) {
        if (!block) {
            return;
        }

        var toggle = block.querySelector('.maca-guest-confirmation-email-toggle');
        var input = block.querySelector('.maca-guest-confirmation-email-input');
        if (!toggle && !input) {
            return;
        }

        setGuestPaymentEmailDraftByKey(
            guestPaymentBlockDraftKey(block),
            {
                confirmationChecked: toggle ? toggle.checked : false,
                confirmationEmail: input ? input.value : '',
            }
        );
    }

    function syncAllGuestPaymentEmailDrafts(container) {
        if (!container) {
            return;
        }
        container.querySelectorAll('.maca-guest-order-payment').forEach(syncGuestPaymentEmailDraftFromBlock);
    }

    function clearGuestPaymentEmailDraft(guestToken, orderId) {
        var key = guestPaymentEmailDraftKey(guestToken, orderId);
        if (key) {
            delete guestPaymentEmailDrafts[key];
        }
    }

    function guestPaymentShowsEmailConfirmation(payment) {
        return payment && payment.show_email_confirmation === true;
    }

    function renderGuestEmailConfirmationSection(payment, guestToken, orderId) {
        if (!guestPaymentShowsEmailConfirmation(payment)) {
            return '';
        }

        var draft = getGuestPaymentEmailDraft(guestToken, orderId);
        var checked = draft && draft.confirmationChecked;
        var emailValue = draft && draft.confirmationEmail ? draft.confirmationEmail : '';

        var html = '<div class="maca-guest-order-payment-email">';
        html += '<label class="maca-guest-confirmation-email-label">';
        html += '<input type="checkbox" class="maca-guest-confirmation-email-toggle" value="1"' + (checked ? ' checked' : '') + '>';
        html += ' <span>' + escapeHtml(t('confirmationEmailToggle')) + '</span>';
        html += '</label>';
        html += '<input type="email" class="maca-guest-confirmation-email-input" inputmode="email" autocomplete="email" placeholder="' + escapeHtml(t('confirmationEmailPlaceholder')) + '" value="' + escapeHtml(emailValue) + '"' + (checked ? '' : ' hidden disabled') + '>';
        html += '</div>';
        return html;
    }

    function appendConfirmationEmailToFormData(formData, paymentBlock) {
        if (!paymentBlock) {
            return true;
        }

        var toggle = paymentBlock.querySelector('.maca-guest-confirmation-email-toggle');
        var input = paymentBlock.querySelector('.maca-guest-confirmation-email-input');
        if (!toggle || !toggle.checked) {
            return true;
        }

        var email = input ? input.value.trim() : '';
        if (!email || email.indexOf('@') < 1) {
            window.alert(t('confirmationEmailInvalid'));
            return false;
        }

        formData.append('send_confirmation', '1');
        formData.append('confirmation_email', email);
        return true;
    }

    function setConfirmationEmailFieldVisible(paymentBlock, visible) {
        if (!paymentBlock) {
            return;
        }

        var input = paymentBlock.querySelector('.maca-guest-confirmation-email-input');
        if (!input) {
            return;
        }

        input.hidden = !visible;
        input.disabled = !visible;
        if (!visible) {
            input.value = '';
        }

        syncGuestPaymentEmailDraftFromBlock(paymentBlock);
    }

    function findPaymentBlockForToken(root, guestToken) {
        if (!root) {
            return null;
        }
        var blocks = root.querySelectorAll('.maca-guest-order-payment');
        for (var i = 0; i < blocks.length; i++) {
            var block = blocks[i];
            var payWaiter = block.querySelector('[data-guest-token="' + guestToken + '"]');
            if (payWaiter || block.getAttribute('data-guest-token') === guestToken) {
                return block;
            }
        }
        return blocks.length === 1 ? blocks[0] : null;
    }

    function saveGuestTip(guestToken, paymentBlock) {
        var cfg = config();
        var formData = new FormData();
        formData.append('action', 'maca_set_table_order_tip');
        formData.append('nonce', cfg.nonce);
        formData.append('guest_token', guestToken);
        appendTipToFormData(formData, paymentBlock);

        return fetch(cfg.ajaxUrl, {
            method: 'POST',
            credentials: 'same-origin',
            body: formData,
        }).then(function (response) {
            return response.json();
        });
    }

    function orderEligibleForCombinedPayment(data, isPrimary) {
        var payment = data && data.payment;
        if (!payment || !payment.enabled || !payment.timing_ok || payment.is_paid) {
            return false;
        }
        if (payment.status === 'pending') {
            return false;
        }
        if (payment.method && payment.method !== 'online') {
            return false;
        }

        var splitInProgress = isPrimary
            && payment.bill_split
            && payment.bill_split.active
            && !payment.bill_split.complete;

        if (payment.payment_transactions && payment.payment_transactions.length && !splitInProgress) {
            return false;
        }
        if (!isPrimary && payment.bill_split && payment.bill_split.active) {
            return false;
        }
        if (!splitInProgress && !payment.can_choose && !payment.can_pay_online) {
            return false;
        }
        return (payment.subtotal || 0) > 0 || (payment.total || 0) > 0;
    }

    function orderEligibleAsCombinedAddOn(data, referenceData) {
        var payment = data && data.payment;
        if (!payment || !payment.enabled || !payment.timing_ok || payment.is_paid) {
            return false;
        }
        if (payment.status === 'pending') {
            return false;
        }
        if (payment.method && payment.method !== 'online') {
            return false;
        }
        if (payment.bill_split && payment.bill_split.active) {
            return false;
        }
        if (payment.payment_transactions && payment.payment_transactions.length) {
            return false;
        }
        if (!ordersShareCombinedPaymentGroup(referenceData, data)) {
            return false;
        }
        return (payment.subtotal || 0) > 0 || (payment.total || 0) > 0;
    }

    function collectCombinablePaymentOrders(statuses) {
        if (!statuses || !statuses.length) {
            return null;
        }

        var splitPrimary = null;
        statuses.forEach(function (entry) {
            if (!entry || !entry.data || !entry.token) {
                return;
            }
            var payment = entry.data.payment;
            if (payment && payment.bill_split && payment.bill_split.active && !payment.bill_split.complete) {
                if (
                    !splitPrimary
                    || (entry.data.order_id || 0) < (splitPrimary.data.order_id || Number.MAX_SAFE_INTEGER)
                ) {
                    splitPrimary = entry;
                }
            }
        });

        if (splitPrimary) {
            var splitReference = splitPrimary.data;
            var splitGroup = statuses.filter(function (entry) {
                var payment = entry && entry.data ? entry.data.payment : null;
                if (!entry || !entry.data || !entry.token || !payment || payment.is_paid) {
                    return false;
                }
                if (payment.status === 'pending') {
                    return false;
                }
                if (!ordersShareCombinedPaymentGroup(splitReference, entry.data)) {
                    return false;
                }
                if ((entry.data.order_id || 0) === (splitReference.order_id || 0)) {
                    return orderEligibleForCombinedPayment(entry.data, true);
                }
                return orderEligibleAsCombinedAddOn(entry.data, splitReference);
            });

            splitGroup.sort(function (a, b) {
                return (a.data.order_id || 0) - (b.data.order_id || 0);
            });

            if (splitGroup.length >= 2) {
                return splitGroup;
            }
        }

        var eligible = statuses.filter(function (entry) {
            return entry && entry.data && entry.token && orderEligibleForCombinedPayment(entry.data, true);
        });

        if (eligible.length < 2) {
            return null;
        }

        var reference = eligible[0].data;

        eligible = eligible.filter(function (entry, index) {
            if (index === 0) {
                return true;
            }
            return orderEligibleForCombinedPayment(entry.data, false)
                && ordersShareCombinedPaymentGroup(reference, entry.data);
        });

        return eligible.length >= 2 ? eligible : null;
    }

    function buildCombinedTipChoices(combinedSubtotal, templatePayment) {
        if (!templatePayment || !templatePayment.tip_choices || !templatePayment.tip_choices.length) {
            return [];
        }

        var payCfg = paymentsConfig();
        var mode = payCfg && payCfg.tipsMode ? payCfg.tipsMode : templatePayment.tips_mode;

        return templatePayment.tip_choices.map(function (choice) {
            if (choice.is_custom) {
                return Object.assign({}, choice);
            }

            var copy = Object.assign({}, choice);
            if (mode === 'percent' && choice.preset !== null && choice.preset !== undefined) {
                var amount = combinedSubtotal * (parseFloat(choice.preset, 10) / 100);
                copy.amount = Math.round(amount * 100) / 100;
                if (copy.amount_label) {
                    copy.amount_label = formatPrice(copy.amount);
                }
            }

            return copy;
        });
    }

    function buildCombinedPaymentState(entries) {
        var subtotal = 0;
        var total = 0;
        var allowManual = true;
        var canPayOnline = true;
        var canChoose = true;
        var showEmail = false;
        var templatePayment = null;
        var tipsEnabled = false;

        entries.forEach(function (entry, index) {
            var payment = entry && entry.data ? entry.data.payment : null;
            if (!payment) {
                return;
            }
            subtotal += payment.subtotal || 0;
            total += payment.total || 0;
            allowManual = allowManual && !!payment.allow_manual;
            canPayOnline = canPayOnline && !!payment.can_pay_online;
            if (!payment.can_choose && !(index === 0 && payment.bill_split && payment.bill_split.active)) {
                canChoose = false;
            }
            showEmail = showEmail || !!payment.show_email_confirmation;
            tipsEnabled = tipsEnabled || !!payment.tips_enabled;
            if (!templatePayment) {
                templatePayment = payment;
            }
        });

        var billSplit = buildCombinedBillSplitState(entries);
        var splitActive = !!(billSplit && billSplit.active && !billSplit.complete);
        var splitPending = entries.some(function (entry) {
            return entry.data.payment && entry.data.payment.status === 'pending';
        });

        if (splitActive) {
            canChoose = false;
            canPayOnline = !splitPending
                && !billSplit.complete
                && entries.some(function (entry) {
                    return entry.data.payment && entry.data.payment.allow_online;
                });
            allowManual = allowManual && !billSplit.complete;
        }

        return {
            enabled: true,
            show_checkout_ui: true,
            is_paid: false,
            subtotal: subtotal,
            subtotal_label: subtotal > 0 ? formatPrice(subtotal) : '',
            total: total,
            total_label: total > 0 ? formatPrice(total) : '',
            tips_enabled: tipsEnabled,
            tip_choices: buildCombinedTipChoices(subtotal, templatePayment),
            tips_allow_none: templatePayment ? templatePayment.tips_allow_none : true,
            tips_allow_custom: templatePayment ? templatePayment.tips_allow_custom : false,
            tip_amount: 0,
            allow_manual: allowManual,
            can_pay_online: canPayOnline,
            can_choose: canChoose && (allowManual || canPayOnline) && !splitActive,
            show_email_confirmation: showEmail,
            method: null,
            status: 'none',
            bill_split: billSplit,
        };
    }

    function renderCombinedPaymentBlock(entries) {
        var tokens = entries.map(function (entry) {
            return entry.token;
        });
        var payment = buildCombinedPaymentState(entries);
        var tokensJson = JSON.stringify(tokens);
        var encodedTokens = encodeURIComponent(tokensJson);
        var html = '<div class="maca-guest-combined-payment maca-guest-order-payment" data-combined-payment="1" data-guest-tokens="' + encodedTokens + '">';

        if (guestPaymentNeedsTipSelection(payment) && payment.tips_allow_none !== true) {
            html = html.replace(
                ' data-combined-payment="1"',
                ' data-combined-payment="1" data-tips-required="1"'
            );
        }

        html += '<h3 class="maca-guest-combined-payment-title">' + escapeHtml(t('combinedPaymentTitle')) + '</h3>';
        html += '<p class="maca-guest-combined-payment-count">' + escapeHtml(t('combinedPaymentCount').replace('%d', String(entries.length))) + '</p>';
        html += renderGuestPaymentTotals(payment);
        html += renderGuestBillSplitSection(payment, 'combined');
        html += renderGuestTipSection(payment, 'combined');
        html += renderGuestEmailConfirmationSection(payment, 'combined', 'combined');

        var buttonTokensAttr = ' data-guest-tokens-button="' + escapeHtml(tokensJson) + '"';

        if (payment.can_choose) {
            html += '<p class="maca-guest-order-payment-prompt">' + escapeHtml(t('paymentHow')) + '</p>';
            html += '<div class="maca-guest-order-payment-actions">';
            if (payment.allow_manual) {
                html += '<button type="button" class="maca-guest-pay-combined-waiter"' + buttonTokensAttr + '>' + escapeHtml(t('payAllWaiter')) + '</button>';
            }
            if (payment.can_pay_online) {
                html += '<button type="button" class="maca-guest-pay-combined-online"' + buttonTokensAttr + '>' + escapeHtml(t('payAllOnline')) + '</button>';
            }
            html += '</div>';
        } else if (payment.bill_split && payment.bill_split.active && !payment.bill_split.complete) {
            html += '<div class="maca-guest-order-payment-actions">';
            if (payment.allow_manual) {
                html += '<button type="button" class="maca-guest-pay-combined-waiter"' + buttonTokensAttr + '>' + escapeHtml(t('payYourShare')) + '</button>';
            }
            if (payment.can_pay_online) {
                html += '<button type="button" class="maca-guest-pay-combined-online"' + buttonTokensAttr + '>' + escapeHtml(t('payYourShare')) + '</button>';
            }
            html += '</div>';
            html += renderGuestShareQrPrompt();
        } else if (payment.allow_manual && !payment.can_pay_online && !(payment.bill_split && payment.bill_split.active && !payment.bill_split.complete)) {
            html += '<div class="maca-guest-order-payment-actions">';
            html += '<button type="button" class="maca-guest-pay-combined-waiter"' + buttonTokensAttr + '>' + escapeHtml(t('payAllWaiter')) + '</button>';
            html += '</div>';
        } else if (payment.can_pay_online) {
            html += '<div class="maca-guest-order-payment-actions">';
            html += '<button type="button" class="maca-guest-pay-combined-online"' + buttonTokensAttr + '>' + escapeHtml(t('payAllOnline')) + '</button>';
            html += '</div>';
        }

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

    function guestCombinedPaymentSignature(entries) {
        if (!entries || !entries.length) {
            return '';
        }

        var payment = buildCombinedPaymentState(entries);

        return [
            entries.map(function (entry) {
                return entry.token;
            }).join(','),
            entries.map(function (entry) {
                return entry.data && entry.data.order_id ? String(entry.data.order_id) : '';
            }).join(','),
            guestOrderPaymentSignature(payment),
        ].join(':');
    }

    function updateCombinedPaymentSection(statuses, ui) {
        if (!ui.guestStatusCombined) {
            return false;
        }

        var combinable = collectCombinablePaymentOrders(statuses);
        if (combinable && combinable.length >= 2) {
            var nextSignature = guestCombinedPaymentSignature(combinable);
            var currentSignature = ui.guestStatusCombined.getAttribute('data-payment-signature') || '';
            var hasRenderedBlock = !!ui.guestStatusCombined.querySelector('[data-combined-payment="1"]');

            if (guestPaymentFormHasFocus(ui.guestStatusCombined) && hasRenderedBlock) {
                ui.guestStatusCombined.hidden = false;
                return true;
            }

            if (currentSignature === nextSignature && hasRenderedBlock) {
                ui.guestStatusCombined.hidden = false;
                return true;
            }

            syncAllGuestPaymentEmailDrafts(ui.guestStatusCombined);
            syncAllGuestBillSplitDrafts(ui.guestStatusCombined);
            ui.guestStatusCombined.innerHTML = renderCombinedPaymentBlock(combinable);
            ui.guestStatusCombined.setAttribute('data-payment-signature', nextSignature);
            ui.guestStatusCombined.hidden = false;
            return true;
        }

        ui.guestStatusCombined.innerHTML = '';
        ui.guestStatusCombined.removeAttribute('data-payment-signature');
        ui.guestStatusCombined.hidden = true;
        return false;
    }

    function showPaymentActionError(error, fallbackKey) {
        var message = error && error.message ? String(error.message) : '';
        if (message === 'tip required' || message === 'invalid confirmation email') {
            return;
        }
        window.alert(message || t(fallbackKey || 'paymentError'));
    }

    function getCombinedGuestTokensFromClick(button) {
        if (!button) {
            return [];
        }

        var block = button.closest('[data-combined-payment="1"]');
        var tokens = getCombinedGuestTokens(block || button);
        if (tokens.length) {
            return tokens;
        }

        var buttonTokens = button.getAttribute('data-guest-tokens-button');
        if (buttonTokens) {
            try {
                var parsedButton = JSON.parse(buttonTokens);
                if (Array.isArray(parsedButton) && parsedButton.length) {
                    return parsedButton.filter(Boolean);
                }
            } catch (buttonError) {
                // Fall through.
            }
        }

        return [];
    }

    function throwPaymentRequestError(payload, fallbackKey) {
        var message = payload && payload.data && payload.data.message
            ? String(payload.data.message)
            : '';
        if (message) {
            throw new Error(message);
        }
        throw new Error(t(fallbackKey || 'paymentError'));
    }

    function normalizeCombinedPaymentGroupKey(data) {
        if (!data) {
            return '';
        }

        var phone = data.pickup_phone ? String(data.pickup_phone).replace(/\s+/g, '') : '';
        var name = data.pickup_name ? String(data.pickup_name).trim().toLowerCase() : '';
        if (phone !== '' && name !== '') {
            return 'takeaway:' + phone + ':' + name;
        }

        var table = data.table_number ? String(data.table_number).trim() : '';
        return table !== '' ? 'table:' + table : '';
    }

    function ordersShareCombinedPaymentGroup(dataA, dataB) {
        var keyA = normalizeCombinedPaymentGroupKey(dataA);
        var keyB = normalizeCombinedPaymentGroupKey(dataB);

        return keyA !== '' && keyA === keyB;
    }

    function getCombinedGuestTokens(paymentBlock) {
        if (!paymentBlock) {
            return [];
        }

        var raw = paymentBlock.getAttribute('data-guest-tokens');
        if (raw) {
            try {
                var parsed = JSON.parse(raw);
                if (Array.isArray(parsed) && parsed.length) {
                    return parsed.filter(Boolean);
                }
            } catch (error) {
                try {
                    var decoded = decodeURIComponent(raw);
                    var parsedDecoded = JSON.parse(decoded);
                    if (Array.isArray(parsedDecoded) && parsedDecoded.length) {
                        return parsedDecoded.filter(Boolean);
                    }
                } catch (decodeError) {
                    // Fall through to session lookup.
                }
            }
        }

        var buttonTokens = paymentBlock.getAttribute('data-guest-tokens-button');
        if (!buttonTokens) {
            var buttonWithTokens = paymentBlock.querySelector('[data-guest-tokens-button]');
            if (buttonWithTokens) {
                buttonTokens = buttonWithTokens.getAttribute('data-guest-tokens-button');
            }
        }
        if (buttonTokens) {
            try {
                var parsedButton = JSON.parse(buttonTokens);
                if (Array.isArray(parsedButton) && parsedButton.length) {
                    return parsedButton.filter(Boolean);
                }
            } catch (buttonError) {
                // Fall through to session lookup.
            }
        }

        var session = loadGuestSession();
        if (session && session.orders.length) {
            return session.orders.map(function (order) {
                return order.guestToken;
            }).filter(Boolean);
        }

        return [];
    }

    function findCombinedPaymentBlock(root) {
        if (!root) {
            return null;
        }

        return root.querySelector('[data-combined-payment="1"]');
    }

    function renderGuestPaymentBlock(data) {
        var payment = data && data.payment ? data.payment : null;
        if (!payment || !payment.enabled || !guestPaymentShowsCheckout(payment)) {
            return '';
        }

        var guestToken = String(data.guest_token || '');
        var html = '<div class="maca-guest-order-payment" data-order-id="' + escapeHtml(String(data.order_id)) + '"';
        html += ' data-guest-token="' + escapeHtml(guestToken) + '"';
        if (guestPaymentNeedsTipSelection(payment) && payment.tips_allow_none !== true) {
            html += ' data-tips-required="1"';
        }
        if (payment.tip_amount !== undefined && payment.tip_amount !== null) {
            html += ' data-tip-amount="' + escapeHtml(String(payment.tip_amount)) + '"';
        }
        html += '>';

        html += renderGuestPaymentTotals(payment);
        html += renderGuestBillSplitSection(payment, guestToken);
        html += renderGuestTipSection(payment, guestToken);
        html += renderGuestEmailConfirmationSection(payment, guestToken, data.order_id);

        html += renderGuestPaymentTransactions(payment);

        if (payment.payment_summary_label) {
            html += '<p class="maca-guest-order-payment-summary">' + escapeHtml(payment.payment_summary_label) + '</p>';
        } else if (payment.message) {
            html += '<p class="maca-guest-order-payment-message">' + escapeHtml(payment.message) + '</p>';
        }

        if (payment.can_choose) {
            if (!payment.message) {
                html += '<p class="maca-guest-order-payment-prompt">' + escapeHtml(t('paymentHow')) + '</p>';
            }
            html += '<div class="maca-guest-order-payment-actions">';
            if (payment.allow_manual) {
                html += '<button type="button" class="maca-guest-pay-waiter" data-guest-token="' + escapeHtml(guestToken) + '">' + escapeHtml(t('payWaiter')) + '</button>';
            }
            if (payment.can_pay_online) {
                var payOnlineLabel = payment.bill_split && payment.bill_split.active
                    ? t('payYourShare')
                    : t('payOnline');
                html += '<button type="button" class="maca-guest-pay-online" data-guest-token="' + escapeHtml(guestToken) + '">' + escapeHtml(payOnlineLabel) + '</button>';
            }
            html += '</div>';
        } else if (payment.method === 'manual' && !payment.is_paid) {
            html += '<p class="maca-guest-order-payment-manual">' + escapeHtml(t('paymentManualChosen')) + '</p>';
        } else if (!payment.is_paid && payment.can_pay_online) {
            var retryOnlineLabel = payment.status === 'pending'
                ? t('paymentPending')
                : (payment.bill_split && payment.bill_split.active ? t('payYourShare') : t('payOnline'));
            var retryOnlineClass = (payment.status === 'pending' || payment.method === 'online')
                ? ' maca-guest-pay-online--resume'
                : '';
            html += '<button type="button" class="maca-guest-pay-online' + retryOnlineClass + '" data-guest-token="' + escapeHtml(guestToken) + '">' + escapeHtml(retryOnlineLabel) + '</button>';
        }

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

    function setGuestTokenOnPaymentBlocks(container, guestToken) {
        if (!container || !guestToken) {
            return;
        }
        container.querySelectorAll('.maca-guest-pay-waiter, .maca-guest-pay-online').forEach(function (btn) {
            if (!btn.getAttribute('data-guest-token')) {
                btn.setAttribute('data-guest-token', guestToken);
            }
        });
    }

    function renderGuestOrderCard(data, index, guestToken, options) {
        var html = '';
        var title = index > 0 ? t('addOnOrder') + ' #' + (index + 1) : t('yourOrder');
        var combinedActive = !!(options && options.combinedPaymentActive);

        html += '<article class="maca-guest-order-card" data-order-id="' + escapeHtml(String(data.order_id)) + '" data-guest-token="' + escapeHtml(String(guestToken || '')) + '" data-guest-kitchen="' + escapeHtml(guestOrderKitchenSnapshot(data)) + '" data-guest-stable="' + escapeHtml(guestOrderStableSnapshot(data)) + '">';
        html += '<h3 class="maca-guest-order-card-title">' + escapeHtml(title) + '</h3>';

        if (data.status_label) {
            html += '<p class="maca-guest-order-card-status">' + escapeHtml(data.status_label) + '</p>';
        }

        html += '<ol class="maca-guest-order-status-steps">';
        html += renderGuestOrderCardStepsHtml(data);
        html += '</ol>';

        if (guestShouldShowReadyIn(data)) {
            html += '<p class="maca-guest-order-status-eta">' + escapeHtml(guestReadyInLabel(data)) + '</p>';
        } else if (data.complete) {
            html += '<p class="maca-guest-order-card-message">' + escapeHtml(t('orderComplete')) + '</p>';
        } else if (data.status === 'ready') {
            html += '<p class="maca-guest-order-card-message">' + escapeHtml(t('readyNow')) + '</p>';
        }

        if (data.lines && data.lines.length) {
            html += '<ul class="maca-guest-order-status-lines">';
            data.lines.forEach(function (line) {
                html += '<li>' + escapeHtml(String(line.qty)) + '× ' + escapeHtml(line.title) + '</li>';
            });
            html += '</ul>';
        }

        if (!data.guest_token && guestToken) {
            data.guest_token = guestToken;
        }

        if (combinedActive) {
            if (data.payment && data.payment.is_paid) {
                html += '<p class="maca-guest-order-card-paid">' + escapeHtml(t('paymentPaid')) + '</p>';
            } else if (data.payment && data.payment.subtotal_label) {
                html += '<p class="maca-guest-order-card-subtotal"><strong>' + escapeHtml(t('subtotal')) + ':</strong> ' + escapeHtml(data.payment.subtotal_label) + '</p>';
            }
        } else if (data.payment && data.payment.enabled && data.payment.is_paid) {
            html += '<p class="maca-guest-order-card-paid">' + escapeHtml(t('paymentPaid')) + '</p>';
        } else {
            html += renderGuestPaymentBlock(data);
        }

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

    function syncGuestSessionFromStatuses(statuses) {
        var session = loadGuestSession();
        if (!session) {
            return null;
        }

        var byToken = {};
        statuses.forEach(function (entry) {
            if (entry && entry.token) {
                byToken[entry.token] = entry.data;
            }
        });

        session.orders = session.orders.map(function (order) {
            var data = byToken[order.guestToken];
            if (!data) {
                return order;
            }
            order.appendable = !!data.appendable;
            order.status = data.status;
            order.eta_minutes = guestOrderEtaMinutes(data);
            order.closed = !!data.closed;
            return order;
        }).filter(function (order) {
            var data = byToken[order.guestToken];
            return !data || !data.closed;
        });

        if (!session.orders.length) {
            clearGuestSession();
            return null;
        }

        statuses.some(function (entry) {
            if (entry && entry.data && entry.data.table_number) {
                session.tableNumber = String(entry.data.table_number);
                return true;
            }
            return false;
        });

        saveGuestSession(session);
        return session;
    }

    function updateGuestSessionBar(ui) {
        if (!ui.sessionBar) {
            return;
        }

        var session = loadGuestSession();
        var visible = guestStatusEnabled() && session && session.orders.length && (!ui.guestStatus || ui.guestStatus.hidden);
        ui.sessionBar.hidden = !visible;

        if (visible && ui.sessionLabel) {
            var count = session.orders.length;
            ui.sessionLabel.textContent = count === 1
                ? t('viewMyOrders')
                : t('viewMyOrders') + ' (' + count + ')';
        }
    }

    function renderGuestStatusLines(lines, listEl) {
        if (!listEl) {
            return;
        }

        if (!lines || !lines.length) {
            listEl.innerHTML = '';
            listEl.hidden = true;
            return;
        }

        var html = '';
        lines.forEach(function (line) {
            html += '<li>' + escapeHtml(String(line.qty)) + '× ' + escapeHtml(line.title) + '</li>';
        });
        listEl.innerHTML = html;
        listEl.hidden = false;
    }

    function ensureGuestStatusUi(ui) {
        if (!ui) {
            return ui;
        }

        if (!ui.guestStatus) {
            ui.guestStatus = document.getElementById('maca-guest-order-status');
        }
        if (!ui.guestStatusOrders) {
            ui.guestStatusOrders = document.getElementById('maca-guest-order-status-orders');
        }
        if (!ui.guestStatusCombined) {
            ui.guestStatusCombined = document.getElementById('maca-guest-order-status-combined');
        }
        if (!ui.guestStatusTable) {
            ui.guestStatusTable = document.getElementById('maca-guest-order-status-table');
        }
        if (!ui.guestStatusSteps) {
            ui.guestStatusSteps = document.getElementById('maca-guest-order-status-steps');
        }
        if (!ui.guestStatusMessage) {
            ui.guestStatusMessage = document.getElementById('maca-guest-order-status-message');
        }
        if (!ui.guestStatusEta) {
            ui.guestStatusEta = document.getElementById('maca-guest-order-status-eta');
        }
        if (!ui.guestStatusLines) {
            ui.guestStatusLines = document.getElementById('maca-guest-order-status-lines');
        }
        if (!ui.guestShareQrBtn) {
            ui.guestShareQrBtn = document.getElementById('maca-guest-order-share-qr');
        }
        if (!ui.guestStatusAllPaid) {
            ui.guestStatusAllPaid = document.getElementById('maca-guest-order-status-all-paid');
        }
        if (!ui.guestStatusHint) {
            ui.guestStatusHint = document.getElementById('maca-guest-order-status-hint');
        }

        return ui;
    }

    function renderGuestStatusOrdersFallback(statuses, ui) {
        ensureGuestStatusUi(ui);
        if (!ui.guestStatusOrders) {
            return;
        }

        var cardsHtml = '';
        statuses.forEach(function (entry, index) {
            if (entry && entry.data) {
                cardsHtml += renderGuestOrderCard(entry.data, index, entry.token, {
                    combinedPaymentActive: false,
                });
            }
        });
        ui.guestStatusOrders.innerHTML = cardsHtml;
        ui.guestStatusOrders.hidden = false;
    }

    function updateGuestStatusView(statuses, ui) {
        ensureGuestStatusUi(ui);

        if (!ui.guestStatus || !statuses || !statuses.length) {
            return;
        }

        var session = syncGuestSessionFromStatuses(statuses);
        if (!session) {
            closeGuestStatus(ui);
            updateGuestSessionBar(ui);
            return;
        }

        var first = statuses[0] && statuses[0].data ? statuses[0].data : null;

        if (ui.guestStatusTable && first) {
            if (first.table_number || session.tableNumber) {
                ui.guestStatusTable.textContent = t('table') + ' ' + (first.table_number || session.tableNumber);
                ui.guestStatusTable.hidden = false;
            } else {
                ui.guestStatusTable.hidden = true;
            }
        }

        if (ui.guestStatusOrders) {
            var combinable = null;
            try {
                combinable = collectCombinablePaymentOrders(statuses);
            } catch (error) {
                combinable = null;
            }
            var combinedActive = !!(combinable && combinable.length >= 2);
            var cards = ui.guestStatusOrders.querySelectorAll('.maca-guest-order-card');
            var patchCards = !combinedActive && canPatchGuestOrderCards(ui.guestStatusOrders, statuses);

            if (patchCards) {
                statuses.forEach(function (entry, index) {
                    if (entry.data) {
                        patchGuestOrderCardKitchenState(cards[index], entry.data);
                    }
                });
            } else if (guestPaymentFormHasFocus(ui.guestStatusOrders)) {
                // Keep payment/bill-split/email fields open while the guest is editing.
            } else {
                syncAllGuestPaymentEmailDrafts(ui.guestStatusOrders);
                syncAllGuestBillSplitDrafts(ui.guestStatusOrders);

                var cardsHtml = '';
                statuses.forEach(function (entry, index) {
                    if (entry.data) {
                        if (entry.data.payment && entry.data.payment.is_paid) {
                            clearGuestPaymentEmailDraft(entry.token, entry.data.order_id);
                        }
                        cardsHtml += renderGuestOrderCard(entry.data, index, entry.token, {
                            combinedPaymentActive: combinedActive,
                        });
                    }
                });
                ui.guestStatusOrders.innerHTML = cardsHtml;
            }
            ui.guestStatusOrders.hidden = false;
        }

        try {
            updateCombinedPaymentSection(statuses, ui);
        } catch (error) {
            if (ui.guestStatusCombined) {
                ui.guestStatusCombined.innerHTML = '';
                ui.guestStatusCombined.removeAttribute('data-payment-signature');
                ui.guestStatusCombined.hidden = true;
            }
        }
        updateGuestAllPaidBanner(statuses, ui);
        updateGuestShareQrButton(statuses, ui);

        if (ui.guestStatusSteps) {
            ui.guestStatusSteps.hidden = true;
        }
        if (ui.guestStatusMessage) {
            ui.guestStatusMessage.hidden = true;
        }
        if (ui.guestStatusEta) {
            ui.guestStatusEta.hidden = true;
        }
        if (ui.guestStatusLines) {
            ui.guestStatusLines.hidden = true;
        }

        updateGuestSessionBar(ui);
    }

    function pollGuestSession(ui) {
        ensureGuestStatusUi(ui);

        var session = loadGuestSession();
        if (!session || !session.orders.length) {
            updateGuestSessionBar(ui);
            return;
        }

        var requests = session.orders.map(function (order) {
            return fetchGuestOrderStatus(order.guestToken).then(function (payload) {
                return {
                    token: order.guestToken,
                    data: payload && payload.success ? payload.data : null,
                };
            });
        });

        Promise.all(requests)
            .then(function (results) {
                var active = results.filter(function (entry) {
                    return entry.data;
                });
                if (!active.length) {
                    clearGuestSession();
                    closeGuestStatus(ui);
                    updateGuestSessionBar(ui);
                    return;
                }
                try {
                    updateGuestStatusView(active, ui);
                } catch (error) {
                    renderGuestStatusOrdersFallback(active, ui);
                }
                scheduleGuestPoll(ui, active);
            })
            .catch(function () {
                scheduleGuestPoll(ui, null);
            });
    }

    function startGuestStatusPolling(ui) {
        if (guestPollTimer) {
            window.clearTimeout(guestPollTimer);
            guestPollTimer = null;
        }

        pollGuestSession(ui);
    }

    function openGuestStatus(ui) {
        ensureGuestStatusUi(ui);

        if (!ui.guestStatus) {
            return;
        }

        closePanel(ui);
        closeWaiter(ui);

        ui.guestStatus.hidden = false;
        ui.guestStatus.setAttribute('aria-hidden', 'false');
        document.body.classList.add('maca-guest-order-status-open');
        setBodyClass(false);
        setWaiterClass(false);
    }

    function closeGuestStatus(ui) {
        if (!ui.guestStatus) {
            return;
        }

        ui.guestStatus.hidden = true;
        ui.guestStatus.setAttribute('aria-hidden', 'true');
        document.body.classList.remove('maca-guest-order-status-open');
        updateBar(loadState(), ui);
        updateGuestSessionBar(ui);
    }

    function ensureGuestTipChoiceBeforePay(guestToken, ui) {
        var paymentBlock = ui ? findPaymentBlockForToken(ui.guestStatus, guestToken) : null;

        if (guestPaymentRequiresTipChoiceFromBlock(paymentBlock)) {
            window.alert(t('tipRequired'));
            if (paymentBlock) {
                var tipSelect = paymentBlock.querySelector('.maca-guest-tip-select');
                if (tipSelect) {
                    tipSelect.focus();
                }
            }
            return false;
        }

        return true;
    }

    function choosePaymentMethod(guestToken, method, ui) {
        if (!ensureGuestTipChoiceBeforePay(guestToken, ui)) {
            return Promise.reject(new Error('tip required'));
        }

        var cfg = config();
        var paymentBlock = findPaymentBlockForToken(ui.guestStatus, guestToken);
        var formData = new FormData();
        formData.append('action', 'maca_set_table_order_payment_method');
        formData.append('nonce', cfg.nonce);
        formData.append('guest_token', guestToken);
        formData.append('method', method);
        appendTipToFormData(formData, paymentBlock);

        return fetch(cfg.ajaxUrl, {
            method: 'POST',
            credentials: 'same-origin',
            body: formData,
        }).then(function (response) {
            return response.json();
        }).then(function (payload) {
            if (!payload || !payload.success) {
                throwPaymentRequestError(payload, 'paymentChooseError');
            }
            if (method === 'online') {
                return startOnlineCheckout(guestToken, ui);
            }
            pollGuestSession(ui);
            return payload;
        });
    }

    function startOnlineCheckout(guestToken, ui) {
        if (!ensureGuestTipChoiceBeforePay(guestToken, ui)) {
            return Promise.reject(new Error('tip required'));
        }

        var cfg = config();
        var paymentBlock = ui ? findPaymentBlockForToken(ui.guestStatus, guestToken) : null;
        var formData = new FormData();
        formData.append('action', 'maca_create_table_order_checkout');
        formData.append('nonce', cfg.nonce);
        formData.append('guest_token', guestToken);
        formData.append('return_url', paymentPageUrl());
        appendTipToFormData(formData, paymentBlock);
        if (!appendConfirmationEmailToFormData(formData, paymentBlock)) {
            return Promise.reject(new Error('invalid confirmation email'));
        }

        return fetch(cfg.ajaxUrl, {
            method: 'POST',
            credentials: 'same-origin',
            body: formData,
        }).then(function (response) {
            return response.json();
        }).then(function (payload) {
            if (!payload || !payload.success || !payload.data || !payload.data.url) {
                throwPaymentRequestError(payload, 'paymentError');
            }
            window.location.href = payload.data.url;
            return payload;
        });
    }

    function ensureCombinedTipChoiceBeforePay(ui) {
        var paymentBlock = ui && ui.guestStatusCombined ? findCombinedPaymentBlock(ui.guestStatusCombined) : null;

        if (guestPaymentRequiresTipChoiceFromBlock(paymentBlock)) {
            window.alert(t('tipRequired'));
            if (paymentBlock) {
                var tipSelect = paymentBlock.querySelector('.maca-guest-tip-select');
                if (tipSelect) {
                    tipSelect.focus();
                }
            }
            return false;
        }

        return true;
    }

    function chooseCombinedPaymentMethod(tokens, method, ui) {
        if (!ensureCombinedTipChoiceBeforePay(ui)) {
            return Promise.reject(new Error('tip required'));
        }

        var cfg = config();
        var paymentBlock = ui.guestStatusCombined ? findCombinedPaymentBlock(ui.guestStatusCombined) : null;
        var formData = new FormData();
        formData.append('action', 'maca_set_combined_table_order_payment_method');
        formData.append('nonce', cfg.nonce);
        formData.append('guest_tokens', JSON.stringify(tokens));
        formData.append('method', method);
        appendTipToFormData(formData, paymentBlock);

        return fetch(cfg.ajaxUrl, {
            method: 'POST',
            credentials: 'same-origin',
            body: formData,
        }).then(function (response) {
            return response.json();
        }).then(function (payload) {
            if (!payload || !payload.success) {
                throwPaymentRequestError(payload, 'paymentChooseError');
            }
            if (method === 'online') {
                return startCombinedOnlineCheckout(tokens, ui);
            }
            pollGuestSession(ui);
            return payload;
        });
    }

    function startCombinedOnlineCheckout(tokens, ui) {
        if (!ensureCombinedTipChoiceBeforePay(ui)) {
            return Promise.reject(new Error('tip required'));
        }

        var cfg = config();
        var paymentBlock = ui && ui.guestStatusCombined ? findCombinedPaymentBlock(ui.guestStatusCombined) : null;
        var formData = new FormData();
        formData.append('action', 'maca_create_combined_table_order_checkout');
        formData.append('nonce', cfg.nonce);
        formData.append('guest_tokens', JSON.stringify(tokens));
        formData.append('return_url', paymentPageUrl());
        appendTipToFormData(formData, paymentBlock);
        if (!appendConfirmationEmailToFormData(formData, paymentBlock)) {
            return Promise.reject(new Error('invalid confirmation email'));
        }

        return fetch(cfg.ajaxUrl, {
            method: 'POST',
            credentials: 'same-origin',
            body: formData,
        }).then(function (response) {
            return response.json();
        }).then(function (payload) {
            if (!payload || !payload.success || !payload.data || !payload.data.url) {
                throwPaymentRequestError(payload, 'paymentError');
            }
            window.location.href = payload.data.url;
            return payload;
        });
    }

    function showGuestStatusAfterSubmit(payload, state, ui) {
        var data = payload.data || {};
        var guestToken = data.guest_token;
        var orderId = data.order_id;

        if (!guestToken || !orderId) {
            openWaiter(state, ui, true, data.appended ? t('itemsAdded') : t('orderSent'));
            return;
        }

        openGuestStatus(ui);
        startGuestStatusPolling(ui);
    }

    function showPaymentReturnNotice(ui) {
        var pay = paymentsConfig();
        if (!pay || !pay.returnNotice || !pay.returnNotice.message) {
            return;
        }

        openGuestStatus(ui);
        if (ui.guestStatusMessage) {
            ui.guestStatusMessage.hidden = false;
            ui.guestStatusMessage.textContent = pay.returnNotice.message;
            ui.guestStatusMessage.className = 'maca-guest-order-status-message maca-guest-order-status-message--' + (pay.returnNotice.type || 'info');
        }

        if (pay.returnNotice.token) {
            if (hasActiveGuestSession()) {
                startGuestStatusPolling(ui);
            } else {
                restoreGuestSessionFromToken(pay.returnNotice.token, ui);
            }
        }
    }

    function guestAjaxUrl() {
        var cfg = config() || {};
        if (cfg.ajaxUrl && cfg.ajaxUrl !== 'undefined') {
            return cfg.ajaxUrl;
        }
        if (typeof window.ajaxurl === 'string' && window.ajaxurl !== '') {
            return window.ajaxurl;
        }
        var origin = window.location.origin || '';
        if (origin !== '') {
            return origin + '/wp-admin/admin-ajax.php';
        }
        return '/wp-admin/admin-ajax.php';
    }

    function parseGuestAjaxResponse(response) {
        return response.text().then(function (body) {
            var trimmed = body ? String(body).trim() : '';
            var payload = null;

            if (trimmed === '0' || trimmed === '-1') {
                throw { transport: true };
            }

            if (trimmed !== '') {
                try {
                    payload = JSON.parse(trimmed);
                } catch (error) {
                    payload = null;
                }
            }

            if (payload === null || typeof payload !== 'object') {
                if (response.status === 429 || response.status === 503 || response.status === 502 || response.status === 508) {
                    throw { transport: true, status: response.status };
                }
                throw { transport: true, status: response.status };
            }

            return payload;
        });
    }

    function guestAjaxErrorMessage(err, fallbackKey) {
        if (err && err.data && err.data.message) {
            return err.data.message;
        }
        if (err && err.transport) {
            return t('connectionError');
        }
        return t(fallbackKey || 'orderSendError');
    }

    function primaryActionLabel() {
        if (usesServer() && hasActiveGuestSession()) {
            return t('sendAddOrder');
        }
        return usesServer() ? t('sendOrder') : t('showWaiter');
    }

    function submitOrderToServer(state) {
        var cfg = config() || {};
        var formData = new FormData();
        var session = loadGuestSession();
        var appendToken = getAppendableGuestToken(session);

        formData.append('action', 'maca_submit_table_order');
        formData.append('nonce', cfg.nonce || '');
        formData.append('order_channel', isTakeawayChannel() ? 'takeaway' : 'dine_in');
        formData.append('table_number', state.tableNumber || '');
        if (cfg.urlTable) {
            formData.append('url_table', cfg.urlTable);
        }
        formData.append('pickup_name', state.pickupName || '');
        formData.append('pickup_phone', state.pickupPhone || '');
        formData.append('order_note', state.orderNote || '');
        formData.append('items', JSON.stringify(state.items));
        if (appendToken) {
            formData.append('guest_token', appendToken);
        }
        if (cfg.applyQrSchedule) {
            formData.append('qr_schedule', '1');
        }

        return fetch(guestAjaxUrl(), {
            method: 'POST',
            credentials: 'same-origin',
            body: formData,
        }).then(function (response) {
            return parseGuestAjaxResponse(response);
        });
    }

    function commitCurrentBatch(state) {
        if (!state.items.length) {
            return;
        }

        if (!state.tableNumber) {
            state.tableNumber = readTableNumberFromUi({ tableSelect: document.getElementById('maca-table-order-table-select') });
        }

        state.sentOrders.push({
            id: Date.now(),
            items: state.items.map(function (item) {
                return Object.assign({}, item);
            }),
            orderNote: state.orderNote || '',
        });
        state.items = [];
        state.orderNote = '';
    }

    function renderWaiterContent(state, orderSent, bannerMessage) {
        var cfg = config();
        var html = '';

        if (orderSent) {
            html += '<p class="maca-table-order-sent-banner">' + escapeHtml(bannerMessage || t('orderSent')) + '</p>';
        }

        if (state.sentOrders && state.sentOrders.length) {
            state.sentOrders.forEach(function (batch, batchIndex) {
                html += '<div class="maca-table-order-waiter-batch">';
                html += '<h3 class="maca-table-order-waiter-batch-title">' + escapeHtml(batchIndex === 0 ? t('yourOrder') : t('addOnOrder') + ' #' + (batchIndex + 1)) + '</h3>';
                html += '<ul class="maca-table-order-waiter-list">';
                batch.items.forEach(function (item) {
                    html += '<li class="maca-table-order-waiter-item">';
                    html += '<div class="maca-table-order-waiter-line">';
                    html += '<span class="maca-table-order-waiter-qty">' + escapeHtml(String(item.qty)) + '×</span>';
                    html += '<span class="maca-table-order-waiter-title">' + escapeHtml(item.title) + '</span>';
                    if (cfg && cfg.showPrices && item.priceLabel) {
                        html += '<span class="maca-table-order-waiter-price">' + escapeHtml(item.priceLabel) + '</span>';
                    }
                    html += '</div>';
                    if (item.note) {
                        html += '<p class="maca-table-order-waiter-note">' + escapeHtml(item.note) + '</p>';
                    }
                    html += '</li>';
                });
                html += '</ul>';
                if (cfg && cfg.orderNote && batch.orderNote) {
                    html += '<p class="maca-table-order-waiter-order-note"><strong>' + escapeHtml(t('orderNote')) + ':</strong> ' + escapeHtml(batch.orderNote) + '</p>';
                }
                html += '</div>';
            });
        }

        if (state.items.length) {
            if (state.sentOrders && state.sentOrders.length) {
                html += '<div class="maca-table-order-waiter-batch">';
                html += '<h3 class="maca-table-order-waiter-batch-title">' + escapeHtml(t('addOnOrder')) + '</h3>';
            }
            html += '<ul class="maca-table-order-waiter-list">';
            state.items.forEach(function (item) {
                html += '<li class="maca-table-order-waiter-item">';
                html += '<div class="maca-table-order-waiter-line">';
                html += '<span class="maca-table-order-waiter-qty">' + escapeHtml(String(item.qty)) + '×</span>';
                html += '<span class="maca-table-order-waiter-title">' + escapeHtml(item.title) + '</span>';
                if (cfg && cfg.showPrices && item.priceLabel) {
                    html += '<span class="maca-table-order-waiter-price">' + escapeHtml(item.priceLabel) + '</span>';
                }
                html += '</div>';
                if (item.note) {
                    html += '<p class="maca-table-order-waiter-note">' + escapeHtml(item.note) + '</p>';
                }
                html += '</li>';
            });
            html += '</ul>';
            if (state.sentOrders && state.sentOrders.length) {
                html += '</div>';
            }
        }

        if (cfg && cfg.orderNote && state.orderNote && state.items.length) {
            html += '<p class="maca-table-order-waiter-order-note"><strong>' + escapeHtml(t('orderNote')) + ':</strong> ' + escapeHtml(state.orderNote) + '</p>';
        }

        if (cfg && cfg.showPrices) {
            var total = calcTotal(state);
            if (state.sentOrders) {
                state.sentOrders.forEach(function (batch) {
                    total += batch.items.reduce(function (sum, item) {
                        if (typeof item.price !== 'number') {
                            return sum;
                        }
                        return sum + item.price * item.qty;
                    }, 0);
                });
            }
            if (total > 0) {
                html += '<p class="maca-table-order-waiter-total"><strong>' + escapeHtml(t('total')) + ':</strong> ' + escapeHtml(formatPrice(total)) + '</p>';
            }
        }

        return html;
    }

    function renderLines(state, ui) {
        var cfg = config();
        var lines = ui.lines;
        var empty = ui.empty;
        var totalWrap = ui.totalWrap;
        var totalEl = ui.totalEl;

        if (!lines) {
            return;
        }

        if (!state.items.length) {
            lines.innerHTML = '';
            if (empty) {
                empty.hidden = false;
            }
            if (totalWrap) {
                totalWrap.hidden = true;
            }
            return;
        }

        if (empty) {
            empty.hidden = true;
        }

        var html = '';

        state.items.forEach(function (item, index) {
            html += '<div class="maca-table-order-line" data-index="' + index + '">';
            html += '<div class="maca-table-order-line-main">';
            html += '<div class="maca-table-order-line-title">' + escapeHtml(item.title) + '</div>';
            if (cfg && cfg.showPrices && item.priceLabel) {
                html += '<div class="maca-table-order-line-price">' + escapeHtml(item.priceLabel) + '</div>';
            }
            html += '</div>';
            html += '<div class="maca-table-order-line-controls">';
            html += '<button type="button" class="maca-table-order-qty-btn" data-action="decrease" data-index="' + index + '" aria-label="-">−</button>';
            html += '<span class="maca-table-order-qty">' + escapeHtml(String(item.qty)) + '</span>';
            html += '<button type="button" class="maca-table-order-qty-btn" data-action="increase" data-index="' + index + '" aria-label="+">+</button>';
            html += '<button type="button" class="maca-table-order-remove" data-action="remove" data-index="' + index + '" aria-label="' + escapeHtml(t('remove')) + '">';
            html += '<span class="maca-table-order-remove-icon" aria-hidden="true">';
            html += '<svg viewBox="0 0 24 24" width="18" height="18" focusable="false"><path fill="currentColor" d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/></svg>';
            html += '</span></button>';
            html += '</div>';

            if (cfg && cfg.lineNotes) {
                html += '<label class="maca-table-order-line-note-label">';
                html += '<span>' + escapeHtml(t('note')) + '</span>';
                html += '<input type="text" class="maca-table-order-line-note" data-index="' + index + '" value="' + escapeHtml(item.note || '') + '" placeholder="' + escapeHtml(t('lineNotePlaceholder')) + '">';
                html += '</label>';
            }

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

        lines.innerHTML = html;

        if (cfg && cfg.showPrices && totalWrap && totalEl) {
            var total = calcTotal(state);
            if (total > 0) {
                totalWrap.hidden = false;
                totalEl.textContent = formatPrice(total);
            } else {
                totalWrap.hidden = true;
            }
        }
    }

    function updateBar(state, ui) {
        var count = itemCount(state);
        var hasItems = count > 0;

        if (ui.root) {
            ui.root.hidden = false;
            ui.root.setAttribute('aria-hidden', 'false');
        }

        if (ui.bar) {
            ui.bar.hidden = !hasItems;
        }

        if (ui.barCount) {
            ui.barCount.textContent = String(count);
        }

        if (ui.barLabel) {
            ui.barLabel.textContent = count === 1
                ? '1 ' + t('item') + ' · ' + t('viewOrder')
                : count + ' ' + t('items') + ' · ' + t('viewOrder');
        }

        document.body.classList.toggle('maca-table-order-has-items', hasItems);

        setBodyClass(hasItems && !(ui.waiter && !ui.waiter.hidden));
    }

    function bindUi(state, ui) {
        renderLines(state, ui);
        updateBar(state, ui);

        syncTableSelectFromState(state, ui);

        if (ui.orderNoteInput && ui.orderNoteInput.value !== state.orderNote) {
            ui.orderNoteInput.value = state.orderNote;
        }

        if (ui.pickupNameInput && ui.pickupNameInput.value !== state.pickupName) {
            ui.pickupNameInput.value = state.pickupName;
        }
        if (ui.pickupPhoneInput && ui.pickupPhoneInput.value !== state.pickupPhone) {
            ui.pickupPhoneInput.value = state.pickupPhone;
        }

        var cfg = config();
        if (ui.orderNoteField) {
            ui.orderNoteField.hidden = !(cfg && cfg.orderNote);
        }
        if (ui.totalWrap) {
            ui.totalWrap.hidden = !(cfg && cfg.showPrices) || calcTotal(state) <= 0;
        }

        if (ui.showWaiterButton) {
            ui.showWaiterButton.textContent = primaryActionLabel();
        }

        updateGuestSessionBar(ui);
    }

    function openPanel(ui) {
        if (!ui.panel || !ui.overlay) {
            return;
        }
        ui.panel.hidden = false;
        ui.panel.setAttribute('aria-hidden', 'false');
        ui.overlay.hidden = false;
        document.body.classList.add('maca-table-order-panel-open');
    }

    function closePanel(ui) {
        if (!ui.panel || !ui.overlay) {
            return;
        }
        ui.panel.hidden = true;
        ui.panel.setAttribute('aria-hidden', 'true');
        ui.overlay.hidden = true;
        document.body.classList.remove('maca-table-order-panel-open');
    }

    function openWaiter(state, ui, orderSent, bannerMessage) {
        if (!ui.waiter) {
            return;
        }

        closePanel(ui);

        if (ui.waiterTable) {
            if (state.tableNumber) {
                ui.waiterTable.textContent = t('table') + ' ' + state.tableNumber;
                ui.waiterTable.hidden = false;
            } else {
                ui.waiterTable.hidden = true;
                ui.waiterTable.textContent = '';
            }
        }

        if (ui.waiterContent) {
            ui.waiterContent.innerHTML = renderWaiterContent(state, !!orderSent, bannerMessage);
        }

        if (ui.waiterMore) {
            ui.waiterMore.hidden = !(orderSent || (state.sentOrders && state.sentOrders.length));
        }

        ui.waiter.hidden = false;
        ui.waiter.setAttribute('aria-hidden', 'false');
        setWaiterClass(true);
        setBodyClass(false);
    }

    function closeWaiter(ui) {
        if (!ui.waiter) {
            return;
        }
        ui.waiter.hidden = true;
        ui.waiter.setAttribute('aria-hidden', 'true');
        setWaiterClass(false);
        updateBar(loadState(), ui);
    }

    function addDishFromButton(button, state, ui) {
        var wrap = button.closest('.maca-dish-order-actions');
        if (!wrap) {
            return;
        }

        var dishId = wrap.getAttribute('data-dish-id');
        if (window.MacaMenulistDishMenu && typeof window.MacaMenulistDishMenu.trackDishView === 'function') {
            window.MacaMenulistDishMenu.trackDishView(dishId, 'add_order');
        }
        var title = wrap.getAttribute('data-dish-title') || '';
        var priceRaw = wrap.getAttribute('data-dish-price');
        var priceLabel = wrap.getAttribute('data-dish-price-label') || '';
        var index = findItemIndex(state, dishId);

        if (index >= 0) {
            state.items[index].qty += 1;
        } else {
            var item = {
                id: dishId,
                title: title,
                qty: 1,
                note: '',
            };
            if (priceRaw !== null && priceRaw !== '') {
                item.price = parseFloat(priceRaw);
                item.priceLabel = priceLabel;
            }
            state.items.push(item);
        }

        saveState(state);
        bindUi(state, ui);

        button.classList.add('is-added');
        window.setTimeout(function () {
            button.classList.remove('is-added');
        }, 600);
    }

    function mountOrderRoot(root) {
        if (!root || root.dataset.macaMounted === '1') {
            return;
        }

        if (root.parentElement !== document.body) {
            document.body.appendChild(root);
        }

        root.dataset.macaMounted = '1';
    }

    function initTableOrder() {
        var cfg = config();
        if (!cfg || !cfg.enabled) {
            return;
        }

        var ui = {
            root: getRoot(),
            bar: document.getElementById('maca-table-order-bar'),
            barCount: document.getElementById('maca-table-order-bar-count'),
            barLabel: document.getElementById('maca-table-order-bar-label'),
            panel: document.getElementById('maca-table-order-panel'),
            overlay: document.getElementById('maca-table-order-overlay'),
            lines: document.getElementById('maca-table-order-lines'),
            empty: document.getElementById('maca-table-order-empty'),
            tableSelect: document.getElementById('maca-table-order-table-select'),
            pickupNameInput: document.getElementById('maca-table-order-pickup-name'),
            pickupPhoneInput: document.getElementById('maca-table-order-pickup-phone'),
            orderNoteInput: document.getElementById('maca-table-order-note-input'),
            orderNoteField: document.querySelector('.maca-table-order-field--order-note'),
            totalWrap: document.getElementById('maca-table-order-total-wrap'),
            totalEl: document.getElementById('maca-table-order-total'),
            waiter: document.getElementById('maca-table-order-waiter'),
            waiterContent: document.getElementById('maca-table-order-waiter-content'),
            waiterTable: document.getElementById('maca-table-order-waiter-table'),
            showWaiterButton: document.getElementById('maca-table-order-show-waiter'),
            guestStatus: document.getElementById('maca-guest-order-status'),
            guestStatusSteps: document.getElementById('maca-guest-order-status-steps'),
            guestStatusMessage: document.getElementById('maca-guest-order-status-message'),
            guestStatusEta: document.getElementById('maca-guest-order-status-eta'),
            guestStatusLines: document.getElementById('maca-guest-order-status-lines'),
            guestStatusOrders: document.getElementById('maca-guest-order-status-orders'),
            guestStatusCombined: document.getElementById('maca-guest-order-status-combined'),
            guestStatusTable: document.getElementById('maca-guest-order-status-table'),
            guestShareQrBtn: document.getElementById('maca-guest-order-share-qr'),
            sessionBar: document.getElementById('maca-guest-order-session-bar'),
            sessionLabel: document.getElementById('maca-guest-order-session-label'),
            waiterMore: document.getElementById('maca-table-order-more'),
        };

        if (!ui.root) {
            return;
        }

        mountOrderRoot(ui.root);

        var state = loadState();
        syncTableSelectFromState(state, ui);
        saveState(state);
        bindUi(state, ui);

        document.addEventListener('click', function (event) {
            var addButton = event.target.closest('.maca-dish-add-to-order');
            if (addButton) {
                event.preventDefault();

                if (!isOrderingOpen()) {
                    var cfg = config();
                    var notice = cfg && cfg.outsideHoursNotice ? String(cfg.outsideHoursNotice) : '';

                    if (notice) {
                        window.alert(notice);
                    }

                    return;
                }

                state = loadState();
                addDishFromButton(addButton, state, ui);
                return;
            }

            if (event.target.closest('#maca-table-order-open')) {
                state = loadState();
                var lockedTable = getLockedTableNumber();

                if (lockedTable) {
                    state.tableNumber = lockedTable;
                    saveState(state);
                }

                bindUi(state, ui);
                openPanel(ui);
                return;
            }

            if (event.target.closest('[data-maca-order-close="panel"]')) {
                closePanel(ui);
                return;
            }

            if (event.target.closest('#maca-table-order-show-waiter')) {
                state = loadState();
                state.tableNumber = readTableNumberFromUi(ui);
                if (ui.orderNoteInput) {
                    state.orderNote = ui.orderNoteInput.value.trim();
                }
                saveState(state);

                if (isTakeawayChannel()) {
                    state.pickupName = ui.pickupNameInput ? ui.pickupNameInput.value.trim() : '';
                    state.pickupPhone = ui.pickupPhoneInput ? ui.pickupPhoneInput.value.trim() : '';
                    saveState(state);
                    if (!state.pickupName) {
                        if (ui.pickupNameInput) {
                            ui.pickupNameInput.focus();
                        }
                        window.alert(t('pickupNameRequired'));
                        return;
                    }
                } else if (tableSelectionRequired() && !state.tableNumber) {
                    if (ui.tableSelect) {
                        ui.tableSelect.focus();
                    }
                    window.alert(t('tableRequired'));
                    return;
                }

                if (usesServer()) {
                    var actionButton = event.target.closest('#maca-table-order-show-waiter');
                    if (actionButton) {
                        actionButton.disabled = true;
                    }
                    submitOrderToServer(state)
                        .then(function (payload) {
                            if (!payload || !payload.success) {
                                throw new Error('submit failed');
                            }
                            var result = payload.data || {};
                            var hadOrders = hasActiveGuestSession();
                            if (result.guest_token && result.order_id) {
                                addOrderToGuestSession(
                                    result.order_id,
                                    result.guest_token,
                                    state.tableNumber || '',
                                    !!result.appended
                                );
                            }
                            var payCfg = paymentsConfig();
                            var needsPrepay =
                                isTakeawayChannel() &&
                                payCfg &&
                                payCfg.takeawayRequiresPrepayment &&
                                payCfg.flowEnabled;

                            if (
                                needsPrepay
                                || guestStatusEnabled()
                                || result.requires_prepayment
                                || result.requires_additional_payment
                            ) {
                                showGuestStatusAfterSubmit(payload, state, ui);
                            } else {
                                var banner = result.appended
                                    ? t('itemsAdded')
                                    : (hadOrders ? t('addOnSent') : t('orderSent'));
                                openWaiter(state, ui, true, banner);
                            }
                            state = defaultState();
                            state.tableNumber = getLockedTableNumber() || readTableNumberFromUi(ui) || getTableFromUrl();
                            saveState(state);
                            bindUi(state, ui);
                            updateGuestSessionBar(ui);
                        })
                        .catch(function (err) {
                            window.alert(guestAjaxErrorMessage(err, 'orderSendError'));
                        })
                        .finally(function () {
                            if (actionButton) {
                                actionButton.disabled = false;
                            }
                        });
                } else {
                    if (!state.items.length) {
                        return;
                    }
                    openWaiter(state, ui, false);
                }
                return;
            }

            if (event.target.closest('#maca-table-order-more')) {
                state = loadState();
                if (!usesServer()) {
                    commitCurrentBatch(state);
                    saveState(state);
                }
                closeWaiter(ui);
                bindUi(state, ui);
                return;
            }

            if (event.target.closest('#maca-guest-order-more')) {
                closeGuestStatus(ui);
                return;
            }

            if (event.target.closest('#maca-guest-order-view-status')) {
                openGuestStatus(ui);
                startGuestStatusPolling(ui);
                return;
            }

            if (event.target.closest('#maca-table-order-back')) {
                closeWaiter(ui);
                return;
            }

            if (event.target.closest('#maca-guest-order-status-close')) {
                closeGuestStatus(ui);
                closeGuestShareQrModal();
                return;
            }

            if (event.target.closest('.maca-guest-order-share-qr')) {
                openGuestShareQrModal();
                return;
            }

            if (event.target.closest('.maca-guest-share-qr-close, .maca-guest-share-qr-modal-backdrop')) {
                closeGuestShareQrModal();
                return;
            }

            var confirmationToggle = event.target.closest('.maca-guest-confirmation-email-toggle');
            if (confirmationToggle) {
                var emailBlock = confirmationToggle.closest('.maca-guest-order-payment');
                setConfirmationEmailFieldVisible(emailBlock, confirmationToggle.checked);
                syncGuestPaymentEmailDraftFromBlock(emailBlock);
                return;
            }

            var tipApplyBtn = event.target.closest('.maca-guest-tip-custom-apply');
            if (tipApplyBtn) {
                var applyToken = tipApplyBtn.getAttribute('data-guest-token');
                var applyBlock = tipApplyBtn.closest('.maca-guest-order-payment');
                if (!applyToken || !applyBlock) {
                    return;
                }
                syncGuestTipBlockFromSelect(applyBlock);
                applyBlock.setAttribute('data-tip-choice', 'custom');
                tipApplyBtn.disabled = true;
                saveGuestTip(applyToken, applyBlock)
                    .then(function (payload) {
                        if (!payload || !payload.success) {
                            throw new Error('tip failed');
                        }
                        pollGuestSession(ui);
                    })
                    .catch(function () {
                        window.alert(t('tipSaveError'));
                    })
                    .finally(function () {
                        tipApplyBtn.disabled = false;
                    });
                return;
            }

            var billSplitToggleBtn = event.target.closest('.maca-guest-bill-split-toggle');
            if (billSplitToggleBtn) {
                var toggleBlock = billSplitToggleBtn.closest('.maca-guest-bill-split');
                var toggleBody = toggleBlock ? toggleBlock.querySelector('.maca-guest-bill-split-body') : null;
                if (!toggleBody) {
                    return;
                }
                var opening = toggleBody.hasAttribute('hidden');
                if (opening) {
                    toggleBody.removeAttribute('hidden');
                    billSplitToggleBtn.setAttribute('aria-expanded', 'true');
                    billSplitToggleBtn.textContent = t('billSplitHide');
                    toggleBlock.classList.add('is-open');
                    syncGuestBillSplitModePanels(toggleBlock);
                } else {
                    toggleBody.setAttribute('hidden', '');
                    billSplitToggleBtn.setAttribute('aria-expanded', 'false');
                    billSplitToggleBtn.textContent = t('billSplitShow');
                    toggleBlock.classList.remove('is-open');
                }
                syncGuestBillSplitDraftFromBlock(toggleBlock);
                return;
            }

            var billSplitModeInput = event.target.closest('input[name="maca-bill-split-mode"]');
            if (billSplitModeInput) {
                var modeBlock = billSplitModeInput.closest('.maca-guest-bill-split');
                syncGuestBillSplitModePanels(modeBlock);
                syncGuestBillSplitDraftFromBlock(modeBlock);
                return;
            }

            var billSplitApplyBtn = event.target.closest('.maca-guest-bill-split-apply');
            if (billSplitApplyBtn) {
                var splitToken = billSplitApplyBtn.getAttribute('data-guest-token');
                var splitBlock = billSplitApplyBtn.closest('.maca-guest-bill-split');
                var combinedPaymentBlock = billSplitApplyBtn.closest('[data-combined-payment="1"]');
                var combinedTokens = combinedPaymentBlock ? getCombinedGuestTokens(combinedPaymentBlock) : [];
                var mode = getGuestBillSplitModeFromBlock(splitBlock);
                var people = 0;
                var fixedAmount = 0;

                if (mode === 'equal') {
                    var splitSelect = splitBlock ? splitBlock.querySelector('.maca-guest-bill-split-count') : null;
                    people = splitSelect ? parseInt(splitSelect.value, 10) : 0;
                    if ((!splitToken && !combinedTokens.length) || people < 2) {
                        return;
                    }
                } else if (mode === 'fixed') {
                    var fixedInput = splitBlock ? splitBlock.querySelector('.maca-guest-bill-split-fixed-amount') : null;
                    fixedAmount = fixedInput ? parseFloat(String(fixedInput.value).replace(',', '.')) : 0;
                    if ((!splitToken && !combinedTokens.length) || !(fixedAmount > 0)) {
                        return;
                    }
                } else {
                    return;
                }

                syncGuestBillSplitDraftFromBlock(splitBlock);
                billSplitApplyBtn.disabled = true;
                var splitRequest = combinedTokens.length
                    ? saveGuestBillSplitCombined(combinedTokens, {
                        mode: mode,
                        people: people,
                        fixed_amount: fixedAmount,
                    })
                    : saveGuestBillSplit(splitToken, {
                        mode: mode,
                        people: people,
                        fixed_amount: fixedAmount,
                    });
                splitRequest
                    .then(function (payload) {
                        if (!payload || !payload.success) {
                            throw new Error('split failed');
                        }
                        clearGuestBillSplitDraft(splitToken || (combinedTokens.length ? 'combined' : ''));
                        pollGuestSession(ui);
                    })
                    .catch(function () {
                        window.alert(t('billSplitError'));
                    })
                    .finally(function () {
                        billSplitApplyBtn.disabled = false;
                    });
                return;
            }

            var billSplitClearBtn = event.target.closest('.maca-guest-bill-split-clear');
            if (billSplitClearBtn) {
                var clearToken = billSplitClearBtn.getAttribute('data-guest-token');
                var clearCombinedBlock = billSplitClearBtn.closest('[data-combined-payment="1"]');
                var clearCombinedTokens = clearCombinedBlock ? getCombinedGuestTokens(clearCombinedBlock) : [];

                if (!clearToken && !clearCombinedTokens.length) {
                    return;
                }

                billSplitClearBtn.disabled = true;
                var clearRequest = clearCombinedTokens.length
                    ? saveGuestBillSplitCombined(clearCombinedTokens, { mode: '', people: 0, fixed_amount: 0 })
                    : saveGuestBillSplit(clearToken, { mode: '', people: 0, fixed_amount: 0 });
                clearRequest
                    .then(function (payload) {
                        if (!payload || !payload.success) {
                            throw new Error('split failed');
                        }
                        clearGuestBillSplitDraft(clearToken || (clearCombinedTokens.length ? 'combined' : ''));
                        pollGuestSession(ui);
                    })
                    .catch(function () {
                        window.alert(t('billSplitError'));
                    })
                    .finally(function () {
                        billSplitClearBtn.disabled = false;
                    });
                return;
            }

            var payWaiterBtn = event.target.closest('.maca-guest-pay-waiter');
            if (payWaiterBtn) {
                var waiterToken = payWaiterBtn.getAttribute('data-guest-token');
                if (!waiterToken) {
                    return;
                }
                payWaiterBtn.disabled = true;
                choosePaymentMethod(waiterToken, 'manual', ui)
                    .catch(function (error) {
                        showPaymentActionError(error, 'paymentChooseError');
                    })
                    .finally(function () {
                        payWaiterBtn.disabled = false;
                    });
                return;
            }

            var payOnlineBtn = event.target.closest('.maca-guest-pay-online');
            if (payOnlineBtn) {
                var onlineToken = payOnlineBtn.getAttribute('data-guest-token');
                if (!onlineToken) {
                    return;
                }
                payOnlineBtn.disabled = true;
                var checkoutPromise = payOnlineBtn.classList.contains('maca-guest-pay-online--resume')
                    ? startOnlineCheckout(onlineToken, ui)
                    : choosePaymentMethod(onlineToken, 'online', ui);
                checkoutPromise
                    .catch(function (error) {
                        showPaymentActionError(error, 'paymentError');
                    })
                    .finally(function () {
                        payOnlineBtn.disabled = false;
                    });
                return;
            }

            var payCombinedWaiterBtn = event.target.closest('.maca-guest-pay-combined-waiter');
            if (payCombinedWaiterBtn) {
                var combinedTokens = getCombinedGuestTokensFromClick(payCombinedWaiterBtn);
                if (!combinedTokens.length) {
                    window.alert(t('paymentChooseError'));
                    return;
                }
                payCombinedWaiterBtn.disabled = true;
                chooseCombinedPaymentMethod(combinedTokens, 'manual', ui)
                    .catch(function (error) {
                        showPaymentActionError(error, 'paymentChooseError');
                    })
                    .finally(function () {
                        payCombinedWaiterBtn.disabled = false;
                    });
                return;
            }

            var payCombinedOnlineBtn = event.target.closest('.maca-guest-pay-combined-online');
            if (payCombinedOnlineBtn) {
                var combinedPayTokens = getCombinedGuestTokensFromClick(payCombinedOnlineBtn);
                if (!combinedPayTokens.length) {
                    window.alert(t('paymentError'));
                    return;
                }
                payCombinedOnlineBtn.disabled = true;
                chooseCombinedPaymentMethod(combinedPayTokens, 'online', ui)
                    .catch(function (error) {
                        showPaymentActionError(error, 'paymentError');
                    })
                    .finally(function () {
                        payCombinedOnlineBtn.disabled = false;
                    });
                return;
            }

            if (event.target.closest('#maca-table-order-clear')) {
                if (!window.confirm(t('clearOrder') + '?')) {
                    return;
                }
                state = defaultState();
                saveState(state);
                bindUi(state, ui);
                closePanel(ui);
                closeWaiter(ui);
                return;
            }

            var qtyButton = event.target.closest('.maca-table-order-qty-btn, .maca-table-order-remove');
            if (qtyButton) {
                var lineIndex = parseInt(qtyButton.getAttribute('data-index'), 10);
                var action = qtyButton.getAttribute('data-action');
                state = loadState();
                if (Number.isNaN(lineIndex) || !state.items[lineIndex]) {
                    return;
                }
                if (action === 'increase') {
                    state.items[lineIndex].qty += 1;
                } else if (action === 'decrease') {
                    state.items[lineIndex].qty -= 1;
                    if (state.items[lineIndex].qty <= 0) {
                        state.items.splice(lineIndex, 1);
                    }
                } else if (action === 'remove') {
                    state.items.splice(lineIndex, 1);
                }
                saveState(state);
                bindUi(state, ui);
            }
        });

        document.addEventListener('input', function (event) {
            if (event.target.matches('.maca-table-order-line-note')) {
                var noteIndex = parseInt(event.target.getAttribute('data-index'), 10);
                state = loadState();
                if (!Number.isNaN(noteIndex) && state.items[noteIndex]) {
                    state.items[noteIndex].note = event.target.value;
                    saveState(state);
                }
                return;
            }

            if (event.target.matches('#maca-table-order-table-select')) {
                if (isTableNumberLocked()) {
                    event.target.value = getLockedTableNumber();
                    return;
                }

                state = loadState();
                state.tableNumber = event.target.value.trim();
                saveState(state);
                return;
            }

            if (event.target.matches('#maca-table-order-note-input')) {
                state = loadState();
                state.orderNote = event.target.value;
                saveState(state);
            }
        });

        document.addEventListener('keydown', function (event) {
            if (event.key === 'Escape') {
                if (ui.guestStatus && !ui.guestStatus.hidden) {
                    closeGuestStatus(ui);
                } else if (ui.waiter && !ui.waiter.hidden) {
                    closeWaiter(ui);
                } else if (ui.panel && !ui.panel.hidden) {
                    closePanel(ui);
                }
            }
        });

        document.addEventListener('change', function (event) {
            var billSplitBlock = event.target && event.target.closest
                ? event.target.closest('.maca-guest-bill-split')
                : null;
            if (billSplitBlock && (
                event.target.classList.contains('maca-guest-bill-split-count')
                || event.target.matches('input[name="maca-bill-split-mode"]')
            )) {
                syncGuestBillSplitDraftFromBlock(billSplitBlock);
            }

            var tipSelect = event.target && event.target.classList
                ? event.target.closest('.maca-guest-tip-select')
                : null;
            if (!tipSelect) {
                return;
            }

            var selectToken = tipSelect.getAttribute('data-guest-token');
            var selectBlock = tipSelect.closest('.maca-guest-order-payment');
            if (!selectToken || !selectBlock || tipSelect.disabled) {
                return;
            }

            syncGuestTipBlockFromSelect(selectBlock);

            if (tipSelect.value === 'custom') {
                var customInput = selectBlock.querySelector('.maca-guest-tip-custom-input');
                if (customInput) {
                    customInput.focus();
                }
                return;
            }

            if (!tipSelect.value) {
                return;
            }

            tipSelect.disabled = true;
            saveGuestTip(selectToken, selectBlock)
                .then(function (payload) {
                    if (!payload || !payload.success) {
                        throw new Error('tip failed');
                    }
                    pollGuestSession(ui);
                })
                .catch(function () {
                    window.alert(t('tipSaveError'));
                })
                .finally(function () {
                    tipSelect.disabled = false;
                });
        });

        document.addEventListener('input', function (event) {
            if (event.target && event.target.classList) {
                if (event.target.classList.contains('maca-guest-confirmation-email-input')) {
                    syncGuestPaymentEmailDraftFromBlock(event.target.closest('.maca-guest-order-payment'));
                } else if (event.target.classList.contains('maca-guest-bill-split-fixed-amount')) {
                    syncGuestBillSplitDraftFromBlock(event.target.closest('.maca-guest-bill-split'));
                }
            }
        });

        var guestBoot = guestStatusEnabled()
            ? restoreGuestSessionFromUrl(ui)
            : Promise.resolve(false);

        guestBoot.finally(function () {
            updateGuestSessionBar(ui);
            if (hasActiveGuestSession()) {
                startGuestStatusPolling(ui);
            }
            if (paymentsFlowEnabled()) {
                showPaymentReturnNotice(ui);
            }
        });
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initTableOrder);
    } else {
        initTableOrder();
    }

    window.MacaMenulistTableOrder = {
        init: initTableOrder,
    };
})();
