/******/ (() => { // webpackBootstrap
/******/ 	"use strict";
/******/ 	var __webpack_modules__ = ({

/***/ 367
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {

/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   Aq: () => (/* binding */ fetchFullOrderHistory),
/* harmony export */   BM: () => (/* binding */ checkHighlight),
/* harmony export */   Et: () => (/* binding */ stopPolling),
/* harmony export */   Gb: () => (/* binding */ fetchOrders),
/* harmony export */   H: () => (/* binding */ cleanupExpiredFlags),
/* harmony export */   KG: () => (/* binding */ loadMenuCache),
/* harmony export */   N4: () => (/* binding */ cancelOrder),
/* harmony export */   P0: () => (/* binding */ showToast),
/* harmony export */   PQ: () => (/* binding */ toggleFlag),
/* harmony export */   VL: () => (/* binding */ isCacheFresh),
/* harmony export */   Y1: () => (/* binding */ renderTagsList),
/* harmony export */   g8: () => (/* binding */ startPolling),
/* harmony export */   i_: () => (/* binding */ updateAuthUI),
/* harmony export */   m9: () => (/* binding */ loadMenuDataFromAPI),
/* harmony export */   oL: () => (/* binding */ addHighlightTag),
/* harmony export */   wH: () => (/* binding */ placeOrder)
/* harmony export */ });
/* unused harmony exports renderHistory, saveFlags, refreshFlaggedItems, pollFlaggedItems, saveHighlightTags, removeHighlightTag, saveMenuCache, updateLastUpdatedTime */
/* harmony import */ var _state_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(901);
/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(413);
/* harmony import */ var _constants_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(521);
/* harmony import */ var _api_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(672);
/* harmony import */ var _ui_helpers_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(842);






let fullOrderHistoryCache = null;

function updateAuthUI() {
    if (!_state_js__WEBPACK_IMPORTED_MODULE_0__/* .authToken */ .gX) {
        try {
            const akita = localStorage.getItem('AkitaStores');
            if (akita) {
                const parsed = JSON.parse(akita);
                if (parsed.auth && parsed.auth.token) {
                    console.log('Found existing Bessa session!');
                    (0,_state_js__WEBPACK_IMPORTED_MODULE_0__/* .setAuthToken */ .O5)(parsed.auth.token);
                    localStorage.setItem('kantine_authToken', parsed.auth.token);

                    if (parsed.auth.user) {
                        (0,_state_js__WEBPACK_IMPORTED_MODULE_0__/* .setCurrentUser */ .lt)(parsed.auth.user.id || 'unknown');
                        localStorage.setItem('kantine_currentUser', parsed.auth.user.id || 'unknown');
                        if (parsed.auth.user.firstName) localStorage.setItem('kantine_firstName', parsed.auth.user.firstName);
                        if (parsed.auth.user.lastName) localStorage.setItem('kantine_lastName', parsed.auth.user.lastName);
                    }
                }
            }
        } catch (e) {
            console.warn('Failed to parse AkitaStores:', e);
        }
    }

    (0,_state_js__WEBPACK_IMPORTED_MODULE_0__/* .setAuthToken */ .O5)(localStorage.getItem('kantine_authToken'));
    (0,_state_js__WEBPACK_IMPORTED_MODULE_0__/* .setCurrentUser */ .lt)(localStorage.getItem('kantine_currentUser'));
    const firstName = localStorage.getItem('kantine_firstName');
    const btnLoginOpen = document.getElementById('btn-login-open');
    const userInfo = document.getElementById('user-info');
    const userIdDisplay = document.getElementById('user-id-display');

    if (_state_js__WEBPACK_IMPORTED_MODULE_0__/* .authToken */ .gX) {
        btnLoginOpen.classList.add('hidden');
        userInfo.classList.remove('hidden');
        userIdDisplay.textContent = firstName || (_state_js__WEBPACK_IMPORTED_MODULE_0__/* .currentUser */ .Ny ? `User ${_state_js__WEBPACK_IMPORTED_MODULE_0__/* .currentUser */ .Ny}` : 'Angemeldet');
        fetchOrders();
    } else {
        btnLoginOpen.classList.remove('hidden');
        userInfo.classList.add('hidden');
        userIdDisplay.textContent = '';
    }

    (0,_ui_helpers_js__WEBPACK_IMPORTED_MODULE_4__/* .renderVisibleWeeks */ .OR)();
}

async function fetchOrders() {
    if (!_state_js__WEBPACK_IMPORTED_MODULE_0__/* .authToken */ .gX) return;
    try {
        const response = await fetch(`${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .API_BASE */ .tE}/user/orders/?venue=${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .VENUE_ID */ .eW}&ordering=-created&limit=50`, {
            headers: (0,_api_js__WEBPACK_IMPORTED_MODULE_3__/* .apiHeaders */ .H)(_state_js__WEBPACK_IMPORTED_MODULE_0__/* .authToken */ .gX)
        });
        const data = await response.json();

        if (response.ok) {
            const newOrderMap = new Map();
            const results = data.results || [];

            for (const order of results) {
                if (order.order_state === 9) continue;
                const orderDate = order.date.split('T')[0];

                for (const item of (order.items || [])) {
                    const key = `${orderDate}_${item.article}`;
                    if (!newOrderMap.has(key)) newOrderMap.set(key, []);
                    newOrderMap.get(key).push(order.id);
                }
            }
            (0,_state_js__WEBPACK_IMPORTED_MODULE_0__/* .setOrderMap */ .di)(newOrderMap);
            console.log(`Fetched ${results.length} orders, mapped active ones.`);
            (0,_ui_helpers_js__WEBPACK_IMPORTED_MODULE_4__/* .renderVisibleWeeks */ .OR)();
            (0,_ui_helpers_js__WEBPACK_IMPORTED_MODULE_4__/* .updateNextWeekBadge */ .gJ)();
        }
    } catch (error) {
        console.error('Error fetching orders:', error);
    }
}

async function fetchFullOrderHistory() {
    const historyLoading = document.getElementById('history-loading');
    const historyContent = document.getElementById('history-content');
    const progressFill = document.getElementById('history-progress-fill');
    const progressText = document.getElementById('history-progress-text');

    let localCache = [];
    if (fullOrderHistoryCache) {
        localCache = fullOrderHistoryCache;
    } else {
        const ls = localStorage.getItem('kantine_history_cache');
        if (ls) {
            try {
                localCache = JSON.parse(ls);
                fullOrderHistoryCache = localCache;
            } catch (e) {
                console.warn('History cache parse error', e);
            }
        }
    }

    if (localCache.length > 0) {
        renderHistory(localCache);
    }

    if (!_state_js__WEBPACK_IMPORTED_MODULE_0__/* .authToken */ .gX) return;

    if (localCache.length === 0) {
        historyContent.innerHTML = '';
        historyLoading.classList.remove('hidden');
    }

    progressFill.style.width = '0%';
    progressText.textContent = localCache.length > 0 ? 'Suche nach neuen Bestellungen...' : 'Lade Bestellhistorie...';
    if (localCache.length > 0) historyLoading.classList.remove('hidden');

    let nextUrl = localCache.length > 0
        ? `${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .API_BASE */ .tE}/user/orders/?venue=${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .VENUE_ID */ .eW}&ordering=-created&limit=5`
        : `${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .API_BASE */ .tE}/user/orders/?venue=${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .VENUE_ID */ .eW}&ordering=-created&limit=50`;
    let fetchedOrders = [];
    let totalCount = 0;
    let requiresFullFetch = localCache.length === 0;
    let deltaComplete = false;

    try {
        while (nextUrl && !deltaComplete) {
            const response = await fetch(nextUrl, { headers: (0,_api_js__WEBPACK_IMPORTED_MODULE_3__/* .apiHeaders */ .H)(_state_js__WEBPACK_IMPORTED_MODULE_0__/* .authToken */ .gX) });
            if (!response.ok) throw new Error(`Fetch failed: ${response.status}`);

            const data = await response.json();

            if (data.count && totalCount === 0) {
                totalCount = data.count;
            }

            const results = data.results || [];

            for (const order of results) {
                const existingOrderIndex = localCache.findIndex(cached => cached.id === order.id);

                if (!requiresFullFetch && existingOrderIndex !== -1) {
                    const existingOrder = localCache[existingOrderIndex];
                    if (existingOrder.updated === order.updated && existingOrder.order_state === order.order_state) {
                        deltaComplete = true;
                        break;
                    }
                }
                fetchedOrders.push(order);
            }

            if (!deltaComplete && requiresFullFetch) {
                if (totalCount > 0) {
                    const pct = Math.round((fetchedOrders.length / totalCount) * 100);
                    progressFill.style.width = `${pct}%`;
                    progressText.textContent = `Lade Bestellung ${fetchedOrders.length} von ${totalCount}...`;
                } else {
                    progressText.textContent = `Lade Bestellung ${fetchedOrders.length}...`;
                }
            } else if (!deltaComplete) {
                progressText.textContent = `${fetchedOrders.length} neue/geänderte Bestellungen gefunden...`;
            }

            nextUrl = deltaComplete ? null : data.next;
        }

        if (fetchedOrders.length > 0) {
            const cacheMap = new Map(localCache.map(o => [o.id, o]));
            for (const order of fetchedOrders) {
                cacheMap.set(order.id, order);
            }
            const mergedOrders = Array.from(cacheMap.values());
            mergedOrders.sort((a, b) => new Date(b.created) - new Date(a.created));

            fullOrderHistoryCache = mergedOrders;
            try {
                localStorage.setItem('kantine_history_cache', JSON.stringify(mergedOrders));
            } catch (e) {
                console.warn('History cache write error', e);
            }
            renderHistory(fullOrderHistoryCache);
        }
    } catch (error) {
        console.error('Error in history sync:', error);
        if (localCache.length === 0) {
            historyContent.innerHTML = `<p style="color:var(--error-color);text-align:center;">Fehler beim Laden der Historie.</p>`;
        } else {
            showToast('Hintergrund-Synchronisation fehlgeschlagen', 'error');
        }
    } finally {
        historyLoading.classList.add('hidden');
    }
}

function renderHistory(orders) {
    const content = document.getElementById('history-content');
    if (!orders || orders.length === 0) {
        content.innerHTML = '<p style="text-align:center;color:var(--text-secondary);padding:20px;">Keine Bestellungen gefunden.</p>';
        return;
    }

    const groups = {};

    orders.forEach(order => {
        const d = new Date(order.date);
        const y = d.getFullYear();
        const m = d.getMonth();
        const monthKey = `${y}-${m.toString().padStart(2, '0')}`;
        const monthName = d.toLocaleString('de-AT', { month: 'long' });

        const kw = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .getISOWeek */ .sn)(d);

        if (!groups[y]) {
            groups[y] = { year: y, months: {} };
        }
        if (!groups[y].months[monthKey]) {
            groups[y].months[monthKey] = { name: monthName, year: y, monthIndex: m, count: 0, total: 0, weeks: {} };
        }
        if (!groups[y].months[monthKey].weeks[kw]) {
            groups[y].months[monthKey].weeks[kw] = { label: `KW ${kw}`, items: [], count: 0, total: 0 };
        }

        const items = order.items || [];
        items.forEach(item => {
            const itemPrice = parseFloat(item.price || order.total || 0);
            groups[y].months[monthKey].weeks[kw].items.push({
                date: order.date,
                name: item.name || 'Menü',
                price: itemPrice,
                state: order.order_state
            });

            if (order.order_state !== 9) {
                groups[y].months[monthKey].weeks[kw].count++;
                groups[y].months[monthKey].weeks[kw].total += itemPrice;
                groups[y].months[monthKey].count++;
                groups[y].months[monthKey].total += itemPrice;
            }
        });
    });

    const sortedYears = Object.keys(groups).sort((a, b) => b - a);
    let html = '';

    sortedYears.forEach(yKey => {
        const yearGroup = groups[yKey];
        html += `<div class="history-year-group">
            <h2 class="history-year-header">${yearGroup.year}</h2>`;

        const sortedMonths = Object.keys(yearGroup.months).sort((a, b) => b.localeCompare(a));

        sortedMonths.forEach(mKey => {
            const monthGroup = yearGroup.months[mKey];

            html += `<div class="history-month-group">
                <div class="history-month-header" tabindex="0" role="button" aria-expanded="false" title="Klicken, um die Bestellungen für diesen Monat ein-/auszublenden">
                    <div style="display:flex; flex-direction:column; gap:4px;">
                        <span>${monthGroup.name}</span>
                        <div class="history-month-summary">
                            <span>${monthGroup.count} Bestellungen &bull; <strong>€${monthGroup.total.toFixed(2)}</strong></span>
                        </div>
                    </div>
                    <span class="material-icons-round">expand_more</span>
                </div>
                <div class="history-month-content">`;

            const sortedKWs = Object.keys(monthGroup.weeks).sort((a, b) => parseInt(b) - parseInt(a));

            sortedKWs.forEach(kw => {
                const week = monthGroup.weeks[kw];
                html += `<div class="history-week-group">
                    <div class="history-week-header">
                        <strong>${week.label}</strong>
                        <span>${week.count} Bestellungen &bull; <strong>€${week.total.toFixed(2)}</strong></span>
                    </div>`;

                week.items.forEach(item => {
                    const dateObj = new Date(item.date);
                    const dayStr = dateObj.toLocaleDateString('de-AT', { weekday: 'short', day: '2-digit', month: '2-digit' });

                    let statusBadge = '';
                    if (item.state === 9) {
                        statusBadge = '<span class="history-item-status">Storniert</span>';
                    } else if (item.state === 8) {
                        statusBadge = '<span class="history-item-status">Abgeschlossen</span>';
                    } else {
                        statusBadge = '<span class="history-item-status">Übertragen</span>';
                    }

                    html += `
                    <div class="history-item ${item.state === 9 ? 'history-item-cancelled' : ''}">
                        <div style="font-size: 0.85rem; color: var(--text-secondary);">${dayStr}</div>
                        <div class="history-item-details">
                            <span class="history-item-name">${(0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .escapeHtml */ .ZD)(item.name)}</span>
                            <div>${statusBadge}</div>
                        </div>
                        <div class="history-item-price ${item.state === 9 ? 'history-item-price-cancelled' : ''}">€${item.price.toFixed(2)}</div>
                    </div>`;
                });
                html += `</div>`;
            });
            html += `</div></div>`;
        });
        html += `</div>`;
    });

    content.innerHTML = html;

    const monthHeaders = content.querySelectorAll('.history-month-header');
    monthHeaders.forEach(header => {
        header.addEventListener('click', () => {
            const parentGroup = header.parentElement;
            const isOpen = parentGroup.classList.contains('open');

            if (isOpen) {
                parentGroup.classList.remove('open');
                header.setAttribute('aria-expanded', 'false');
            } else {
                parentGroup.classList.add('open');
                header.setAttribute('aria-expanded', 'true');
            }
        });
    });
}

async function placeOrder(date, articleId, name, price, description) {
    if (!_state_js__WEBPACK_IMPORTED_MODULE_0__/* .authToken */ .gX) return;
    try {
        const userResp = await fetch(`${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .API_BASE */ .tE}/auth/user/`, {
            headers: (0,_api_js__WEBPACK_IMPORTED_MODULE_3__/* .apiHeaders */ .H)(_state_js__WEBPACK_IMPORTED_MODULE_0__/* .authToken */ .gX)
        });
        if (!userResp.ok) {
            showToast('Fehler: Benutzerdaten konnten nicht geladen werden', 'error');
            return;
        }
        const userData = await userResp.json();
        const now = new Date().toISOString();

        const orderPayload = {
            uuid: crypto.randomUUID(),
            created: now,
            updated: now,
            order_type: 7,
            items: [{
                article: articleId,
                course_group: null,
                modifiers: [],
                uuid: crypto.randomUUID(),
                name: name,
                description: description || '',
                price: String(parseFloat(price)),
                amount: 1,
                vat: '10.00',
                comment: ''
            }],
            table: null,
            total: parseFloat(price),
            tip: 0,
            currency: 'EUR',
            venue: _constants_js__WEBPACK_IMPORTED_MODULE_2__/* .VENUE_ID */ .eW,
            states: [],
            order_state: 1,
            date: `${date}T10:30:00Z`,
            payment_method: 'payroll',
            customer: {
                first_name: userData.first_name,
                last_name: userData.last_name,
                email: userData.email,
                newsletter: false
            },
            preorder: true,
            delivery_fee: 0,
            cash_box_table_name: null,
            take_away: false
        };

        const response = await fetch(`${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .API_BASE */ .tE}/user/orders/`, {
            method: 'POST',
            headers: (0,_api_js__WEBPACK_IMPORTED_MODULE_3__/* .apiHeaders */ .H)(_state_js__WEBPACK_IMPORTED_MODULE_0__/* .authToken */ .gX),
            body: JSON.stringify(orderPayload)
        });

        if (response.ok || response.status === 201) {
            showToast(`Bestellt: ${name}`, 'success');
            fullOrderHistoryCache = null;
            await fetchOrders();
        } else {
            const data = await response.json();
            showToast(`Fehler: ${data.detail || data.non_field_errors?.[0] || 'Bestellung fehlgeschlagen'}`, 'error');
        }
    } catch (error) {
        console.error('Order error:', error);
        showToast('Netzwerkfehler bei Bestellung', 'error');
    }
}

async function cancelOrder(date, articleId, name) {
    if (!_state_js__WEBPACK_IMPORTED_MODULE_0__/* .authToken */ .gX) return;
    const key = `${date}_${articleId}`;
    const orderIds = _state_js__WEBPACK_IMPORTED_MODULE_0__/* .orderMap */ .L.get(key);
    if (!orderIds || orderIds.length === 0) return;

    const orderId = orderIds[orderIds.length - 1];
    try {
        const response = await fetch(`${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .API_BASE */ .tE}/user/orders/${orderId}/cancel/`, {
            method: 'PATCH',
            headers: (0,_api_js__WEBPACK_IMPORTED_MODULE_3__/* .apiHeaders */ .H)(_state_js__WEBPACK_IMPORTED_MODULE_0__/* .authToken */ .gX),
            body: JSON.stringify({})
        });

        if (response.ok) {
            showToast(`Storniert: ${name}`, 'success');
            fullOrderHistoryCache = null;
            await fetchOrders();
        } else {
            const data = await response.json();
            showToast(`Fehler: ${data.detail || 'Stornierung fehlgeschlagen'}`, 'error');
        }
    } catch (error) {
        console.error('Cancel error:', error);
        showToast('Netzwerkfehler bei Stornierung', 'error');
    }
}

function saveFlags() {
    localStorage.setItem('kantine_flags', JSON.stringify([..._state_js__WEBPACK_IMPORTED_MODULE_0__/* .userFlags */ .BY]));
}

async function refreshFlaggedItems() {
    if (_state_js__WEBPACK_IMPORTED_MODULE_0__/* .userFlags */ .BY.size === 0) return;
    const token = _state_js__WEBPACK_IMPORTED_MODULE_0__/* .authToken */ .gX || _constants_js__WEBPACK_IMPORTED_MODULE_2__/* .GUEST_TOKEN */ .f9;
    const datesToFetch = new Set();

    for (const flagId of _state_js__WEBPACK_IMPORTED_MODULE_0__/* .userFlags */ .BY) {
        const [dateStr] = flagId.split('_');
        datesToFetch.add(dateStr);
    }

    let updated = false;
    for (const dateStr of datesToFetch) {
        try {
            const resp = await fetch(`${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .API_BASE */ .tE}/venues/${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .VENUE_ID */ .eW}/menu/${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .MENU_ID */ .YU}/${dateStr}/`, {
                headers: (0,_api_js__WEBPACK_IMPORTED_MODULE_3__/* .apiHeaders */ .H)(token)
            });
            if (!resp.ok) continue;
            const data = await resp.json();
            const menuGroups = data.results || [];
            let dayItems = [];
            for (const group of menuGroups) {
                if (group.items && Array.isArray(group.items)) {
                    dayItems = dayItems.concat(group.items);
                }
            }

            for (let week of _state_js__WEBPACK_IMPORTED_MODULE_0__/* .allWeeks */ .p_) {
                if (!week.days) continue;
                let dayObj = week.days.find(d => d.date === dateStr);
                if (dayObj) {
                    dayObj.items = dayItems.map(item => {
                        const isUnlimited = item.amount_tracking === false;
                        const hasStock = parseInt(item.available_amount) > 0;
                        return {
                            id: `${dateStr}_${item.id}`,
                            articleId: item.id,
                            name: item.name || 'Unknown',
                            description: item.description || '',
                            price: parseFloat(item.price) || 0,
                            available: isUnlimited || hasStock,
                            availableAmount: parseInt(item.available_amount) || 0,
                            amountTracking: item.amount_tracking !== false
                        };
                    });
                    updated = true;
                }
            }
        } catch (e) {
            console.error('Error refreshing flag date', dateStr, e);
        }
    }

    if (updated) {
        saveMenuCache();
        updateLastUpdatedTime(new Date().toISOString());
        (0,_ui_helpers_js__WEBPACK_IMPORTED_MODULE_4__/* .updateAlarmBell */ .Mb)();
        (0,_ui_helpers_js__WEBPACK_IMPORTED_MODULE_4__/* .renderVisibleWeeks */ .OR)();
    }
}


function toggleFlag(date, articleId, name, cutoff) {
    const id = `${date}_${articleId}`;
    let flagAdded = false;
    if (_state_js__WEBPACK_IMPORTED_MODULE_0__/* .userFlags */ .BY.has(id)) {
        _state_js__WEBPACK_IMPORTED_MODULE_0__/* .userFlags */ .BY.delete(id);
        showToast(`Flag entfernt für ${name}`, 'success');
    } else {
        _state_js__WEBPACK_IMPORTED_MODULE_0__/* .userFlags */ .BY.add(id);
        flagAdded = true;
        showToast(`Benachrichtigung aktiviert für ${name}`, 'success');
        if (Notification.permission === 'default') {
            Notification.requestPermission();
        }
    }
    saveFlags();
    (0,_ui_helpers_js__WEBPACK_IMPORTED_MODULE_4__/* .updateAlarmBell */ .Mb)();
    (0,_ui_helpers_js__WEBPACK_IMPORTED_MODULE_4__/* .renderVisibleWeeks */ .OR)();

    if (flagAdded) {
        refreshFlaggedItems();
    }
}

function cleanupExpiredFlags() {
    const now = new Date();
    const todayStr = now.toISOString().split('T')[0];
    let changed = false;

    for (const flagId of [..._state_js__WEBPACK_IMPORTED_MODULE_0__/* .userFlags */ .BY]) {
        const [dateStr] = flagId.split('_');

        let isExpired = false;

        if (dateStr < todayStr) {
            isExpired = true;
        } else if (dateStr === todayStr) {
            const cutoff = new Date(dateStr);
            cutoff.setHours(10, 0, 0, 0);
            if (now >= cutoff) {
                isExpired = true;
            }
        }

        if (isExpired) {
            _state_js__WEBPACK_IMPORTED_MODULE_0__/* .userFlags */ .BY.delete(flagId);
            changed = true;
        }
    }
    if (changed) saveFlags();
}

function startPolling() {
    if (_state_js__WEBPACK_IMPORTED_MODULE_0__/* .pollIntervalId */ .K8) return;
    if (!_state_js__WEBPACK_IMPORTED_MODULE_0__/* .authToken */ .gX) return;
    (0,_state_js__WEBPACK_IMPORTED_MODULE_0__/* .setPollIntervalId */ .cc)(setInterval(() => pollFlaggedItems(), _constants_js__WEBPACK_IMPORTED_MODULE_2__/* .POLL_INTERVAL_MS */ .fv));
    console.log('Polling started (every 5 min)');
}

function stopPolling() {
    if (_state_js__WEBPACK_IMPORTED_MODULE_0__/* .pollIntervalId */ .K8) {
        clearInterval(_state_js__WEBPACK_IMPORTED_MODULE_0__/* .pollIntervalId */ .K8);
        (0,_state_js__WEBPACK_IMPORTED_MODULE_0__/* .setPollIntervalId */ .cc)(null);
        console.log('Polling stopped');
    }
}

async function pollFlaggedItems() {
    if (_state_js__WEBPACK_IMPORTED_MODULE_0__/* .userFlags */ .BY.size === 0 || !_state_js__WEBPACK_IMPORTED_MODULE_0__/* .authToken */ .gX) return;
    console.log(`Polling ${_state_js__WEBPACK_IMPORTED_MODULE_0__/* .userFlags */ .BY.size} flagged items...`);

    for (const flagId of _state_js__WEBPACK_IMPORTED_MODULE_0__/* .userFlags */ .BY) {
        const [date, articleIdStr] = flagId.split('_');
        const articleId = parseInt(articleIdStr);

        try {
            const response = await fetch(`${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .API_BASE */ .tE}/venues/${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .VENUE_ID */ .eW}/menu/${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .MENU_ID */ .YU}/${date}/`, {
                headers: (0,_api_js__WEBPACK_IMPORTED_MODULE_3__/* .apiHeaders */ .H)(_state_js__WEBPACK_IMPORTED_MODULE_0__/* .authToken */ .gX)
            });
            if (!response.ok) continue;

            const data = await response.json();
            const groups = data.results || [];
            let foundItem = null;
            for (const group of groups) {
                if (group.items) {
                    foundItem = group.items.find(i => i.id === articleId || i.article === articleId);
                    if (foundItem) break;
                }
            }

            if (foundItem) {
                const isAvailable = (foundItem.amount_tracking === false) || (parseInt(foundItem.available_amount) > 0);
                if (isAvailable) {
                    const itemName = foundItem.name || 'Unbekannt';
                    showToast(`${itemName} ist jetzt verfügbar!`, 'success');
                    if (Notification.permission === 'granted') {
                        new Notification('Kantine Wrapper', {
                            body: `${itemName} ist jetzt verfügbar!`,
                            icon: '🍽️'
                        });
                    }
                    loadMenuDataFromAPI();
                }
            }
        } catch (err) {
            console.error(`Poll error for ${flagId}:`, err);
            await new Promise(r => setTimeout(r, 200));
        }
    }
    localStorage.setItem('kantine_last_checked', new Date().toISOString());
    (0,_ui_helpers_js__WEBPACK_IMPORTED_MODULE_4__/* .updateAlarmBell */ .Mb)();
}

function saveHighlightTags() {
    localStorage.setItem('kantine_highlightTags', JSON.stringify(_state_js__WEBPACK_IMPORTED_MODULE_0__/* .highlightTags */ .yz));
    (0,_ui_helpers_js__WEBPACK_IMPORTED_MODULE_4__/* .renderVisibleWeeks */ .OR)();
    (0,_ui_helpers_js__WEBPACK_IMPORTED_MODULE_4__/* .updateNextWeekBadge */ .gJ)();
}

function addHighlightTag(tag) {
    tag = tag.trim().toLowerCase();
    if (tag && !_state_js__WEBPACK_IMPORTED_MODULE_0__/* .highlightTags */ .yz.includes(tag)) {
        const newTags = [..._state_js__WEBPACK_IMPORTED_MODULE_0__/* .highlightTags */ .yz, tag];
        (0,_state_js__WEBPACK_IMPORTED_MODULE_0__/* .setHighlightTags */ .iw)(newTags);
        saveHighlightTags();
        return true;
    }
    return false;
}

function removeHighlightTag(tag) {
    const newTags = _state_js__WEBPACK_IMPORTED_MODULE_0__/* .highlightTags */ .yz.filter(t => t !== tag);
    (0,_state_js__WEBPACK_IMPORTED_MODULE_0__/* .setHighlightTags */ .iw)(newTags);
    saveHighlightTags();
}

function renderTagsList() {
    const list = document.getElementById('tags-list');
    list.innerHTML = '';
    _state_js__WEBPACK_IMPORTED_MODULE_0__/* .highlightTags */ .yz.forEach(tag => {
        const badge = document.createElement('span');
        badge.className = 'tag-badge';
        badge.innerHTML = `${tag} <span class="tag-remove" data-tag="${tag}" title="Schlagwort entfernen">&times;</span>`;
        list.appendChild(badge);
    });

    list.querySelectorAll('.tag-remove').forEach(btn => {
        btn.addEventListener('click', (e) => {
            removeHighlightTag(e.target.dataset.tag);
            renderTagsList();
        });
    });
}

function checkHighlight(text) {
    if (!text) return [];
    text = text.toLowerCase();
    return _state_js__WEBPACK_IMPORTED_MODULE_0__/* .highlightTags */ .yz.filter(tag => text.includes(tag));
}

const CACHE_KEY = 'kantine_menuCache';
const CACHE_TS_KEY = 'kantine_menuCacheTs';

function saveMenuCache() {
    try {
        localStorage.setItem(CACHE_KEY, JSON.stringify(_state_js__WEBPACK_IMPORTED_MODULE_0__/* .allWeeks */ .p_));
        localStorage.setItem(CACHE_TS_KEY, new Date().toISOString());
    } catch (e) {
        console.warn('Failed to cache menu data:', e);
    }
}

function loadMenuCache() {
    try {
        const cached = localStorage.getItem(CACHE_KEY);
        const cachedTs = localStorage.getItem(CACHE_TS_KEY);
        console.log(`[Cache] localStorage: key=${!!cached} (${cached ? cached.length : 0} chars), ts=${cachedTs}`);
        if (cached) {
            (0,_state_js__WEBPACK_IMPORTED_MODULE_0__/* .setAllWeeks */ .tn)(JSON.parse(cached));
            (0,_state_js__WEBPACK_IMPORTED_MODULE_0__/* .setCurrentWeekNumber */ .Xt)((0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .getISOWeek */ .sn)(new Date()));
            (0,_state_js__WEBPACK_IMPORTED_MODULE_0__/* .setCurrentYear */ .pK)(new Date().getFullYear());
            console.log(`[Cache] Parsed ${_state_js__WEBPACK_IMPORTED_MODULE_0__/* .allWeeks */ .p_.length} weeks:`, _state_js__WEBPACK_IMPORTED_MODULE_0__/* .allWeeks */ .p_.map(w => `KW${w.weekNumber}/${w.year} (${(w.days || []).length} days)`));
            (0,_ui_helpers_js__WEBPACK_IMPORTED_MODULE_4__/* .renderVisibleWeeks */ .OR)();
            (0,_ui_helpers_js__WEBPACK_IMPORTED_MODULE_4__/* .updateNextWeekBadge */ .gJ)();
            (0,_ui_helpers_js__WEBPACK_IMPORTED_MODULE_4__/* .updateAlarmBell */ .Mb)();
            if (cachedTs) updateLastUpdatedTime(cachedTs);

            try {
                const uniqueMenus = new Set();
                _state_js__WEBPACK_IMPORTED_MODULE_0__/* .allWeeks */ .p_.forEach(w => {
                    (w.days || []).forEach(d => {
                        (d.items || []).forEach(item => {
                            let text = (item.description || '').replace(/\s+/g, ' ').trim();
                            if (text && text.includes(' / ')) {
                                uniqueMenus.add(text);
                            }
                        });
                    });
                });
                const res = Array.from(uniqueMenus).join('\n\n');
                console.log("=== GEFUNDENE MENÜ-TEXTE (" + uniqueMenus.size + ") ===");
                console.log(res);
            } catch (e) { }

            console.log('Loaded menu from cache');
            return true;
        }
    } catch (e) {
        console.warn('Failed to load cached menu:', e);
    }
    return false;
}

function isCacheFresh() {
    const cachedTs = localStorage.getItem(CACHE_TS_KEY);
    if (!cachedTs) {
        console.log('[Cache] No timestamp found');
        return false;
    }

    const ageMs = Date.now() - new Date(cachedTs).getTime();
    const ageMin = Math.round(ageMs / 60000);
    if (ageMs > 60 * 60 * 1000) {
        console.log(`[Cache] Stale: ${ageMin}min old (max 60)`);
        return false;
    }

    const thisWeek = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .getISOWeek */ .sn)(new Date());
    const thisYear = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .getWeekYear */ .Ao)(new Date());
    const hasCurrentWeek = _state_js__WEBPACK_IMPORTED_MODULE_0__/* .allWeeks */ .p_.some(w => w.weekNumber === thisWeek && w.year === thisYear && w.days && w.days.length > 0);

    console.log(`[Cache] Age: ${ageMin}min, looking for KW${thisWeek}/${thisYear}, found: ${hasCurrentWeek}`);
    return hasCurrentWeek;
}

async function loadMenuDataFromAPI() {
    const loading = document.getElementById('loading');
    const progressModal = document.getElementById('progress-modal');
    const progressFill = document.getElementById('progress-fill');
    const progressPercent = document.getElementById('progress-percent');
    const progressMessage = document.getElementById('progress-message');

    loading.classList.remove('hidden');

    const token = _state_js__WEBPACK_IMPORTED_MODULE_0__/* .authToken */ .gX || _constants_js__WEBPACK_IMPORTED_MODULE_2__/* .GUEST_TOKEN */ .f9;

    try {
        progressModal.classList.remove('hidden');
        progressMessage.textContent = 'Hole verfügbare Daten...';
        progressFill.style.width = '0%';
        progressPercent.textContent = '0%';

        const datesResponse = await fetch(`${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .API_BASE */ .tE}/venues/${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .VENUE_ID */ .eW}/menu/dates/`, {
            headers: (0,_api_js__WEBPACK_IMPORTED_MODULE_3__/* .apiHeaders */ .H)(token)
        });

        if (!datesResponse.ok) throw new Error(`Failed to fetch dates: ${datesResponse.status}`);

        const datesData = await datesResponse.json();
        let availableDates = datesData.results || [];

        const cutoff = new Date();
        cutoff.setDate(cutoff.getDate() - 7);
        const cutoffStr = cutoff.toISOString().split('T')[0];

        availableDates = availableDates
            .filter(d => d.date >= cutoffStr)
            .sort((a, b) => a.date.localeCompare(b.date))
            .slice(0, 30);

        const totalDates = availableDates.length;
        progressMessage.textContent = `${totalDates} Tage gefunden. Lade Details...`;

        const allDays = [];
        let completed = 0;

        for (const dateObj of availableDates) {
            const dateStr = dateObj.date;
            const pct = Math.round(((completed + 1) / totalDates) * 100);
            progressFill.style.width = `${pct}%`;
            progressPercent.textContent = `${pct}%`;
            progressMessage.textContent = `Lade Menü für ${dateStr}...`;

            try {
                const detailResp = await fetch(`${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .API_BASE */ .tE}/venues/${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .VENUE_ID */ .eW}/menu/${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .MENU_ID */ .YU}/${dateStr}/`, {
                    headers: (0,_api_js__WEBPACK_IMPORTED_MODULE_3__/* .apiHeaders */ .H)(token)
                });

                if (detailResp.ok) {
                    const detailData = await detailResp.json();
                    if (completed === 0) {
                        console.log('[Kantine Debug] Raw API response for', dateStr, ':', JSON.stringify(detailData).substring(0, 2000));
                    }
                    const menuGroups = detailData.results || [];
                    let dayItems = [];
                    for (const group of menuGroups) {
                        if (group.items && Array.isArray(group.items)) {
                            dayItems = dayItems.concat(group.items);
                        }
                    }
                    if (dayItems.length > 0) {
                        if (completed === 0) {
                            console.log('[Kantine Debug] First item keys:', Object.keys(dayItems[0]));
                            console.log('[Kantine Debug] First item:', JSON.stringify(dayItems[0]).substring(0, 500));
                        }
                        allDays.push({
                            date: dateStr,
                            menu_items: dayItems,
                            orders: dateObj.orders || []
                        });
                    }
                }
            } catch (err) {
                console.error(`Failed to fetch details for ${dateStr}:`, err);
            }

            completed++;
            await new Promise(r => setTimeout(r, 100));
        }

        const weeksMap = new Map();

        if (_state_js__WEBPACK_IMPORTED_MODULE_0__/* .allWeeks */ .p_ && _state_js__WEBPACK_IMPORTED_MODULE_0__/* .allWeeks */ .p_.length > 0) {
            _state_js__WEBPACK_IMPORTED_MODULE_0__/* .allWeeks */ .p_.forEach(w => {
                const key = `${w.year}-${w.weekNumber}`;
                try {
                    weeksMap.set(key, {
                        year: w.year,
                        weekNumber: w.weekNumber,
                        days: w.days ? w.days.map(d => ({ ...d, items: d.items ? [...d.items] : [] })) : []
                    });
                } catch (e) { console.warn('Error hydrating week:', e); }
            });
        }

        for (const day of allDays) {
            const d = new Date(day.date);
            const weekNum = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .getISOWeek */ .sn)(d);
            const year = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .getWeekYear */ .Ao)(d);
            const key = `${year}-${weekNum}`;

            if (!weeksMap.has(key)) {
                weeksMap.set(key, { year, weekNumber: weekNum, days: [] });
            }

            const weekObj = weeksMap.get(key);
            const weekday = d.toLocaleDateString('en-US', { weekday: 'long' });
            const orderCutoffDate = new Date(day.date);
            orderCutoffDate.setHours(10, 0, 0, 0);

            const newDayObj = {
                date: day.date,
                weekday: weekday,
                orderCutoff: orderCutoffDate.toISOString(),
                items: day.menu_items.map(item => {
                    const isUnlimited = item.amount_tracking === false;
                    const hasStock = parseInt(item.available_amount) > 0;
                    return {
                        id: `${day.date}_${item.id}`,
                        articleId: item.id,
                        name: item.name || 'Unknown',
                        description: item.description || '',
                        price: parseFloat(item.price) || 0,
                        available: isUnlimited || hasStock,
                        availableAmount: parseInt(item.available_amount) || 0,
                        amountTracking: item.amount_tracking !== false
                    };
                })
            };

            const existingIndex = weekObj.days.findIndex(existing => existing.date === day.date);
            if (existingIndex >= 0) {
                weekObj.days[existingIndex] = newDayObj;
            } else {
                weekObj.days.push(newDayObj);
            }
        }

        const newAllWeeks = Array.from(weeksMap.values()).sort((a, b) => {
            if (a.year !== b.year) return a.year - b.year;
            return a.weekNumber - b.weekNumber;
        });
        newAllWeeks.forEach(w => {
            if (w.days) w.days.sort((a, b) => a.date.localeCompare(b.date));
        });
        (0,_state_js__WEBPACK_IMPORTED_MODULE_0__/* .setAllWeeks */ .tn)(newAllWeeks);

        saveMenuCache();

        updateLastUpdatedTime(new Date().toISOString());

        (0,_state_js__WEBPACK_IMPORTED_MODULE_0__/* .setCurrentWeekNumber */ .Xt)((0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .getISOWeek */ .sn)(new Date()));
        (0,_state_js__WEBPACK_IMPORTED_MODULE_0__/* .setCurrentYear */ .pK)(new Date().getFullYear());

        updateAuthUI();
        (0,_ui_helpers_js__WEBPACK_IMPORTED_MODULE_4__/* .renderVisibleWeeks */ .OR)();
        (0,_ui_helpers_js__WEBPACK_IMPORTED_MODULE_4__/* .updateNextWeekBadge */ .gJ)();
        (0,_ui_helpers_js__WEBPACK_IMPORTED_MODULE_4__/* .updateAlarmBell */ .Mb)();

        progressMessage.textContent = 'Fertig!';
        setTimeout(() => progressModal.classList.add('hidden'), 500);

    } catch (error) {
        console.error('Error fetching menu:', error);
        progressModal.classList.add('hidden');
        Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, 842)).then(uiHelpers => {
            uiHelpers.showErrorModal(
                'Keine Verbindung',
                `Die Menüdaten konnten nicht geladen werden. Möglicherweise besteht keine Verbindung zur API oder zur Bessa-Webseite.<br><br><small style="color:var(--text-secondary)">${error.message}</small>`,
                'Zur Original-Seite',
                'https://web.bessa.app/knapp-kantine'
            );
        });
    } finally {
        loading.classList.add('hidden');
    }
}

let lastUpdatedTimestamp = null;
let lastUpdatedIntervalId = null;

function updateLastUpdatedTime(isoTimestamp) {
    const subtitle = document.getElementById('last-updated-subtitle');
    if (!isoTimestamp) return;
    lastUpdatedTimestamp = isoTimestamp;
    localStorage.setItem('kantine_last_updated', isoTimestamp);
    localStorage.setItem('kantine_last_checked', isoTimestamp);
    try {
        const date = new Date(isoTimestamp);
        const timeStr = date.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' });
        const dateStr = date.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit' });
        const ago = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .getRelativeTime */ .gs)(date);
        subtitle.textContent = `Aktualisiert: ${dateStr} ${timeStr} (${ago})`;
    } catch (e) {
        subtitle.textContent = '';
    }
    if (!lastUpdatedIntervalId) {
        lastUpdatedIntervalId = setInterval(() => {
            if (lastUpdatedTimestamp) {
                updateLastUpdatedTime(lastUpdatedTimestamp);
                (0,_ui_helpers_js__WEBPACK_IMPORTED_MODULE_4__/* .updateAlarmBell */ .Mb)();
            }
        }, 60 * 1000);
    }
}

function showToast(message, type = 'info') {
    let container = document.getElementById('toast-container');
    if (!container) {
        container = document.createElement('div');
        container.id = 'toast-container';
        document.body.appendChild(container);
    }
    const toast = document.createElement('div');
    toast.className = `toast toast-${type}`;
    const icon = type === 'success' ? 'check_circle' : type === 'error' ? 'error' : 'info';
    toast.innerHTML = `<span class="material-icons-round">${icon}</span><span>${message}</span>`;
    container.appendChild(toast);
    requestAnimationFrame(() => toast.classList.add('show'));
    setTimeout(() => {
        toast.classList.remove('show');
        setTimeout(() => toast.remove(), 300);
    }, 3000);
}


/***/ },

/***/ 672
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {

/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   H: () => (/* binding */ apiHeaders),
/* harmony export */   O: () => (/* binding */ githubHeaders)
/* harmony export */ });
/* harmony import */ var _constants_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(521);


function apiHeaders(token) {
    return {
        'Authorization': `Token ${token || _constants_js__WEBPACK_IMPORTED_MODULE_0__/* .GUEST_TOKEN */ .f9}`,
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        'X-Client-Version': _constants_js__WEBPACK_IMPORTED_MODULE_0__/* .CLIENT_VERSION */ .fZ
    };
}

function githubHeaders() {
    return { 'Accept': 'application/vnd.github.v3+json' };
}


/***/ },

/***/ 521
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {

/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   YU: () => (/* binding */ MENU_ID),
/* harmony export */   d_: () => (/* binding */ INSTALLER_BASE),
/* harmony export */   eW: () => (/* binding */ VENUE_ID),
/* harmony export */   f9: () => (/* binding */ GUEST_TOKEN),
/* harmony export */   fZ: () => (/* binding */ CLIENT_VERSION),
/* harmony export */   fv: () => (/* binding */ POLL_INTERVAL_MS),
/* harmony export */   pe: () => (/* binding */ GITHUB_API),
/* harmony export */   tE: () => (/* binding */ API_BASE)
/* harmony export */ });
/* unused harmony export GITHUB_REPO */
const API_BASE = 'https://api.bessa.app/v1';
const GUEST_TOKEN = 'c3418725e95a9f90e3645cbc846b4d67c7c66131';
const CLIENT_VERSION = 'v1.6.11';
const VENUE_ID = 591;
const MENU_ID = 7;
const POLL_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes

const GITHUB_REPO = 'TauNeutrino/kantine-overview';
const GITHUB_API = `https://api.github.com/repos/${GITHUB_REPO}`;
const INSTALLER_BASE = `https://htmlpreview.github.io/?https://github.com/${GITHUB_REPO}/blob`;


/***/ },

/***/ 901
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {

/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   BT: () => (/* binding */ currentWeekNumber),
/* harmony export */   BY: () => (/* binding */ userFlags),
/* harmony export */   K8: () => (/* binding */ pollIntervalId),
/* harmony export */   Kl: () => (/* binding */ langMode),
/* harmony export */   L: () => (/* binding */ orderMap),
/* harmony export */   Ny: () => (/* binding */ currentUser),
/* harmony export */   O5: () => (/* binding */ setAuthToken),
/* harmony export */   UD: () => (/* binding */ setLangMode),
/* harmony export */   Xt: () => (/* binding */ setCurrentWeekNumber),
/* harmony export */   cc: () => (/* binding */ setPollIntervalId),
/* harmony export */   di: () => (/* binding */ setOrderMap),
/* harmony export */   gX: () => (/* binding */ authToken),
/* harmony export */   iw: () => (/* binding */ setHighlightTags),
/* harmony export */   lt: () => (/* binding */ setCurrentUser),
/* harmony export */   pK: () => (/* binding */ setCurrentYear),
/* harmony export */   p_: () => (/* binding */ allWeeks),
/* harmony export */   qo: () => (/* binding */ setDisplayMode),
/* harmony export */   sw: () => (/* binding */ displayMode),
/* harmony export */   tn: () => (/* binding */ setAllWeeks),
/* harmony export */   vW: () => (/* binding */ currentYear),
/* harmony export */   yz: () => (/* binding */ highlightTags)
/* harmony export */ });
/* unused harmony export setUserFlags */
/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(413);


let allWeeks = [];
let currentWeekNumber = (0,_utils_js__WEBPACK_IMPORTED_MODULE_0__/* .getISOWeek */ .sn)(new Date());
let currentYear = new Date().getFullYear();
let displayMode = 'this-week';
let authToken = localStorage.getItem('kantine_authToken');
let currentUser = localStorage.getItem('kantine_currentUser');
let orderMap = new Map();
let userFlags = new Set(JSON.parse(localStorage.getItem('kantine_flags') || '[]'));
let pollIntervalId = null;
let langMode = localStorage.getItem('kantine_lang') || 'de';
let highlightTags = JSON.parse(localStorage.getItem('kantine_highlightTags') || '[]');

function setAllWeeks(weeks) { allWeeks = weeks; }
function setCurrentWeekNumber(week) { currentWeekNumber = week; }
function setCurrentYear(year) { currentYear = year; }
function setDisplayMode(mode) { displayMode = mode; }
function setAuthToken(token) { authToken = token; }
function setCurrentUser(user) { currentUser = user; }
function setOrderMap(map) { orderMap = map; }
function setUserFlags(flags) { userFlags = flags; }
function setPollIntervalId(id) { pollIntervalId = id; }
function setLangMode(lang) { langMode = lang; }
function setHighlightTags(tags) { highlightTags = tags; }


/***/ },

/***/ 842
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {

/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   Gk: () => (/* binding */ openVersionMenu),
/* harmony export */   Mb: () => (/* binding */ updateAlarmBell),
/* harmony export */   OR: () => (/* binding */ renderVisibleWeeks),
/* harmony export */   Ux: () => (/* binding */ checkForUpdates),
/* harmony export */   gJ: () => (/* binding */ updateNextWeekBadge),
/* harmony export */   showErrorModal: () => (/* binding */ showErrorModal)
/* harmony export */ });
/* unused harmony exports updateWeeklyCost, syncMenuItemHeights, createDayCard, fetchVersions, updateCountdown, removeCountdown */
/* harmony import */ var _state_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(901);
/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(413);
/* harmony import */ var _constants_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(521);
/* harmony import */ var _api_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(672);
/* harmony import */ var _actions_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(367);






function updateNextWeekBadge() {
    const btnNextWeek = document.getElementById('btn-next-week');
    let nextWeek = _state_js__WEBPACK_IMPORTED_MODULE_0__/* .currentWeekNumber */ .BT + 1;
    let nextYear = _state_js__WEBPACK_IMPORTED_MODULE_0__/* .currentYear */ .vW;
    if (nextWeek > 52) { nextWeek = 1; nextYear++; }

    const nextWeekData = _state_js__WEBPACK_IMPORTED_MODULE_0__/* .allWeeks */ .p_.find(w => w.weekNumber === nextWeek && w.year === nextYear);
    let totalDataCount = 0;
    let orderableCount = 0;
    let daysWithOrders = 0;
    let daysWithOrderableAndNoOrder = 0;

    if (nextWeekData && nextWeekData.days) {
        nextWeekData.days.forEach(day => {
            if (day.items && day.items.length > 0) {
                totalDataCount++;
                const isOrderable = day.items.some(item => item.available);
                if (isOrderable) orderableCount++;

                let hasOrder = false;
                day.items.forEach(item => {
                    const articleId = item.articleId || parseInt(item.id.split('_')[1]);
                    const key = `${day.date}_${articleId}`;
                    if (_state_js__WEBPACK_IMPORTED_MODULE_0__/* .orderMap */ .L.has(key) && _state_js__WEBPACK_IMPORTED_MODULE_0__/* .orderMap */ .L.get(key).length > 0) hasOrder = true;
                });

                if (hasOrder) daysWithOrders++;
                if (isOrderable && !hasOrder) daysWithOrderableAndNoOrder++;
            }
        });
    }

    let badge = btnNextWeek.querySelector('.nav-badge');
    if (totalDataCount > 0) {
        if (!badge) {
            badge = document.createElement('span');
            badge.className = 'nav-badge';
            btnNextWeek.appendChild(badge);
        }

        badge.title = `${daysWithOrders} bestellt / ${orderableCount} bestellbar / ${totalDataCount} gesamt`;
        badge.innerHTML = `<span class="ordered">${daysWithOrders}</span><span class="separator">/</span><span class="orderable">${orderableCount}</span><span class="separator">/</span><span class="total">${totalDataCount}</span>`;

        badge.classList.remove('badge-violet', 'badge-green', 'badge-red', 'badge-blue');

        if (daysWithOrders > 0 && daysWithOrderableAndNoOrder === 0) {
            badge.classList.add('badge-violet');
        } else if (daysWithOrderableAndNoOrder > 0) {
            badge.classList.add('badge-green');
        } else if (orderableCount === 0) {
            badge.classList.add('badge-red');
        } else {
            badge.classList.add('badge-blue');
        }

        let highlightCount = 0;
        if (nextWeekData && nextWeekData.days) {
            nextWeekData.days.forEach(day => {
                day.items.forEach(item => {
                    const nameMatches = (0,_actions_js__WEBPACK_IMPORTED_MODULE_4__/* .checkHighlight */ .BM)(item.name);
                    const descMatches = (0,_actions_js__WEBPACK_IMPORTED_MODULE_4__/* .checkHighlight */ .BM)(item.description);
                    if (nameMatches.length > 0 || descMatches.length > 0) {
                        highlightCount++;
                    }
                });
            });
        }

        if (highlightCount > 0) {
            badge.innerHTML += `<span class="highlight-count" title="${highlightCount} Highlight Menüs">(${highlightCount})</span>`;
            badge.title += ` • ${highlightCount} Highlights gefunden`;
            badge.classList.add('has-highlights');
        }

        if (daysWithOrders === 0) {
            btnNextWeek.classList.add('new-week-available');
            const storageKey = `kantine_notified_nextweek_${nextYear}_${nextWeek}`;
            if (!localStorage.getItem(storageKey)) {
                localStorage.setItem(storageKey, 'true');
                (0,_actions_js__WEBPACK_IMPORTED_MODULE_4__/* .showToast */ .P0)('Neue Menüdaten für nächste Woche verfügbar!', 'info');
            }
        } else {
            btnNextWeek.classList.remove('new-week-available');
        }

    } else if (badge) {
        badge.remove();
    }
}

function updateWeeklyCost(days) {
    let totalCost = 0;
    if (days && days.length > 0) {
        days.forEach(day => {
            if (day.items) {
                day.items.forEach(item => {
                    const articleId = item.articleId || parseInt(item.id.split('_')[1]);
                    const key = `${day.date}_${articleId}`;
                    const orders = _state_js__WEBPACK_IMPORTED_MODULE_0__/* .orderMap */ .L.get(key) || [];
                    if (orders.length > 0) totalCost += item.price * orders.length;
                });
            }
        });
    }

    const costDisplay = document.getElementById('weekly-cost-display');
    if (totalCost > 0) {
        costDisplay.innerHTML = `<span class="material-icons-round">shopping_bag</span> <span>Gesamt: ${totalCost.toFixed(2).replace('.', ',')} €</span>`;
        costDisplay.classList.remove('hidden');
    } else {
        costDisplay.classList.add('hidden');
    }
}

function renderVisibleWeeks() {
    const menuContainer = document.getElementById('menu-container');
    if (!menuContainer) return;
    menuContainer.innerHTML = '';

    let targetWeek = _state_js__WEBPACK_IMPORTED_MODULE_0__/* .currentWeekNumber */ .BT;
    let targetYear = _state_js__WEBPACK_IMPORTED_MODULE_0__/* .currentYear */ .vW;

    if (_state_js__WEBPACK_IMPORTED_MODULE_0__/* .displayMode */ .sw === 'next-week') {
        targetWeek++;
        if (targetWeek > 52) { targetWeek = 1; targetYear++; }
    }

    const allDays = _state_js__WEBPACK_IMPORTED_MODULE_0__/* .allWeeks */ .p_.flatMap(w => w.days || []);
    const daysInTargetWeek = allDays.filter(day => {
        const d = new Date(day.date);
        return (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .getISOWeek */ .sn)(d) === targetWeek && (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .getWeekYear */ .Ao)(d) === targetYear;
    });

    if (daysInTargetWeek.length === 0) {
        menuContainer.innerHTML = `
            <div class="empty-state">
                <p>Keine Menüdaten für KW ${targetWeek} (${targetYear}) verfügbar.</p>
                <small>Versuchen Sie eine andere Woche oder schauen Sie später vorbei.</small>
            </div>`;
        document.getElementById('weekly-cost-display').classList.add('hidden');
        return;
    }

    updateWeeklyCost(daysInTargetWeek);

    const headerWeekInfo = document.getElementById('header-week-info');
    const weekTitle = _state_js__WEBPACK_IMPORTED_MODULE_0__/* .displayMode */ .sw === 'this-week' ? 'Diese Woche' : 'Nächste Woche';
    headerWeekInfo.innerHTML = `
        <div class="header-week-title">${weekTitle}</div>
        <div class="header-week-subtitle">Week ${targetWeek} • ${targetYear}</div>`;

    const grid = document.createElement('div');
    grid.className = 'days-grid';

    daysInTargetWeek.sort((a, b) => a.date.localeCompare(b.date));

    const workingDays = daysInTargetWeek.filter(d => {
        const date = new Date(d.date);
        const day = date.getDay();
        return day !== 0 && day !== 6;
    });

    workingDays.forEach(day => {
        const card = createDayCard(day);
        if (card) grid.appendChild(card);
    });

    menuContainer.appendChild(grid);
    setTimeout(() => syncMenuItemHeights(grid), 0);
}

function syncMenuItemHeights(grid) {
    const cards = grid.querySelectorAll('.menu-card');
    if (cards.length === 0) return;
    let maxItems = 0;
    cards.forEach(card => {
        maxItems = Math.max(maxItems, card.querySelectorAll('.menu-item').length);
    });
    for (let i = 0; i < maxItems; i++) {
        let maxHeight = 0;
        const itemsAtPos = [];
        cards.forEach(card => {
            const items = card.querySelectorAll('.menu-item');
            if (items[i]) {
                items[i].style.height = 'auto';
                maxHeight = Math.max(maxHeight, items[i].offsetHeight);
                itemsAtPos.push(items[i]);
            }
        });
        itemsAtPos.forEach(item => { item.style.height = `${maxHeight}px`; });
    }
}

function createDayCard(day) {
    if (!day.items || day.items.length === 0) return null;

    const card = document.createElement('div');
    card.className = 'menu-card';

    const now = new Date();
    const cardDate = new Date(day.date);

    let isPastCutoff = false;
    if (day.orderCutoff) {
        isPastCutoff = now >= new Date(day.orderCutoff);
    } else {
        const today = new Date();
        today.setHours(0, 0, 0, 0);
        const cd = new Date(day.date);
        cd.setHours(0, 0, 0, 0);
        isPastCutoff = cd < today;
    }

    if (isPastCutoff) card.classList.add('past-day');

    const menuBadges = [];
    if (day.items) {
        day.items.forEach(item => {
            const articleId = item.articleId || parseInt(item.id.split('_')[1]);
            const orderKey = `${day.date}_${articleId}`;
            const orders = _state_js__WEBPACK_IMPORTED_MODULE_0__/* .orderMap */ .L.get(orderKey) || [];
            const count = orders.length;

            if (count > 0) {
                const match = item.name.match(/([M][1-9][Ff]?)/);
                if (match) {
                    let code = match[1];
                    if (count > 1) code += '+';
                    menuBadges.push(code);
                }
            }
        });
    }

    const header = document.createElement('div');
    header.className = 'card-header';
    const dateStr = cardDate.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit' });

    const badgesHtml = menuBadges.map(code => `<span class="menu-code-badge">${code}</span>`).join('');

    let headerClass = '';
    const hasAnyOrder = day.items && day.items.some(item => {
        const articleId = item.articleId || parseInt(item.id.split('_')[1]);
        const key = `${day.date}_${articleId}`;
        return _state_js__WEBPACK_IMPORTED_MODULE_0__/* .orderMap */ .L.has(key) && _state_js__WEBPACK_IMPORTED_MODULE_0__/* .orderMap */ .L.get(key).length > 0;
    });

    const hasOrderable = day.items && day.items.some(item => item.available);

    if (hasAnyOrder) {
        headerClass = 'header-violet';
    } else if (hasOrderable && !isPastCutoff) {
        headerClass = 'header-green';
    } else {
        headerClass = 'header-red';
    }

    if (headerClass) header.classList.add(headerClass);

    header.innerHTML = `
        <div class="day-header-left">
            <span class="day-name">${(0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .translateDay */ .FS)(day.weekday)}</span>
            <div class="day-badges">${badgesHtml}</div>
        </div>
        <span class="day-date">${dateStr}</span>`;
    card.appendChild(header);

    const body = document.createElement('div');
    body.className = 'card-body';

    const todayDateStr = new Date().toISOString().split('T')[0];
    const isToday = day.date === todayDateStr;

    const sortedItems = [...day.items].sort((a, b) => {
        if (isToday) {
            const aId = a.articleId || parseInt(a.id.split('_')[1]);
            const bId = b.articleId || parseInt(b.id.split('_')[1]);
            const aOrdered = _state_js__WEBPACK_IMPORTED_MODULE_0__/* .orderMap */ .L.has(`${day.date}_${aId}`);
            const bOrdered = _state_js__WEBPACK_IMPORTED_MODULE_0__/* .orderMap */ .L.has(`${day.date}_${bId}`);

            if (aOrdered && !bOrdered) return -1;
            if (!aOrdered && bOrdered) return 1;
        }
        return a.name.localeCompare(b.name);
    });

    sortedItems.forEach(item => {
        const itemEl = document.createElement('div');
        itemEl.className = 'menu-item';

        const articleId = item.articleId || parseInt(item.id.split('_')[1]);
        const orderKey = `${day.date}_${articleId}`;
        const orderIds = _state_js__WEBPACK_IMPORTED_MODULE_0__/* .orderMap */ .L.get(orderKey) || [];
        const orderCount = orderIds.length;

        let statusBadge = '';
        if (item.available) {
            statusBadge = item.amountTracking
                ? `<span class="badge available">Verfügbar (${item.availableAmount})</span>`
                : `<span class="badge available">Verfügbar</span>`;
        } else {
            statusBadge = `<span class="badge sold-out">Ausverkauft</span>`;
        }

        let orderedBadge = '';
        if (orderCount > 0) {
            const countBadge = orderCount > 1 ? `<span class="order-count-badge">${orderCount}</span>` : '';
            orderedBadge = `<span class="badge ordered"><span class="material-icons-round">check_circle</span> Bestellt${countBadge}</span>`;
            itemEl.classList.add('ordered');
            if (new Date(day.date).toDateString() === now.toDateString()) {
                itemEl.classList.add('today-ordered');
            }
        }

        const flagId = `${day.date}_${articleId}`;
        const isFlagged = _state_js__WEBPACK_IMPORTED_MODULE_0__/* .userFlags */ .BY.has(flagId);
        if (isFlagged) {
            itemEl.classList.add(item.available ? 'flagged-available' : 'flagged-sold-out');
        }

        const matchedTags = [...new Set([...(0,_actions_js__WEBPACK_IMPORTED_MODULE_4__/* .checkHighlight */ .BM)(item.name), ...(0,_actions_js__WEBPACK_IMPORTED_MODULE_4__/* .checkHighlight */ .BM)(item.description)])];
        if (matchedTags.length > 0) {
            itemEl.classList.add('highlight-glow');
        }

        let orderButton = '';
        let cancelButton = '';
        let flagButton = '';

        if (_state_js__WEBPACK_IMPORTED_MODULE_0__/* .authToken */ .gX && !isPastCutoff) {
            const flagIcon = isFlagged ? 'notifications_active' : 'notifications_none';
            const flagClass = isFlagged ? 'btn-flag active' : 'btn-flag';
            const flagTitle = isFlagged ? 'Benachrichtigung deaktivieren' : 'Benachrichtigen wenn verfügbar';
            if (!item.available || isFlagged) {
                flagButton = `<button class="${flagClass}" data-date="${day.date}" data-article="${articleId}" data-name="${(0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .escapeHtml */ .ZD)(item.name)}" data-cutoff="${day.orderCutoff}" title="${flagTitle}"><span class="material-icons-round">${flagIcon}</span></button>`;
            }

            if (item.available) {
                if (orderCount > 0) {
                    orderButton = `<button class="btn-order btn-order-compact" data-date="${day.date}" data-article="${articleId}" data-name="${(0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .escapeHtml */ .ZD)(item.name)}" data-price="${item.price}" data-desc="${(0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .escapeHtml */ .ZD)(item.description || '')}" title="${(0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .escapeHtml */ .ZD)(item.name)} nochmal bestellen"><span class="material-icons-round">add</span></button>`;
                } else {
                    orderButton = `<button class="btn-order" data-date="${day.date}" data-article="${articleId}" data-name="${(0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .escapeHtml */ .ZD)(item.name)}" data-price="${item.price}" data-desc="${(0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .escapeHtml */ .ZD)(item.description || '')}" title="${(0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .escapeHtml */ .ZD)(item.name)} bestellen"><span class="material-icons-round">add_shopping_cart</span> Bestellen</button>`;
                }
            }

            if (orderCount > 0) {
                const cancelIcon = orderCount === 1 ? 'close' : 'remove';
                const cancelTitle = orderCount === 1 ? 'Bestellung stornieren' : 'Eine Bestellung stornieren';
                cancelButton = `<button class="btn-cancel" data-date="${day.date}" data-article="${articleId}" data-name="${(0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .escapeHtml */ .ZD)(item.name)}" title="${cancelTitle}"><span class="material-icons-round">${cancelIcon}</span></button>`;
            }
        }

        let tagsHtml = '';
        if (matchedTags.length > 0) {
            const badges = matchedTags.map(t => `<span class="tag-badge-small"><span class="material-icons-round" style="font-size:10px;margin-right:2px">star</span>${(0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .escapeHtml */ .ZD)(t)}</span>`).join('');
            tagsHtml = `<div class="matched-tags">${badges}</div>`;
        }

        itemEl.innerHTML = `
            <div class="item-header">
                <span class="item-name">${(0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .escapeHtml */ .ZD)(item.name)}</span>
                <span class="item-price">${item.price.toFixed(2)} €</span>
            </div>
            <div class="item-status-row">
                ${orderedBadge}
                ${cancelButton}
                ${orderButton}
                ${flagButton}
                <div class="badges">${statusBadge}</div>
            </div>
            ${tagsHtml}
            <p class="item-desc">${(0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .escapeHtml */ .ZD)((0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .getLocalizedText */ .PC)(item.description))}</p>`;

        const orderBtn = itemEl.querySelector('.btn-order');
        if (orderBtn) {
            orderBtn.addEventListener('click', (e) => {
                e.stopPropagation();
                const btn = e.currentTarget;
                btn.disabled = true;
                btn.classList.add('loading');
                (0,_actions_js__WEBPACK_IMPORTED_MODULE_4__/* .placeOrder */ .wH)(btn.dataset.date, parseInt(btn.dataset.article), btn.dataset.name, parseFloat(btn.dataset.price), btn.dataset.desc || '')
                    .finally(() => { btn.disabled = false; btn.classList.remove('loading'); });
            });
        }

        const cancelBtn = itemEl.querySelector('.btn-cancel');
        if (cancelBtn) {
            cancelBtn.addEventListener('click', (e) => {
                e.stopPropagation();
                const btn = e.currentTarget;
                btn.disabled = true;
                (0,_actions_js__WEBPACK_IMPORTED_MODULE_4__/* .cancelOrder */ .N4)(btn.dataset.date, parseInt(btn.dataset.article), btn.dataset.name)
                    .finally(() => { btn.disabled = false; });
            });
        }

        const flagBtn = itemEl.querySelector('.btn-flag');
        if (flagBtn) {
            flagBtn.addEventListener('click', (e) => {
                e.stopPropagation();
                const btn = e.currentTarget;
                (0,_actions_js__WEBPACK_IMPORTED_MODULE_4__/* .toggleFlag */ .PQ)(btn.dataset.date, parseInt(btn.dataset.article), btn.dataset.name, btn.dataset.cutoff);
            });
        }

        body.appendChild(itemEl);
    });

    card.appendChild(body);
    return card;
}

async function fetchVersions(devMode) {
    const endpoint = devMode
        ? `${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .GITHUB_API */ .pe}/tags?per_page=20`
        : `${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .GITHUB_API */ .pe}/releases?per_page=20`;

    const resp = await fetch(endpoint, { headers: (0,_api_js__WEBPACK_IMPORTED_MODULE_3__/* .githubHeaders */ .O)() });
    if (!resp.ok) {
        if (resp.status === 403) {
            throw new Error('API Rate Limit erreicht (403). Bitte später erneut versuchen.');
        }
        throw new Error(`GitHub API ${resp.status}`);
    }
    const data = await resp.json();

    return data.map(item => {
        const tag = devMode ? item.name : item.tag_name;
        return {
            tag,
            name: devMode ? tag : (item.name || tag),
            url: `${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .INSTALLER_BASE */ .d_}/${tag}/dist/install.html`,
            body: item.body || ''
        };
    });
}

async function checkForUpdates() {
    const currentVersion = '{{VERSION}}';
    const devMode = localStorage.getItem('kantine_dev_mode') === 'true';

    try {
        const versions = await fetchVersions(devMode);
        if (!versions.length) return;

        localStorage.setItem('kantine_version_cache', JSON.stringify({
            timestamp: Date.now(), devMode, versions
        }));

        const latest = versions[0].tag;
        console.log(`[Kantine] Version Check: Local [${currentVersion}] vs Latest [${latest}] (${devMode ? 'dev' : 'stable'})`);

        if (!(0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .isNewer */ .U4)(latest, currentVersion)) return;

        console.log(`[Kantine] Update verfügbar: ${latest}`);

        const headerTitle = document.querySelector('.header-left h1');
        if (headerTitle && !headerTitle.querySelector('.update-icon')) {
            const icon = document.createElement('a');
            icon.className = 'update-icon';
            icon.href = versions[0].url;
            icon.target = '_blank';
            icon.innerHTML = '🆕';
            icon.title = `Update: ${latest} — Klick zum Installieren`;
            icon.style.cssText = 'margin-left:8px;font-size:1em;text-decoration:none;cursor:pointer;vertical-align:middle;';
            headerTitle.appendChild(icon);
        }
    } catch (e) {
        console.warn('[Kantine] Version check failed:', e);
    }
}

function openVersionMenu() {
    const modal = document.getElementById('version-modal');
    const container = document.getElementById('version-list-container');
    const devToggle = document.getElementById('dev-mode-toggle');
    const currentVersion = '{{VERSION}}';

    if (!modal) return;
    modal.classList.remove('hidden');

    const cur = document.getElementById('version-current');
    if (cur) cur.textContent = currentVersion;

    const devMode = localStorage.getItem('kantine_dev_mode') === 'true';
    devToggle.checked = devMode;

    async function loadVersions(forceRefresh) {
        const dm = devToggle.checked;
        container.innerHTML = '<p style="color:var(--text-secondary);">Lade Versionen...</p>';

        function renderVersionsList(versions) {
            if (!versions || !versions.length) {
                container.innerHTML = '<p style="color:var(--text-secondary);">Keine Versionen gefunden.</p>';
                return;
            }

            container.innerHTML = '<ul class="version-list"></ul>';
            const list = container.querySelector('.version-list');

            versions.forEach(v => {
                const isCurrent = v.tag === currentVersion;
                const isNew = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .isNewer */ .U4)(v.tag, currentVersion);
                const li = document.createElement('li');
                li.className = 'version-item' + (isCurrent ? ' current' : '');

                let badge = '';
                if (isCurrent) badge = '<span class="badge-current">✓ Installiert</span>';
                else if (isNew) badge = '<span class="badge-new">⬆ Neu!</span>';

                let action = '';
                if (!isCurrent) {
                    action = `<a href="${v.url}" target="_blank" class="install-link" title="${v.tag} installieren">Installieren</a>`;
                }

                li.innerHTML = `
                    <div class="version-info">
                        <strong>${v.tag}</strong>
                        ${badge}
                    </div>
                    ${action}
                `;
                list.appendChild(li);
            });
        }

        try {
            const cachedRaw = localStorage.getItem('kantine_version_cache');
            let cached = null;
            if (cachedRaw) {
                try { cached = JSON.parse(cachedRaw); } catch (e) { }
            }

            if (cached && cached.devMode === dm && cached.versions) {
                renderVersionsList(cached.versions);
            }

            const liveVersions = await fetchVersions(dm);

            const liveVersionsStr = JSON.stringify(liveVersions);
            const cachedVersionsStr = cached ? JSON.stringify(cached.versions) : '';

            if (liveVersionsStr !== cachedVersionsStr) {
                localStorage.setItem('kantine_version_cache', JSON.stringify({
                    timestamp: Date.now(), devMode: dm, versions: liveVersions
                }));
                renderVersionsList(liveVersions);
            }

        } catch (e) {
            container.innerHTML = `<p style="color:#e94560;">Fehler: ${e.message}</p>`;
        }
    }

    loadVersions(false);

    devToggle.onchange = () => {
        localStorage.setItem('kantine_dev_mode', devToggle.checked);
        localStorage.removeItem('kantine_version_cache');
        loadVersions(true);
    };
}

function updateCountdown() {
    if (!_state_js__WEBPACK_IMPORTED_MODULE_0__/* .authToken */ .gX || !_state_js__WEBPACK_IMPORTED_MODULE_0__/* .currentUser */ .Ny) {
        removeCountdown();
        return;
    }

    const now = new Date();
    const currentDay = now.getDay();
    if (currentDay === 0 || currentDay === 6) {
        removeCountdown();
        return;
    }

    const todayStr = now.toISOString().split('T')[0];

    let hasOrder = false;
    for (const key of _state_js__WEBPACK_IMPORTED_MODULE_0__/* .orderMap */ .L.keys()) {
        if (key.startsWith(todayStr)) {
            hasOrder = true;
            break;
        }
    }

    if (hasOrder) {
        removeCountdown();
        return;
    }

    const cutoff = new Date();
    cutoff.setHours(10, 0, 0, 0);

    const diff = cutoff - now;

    if (diff <= 0) {
        removeCountdown();
        return;
    }

    const diffHrs = Math.floor(diff / 3600000);
    const diffMins = Math.floor((diff % 3600000) / 60000);

    const headerCenter = document.querySelector('.header-center-wrapper');
    if (!headerCenter) return;

    let countdownEl = document.getElementById('order-countdown');
    if (!countdownEl) {
        countdownEl = document.createElement('div');
        countdownEl.id = 'order-countdown';
        headerCenter.insertBefore(countdownEl, headerCenter.firstChild);
    }

    countdownEl.innerHTML = `<span>Bestellschluss:</span> <strong>${diffHrs}h ${diffMins}m</strong>`;

    if (diff < 3600000) {
        countdownEl.classList.add('urgent');

        const notifiedKey = `kantine_notified_${todayStr}`;
        if (!localStorage.getItem(notifiedKey)) {
            if (Notification.permission === 'granted') {
                new Notification('Kantine: Bestellschluss naht!', {
                    body: 'Du hast heute noch nichts bestellt. Nur noch 1 Stunde!',
                    icon: '⏳'
                });
            } else if (Notification.permission === 'default') {
                Notification.requestPermission();
            }
            localStorage.setItem(notifiedKey, 'true');
        }
    } else {
        countdownEl.classList.remove('urgent');
    }
}

function removeCountdown() {
    const el = document.getElementById('order-countdown');
    if (el) el.remove();
}

setInterval(updateCountdown, 60000);
setTimeout(updateCountdown, 1000);

function showErrorModal(title, htmlContent, btnText, url) {
    const modalId = 'error-modal';
    let modal = document.getElementById(modalId);
    if (modal) modal.remove();

    modal = document.createElement('div');
    modal.id = modalId;
    modal.className = 'modal hidden';
    modal.innerHTML = `
        <div class="modal-content">
            <div class="modal-header">
                <h2 style="color: var(--error-color); display: flex; align-items: center; gap: 10px;">
                    <span class="material-icons-round">signal_wifi_off</span>
                    ${title}
                </h2>
            </div>
            <div style="padding: 20px;">
                <p style="margin-bottom: 15px; color: var(--text-primary);">${htmlContent}</p>
                <div style="margin-top: 20px; display: flex; justify-content: center;">
                    <button id="btn-error-redirect" style="
                        background-color: var(--accent-color);
                        color: white;
                        padding: 12px 24px;
                        border-radius: 8px;
                        border: none;
                        font-weight: 600;
                        cursor: pointer;
                        display: flex;
                        align-items: center;
                        gap: 8px;
                        width: 100%;
                        justify-content: center;
                        transition: transform 0.1s;
                    ">
                        ${btnText}
                        <span class="material-icons-round">open_in_new</span>
                    </button>
                </div>
            </div>
        </div>
    `;
    document.body.appendChild(modal);

    document.getElementById('btn-error-redirect').addEventListener('click', () => {
        window.location.href = url;
    });

    requestAnimationFrame(() => {
        modal.classList.remove('hidden');
    });
}

function updateAlarmBell() {
    const bellBtn = document.getElementById('alarm-bell');
    const bellIcon = document.getElementById('alarm-bell-icon');
    if (!bellBtn || !bellIcon) return;

    if (_state_js__WEBPACK_IMPORTED_MODULE_0__/* .userFlags */ .BY.size === 0) {
        bellBtn.classList.add('hidden');
        bellBtn.style.display = 'none';
        bellIcon.style.color = 'var(--text-secondary)';
        bellIcon.style.textShadow = 'none';
        return;
    }

    bellBtn.classList.remove('hidden');
    bellBtn.style.display = 'inline-flex';

    let anyAvailable = false;
    for (const wk of _state_js__WEBPACK_IMPORTED_MODULE_0__/* .allWeeks */ .p_) {
        if (!wk.days) continue;
        for (const d of wk.days) {
            if (!d.items) continue;
            for (const item of d.items) {
                if (item.available && _state_js__WEBPACK_IMPORTED_MODULE_0__/* .userFlags */ .BY.has(item.id)) {
                    anyAvailable = true;
                    break;
                }
            }
            if (anyAvailable) break;
        }
        if (anyAvailable) break;
    }

    let lastUpdatedStr = localStorage.getItem('kantine_last_checked');
    let timeStr = 'gerade eben';
    if (!lastUpdatedStr) {
        lastUpdatedStr = new Date().toISOString();
        localStorage.setItem('kantine_last_checked', lastUpdatedStr);
    }

    const lastUpdated = new Date(lastUpdatedStr);
    timeStr = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__/* .getRelativeTime */ .gs)(lastUpdated);

    bellBtn.title = `Zuletzt geprüft: ${timeStr}`;

    if (anyAvailable) {
        bellIcon.style.color = '#10b981';
        bellIcon.style.textShadow = '0 0 10px rgba(16, 185, 129, 0.4)';
    } else {
        bellIcon.style.color = '#f59e0b';
        bellIcon.style.textShadow = '0 0 10px rgba(245, 158, 11, 0.4)';
    }
}


/***/ },

/***/ 413
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {

/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   Ao: () => (/* binding */ getWeekYear),
/* harmony export */   FS: () => (/* binding */ translateDay),
/* harmony export */   PC: () => (/* binding */ getLocalizedText),
/* harmony export */   U4: () => (/* binding */ isNewer),
/* harmony export */   ZD: () => (/* binding */ escapeHtml),
/* harmony export */   gs: () => (/* binding */ getRelativeTime),
/* harmony export */   sn: () => (/* binding */ getISOWeek)
/* harmony export */ });
/* unused harmony export splitLanguage */
/* harmony import */ var _state_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(901);


function getISOWeek(date) {
    const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
    const dayNum = d.getUTCDay() || 7;
    d.setUTCDate(d.getUTCDate() + 4 - dayNum);
    const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
    return Math.ceil(((d - yearStart) / 86400000 + 1) / 7);
}

function getWeekYear(d) {
    const date = new Date(d.getTime());
    date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7);
    return date.getFullYear();
}

function translateDay(englishDay) {
    const map = { Monday: 'Montag', Tuesday: 'Dienstag', Wednesday: 'Mittwoch', Thursday: 'Donnerstag', Friday: 'Freitag', Saturday: 'Samstag', Sunday: 'Sonntag' };
    return map[englishDay] || englishDay;
}

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

function isNewer(remote, local) {
    if (!remote || !local) return false;
    const r = remote.replace(/^v/, '').split('.').map(Number);
    const l = local.replace(/^v/, '').split('.').map(Number);
    for (let i = 0; i < Math.max(r.length, l.length); i++) {
        if ((r[i] || 0) > (l[i] || 0)) return true;
        if ((r[i] || 0) < (l[i] || 0)) return false;
    }
    return false;
}

function getRelativeTime(date) {
    const diffMs = Date.now() - date.getTime();
    const diffMin = Math.floor(diffMs / 60000);
    if (diffMin < 1) return 'gerade eben';
    if (diffMin === 1) return 'vor 1 min.';
    if (diffMin < 60) return `vor ${diffMin} min.`;
    const diffH = Math.floor(diffMin / 60);
    if (diffH === 1) return 'vor 1 Std.';
    return `vor ${diffH} Std.`;
}

// === Language Filter (FR-100) ===
const DE_STEMS = [
    'apfel', 'achtung', 'aubergine', 'auflauf', 'beere', 'blumenkohl', 'bohne', 'braten', 'brokkoli', 'brot', 'brust',
    'brötchen', 'butter', 'chili', 'dessert', 'dip', 'eier', 'eintopf', 'eis', 'erbse', 'erdbeer',
    'essig', 'filet', 'fisch', 'fisole', 'fleckerl', 'fleisch', 'flügel', 'frucht', 'für', 'gebraten',
    'gemüse', 'gewürz', 'gratin', 'grieß', 'gulasch', 'gurke', 'himbeer', 'honig', 'huhn', 'hähnchen',
    'jambalaya', 'joghurt', 'karotte', 'kartoffel', 'keule', 'kirsch', 'knacker', 'knoblauch', 'knödel', 'kompott',
    'kraut', 'kräuter', 'kuchen', 'käse', 'kürbis', 'lauch', 'mandel', 'milch', 'mild', 'mit',
    'mohn', 'most', 'möhre', 'natur', 'nockerl', 'nudel', 'nuss', 'nuß', 'obst', 'oder',
    'olive', 'paprika', 'pfanne', 'pfannkuchen', 'pfeffer', 'pikant', 'pilz', 'plunder', 'püree', 'ragout',
    'rahm', 'reis', 'rind', 'sahne', 'salami', 'salat', 'salz', 'sauer', 'scharf', 'schinken',
    'schnitte', 'schnitzel', 'schoko', 'schupf', 'schwein', 'sellerie', 'senf', 'sosse', 'soße', 'spargel',
    'spätzle', 'speck', 'spieß', 'spinat', 'steak', 'suppe', 'süß', 'tofu', 'tomate', 'topfen',
    'torte', 'trüffel', 'und', 'vanille', 'vogerl', 'vom', 'wien', 'wurst', 'zucchini', 'zum',
    'zur', 'zwiebel', 'öl'
];

const EN_STEMS = [
    'almond', 'and', 'apple', 'asparagus', 'bacon', 'baked', 'ball', 'bean', 'beef', 'berry',
    'bread', 'breast', 'broccoli', 'bun', 'butter', 'cabbage', 'cake', 'caper', 'carrot', 'casserole',
    'cauliflower', 'celery', 'cheese', 'cherry', 'chicken', 'chili', 'choco', 'chocolate', 'cider', 'cilantro',
    'coffee', 'compote', 'cream', 'cucumber', 'curd', 'danish', 'dessert', 'dip', 'dumpling', 'egg',
    'eggplant', 'filet', 'fish', 'for', 'fried', 'from', 'fruit', 'garlic', 'goulash', 'gratin',
    'ham', 'herb', 'honey', 'hot', 'ice', 'jambalaya', 'leek', 'leg', 'mash', 'meat',
    'mexican', 'mild', 'milk', 'mint', 'mushroom', 'mustard', 'noodle', 'nut', 'oat', 'oil',
    'olive', 'onion', 'or', 'oven', 'pan', 'pancake', 'pea', 'pepper', 'plain', 'plate',
    'poppy', 'pork', 'potato', 'pumpkin', 'radish', 'ragout', 'raspberry', 'rice', 'roast', 'roll',
    'salad', 'salami', 'salt', 'sauce', 'sausage', 'shrimp', 'skewer', 'slice', 'soup', 'sour',
    'spice', 'spicy', 'spinach', 'steak', 'stew', 'strawberr', 'strawberry', 'strudel', 'sweet', 'tart',
    'thyme', 'to', 'tofu', 'tomat', 'tomato', 'truffle', 'trukey', 'turkey', 'vanilla', 'vegan',
    'vegetable', 'vinegar', 'wedge', 'wing', 'with', 'wok', 'yogurt', 'zucchini'
];

function splitLanguage(text) {
    if (!text) return { de: '', en: '', raw: '' };

    const raw = text;
    let formattedRaw = text.replace(/(?:\(|(?:\/|\s|^))([A-Z,]+)\)\s*(?=\S)(?!\s*\/)/g, '($1)\n• ');
    if (!formattedRaw.startsWith('• ')) {
        formattedRaw = '• ' + formattedRaw;
    }

    function scoreBlock(wordArray) {
        let de = 0, en = 0;
        wordArray.forEach(word => {
            const w = word.toLowerCase().replace(/[^a-zäöüß]/g, '');
            if (w) {
                let bestDeMatch = 0;
                let bestEnMatch = 0;
                if (DE_STEMS.includes(w)) bestDeMatch = w.length;
                else DE_STEMS.forEach(s => { if (w.includes(s) && s.length > bestDeMatch) bestDeMatch = s.length; });

                if (EN_STEMS.includes(w)) bestEnMatch = w.length;
                else EN_STEMS.forEach(s => { if (w.includes(s) && s.length > bestEnMatch) bestEnMatch = s.length; });

                if (bestDeMatch > 0) de += (bestDeMatch / w.length);
                if (bestEnMatch > 0) en += (bestEnMatch / w.length);

                if (/^[A-ZÄÖÜ]/.test(word)) {
                    de += 0.5;
                }
            }
        });
        return { de, en };
    }

    function heuristicSplitEnDe(fragment) {
        const words = fragment.trim().split(/\s+/);
        if (words.length < 2) return { enPart: fragment, nextDe: '' };

        let bestK = -1;
        let maxScore = -9999;

        for (let k = 1; k < words.length; k++) {
            const left = words.slice(0, k);
            const right = words.slice(k);

            const leftScore = scoreBlock(left);
            const rightScore = scoreBlock(right);

            const rightFirstWord = right[0];
            let capitalBonus = 0;
            if (/^[A-ZÄÖÜ]/.test(rightFirstWord)) {
                capitalBonus = 1.0;
            }

            const score = (leftScore.en - leftScore.de) + (rightScore.de - rightScore.en) + capitalBonus;

            const leftLooksEnglish = (leftScore.en > leftScore.de) || (leftScore.en > 0);
            const rightLooksGerman = (rightScore.de + capitalBonus) > rightScore.en;

            if (leftLooksEnglish && rightLooksGerman && score > maxScore) {
                maxScore = score;
                bestK = k;
            }
        }

        if (bestK !== -1) {
            return {
                enPart: words.slice(0, bestK).join(' '),
                nextDe: words.slice(bestK).join(' ')
            };
        }
        return { enPart: fragment, nextDe: '' };
    }

    const allergenRegex = /(.*?)(?:\(|(?:\/|\s|^))([A-Z,]+)\)\s*(?!\s*[/])/g;
    let match;
    const rawCourses = [];
    let lastScanIndex = 0;

    while ((match = allergenRegex.exec(text)) !== null) {
        if (match.index > lastScanIndex) {
            rawCourses.push(text.substring(lastScanIndex, match.index).trim());
        }
        rawCourses.push(match[0].trim());
        lastScanIndex = allergenRegex.lastIndex;
    }
    if (lastScanIndex < text.length) {
        rawCourses.push(text.substring(lastScanIndex).trim());
    }
    if (rawCourses.length === 0 && text.trim() !== '') {
        rawCourses.push(text.trim());
    }

    const deParts = [];
    const enParts = [];

    for (let course of rawCourses) {
        let courseMatch = course.match(/(.*?)(?:\(|(?:\/|\s|^))([A-Z,]+)\)\s*$/);
        let courseText = course;
        let allergenTxt = "";
        let allergenCode = "";

        if (courseMatch) {
            courseText = courseMatch[1].trim();
            allergenCode = courseMatch[2];
            allergenTxt = ` (${allergenCode})`;
        }

        const slashParts = courseText.split(/\s*\/\s*(?![A-Z,]+$)/);

        if (slashParts.length >= 2) {
            const deCandidate = slashParts[0].trim();
            let enCandidate = slashParts.slice(1).join(' / ').trim();

            const nestedSplit = heuristicSplitEnDe(enCandidate);
            if (nestedSplit.nextDe) {
                deParts.push(deCandidate + allergenTxt);
                enParts.push(nestedSplit.enPart + allergenTxt);

                const nestedDe = nestedSplit.nextDe + allergenTxt;
                deParts.push(nestedDe);
                enParts.push(nestedDe);
            } else {
                const enFinal = enCandidate + allergenTxt;
                const deFinal = deCandidate.includes(allergenTxt.trim()) ? deCandidate : (deCandidate + allergenTxt);

                deParts.push(deFinal);
                enParts.push(enFinal);
            }
        } else {
            const heuristicSplit = heuristicSplitEnDe(courseText);
            if (heuristicSplit.nextDe) {
                enParts.push(heuristicSplit.enPart + allergenTxt);
                deParts.push(heuristicSplit.nextDe + allergenTxt);
            } else {
                deParts.push(courseText + allergenTxt);
                enParts.push(courseText + allergenTxt);
            }
        }
    }

    let deJoined = deParts.join('\n• ');
    if (deParts.length > 0 && !deJoined.startsWith('• ')) deJoined = '• ' + deJoined;

    let enJoined = enParts.join('\n• ');
    if (enParts.length > 0 && !enJoined.startsWith('• ')) enJoined = '• ' + enJoined;

    return {
        de: deJoined,
        en: enJoined,
        raw: formattedRaw
    };
}

function getLocalizedText(text) {
    if (_state_js__WEBPACK_IMPORTED_MODULE_0__/* .langMode */ .Kl === 'all') return text || '';
    const split = splitLanguage(text);
    if (_state_js__WEBPACK_IMPORTED_MODULE_0__/* .langMode */ .Kl === 'en') return split.en || split.raw;
    return split.de || split.raw;
}


/***/ }

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/
/************************************************************************/
/******/ 	/* webpack/runtime/define property getters */
/******/ 	(() => {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = (exports, definition) => {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	})();
/******/
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	(() => {
/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ 	})();
/******/
/************************************************************************/
var __webpack_exports__ = {};

// EXTERNAL MODULE: ./src/state.js
var state = __webpack_require__(901);
;// ./src/ui.js


function injectUI() {
    document.title = 'Kantine Weekly Menu';

    if (document.querySelectorAll) {
        document.querySelectorAll('link[rel*="icon"]').forEach(el => el.remove());
    }
    const favicon = document.createElement('link');
    favicon.rel = 'icon';
    favicon.type = 'image/png';
    favicon.href = '{{FAVICON_DATA_URI}}';
    document.head.appendChild(favicon);

    if (!document.querySelector('link[href*="fonts.googleapis.com/css2?family=Inter"]')) {
        const fontLink = document.createElement('link');
        fontLink.rel = 'stylesheet';
        fontLink.href = 'https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap';
        document.head.appendChild(fontLink);
    }
    if (!document.querySelector('link[href*="Material+Icons+Round"]')) {
        const iconLink = document.createElement('link');
        iconLink.rel = 'stylesheet';
        iconLink.href = 'https://fonts.googleapis.com/icon?family=Material+Icons+Round';
        document.head.appendChild(iconLink);
    }

    const htmlContent = `
    <div id="kantine-wrapper">
        <header class="app-header">
            <div class="header-content">
                <div class="brand">
                    <img src="{{FAVICON_DATA_URI}}" alt="Logo" class="logo-img" style="height: 2em; width: 2em; object-fit: contain;">
                    <div class="header-left">
                        <h1>Kantinen Übersicht <small class="version-tag" style="font-size: 0.6em; opacity: 0.7; font-weight: 400; cursor: pointer;" title="Klick für Versionsmenü">{{VERSION}}</small></h1>
                        <div id="last-updated-subtitle" class="subtitle"></div>
                    </div>
                    <div class="nav-group" style="margin-left: 1rem;">
                        <button id="btn-this-week" class="nav-btn active" title="Menü dieser Woche anzeigen">Diese Woche</button>
                        <button id="btn-next-week" class="nav-btn" title="Menü nächster Woche anzeigen">Nächste Woche</button>
                    </div>
                    <button id="alarm-bell" class="icon-btn hidden" aria-label="Benachrichtigungen" title="Keine beobachteten Menüs" style="margin-left: -0.5rem;">
                        <span class="material-icons-round" id="alarm-bell-icon" style="color:var(--text-secondary); transition: color 0.3s;">notifications</span>
                    </button>
                </div>
                <div class="header-center-wrapper">
                    <div id="lang-toggle" class="lang-toggle" title="Sprache der Menübeschreibung">
                        <button class="lang-btn${state/* langMode */.Kl === 'de' ? ' active' : ''}" data-lang="de">DE</button>
                        <button class="lang-btn${state/* langMode */.Kl === 'en' ? ' active' : ''}" data-lang="en">EN</button>
                        <button class="lang-btn${state/* langMode */.Kl === 'all' ? ' active' : ''}" data-lang="all">ALL</button>
                    </div>
                    <div id="header-week-info" class="header-week-info"></div>
                    <div id="weekly-cost-display" class="weekly-cost hidden"></div>
                </div>
                <div class="controls">
                    <button id="btn-refresh" class="icon-btn" aria-label="Menüdaten aktualisieren" title="Menüdaten neu laden">
                        <span class="material-icons-round">refresh</span>
                    </button>
                    <button id="btn-history" class="icon-btn" aria-label="Bestellhistorie" title="Bestellhistorie">
                        <span class="material-icons-round">receipt_long</span>
                    </button>
                    <button id="btn-highlights" class="icon-btn" aria-label="Persönliche Highlights verwalten" title="Persönliche Highlights verwalten">
                        <span class="material-icons-round">label</span>
                    </button>
                    <button id="theme-toggle" class="icon-btn" aria-label="Toggle Theme" title="Erscheinungsbild (Hell/Dunkel) wechseln">
                        <span class="material-icons-round theme-icon">light_mode</span>
                    </button>
                    <button id="btn-login-open" class="user-badge-btn icon-btn-small" title="Mit Bessa.app Account anmelden">
                        <span class="material-icons-round">login</span>
                        <span>Anmelden</span>
                    </button>
                    <div id="user-info" class="user-badge hidden">
                        <span class="material-icons-round">person</span>
                        <span id="user-id-display"></span>
                        <button id="btn-logout" class="icon-btn-small" aria-label="Logout" title="Von Bessa.app abmelden">
                            <span class="material-icons-round">logout</span>
                        </button>
                    </div>
                </div>
            </div>
        </header>

        <div id="login-modal" class="modal hidden">
            <div class="modal-content">
                <div class="modal-header">
                    <h2>Login</h2>
                    <button id="btn-login-close" class="icon-btn" aria-label="Close" title="Schließen">
                        <span class="material-icons-round">close</span>
                    </button>
                </div>
                <form id="login-form">
                    <div class="form-group">
                        <label for="employee-id">Mitarbeiternummer</label>
                        <input type="text" id="employee-id" name="employee-id" placeholder="z.B. 2041" required>
                        <small class="help-text">Deine offizielle Knapp Mitarbeiternummer.</small>
                    </div>
                    <div class="form-group">
                        <label for="password">Passwort</label>
                        <input type="password" id="password" name="password" placeholder="Bessa Passwort" required>
                        <small class="help-text">Das Passwort für deinen Bessa Account.</small>
                    </div>
                    <div id="login-error" class="error-msg hidden"></div>
                    <div class="modal-actions">
                        <button type="submit" class="btn-primary wide">Einloggen</button>
                    </div>
                </form>
            </div>
        </div>

        <div id="progress-modal" class="modal hidden">
            <div class="modal-content">
                <div class="modal-header">
                    <h2>Menüdaten aktualisieren</h2>
                </div>
                <div class="modal-body" style="padding: 20px;">
                    <div class="progress-container">
                        <div class="progress-bar">
                            <div id="progress-fill" class="progress-fill"></div>
                        </div>
                        <div id="progress-percent" class="progress-percent">0%</div>
                    </div>
                    <p id="progress-message" class="progress-message">Initialisierung...</p>
                </div>
            </div>
        </div>

        <div id="highlights-modal" class="modal hidden">
            <div class="modal-content">
                <div class="modal-header">
                    <h2>Meine Highlights</h2>
                    <button id="btn-highlights-close" class="icon-btn" aria-label="Close" title="Schließen">
                        <span class="material-icons-round">close</span>
                    </button>
                </div>
                <div class="modal-body">
                    <p style="margin-bottom: 1rem; color: var(--text-secondary);">
                        Markiere Menüs automatisch, wenn sie diese Schlagwörter enthalten.
                    </p>
                    <div class="input-group">
                        <input type="text" id="tag-input" placeholder="z.B. Schnitzel, Vegetarisch..." title="Neues Schlagwort zum Hervorheben eingeben">
                        <button id="btn-add-tag" class="btn-primary" title="Schlagwort zur Liste hinzufügen">Hinzufügen</button>
                    </div>
                    <div id="tags-list"></div>
                </div>
            </div>
        </div>

        <div id="history-modal" class="modal hidden">
            <div class="modal-content history-modal-content">
                <div class="modal-header">
                    <h2>Bestellhistorie</h2>
                    <button id="btn-history-close" class="icon-btn" aria-label="Close" title="Schließen">
                        <span class="material-icons-round">close</span>
                    </button>
                </div>
                <div class="modal-body">
                    <div id="history-loading" class="hidden">
                        <p id="history-progress-text" style="text-align: center; margin-bottom: 1rem; color: var(--text-secondary);">Lade Historie...</p>
                        <div class="progress-container">
                            <div class="progress-bar">
                                <div id="history-progress-fill" class="progress-fill"></div>
                            </div>
                        </div>
                    </div>
                    <div id="history-content">
                    </div>
                </div>
            </div>
        </div>

        <div id="version-modal" class="modal hidden">
            <div class="modal-content">
                <div class="modal-header">
                    <h2>📦 Versionen</h2>
                    <button id="btn-version-close" class="icon-btn" aria-label="Close" title="Schließen">
                        <span class="material-icons-round">close</span>
                    </button>
                </div>
                <div class="modal-body">
                    <div style="margin-bottom: 1rem;">
                        <strong>Aktuell:</strong> <span id="version-current">{{VERSION}}</span>
                    </div>
                    <div class="dev-toggle">
                        <label style="display:flex;align-items:center;gap:8px;cursor:pointer;">
                            <input type="checkbox" id="dev-mode-toggle">
                            <span>Dev-Mode (alle Tags anzeigen)</span>
                        </label>
                    </div>
                    <div id="version-list-container" style="margin-top:1rem; max-height: 250px; overflow-y: auto;">
                        <p style="color:var(--text-secondary);">Lade Versionen...</p>
                    </div>
                    <div style="margin-top: 1.5rem; padding-top: 1rem; border-top: 1px solid var(--border-color); display: flex; flex-direction: column; gap: 0.75rem; font-size: 0.9em;">
                        <a href="https://github.com/TauNeutrino/kantine-overview/issues" target="_blank" rel="noopener noreferrer" style="color: var(--primary-color); text-decoration: none; display: flex; align-items: center; gap: 0.5rem;" title="Melde einen Fehler auf GitHub">
                            <span class="material-icons-round" style="font-size: 1.2em;">bug_report</span> Fehler melden
                        </a>
                        <a href="https://github.com/TauNeutrino/kantine-overview/discussions/categories/ideas" target="_blank" rel="noopener noreferrer" style="color: var(--primary-color); text-decoration: none; display: flex; align-items: center; gap: 0.5rem;" title="Schlage ein neues Feature auf GitHub vor">
                            <span class="material-icons-round" style="font-size: 1.2em;">lightbulb</span> Feature vorschlagen
                        </a>
                        <button id="btn-clear-cache" style="background: none; border: none; padding: 0; color: var(--error-color); text-decoration: none; display: flex; align-items: center; gap: 0.5rem; cursor: pointer; text-align: left; font-size: inherit; font-family: inherit;" title="Löscht alle lokalen Daten & erzwingt einen Neuladen">
                            <span class="material-icons-round" style="font-size: 1.2em;">delete_forever</span> Lokalen Cache leeren
                        </button>
                    </div>
                </div>
            </div>
        </div>

        <main class="container">
            <div id="last-updated-banner" class="banner hidden">
                <span class="material-icons-round">update</span>
                <span id="last-updated-text">Gerade aktualisiert</span>
            </div>
            <div id="loading" class="loading-state">
                <div class="spinner"></div>
                <p>Lade Menüdaten...</p>
            </div>
            <div id="menu-container" class="menu-grid"></div>
        </main>

        <footer class="app-footer">
            <p>Jetzt Bessa Einfach! &bull; Knapp-Kantine Wrapper &bull; <span id="current-year">${new Date().getFullYear()}</span> by Kaufi 😃👍 mit Hilfe von KI 🤖</p>
        </footer>
    </div>`;
    document.body.innerHTML = htmlContent;
}

// EXTERNAL MODULE: ./src/actions.js
var actions = __webpack_require__(367);
// EXTERNAL MODULE: ./src/ui_helpers.js
var ui_helpers = __webpack_require__(842);
// EXTERNAL MODULE: ./src/constants.js
var constants = __webpack_require__(521);
// EXTERNAL MODULE: ./src/api.js
var api = __webpack_require__(672);
;// ./src/events.js






function bindEvents() {
    const btnThisWeek = document.getElementById('btn-this-week');
    const btnNextWeek = document.getElementById('btn-next-week');
    const btnRefresh = document.getElementById('btn-refresh');
    const themeToggle = document.getElementById('theme-toggle');
    const btnLoginOpen = document.getElementById('btn-login-open');
    const btnLoginClose = document.getElementById('btn-login-close');
    const btnLogout = document.getElementById('btn-logout');
    const loginForm = document.getElementById('login-form');
    const loginModal = document.getElementById('login-modal');

    const btnHighlights = document.getElementById('btn-highlights');
    const highlightsModal = document.getElementById('highlights-modal');
    const btnHighlightsClose = document.getElementById('btn-highlights-close');
    const btnAddTag = document.getElementById('btn-add-tag');
    const tagInput = document.getElementById('tag-input');

    const btnHistory = document.getElementById('btn-history');
    const historyModal = document.getElementById('history-modal');
    const btnHistoryClose = document.getElementById('btn-history-close');

    document.querySelectorAll('.lang-btn').forEach(btn => {
        btn.addEventListener('click', () => {
            (0,state/* setLangMode */.UD)(btn.dataset.lang);
            localStorage.setItem('kantine_lang', btn.dataset.lang);
            document.querySelectorAll('.lang-btn').forEach(b => b.classList.remove('active'));
            btn.classList.add('active');
            (0,ui_helpers/* renderVisibleWeeks */.OR)();
        });
    });

    if (btnHighlights) {
        btnHighlights.addEventListener('click', () => {
            highlightsModal.classList.remove('hidden');
        });
    }

    if (btnHighlightsClose) {
        btnHighlightsClose.addEventListener('click', () => {
            highlightsModal.classList.add('hidden');
        });
    }

    btnHistory.addEventListener('click', () => {
        if (!state/* authToken */.gX) {
            loginModal.classList.remove('hidden');
            return;
        }
        historyModal.classList.remove('hidden');
        (0,actions/* fetchFullOrderHistory */.Aq)();
    });

    btnHistoryClose.addEventListener('click', () => {
        historyModal.classList.add('hidden');
    });

    window.addEventListener('click', (e) => {
        if (e.target === historyModal) historyModal.classList.add('hidden');
        if (e.target === highlightsModal) highlightsModal.classList.add('hidden');
    });

    const versionTag = document.querySelector('.version-tag');
    const versionModal = document.getElementById('version-modal');
    const btnVersionClose = document.getElementById('btn-version-close');

    if (versionTag) {
        versionTag.addEventListener('click', (e) => {
            e.preventDefault();
            e.stopPropagation();
            (0,ui_helpers/* openVersionMenu */.Gk)();
        });
    }

    if (btnVersionClose) {
        btnVersionClose.addEventListener('click', () => {
            versionModal.classList.add('hidden');
        });
    }

    const btnClearCache = document.getElementById('btn-clear-cache');
    if (btnClearCache) {
        btnClearCache.addEventListener('click', () => {
            if (confirm('Möchtest du wirklich alle lokalen Daten (inkl. Login-Session, Cache und Einstellungen) löschen? Die Seite wird danach neu geladen.')) {
                Object.keys(localStorage).forEach(key => {
                    if (key.startsWith('kantine_')) {
                        localStorage.removeItem(key);
                    }
                });
                window.location.reload();
            }
        });
    }

    window.addEventListener('click', (e) => {
        if (e.target === versionModal) versionModal.classList.add('hidden');
    });

    btnAddTag.addEventListener('click', () => {
        const tag = tagInput.value;
        if ((0,actions/* addHighlightTag */.oL)(tag)) {
            tagInput.value = '';
            (0,actions/* renderTagsList */.Y1)();
        }
    });

    tagInput.addEventListener('keypress', (e) => {
        if (e.key === 'Enter') {
            btnAddTag.click();
        }
    });

    const savedTheme = localStorage.getItem('theme');
    const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
    const themeIcon = themeToggle.querySelector('.theme-icon');

    if (savedTheme === 'dark' || (!savedTheme && prefersDark)) {
        document.documentElement.setAttribute('data-theme', 'dark');
        themeIcon.textContent = 'dark_mode';
    } else {
        document.documentElement.setAttribute('data-theme', 'light');
        themeIcon.textContent = 'light_mode';
    }

    themeToggle.addEventListener('click', () => {
        const current = document.documentElement.getAttribute('data-theme');
        const next = current === 'dark' ? 'light' : 'dark';
        document.documentElement.setAttribute('data-theme', next);
        localStorage.setItem('theme', next);
        themeIcon.textContent = next === 'dark' ? 'dark_mode' : 'light_mode';
    });

    btnThisWeek.addEventListener('click', () => {
        if (state/* displayMode */.sw !== 'this-week') {
            (0,state/* setDisplayMode */.qo)('this-week');
            btnThisWeek.classList.add('active');
            btnNextWeek.classList.remove('active');
            (0,ui_helpers/* renderVisibleWeeks */.OR)();
        }
    });

    btnNextWeek.addEventListener('click', () => {
        btnNextWeek.classList.remove('new-week-available');
        if (state/* displayMode */.sw !== 'next-week') {
            (0,state/* setDisplayMode */.qo)('next-week');
            btnNextWeek.classList.add('active');
            btnThisWeek.classList.remove('active');
            (0,ui_helpers/* renderVisibleWeeks */.OR)();
        }
    });

    btnRefresh.addEventListener('click', () => {
        if (!state/* authToken */.gX) {
            loginModal.classList.remove('hidden');
            return;
        }
        (0,actions/* loadMenuDataFromAPI */.m9)();
    });

    btnLoginOpen.addEventListener('click', () => {
        loginModal.classList.remove('hidden');
        document.getElementById('login-error').classList.add('hidden');
        loginForm.reset();
    });

    btnLoginClose.addEventListener('click', () => {
        loginModal.classList.add('hidden');
    });

    window.addEventListener('click', (e) => {
        if (e.target === loginModal) loginModal.classList.add('hidden');
    });

    loginForm.addEventListener('submit', async (e) => {
        e.preventDefault();
        const employeeId = document.getElementById('employee-id').value.trim();
        const password = document.getElementById('password').value;
        const loginError = document.getElementById('login-error');
        const submitBtn = loginForm.querySelector('button[type="submit"]');
        const originalText = submitBtn.textContent;

        submitBtn.disabled = true;
        submitBtn.textContent = 'Wird eingeloggt...';

        try {
            const email = `knapp-${employeeId}@bessa.app`;
            const response = await fetch(`${constants/* API_BASE */.tE}/auth/login/`, {
                method: 'POST',
                headers: (0,api/* apiHeaders */.H)(constants/* GUEST_TOKEN */.f9),
                body: JSON.stringify({ email, password })
            });

            const data = await response.json();

            if (response.ok) {
                (0,state/* setAuthToken */.O5)(data.key);
                (0,state/* setCurrentUser */.lt)(employeeId);
                localStorage.setItem('kantine_authToken', data.key);
                localStorage.setItem('kantine_currentUser', employeeId);

                try {
                    const userResp = await fetch(`${constants/* API_BASE */.tE}/auth/user/`, {
                        headers: (0,api/* apiHeaders */.H)(data.key)
                    });
                    if (userResp.ok) {
                        const userData = await userResp.json();
                        if (userData.first_name) localStorage.setItem('kantine_firstName', userData.first_name);
                        if (userData.last_name) localStorage.setItem('kantine_lastName', userData.last_name);
                    }
                } catch (err) {
                    console.error('Failed to fetch user info:', err);
                }

                (0,actions/* updateAuthUI */.i_)();
                loginModal.classList.add('hidden');
                (0,actions/* fetchOrders */.Gb)();
                loginForm.reset();
                (0,actions/* startPolling */.g8)();
                (0,actions/* loadMenuDataFromAPI */.m9)();
            } else {
                loginError.textContent = data.non_field_errors?.[0] || data.error || 'Login fehlgeschlagen';
                loginError.classList.remove('hidden');
            }
        } catch (error) {
            console.error('Login error:', error);
            loginError.textContent = 'Ein Fehler ist aufgetreten';
            loginError.classList.remove('hidden');
        } finally {
            submitBtn.disabled = false;
            submitBtn.textContent = originalText;
        }
    });

    btnLogout.addEventListener('click', () => {
        localStorage.removeItem('kantine_authToken');
        localStorage.removeItem('kantine_currentUser');
        localStorage.removeItem('kantine_firstName');
        localStorage.removeItem('kantine_lastName');
        (0,state/* setAuthToken */.O5)(null);
        (0,state/* setCurrentUser */.lt)(null);
        (0,state/* setOrderMap */.di)(new Map());
        (0,actions/* stopPolling */.Et)();
        (0,actions/* updateAuthUI */.i_)();
        (0,ui_helpers/* renderVisibleWeeks */.OR)();
    });
}

;// ./src/index.js






if (window.__KANTINE_LOADED) {
    console.log("Kantine Wrapper already loaded.");
} else {
    window.__KANTINE_LOADED = true;

    injectUI();
    bindEvents();
    (0,actions/* updateAuthUI */.i_)();
    (0,actions/* cleanupExpiredFlags */.H)();

    const hadCache = (0,actions/* loadMenuCache */.KG)();
    if (hadCache) {
        document.getElementById('loading').classList.add('hidden');
        if (!(0,actions/* isCacheFresh */.VL)()) {
            console.log('Cache stale or incomplete – refreshing from API');
            (0,actions/* loadMenuDataFromAPI */.m9)();
        } else {
            console.log('Cache fresh & complete – skipping API refresh');
        }
    } else {
        (0,actions/* loadMenuDataFromAPI */.m9)();
    }

    if (state/* authToken */.gX) {
        (0,actions/* startPolling */.g8)();
    }

    (0,ui_helpers/* checkForUpdates */.Ux)();
    setInterval(ui_helpers/* checkForUpdates */.Ux, 60 * 60 * 1000);

    console.log('Kantine Wrapper loaded ✅');
}

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