diff --git a/changelog.md b/changelog.md index 0058f11..dfabab3 100755 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,6 @@ -## v1.6.17 (2026-03-11) +## v1.6.18 (2026-03-11) +- 🎨 **UX**: Glow-Styling angepasst – Die farblichen Hervorhebungen (Bestellt, Highlight, Flagged) wurden so korrigiert, dass sie nicht mehr bis an den Kartenrand reichen, sondern innerhalb des Karten-Bodys mit entsprechendem Seitenabstand angezeigt werden. + - 🎨 **UX**: Fix Card Content Overflow – In der 5-Tage-Ansicht (Landscape) auf schmalen Bildschirmen umbrechen die Status-Badges und Buttons jetzt korrekt in eine neue Zeile, statt über den Kartenrand hinauszuragen. Das Karten-Padding wurde für Desktop-Ansichten optimiert. - 🧹 **Wartbarkeit**: Alle verbliebenen hardcodierten deutschen UI-Strings in `actions.js` via `t()` übersetzt (Progress-Texte, Fehler-Labels, 'Angemeldet', 'Hintergrund-Synchronisation'). diff --git a/dist/bookmarklet-payload.js b/dist/bookmarklet-payload.js index 3503744..1a5882c 100755 --- a/dist/bookmarklet-payload.js +++ b/dist/bookmarklet-payload.js @@ -1,8 +1,8 @@ javascript:(function(){ if(window.__KANTINE_LOADED){alert('Kantine Wrapper already loaded!');return;} -var s=document.createElement('style');s.textContent=':root { /* Premium Slate/Gray-Blue Palette - Light Mode */ --bg-body: #f1f5f9; /* Slate 100 */ --bg-card: #ffffff; --text-primary: #334155; /* Slate 700 */ --text-secondary: #64748b; --accent-color: #0f172a; /* Slate 900 (High contrast) */ --border-color: #cbd5e1; /* Slate 300 */ --banner-bg: #e2e8f0; --banner-text: #1e293b; --success-color: #059669; --error-color: #dc2626; --card-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.05), 0 2px 4px -2px rgb(0 0 0 / 0.05); --header-bg: rgba(255, 255, 255, 0.9); --header-border: 1px solid rgba(203, 213, 225, 0.6); } [data-theme="dark"] { /* Premium Slate/Gray-Blue Palette - Dark Mode */ --bg-body: #1e293b; /* Deep Slate Gray (Requested) */ --bg-card: #334155; /* Slate 700 */ --text-primary: #f8fafc; /* Slate 50 */ --text-secondary: #cbd5e1; /* Slate 300 */ --accent-color: #60a5fa; /* Blue 400 */ --border-color: #475569; /* Slate 600 */ --banner-bg: #475569; --banner-text: #e2e8f0; --header-bg: rgba(30, 41, 59, 0.9); --header-border: 1px solid rgba(71, 85, 105, 0.6); --card-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.4); } * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: \'Inter\', system-ui, -apple-system, sans-serif; background-color: var(--bg-body); color: var(--text-primary); transition: background-color 0.3s ease, color 0.3s ease; line-height: 1.5; -webkit-font-smoothing: antialiased; } /* Fix scrolling bug: Reset html/body styles from host page */ /* IMPORTANT: html must NOT have overflow set, or it creates a scroll container that breaks position: sticky */ html { height: auto !important; min-height: 100% !important; overflow: visible !important; position: static !important; margin: 0 !important; padding: 0 !important; } body { height: auto !important; min-height: 100% !important; overflow-x: clip !important; /* clip prevents horizontal overflow without breaking sticky */ overflow-y: visible !important; position: static !important; margin: 0 !important; padding: 0 !important; } /* Header */ .app-header { flex-shrink: 0; z-index: 100; backdrop-filter: blur(12px); background-color: var(--header-bg); border-bottom: var(--header-border); padding: 1rem 0; } .header-content { width: 100%; /* Full width */ padding: 0 2rem; /* Comfortable padding */ display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 1rem; } .brand { display: flex; align-items: center; gap: 0.75rem; } .brand-text { display: flex; flex-direction: column; } .brand h1 { font-size: 1.25rem; font-weight: 700; letter-spacing: -0.025em; margin-bottom: 0; } .subtitle { font-size: 0.85rem; color: var(--text-secondary); font-weight: 400; margin-left: 2px; } .logo-icon { font-size: 1.5rem; color: var(--accent-color); } /* Controls */ .controls { display: flex; align-items: center; gap: 1.5rem; justify-self: end; } /* Header Week Info (centered) */ .header-week-info { text-align: center; line-height: 1.3; } .header-center-wrapper { display: flex; flex-direction: row; align-items: center; gap: 1.5rem; justify-content: center; } .header-week-title { font-size: 1.1rem; font-weight: 600; color: var(--text-primary); } .header-week-subtitle { font-size: 0.85rem; color: var(--text-secondary); } /* Language Toggle (FR-100) */ .lang-toggle { display: inline-flex; gap: 0; border-radius: 6px; overflow: hidden; border: 1px solid var(--border-color); background: var(--bg-card); } .lang-btn { padding: 3px 10px; font-size: 0.7rem; font-weight: 600; letter-spacing: 0.03em; background: transparent; color: var(--text-secondary); border: none; cursor: pointer; transition: all 0.2s; } .lang-btn:hover { color: var(--text-primary); background: rgba(100, 116, 139, 0.1); } .lang-btn.active { background: var(--accent-color); color: white; } .nav-group { display: flex; background-color: var(--bg-card); border: 1px solid var(--border-color); padding: 0.25rem; border-radius: 8px; } .nav-btn { background: none; border: none; padding: 0.5rem 1rem; font-size: 0.875rem; font-weight: 500; color: var(--text-secondary); cursor: pointer; border-radius: 6px; transition: all 0.2s; display: flex; align-items: center; gap: 0.5rem; } .nav-btn:hover { color: var(--text-primary); background-color: rgba(100, 116, 139, 0.1); } .nav-btn.active { background-color: var(--accent-color); color: white; } /* Notification state for Next Week */ .nav-btn.new-week-available { animation: goldPulse 2s infinite; border-color: #f59e0b; color: var(--accent-color); } .nav-btn.new-week-available.active { color: white; } @keyframes goldPulse { 0% { box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.7); } 70% { box-shadow: 0 0 0 10px rgba(245, 158, 11, 0); } 100% { box-shadow: 0 0 0 0 rgba(245, 158, 11, 0); } } /* Badge for nav buttons (day count indicator) */ .nav-badge { background-color: var(--error-color); color: white; font-size: 0.75rem; font-weight: 600; padding: 0 6px; border-radius: 10px; min-width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center; margin-left: 8px; gap: 3px; line-height: 1; } .nav-badge .orderable { color: #fff; font-weight: 800; } .nav-badge .separator { opacity: 0.6; font-weight: 400; } .nav-badge .total { opacity: 0.8; font-weight: 400; } .nav-btn.active .nav-badge { background: rgba(255, 255, 255, 0.3); } /* Primary style for Login Button to match header */ #btn-login-open { background-color: var(--accent-color); color: white; padding: 0.5rem 1.25rem; border-radius: 8px; font-weight: 600; letter-spacing: 0.025em; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } #btn-login-open:hover { background-color: #334155; /* Slightly lighter than slate-900 */ transform: translateY(-1px); box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } /* User Badge Button (Login) */ .user-badge-btn { display: flex; align-items: center; gap: 8px; padding: 6px 12px; background: var(--bg-card); border: 1px solid var(--border-color); border-radius: 20px; font-size: 0.9rem; font-weight: 500; color: var(--text-primary); cursor: pointer; transition: all 0.2s; } .user-badge-btn:hover { background: rgba(100, 116, 139, 0.1); border-color: var(--accent-color); } .user-badge-btn .material-icons-round { font-size: 1.25rem; color: var(--accent-color); } .icon-btn { background: none; border: none; color: var(--text-primary); cursor: pointer; padding: 0.5rem; border-radius: 50%; transition: background-color 0.2s; display: flex; align-items: center; justify-content: center; } .icon-btn:hover { background-color: rgba(100, 116, 139, 0.1); } /* Refresh button animation */ #btn-refresh.refreshing .material-icons-round, #alarm-bell.refreshing .material-icons-round { animation: rotate 1s linear infinite; } @keyframes rotate { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } /* Progress Modal */ .progress-container { margin-bottom: 1.5rem; } .progress-bar { width: 100%; height: 8px; background-color: var(--border-color); border-radius: 4px; overflow: hidden; margin-bottom: 0.75rem; } .progress-fill { height: 100%; background: linear-gradient(90deg, var(--accent-color) 0%, #60a5fa 100%); width: 0%; transition: width 0.3s ease; border-radius: 4px; } .progress-percent { text-align: center; font-size: 1.5rem; font-weight: 700; color: var(--text-primary); margin-bottom: 0.5rem; } .progress-message { text-align: center; color: var(--text-secondary); font-size: 0.9rem; font-weight: 500; } .weekly-cost { background-color: rgba(59, 130, 246, 0.1); /* Blue tint */ color: var(--accent-color); padding: 0.4rem 0.8rem; border-radius: 8px; font-weight: 600; font-size: 0.9rem; display: flex; align-items: center; gap: 0.5rem; border: 1px solid rgba(59, 130, 246, 0.2); } .weekly-cost .material-icons-round { font-size: 18px; } /* Container - flex column, full width so child scrollbar is at edge */ .container { flex: 1; width: 100%; overflow: hidden; padding: 0 0 0 0; /* Only top padding, no horizontal so child fills width */ display: flex; flex-direction: column; } /* Add horizontal padding to direct children of container to maintain layout */ .container>*:not(.menu-grid) { padding-left: 2rem; padding-right: 2rem; } /* Banner */ .banner { background-color: var(--banner-bg); color: var(--banner-text); padding: 0.75rem 1rem; border-radius: 8px; display: flex; align-items: center; gap: 0.5rem; margin-bottom: 2rem; font-size: 0.875rem; font-weight: 500; border: 1px solid var(--border-color); max-width: fit-content; } /* User Badge */ .user-badge { display: flex; align-items: center; gap: 8px; padding: 6px 12px; background: var(--bg-card); /* Changed from --surface */ border: 1px solid var(--border-color); /* Changed from --border */ border-radius: 20px; font-size: 0.9rem; font-weight: 500; } .icon-btn-small { background: none; border: none; padding: 4px; cursor: pointer; color: var(--text-secondary); /* Changed from --text-muted */ display: flex; align-items: center; justify-content: center; border-radius: 50%; transition: all 0.2s; } .icon-btn-small:hover { color: var(--error-color); /* Changed from --danger */ background: rgba(239, 68, 68, 0.1); } /* Modal */ .modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); backdrop-filter: blur(4px); display: flex; align-items: center; justify-content: center; z-index: 1000; transition: all 0.3s; } .modal.hidden { opacity: 0; pointer-events: none; } .modal-content { background: var(--bg-card); width: 90%; max-width: 400px; border-radius: 16px; box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); overflow: hidden; animation: modalSlide 0.3s ease-out; } /* History Modal specific */ .history-modal-content { max-width: 600px; max-height: 85vh; display: flex; flex-direction: column; } .history-modal-content .modal-body { overflow-y: auto; padding: 0; /* Padding is handled by inner elements */ } /* History Styles */ .history-year-group { margin-bottom: 16px; } .history-year-header { background: var(--bg-card); padding: 12px 20px; margin: 0; font-size: 1.2rem; font-weight: 700; color: var(--text-primary); border-bottom: 2px solid var(--border-color); position: sticky; top: 0; z-index: 12; } .history-month-group { border-bottom: 1px solid var(--border-color); } .history-month-header { display: flex; justify-content: space-between; align-items: center; padding: 14px 20px; margin: 0; font-size: 1.05rem; font-weight: 600; color: var(--text-primary); background: var(--bg-body); cursor: pointer; transition: background 0.2s; } .history-month-header:hover { background: var(--border-color); /* Slight hover effect */ } .history-month-summary { display: flex; align-items: center; gap: 12px; font-size: 0.95rem; color: var(--text-secondary); } .history-month-content { display: none; /* Collapsed by default */ background: var(--bg-card); } .history-month-group.open .history-month-content { display: block; /* Expanded when open class is present */ } .history-month-group.open .history-month-header .material-icons-round { transform: rotate(180deg); } .history-month-header .material-icons-round { transition: transform 0.3s; font-size: 20px; } .history-week-group { padding: 12px 20px; border-bottom: 1px dashed var(--border-color); } .history-week-group:last-child { border-bottom: none; } .history-week-header { display: flex; justify-content: space-between; align-items: center; font-size: 0.9rem; font-weight: 600; color: var(--text-secondary); margin-bottom: 10px; } .history-week-summary { font-size: 0.85rem; font-weight: 500; background: rgba(100, 116, 139, 0.1); padding: 4px 10px; border-radius: 12px; } .history-items { display: flex; flex-direction: column; gap: 8px; } .history-item { display: grid; grid-template-columns: 50px 1fr auto; align-items: center; gap: 12px; padding: 10px 12px; background: var(--bg-body); border-radius: 8px; border: 1px solid var(--border-color); } .history-item-date { font-size: 0.85rem; color: var(--text-secondary); font-weight: 500; } .history-item-details { display: flex; flex-direction: column; gap: 4px; } .history-item-name { font-size: 0.95rem; font-weight: 500; color: var(--text-primary); } .history-item-price { font-weight: 600; color: var(--text-primary); } .history-item-status { font-size: 0.8rem; font-weight: 600; color: var(--text-primary); text-transform: uppercase; letter-spacing: 0.5px; } .history-item-cancelled { opacity: 0.5; filter: grayscale(1); } .history-item-price-cancelled { text-decoration: line-through; color: var(--text-secondary); } @keyframes modalSlide { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } .modal-header { display: flex; align-items: center; justify-content: space-between; padding: 20px; border-bottom: 1px solid var(--border-color); } .modal-header h2 { margin: 0; font-size: 1.25rem; } .modal-body { padding: 20px; } #login-form { padding: 20px; } .form-group { margin-bottom: 20px; } .form-group label { display: block; margin-bottom: 6px; font-weight: 500; font-size: 0.9rem; } .form-group input { width: 100%; padding: 10px 12px; border: 1px solid var(--border-color); /* Changed from --border */ border-radius: 8px; background: var(--bg-body); /* Changed from --bg */ color: var(--text-primary); /* Changed from --text */ font-family: inherit; transition: border-color 0.2s; } .form-group input:focus { outline: none; border-color: var(--accent-color); /* Changed from --primary */ } .help-text { display: block; margin-top: 4px; color: var(--text-secondary); /* Changed from --text-muted */ font-size: 0.75rem; } .error-msg { margin-bottom: 16px; padding: 10px; background: rgba(239, 68, 68, 0.1); color: var(--error-color); /* Changed from --danger */ border-radius: 8px; font-size: 0.85rem; text-align: center; } .modal-actions { margin-top: 24px; } .btn-primary.wide { width: 100%; justify-content: center; } .hidden { display: none !important; } /* Menu Grid Container */ .menu-grid { display: flex; flex-direction: column; flex: 1; overflow: hidden; gap: 1rem; } .week-section { margin-bottom: 2rem; } .week-header { margin-bottom: 1.5rem; border-bottom: 1px solid var(--border-color); padding-bottom: 1rem; text-align: center; } .week-title { font-size: 1.75rem; font-weight: 700; color: var(--text-primary); } .week-range { color: var(--text-secondary); font-size: 0.9rem; margin-top: 0.25rem; } /* Full-viewport layout: header + scrollable content + footer */ #kantine-wrapper { display: flex; flex-direction: column; height: 100vh; height: 100dvh; /* Dynamic viewport height for mobile browsers */ overflow: hidden; } .days-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 0.5rem; flex: 1; overflow-y: auto; /* This is the scroll container at the window edge */ align-content: start; padding: 0 2rem 2rem 2rem; } /* Card */ .menu-card { background-color: var(--bg-card); border-radius: 12px; border: 1px solid var(--border-color); box-shadow: var(--card-shadow); overflow: clip; /* Clips scrolling content behind sticky header */ transition: box-shadow 0.2s ease; display: flex; flex-direction: column; } /* Past Day Styling - Target specific elements so ordered items can remain visible AND preserve sticky context */ /* We MUST apply filter/opacity to children, not the parent .menu-card, or else position: sticky breaks */ /* Header keeps fully opaque background to hide scrolling items, only grayscales */ .menu-card.past-day .card-header { filter: grayscale(0.8); transition: filter 0.3s; } /* Items become semi-transparent */ .menu-card.past-day .menu-item:not(.ordered) { opacity: 0.6; filter: grayscale(0.8); transition: opacity 0.3s, filter 0.3s; } .menu-card.past-day:hover .card-header { filter: grayscale(0.4); } .menu-card.past-day:hover .menu-item:not(.ordered) { opacity: 0.8; filter: grayscale(0.4); } /* Past ordered items get no special frame or shadow, but remain visually distinct by staying fully opaque (via the :not(.ordered) selector above) */ .menu-item.today-ordered { border: 2px solid #8b5cf6; box-shadow: 0 0 30px rgba(139, 92, 246, 0.6); border-radius: 8px; padding: 1rem; margin: 0 -1rem 1.5rem -1rem; background: var(--bg-card); position: relative; z-index: 5; animation: pulse-glow-strong 3s infinite; } @keyframes pulse-glow-strong { 0% { box-shadow: 0 0 20px rgba(139, 92, 246, 0.4); } 50% { box-shadow: 0 0 40px rgba(139, 92, 246, 0.8); } 100% { box-shadow: 0 0 20px rgba(139, 92, 246, 0.4); } } .menu-card:hover { box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); } .card-header { padding: 1rem 1.25rem; border-bottom: 1px solid var(--border-color); display: flex; justify-content: space-between; align-items: baseline; background-color: var(--bg-card); /* Removed border-radius: 12px 12px 0 0; .menu-card\'s overflow: clip will round the corners initially. When sticky at the top, it will be square and perfectly hide scrolling content! */ /* Sticky within .container scroll area */ position: sticky; top: 0; z-index: 90; } .card-body { padding: 1.25rem; display: grid; grid-template-rows: auto; align-content: start; } .day-name { font-size: 1.125rem; font-weight: 600; } .day-date { font-size: 0.875rem; color: var(--text-secondary); } .empty-state { color: var(--text-secondary); font-style: italic; text-align: center; padding: 1rem; } /* Menu Items */ .menu-item { margin-bottom: 1.5rem; padding-bottom: 1.5rem; border-bottom: 1px solid var(--border-color); } .menu-item:last-child { margin-bottom: 0; padding-bottom: 0; border-bottom: none; } .item-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 0.5rem; gap: 1rem; } .item-name { font-weight: 600; color: var(--text-primary); font-size: 1rem; } .item-price { font-weight: 700; color: var(--accent-color); white-space: nowrap; } .item-desc { font-size: 0.875rem; color: var(--text-secondary); line-height: 1.6; margin-bottom: 0.75rem; white-space: pre-wrap; } .badges { display: flex; gap: 0.5rem; margin-left: auto; flex-wrap: wrap; } .item-status-row { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.75rem; flex-wrap: wrap; } .badge { display: inline-flex; align-items: center; justify-content: center; height: 24px; font-size: 0.75rem; padding: 0 10px; border-radius: 4px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; line-height: normal; white-space: nowrap; } .badge.available { background-color: rgba(16, 185, 129, 0.1); /* Emerald 500 / 10% */ color: var(--success-color); border: 1px solid rgba(16, 185, 129, 0.2); } .badge.sold-out { background-color: rgba(239, 68, 68, 0.1); /* Red 500 / 10% */ color: var(--error-color); border: 1px solid rgba(239, 68, 68, 0.2); } .badge.ordered { background-color: rgba(139, 92, 246, 0.1); /* Violet 500 / 10% */ color: #8b5cf6; border: 1px solid rgba(139, 92, 246, 0.2); gap: 4px; } .badge.ordered .material-icons-round { font-size: 1rem; } /* Loading */ .loading-state { text-align: center; padding: 4rem; color: var(--text-secondary); } .spinner { width: 40px; height: 40px; border: 3px solid var(--border-color); border-top-color: var(--accent-color); border-radius: 50%; margin: 0 auto 1rem; animation: spin 1s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } /* Footer */ .app-footer { flex-shrink: 0; text-align: center; padding: 0.4rem 2rem; color: var(--text-secondary); font-size: 0.8rem; border-top: 1px solid var(--border-color); } /* === Order / Cancel Buttons (inline in status row) === */ .btn-order { display: inline-flex; align-items: center; gap: 4px; padding: 4px 10px; border: none; border-radius: 6px; background: var(--success-color); color: white; font-size: 0.75rem; font-weight: 600; cursor: pointer; transition: all 0.2s ease; font-family: inherit; } .btn-order .material-icons-round { font-size: 16px; } .btn-order:hover:not(:disabled) { filter: brightness(1.15); transform: translateY(-1px); } .btn-order:disabled { opacity: 0.5; cursor: not-allowed; } .btn-order.loading { pointer-events: none; opacity: 0.6; } .btn-order-compact { padding: 2px 4px; gap: 0; } .btn-order-compact .material-icons-round { font-size: 16px; } .btn-cancel { display: inline-flex; align-items: center; justify-content: center; padding: 4px 6px; border: none; border-radius: 6px; background: var(--error-color); color: white; font-size: 0.75rem; cursor: pointer; transition: all 0.2s ease; font-family: inherit; } .btn-cancel .material-icons-round { font-size: 16px; } .btn-cancel:hover:not(:disabled) { filter: brightness(1.15); transform: translateY(-1px); } .btn-cancel:disabled { opacity: 0.5; cursor: not-allowed; } /* Past days: hide action buttons */ .past-day .item-actions { display: none; } /* Order count badge (for multi-orders) */ .order-count-badge { display: inline-flex; align-items: center; justify-content: center; background: rgba(255, 255, 255, 0.3); color: white; font-size: 0.65rem; font-weight: 700; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px; margin-left: 4px; line-height: 1; } /* === Toast Notifications === */ #toast-container { position: fixed; bottom: 20px; right: 20px; z-index: 10000; display: flex; flex-direction: column; gap: 8px; pointer-events: none; } .toast { display: flex; align-items: center; gap: 8px; padding: 10px 16px; border-radius: 8px; font-size: 0.85rem; font-weight: 500; font-family: \'Inter\', sans-serif; color: white; backdrop-filter: blur(10px); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); pointer-events: auto; transform: translateX(120%); opacity: 0; transition: transform 0.3s ease, opacity 0.3s ease; } .toast.show { transform: translateX(0); opacity: 1; } .toast .material-icons-round { font-size: 18px; } .toast-success { background: rgba(5, 150, 105, 0.95); } .toast-error { background: rgba(220, 38, 38, 0.95); } .toast-info { background: rgba(59, 130, 246, 0.95); } /* === Mobile Responsiveness === */ @media (max-width: 600px) { .header-content { flex-direction: column; gap: 1rem; padding: 0.75rem; } .week-nav { width: 100%; justify-content: center; } .nav-pills { width: 100%; justify-content: space-between; } .nav-btn { flex: 1; justify-content: center; padding: 0.5rem; font-size: 0.85rem; } .days-grid { grid-template-columns: 1fr; /* Force single column */ } .main-content { padding: 1rem; } .week-title { font-size: 1.5rem; } /* Adjust toast position for mobile */ .toast-container { bottom: 1rem; right: 1rem; left: 1rem; /* Center on mobile */ width: auto; } .menu-card { margin-bottom: 1rem; } } /* Tighter layout for high column counts (e.g., 5-day landscape) */ @media (min-width: 1024px) { .card-body { padding: 1rem 0.75rem; } .item-header { gap: 0.5rem; } } /* === Flagging & Notification Styles === */ .btn-flag { display: inline-flex; align-items: center; justify-content: center; background: transparent; border: 1px solid var(--text-secondary); color: var(--text-secondary); border-radius: 6px; padding: 4px; cursor: pointer; transition: all 0.2s; margin-right: 0.5rem; width: 28px; height: 28px; } .btn-flag:hover { background: rgba(234, 179, 8, 0.1); /* Yellow-500 / 10% */ color: #eab308; border-color: #eab308; } .btn-flag.active { background: rgba(234, 179, 8, 0.1); color: #eab308; border-color: #eab308; } .btn-flag .material-icons-round { font-size: 1.1rem; } /* Flagged & Sold Out (Yellow Glow) */ .menu-item.flagged-sold-out { border: 1px solid #eab308; box-shadow: 0 0 10px rgba(234, 179, 8, 0.2); border-radius: 8px; padding: 1rem; margin: 0 -1rem 1.5rem -1rem; background: var(--bg-card); position: relative; z-index: 5; animation: yellow-pulse 3s infinite; } @keyframes yellow-pulse { 0% { box-shadow: 0 0 8px rgba(234, 179, 8, 0.2); } 50% { box-shadow: 0 0 16px rgba(234, 179, 8, 0.5); } 100% { box-shadow: 0 0 8px rgba(234, 179, 8, 0.2); } } /* Flagged & Available (Green Glow) */ .menu-item.flagged-available { border: 2px solid var(--success-color); box-shadow: 0 0 15px rgba(16, 185, 129, 0.3); border-radius: 8px; padding: 1rem; margin: 0 -1rem 1.5rem -1rem; background: var(--bg-card); position: relative; z-index: 5; animation: green-pulse 3s infinite; } @keyframes green-pulse { 0% { box-shadow: 0 0 10px rgba(16, 185, 129, 0.3); } 50% { box-shadow: 0 0 20px rgba(16, 185, 129, 0.6); } 100% { box-shadow: 0 0 10px rgba(16, 185, 129, 0.3); } } /* Day Header Badges */ .day-header-left { display: flex; align-items: center; gap: 0.75rem; } .menu-code-badge { font-size: 0.75rem; font-weight: 700; color: #8b5cf6; /* Violet 500 */ background-color: rgba(139, 92, 246, 0.15); border: 1px solid rgba(139, 92, 246, 0.3); padding: 2px 6px; border-radius: 6px; line-height: normal; display: inline-block; } /* Detailed Badge Colors */ .nav-badge.badge-violet { background-color: #8b5cf6; } .nav-badge.badge-green { background-color: var(--success-color); } .nav-badge.badge-red { background-color: var(--error-color); } .nav-badge.badge-blue { background-color: var(--accent-color); } /* Day Header Status Colors (User Request) */ .card-header.header-violet { background-color: var(--bg-card); background-image: linear-gradient(rgba(139, 92, 246, 0.15), rgba(139, 92, 246, 0.15)); border-bottom: 2px solid #8b5cf6; } .card-header.header-green { background-color: var(--bg-card); background-image: linear-gradient(rgba(16, 185, 129, 0.15), rgba(16, 185, 129, 0.15)); border-bottom: 2px solid var(--success-color); } .card-header.header-red { background-color: var(--bg-card); background-image: linear-gradient(rgba(239, 68, 68, 0.15), rgba(239, 68, 68, 0.15)); border-bottom: 2px solid var(--error-color); } .card-header.header-violet .day-name, .card-header.header-green .day-name, .card-header.header-red .day-name { font-weight: 700; color: var(--text-primary); /* Ensure text remains standard color */ } /* Update Icon */ .update-icon { display: inline-flex; align-items: center; justify-content: center; margin-left: 8px; background-color: rgba(16, 185, 129, 0.2); /* Green tint */ color: var(--success-color); border-radius: 50%; width: 24px; height: 24px; cursor: pointer; font-size: 14px; transition: all 0.2s; text-decoration: none; animation: pulse 2s infinite; } .update-icon:hover { background-color: var(--success-color); color: white; transform: scale(1.1); } @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.4); } 70% { box-shadow: 0 0 0 6px rgba(16, 185, 129, 0); } 100% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0); } } /* Order Countdown */ #order-countdown { background: rgba(255, 255, 255, 0.1); padding: 0.25rem 0.75rem; border-radius: 99px; font-size: 0.85rem; display: flex; align-items: center; gap: 0.5rem; white-space: nowrap; border: 1px solid var(--border-color); } #order-countdown span { opacity: 0.7; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.5px; } #order-countdown.urgent { background: rgba(239, 68, 68, 0.2); border-color: rgba(239, 68, 68, 0.5); color: #ef4444; animation: pulse-red 2s infinite; } @keyframes pulse-red { 0% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.4); } 70% { box-shadow: 0 0 0 6px rgba(239, 68, 68, 0); } 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0); } } /* Smart Highlights (Blue Glow - matches today-ordered/flagged pattern) */ .menu-item.highlight-glow { border: 2px solid rgba(59, 130, 246, 0.7); box-shadow: 0 0 20px rgba(59, 130, 246, 0.4); border-radius: 8px; padding: 1rem; margin: 0 -1rem 1.5rem -1rem; background: var(--bg-card); position: relative; z-index: 5; animation: blue-pulse 3s infinite; } @keyframes blue-pulse { 0% { box-shadow: 0 0 15px rgba(59, 130, 246, 0.3); } 50% { box-shadow: 0 0 25px rgba(59, 130, 246, 0.6); } 100% { box-shadow: 0 0 15px rgba(59, 130, 246, 0.3); } } /* Nav Badge with Count */ .nav-badge.has-highlights { background-color: var(--bg-card); /* Neutral background */ color: var(--text-primary); border: 1px solid var(--border-color); padding: 2px 6px; } .nav-badge .highlight-count { color: #3b82f6; /* Blue 500 */ font-weight: 700; margin-left: 4px; } /* Tag Management Modal */ #tags-list { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1rem; min-height: 50px; } /* Tag badges styled consistently with .badge (verfügbar/ausverkauft) */ .tag-badge { display: inline-flex; align-items: center; justify-content: center; height: 24px; font-size: 0.75rem; padding: 0 10px; border-radius: 4px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; line-height: normal; white-space: nowrap; background-color: rgba(59, 130, 246, 0.1); color: #3b82f6; border: 1px solid rgba(59, 130, 246, 0.2); gap: 4px; } .tag-remove { cursor: pointer; opacity: 0.7; font-size: 1.1em; line-height: 1; transition: all 0.2s; } .tag-remove:hover { opacity: 1; color: #ef4444; } .input-group { display: flex; gap: 0.5rem; } .input-group input { flex: 1; padding: 0.75rem; background: var(--bg-body); border: 1px solid var(--border-color); color: var(--text-primary); border-radius: 8px; font-family: inherit; } /* Add tag button - styled like .btn-order with nav-btn.active color */ #btn-add-tag { display: inline-flex; align-items: center; gap: 4px; padding: 0.5rem 1rem; border: none; border-radius: 6px; background: var(--accent-color); color: white; font-size: 0.8rem; font-weight: 600; cursor: pointer; transition: all 0.2s ease; font-family: inherit; white-space: nowrap; } #btn-add-tag:hover { filter: brightness(1.15); transform: translateY(-1px); } .matched-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; /* Space between tags and title */ margin-top: -5px; /* Pull closer to header */ } .tag-badge-small { display: inline-flex; align-items: center; font-size: 0.7rem; padding: 2px 8px; border-radius: 4px; background: rgba(59, 130, 246, 0.15); color: #60a5fa; border: 1px solid rgba(59, 130, 246, 0.3); font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; } [data-theme="light"] .tag-badge-small { background: rgba(37, 99, 235, 0.1); color: #2563eb; border: 1px solid rgba(37, 99, 235, 0.2); } /* Installer Changelog */ .changelog-container ul { padding-left: 1.5rem; margin: 0.5rem 0; } .changelog-container li { margin-bottom: 0.4rem; line-height: 1.5; } .changelog-container h3 { margin-top: 1.5rem; margin-bottom: 0.5rem; font-size: 1.1em; color: var(--accent-color); } /* === Version Menu === */ .version-tag { cursor: pointer; transition: opacity 0.2s ease, text-decoration 0.2s ease; } .version-tag:hover { opacity: 1 !important; text-decoration: underline; } .version-list { list-style: none; padding: 0; margin: 0; } .version-item { display: flex; justify-content: space-between; align-items: center; padding: 10px 14px; border-radius: 8px; margin-bottom: 4px; transition: background 0.2s; } .version-item:hover { background: rgba(100, 116, 139, 0.08); } .version-item.current { background: rgba(2, 154, 168, 0.1); border: 1px solid rgba(2, 154, 168, 0.25); } [data-theme="dark"] .version-item:hover { background: rgba(255, 255, 255, 0.05); } [data-theme="dark"] .version-item.current { background: rgba(96, 165, 250, 0.12); border: 1px solid rgba(96, 165, 250, 0.25); } .version-info { display: flex; align-items: center; gap: 10px; } .badge-current { font-size: 0.75rem; font-weight: 600; color: var(--success-color); padding: 2px 8px; border-radius: 4px; background: rgba(5, 150, 105, 0.1); } .badge-new { font-size: 0.75rem; font-weight: 600; color: #029aa8; padding: 2px 8px; border-radius: 4px; background: rgba(2, 154, 168, 0.1); } [data-theme="dark"] .badge-new { color: #60a5fa; background: rgba(96, 165, 250, 0.12); } .install-link { font-size: 0.8rem; font-weight: 500; padding: 4px 12px; border-radius: 6px; background: rgba(2, 154, 168, 0.1); color: #029aa8; text-decoration: none; border: 1px solid rgba(2, 154, 168, 0.25); transition: all 0.2s; white-space: nowrap; } .install-link:hover { background: rgba(2, 154, 168, 0.2); border-color: rgba(2, 154, 168, 0.4); } [data-theme="dark"] .install-link { color: #60a5fa; background: rgba(96, 165, 250, 0.12); border: 1px solid rgba(96, 165, 250, 0.25); } [data-theme="dark"] .install-link:hover { background: rgba(96, 165, 250, 0.2); border-color: rgba(96, 165, 250, 0.4); } .dev-toggle { padding: 10px 14px; border-radius: 8px; background: rgba(100, 116, 139, 0.05); border: 1px solid var(--border-color); } .dev-toggle input[type="checkbox"] { accent-color: #029aa8; width: 16px; height: 16px; } [data-theme="dark"] .dev-toggle input[type="checkbox"] { accent-color: #60a5fa; } ';document.head.appendChild(s); +var s=document.createElement('style');s.textContent=':root { /* Premium Slate/Gray-Blue Palette - Light Mode */ --bg-body: #f1f5f9; /* Slate 100 */ --bg-card: #ffffff; --text-primary: #334155; /* Slate 700 */ --text-secondary: #64748b; --accent-color: #0f172a; /* Slate 900 (High contrast) */ --border-color: #cbd5e1; /* Slate 300 */ --banner-bg: #e2e8f0; --banner-text: #1e293b; --success-color: #059669; --error-color: #dc2626; --card-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.05), 0 2px 4px -2px rgb(0 0 0 / 0.05); --header-bg: rgba(255, 255, 255, 0.9); --header-border: 1px solid rgba(203, 213, 225, 0.6); } [data-theme="dark"] { /* Premium Slate/Gray-Blue Palette - Dark Mode */ --bg-body: #1e293b; /* Deep Slate Gray (Requested) */ --bg-card: #334155; /* Slate 700 */ --text-primary: #f8fafc; /* Slate 50 */ --text-secondary: #cbd5e1; /* Slate 300 */ --accent-color: #60a5fa; /* Blue 400 */ --border-color: #475569; /* Slate 600 */ --banner-bg: #475569; --banner-text: #e2e8f0; --header-bg: rgba(30, 41, 59, 0.9); --header-border: 1px solid rgba(71, 85, 105, 0.6); --card-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.4); } * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: \'Inter\', system-ui, -apple-system, sans-serif; background-color: var(--bg-body); color: var(--text-primary); transition: background-color 0.3s ease, color 0.3s ease; line-height: 1.5; -webkit-font-smoothing: antialiased; } /* Fix scrolling bug: Reset html/body styles from host page */ /* IMPORTANT: html must NOT have overflow set, or it creates a scroll container that breaks position: sticky */ html { height: auto !important; min-height: 100% !important; overflow: visible !important; position: static !important; margin: 0 !important; padding: 0 !important; } body { height: auto !important; min-height: 100% !important; overflow-x: clip !important; /* clip prevents horizontal overflow without breaking sticky */ overflow-y: visible !important; position: static !important; margin: 0 !important; padding: 0 !important; } /* Header */ .app-header { flex-shrink: 0; z-index: 100; backdrop-filter: blur(12px); background-color: var(--header-bg); border-bottom: var(--header-border); padding: 1rem 0; } .header-content { width: 100%; /* Full width */ padding: 0 2rem; /* Comfortable padding */ display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 1rem; } .brand { display: flex; align-items: center; gap: 0.75rem; } .brand-text { display: flex; flex-direction: column; } .brand h1 { font-size: 1.25rem; font-weight: 700; letter-spacing: -0.025em; margin-bottom: 0; } .subtitle { font-size: 0.85rem; color: var(--text-secondary); font-weight: 400; margin-left: 2px; } .logo-icon { font-size: 1.5rem; color: var(--accent-color); } /* Controls */ .controls { display: flex; align-items: center; gap: 1.5rem; justify-self: end; } /* Header Week Info (centered) */ .header-week-info { text-align: center; line-height: 1.3; } .header-center-wrapper { display: flex; flex-direction: row; align-items: center; gap: 1.5rem; justify-content: center; } .header-week-title { font-size: 1.1rem; font-weight: 600; color: var(--text-primary); } .header-week-subtitle { font-size: 0.85rem; color: var(--text-secondary); } /* Language Toggle (FR-100) */ .lang-toggle { display: inline-flex; gap: 0; border-radius: 6px; overflow: hidden; border: 1px solid var(--border-color); background: var(--bg-card); } .lang-btn { padding: 3px 10px; font-size: 0.7rem; font-weight: 600; letter-spacing: 0.03em; background: transparent; color: var(--text-secondary); border: none; cursor: pointer; transition: all 0.2s; } .lang-btn:hover { color: var(--text-primary); background: rgba(100, 116, 139, 0.1); } .lang-btn.active { background: var(--accent-color); color: white; } .nav-group { display: flex; background-color: var(--bg-card); border: 1px solid var(--border-color); padding: 0.25rem; border-radius: 8px; } .nav-btn { background: none; border: none; padding: 0.5rem 1rem; font-size: 0.875rem; font-weight: 500; color: var(--text-secondary); cursor: pointer; border-radius: 6px; transition: all 0.2s; display: flex; align-items: center; gap: 0.5rem; } .nav-btn:hover { color: var(--text-primary); background-color: rgba(100, 116, 139, 0.1); } .nav-btn.active { background-color: var(--accent-color); color: white; } /* Notification state for Next Week */ .nav-btn.new-week-available { animation: goldPulse 2s infinite; border-color: #f59e0b; color: var(--accent-color); } .nav-btn.new-week-available.active { color: white; } @keyframes goldPulse { 0% { box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.7); } 70% { box-shadow: 0 0 0 10px rgba(245, 158, 11, 0); } 100% { box-shadow: 0 0 0 0 rgba(245, 158, 11, 0); } } /* Badge for nav buttons (day count indicator) */ .nav-badge { background-color: var(--error-color); color: white; font-size: 0.75rem; font-weight: 600; padding: 0 6px; border-radius: 10px; min-width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center; margin-left: 8px; gap: 3px; line-height: 1; } .nav-badge .orderable { color: #fff; font-weight: 800; } .nav-badge .separator { opacity: 0.6; font-weight: 400; } .nav-badge .total { opacity: 0.8; font-weight: 400; } .nav-btn.active .nav-badge { background: rgba(255, 255, 255, 0.3); } /* Primary style for Login Button to match header */ #btn-login-open { background-color: var(--accent-color); color: white; padding: 0.5rem 1.25rem; border-radius: 8px; font-weight: 600; letter-spacing: 0.025em; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } #btn-login-open:hover { background-color: #334155; /* Slightly lighter than slate-900 */ transform: translateY(-1px); box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } /* User Badge Button (Login) */ .user-badge-btn { display: flex; align-items: center; gap: 8px; padding: 6px 12px; background: var(--bg-card); border: 1px solid var(--border-color); border-radius: 20px; font-size: 0.9rem; font-weight: 500; color: var(--text-primary); cursor: pointer; transition: all 0.2s; } .user-badge-btn:hover { background: rgba(100, 116, 139, 0.1); border-color: var(--accent-color); } .user-badge-btn .material-icons-round { font-size: 1.25rem; color: var(--accent-color); } .icon-btn { background: none; border: none; color: var(--text-primary); cursor: pointer; padding: 0.5rem; border-radius: 50%; transition: background-color 0.2s; display: flex; align-items: center; justify-content: center; } .icon-btn:hover { background-color: rgba(100, 116, 139, 0.1); } /* Refresh button animation */ #btn-refresh.refreshing .material-icons-round, #alarm-bell.refreshing .material-icons-round { animation: rotate 1s linear infinite; } @keyframes rotate { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } /* Progress Modal */ .progress-container { margin-bottom: 1.5rem; } .progress-bar { width: 100%; height: 8px; background-color: var(--border-color); border-radius: 4px; overflow: hidden; margin-bottom: 0.75rem; } .progress-fill { height: 100%; background: linear-gradient(90deg, var(--accent-color) 0%, #60a5fa 100%); width: 0%; transition: width 0.3s ease; border-radius: 4px; } .progress-percent { text-align: center; font-size: 1.5rem; font-weight: 700; color: var(--text-primary); margin-bottom: 0.5rem; } .progress-message { text-align: center; color: var(--text-secondary); font-size: 0.9rem; font-weight: 500; } .weekly-cost { background-color: rgba(59, 130, 246, 0.1); /* Blue tint */ color: var(--accent-color); padding: 0.4rem 0.8rem; border-radius: 8px; font-weight: 600; font-size: 0.9rem; display: flex; align-items: center; gap: 0.5rem; border: 1px solid rgba(59, 130, 246, 0.2); } .weekly-cost .material-icons-round { font-size: 18px; } /* Container - flex column, full width so child scrollbar is at edge */ .container { flex: 1; width: 100%; overflow: hidden; padding: 0 0 0 0; /* Only top padding, no horizontal so child fills width */ display: flex; flex-direction: column; } /* Add horizontal padding to direct children of container to maintain layout */ .container>*:not(.menu-grid) { padding-left: 2rem; padding-right: 2rem; } /* Banner */ .banner { background-color: var(--banner-bg); color: var(--banner-text); padding: 0.75rem 1rem; border-radius: 8px; display: flex; align-items: center; gap: 0.5rem; margin-bottom: 2rem; font-size: 0.875rem; font-weight: 500; border: 1px solid var(--border-color); max-width: fit-content; } /* User Badge */ .user-badge { display: flex; align-items: center; gap: 8px; padding: 6px 12px; background: var(--bg-card); /* Changed from --surface */ border: 1px solid var(--border-color); /* Changed from --border */ border-radius: 20px; font-size: 0.9rem; font-weight: 500; } .icon-btn-small { background: none; border: none; padding: 4px; cursor: pointer; color: var(--text-secondary); /* Changed from --text-muted */ display: flex; align-items: center; justify-content: center; border-radius: 50%; transition: all 0.2s; } .icon-btn-small:hover { color: var(--error-color); /* Changed from --danger */ background: rgba(239, 68, 68, 0.1); } /* Modal */ .modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); backdrop-filter: blur(4px); display: flex; align-items: center; justify-content: center; z-index: 1000; transition: all 0.3s; } .modal.hidden { opacity: 0; pointer-events: none; } .modal-content { background: var(--bg-card); width: 90%; max-width: 400px; border-radius: 16px; box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); overflow: hidden; animation: modalSlide 0.3s ease-out; } /* History Modal specific */ .history-modal-content { max-width: 600px; max-height: 85vh; display: flex; flex-direction: column; } .history-modal-content .modal-body { overflow-y: auto; padding: 0; /* Padding is handled by inner elements */ } /* History Styles */ .history-year-group { margin-bottom: 16px; } .history-year-header { background: var(--bg-card); padding: 12px 20px; margin: 0; font-size: 1.2rem; font-weight: 700; color: var(--text-primary); border-bottom: 2px solid var(--border-color); position: sticky; top: 0; z-index: 12; } .history-month-group { border-bottom: 1px solid var(--border-color); } .history-month-header { display: flex; justify-content: space-between; align-items: center; padding: 14px 20px; margin: 0; font-size: 1.05rem; font-weight: 600; color: var(--text-primary); background: var(--bg-body); cursor: pointer; transition: background 0.2s; } .history-month-header:hover { background: var(--border-color); /* Slight hover effect */ } .history-month-summary { display: flex; align-items: center; gap: 12px; font-size: 0.95rem; color: var(--text-secondary); } .history-month-content { display: none; /* Collapsed by default */ background: var(--bg-card); } .history-month-group.open .history-month-content { display: block; /* Expanded when open class is present */ } .history-month-group.open .history-month-header .material-icons-round { transform: rotate(180deg); } .history-month-header .material-icons-round { transition: transform 0.3s; font-size: 20px; } .history-week-group { padding: 12px 20px; border-bottom: 1px dashed var(--border-color); } .history-week-group:last-child { border-bottom: none; } .history-week-header { display: flex; justify-content: space-between; align-items: center; font-size: 0.9rem; font-weight: 600; color: var(--text-secondary); margin-bottom: 10px; } .history-week-summary { font-size: 0.85rem; font-weight: 500; background: rgba(100, 116, 139, 0.1); padding: 4px 10px; border-radius: 12px; } .history-items { display: flex; flex-direction: column; gap: 8px; } .history-item { display: grid; grid-template-columns: 50px 1fr auto; align-items: center; gap: 12px; padding: 10px 12px; background: var(--bg-body); border-radius: 8px; border: 1px solid var(--border-color); } .history-item-date { font-size: 0.85rem; color: var(--text-secondary); font-weight: 500; } .history-item-details { display: flex; flex-direction: column; gap: 4px; } .history-item-name { font-size: 0.95rem; font-weight: 500; color: var(--text-primary); } .history-item-price { font-weight: 600; color: var(--text-primary); } .history-item-status { font-size: 0.8rem; font-weight: 600; color: var(--text-primary); text-transform: uppercase; letter-spacing: 0.5px; } .history-item-cancelled { opacity: 0.5; filter: grayscale(1); } .history-item-price-cancelled { text-decoration: line-through; color: var(--text-secondary); } @keyframes modalSlide { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } .modal-header { display: flex; align-items: center; justify-content: space-between; padding: 20px; border-bottom: 1px solid var(--border-color); } .modal-header h2 { margin: 0; font-size: 1.25rem; } .modal-body { padding: 20px; } #login-form { padding: 20px; } .form-group { margin-bottom: 20px; } .form-group label { display: block; margin-bottom: 6px; font-weight: 500; font-size: 0.9rem; } .form-group input { width: 100%; padding: 10px 12px; border: 1px solid var(--border-color); /* Changed from --border */ border-radius: 8px; background: var(--bg-body); /* Changed from --bg */ color: var(--text-primary); /* Changed from --text */ font-family: inherit; transition: border-color 0.2s; } .form-group input:focus { outline: none; border-color: var(--accent-color); /* Changed from --primary */ } .help-text { display: block; margin-top: 4px; color: var(--text-secondary); /* Changed from --text-muted */ font-size: 0.75rem; } .error-msg { margin-bottom: 16px; padding: 10px; background: rgba(239, 68, 68, 0.1); color: var(--error-color); /* Changed from --danger */ border-radius: 8px; font-size: 0.85rem; text-align: center; } .modal-actions { margin-top: 24px; } .btn-primary.wide { width: 100%; justify-content: center; } .hidden { display: none !important; } /* Menu Grid Container */ .menu-grid { display: flex; flex-direction: column; flex: 1; overflow: hidden; gap: 1rem; } .week-section { margin-bottom: 2rem; } .week-header { margin-bottom: 1.5rem; border-bottom: 1px solid var(--border-color); padding-bottom: 1rem; text-align: center; } .week-title { font-size: 1.75rem; font-weight: 700; color: var(--text-primary); } .week-range { color: var(--text-secondary); font-size: 0.9rem; margin-top: 0.25rem; } /* Full-viewport layout: header + scrollable content + footer */ #kantine-wrapper { display: flex; flex-direction: column; height: 100vh; height: 100dvh; /* Dynamic viewport height for mobile browsers */ overflow: hidden; } .days-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 0.5rem; flex: 1; overflow-y: auto; /* This is the scroll container at the window edge */ align-content: start; padding: 0 2rem 2rem 2rem; } /* Card */ .menu-card { background-color: var(--bg-card); border-radius: 12px; border: 1px solid var(--border-color); box-shadow: var(--card-shadow); overflow: clip; /* Clips scrolling content behind sticky header */ transition: box-shadow 0.2s ease; display: flex; flex-direction: column; } /* Past Day Styling - Target specific elements so ordered items can remain visible AND preserve sticky context */ /* We MUST apply filter/opacity to children, not the parent .menu-card, or else position: sticky breaks */ /* Header keeps fully opaque background to hide scrolling items, only grayscales */ .menu-card.past-day .card-header { filter: grayscale(0.8); transition: filter 0.3s; } /* Items become semi-transparent */ .menu-card.past-day .menu-item:not(.ordered) { opacity: 0.6; filter: grayscale(0.8); transition: opacity 0.3s, filter 0.3s; } .menu-card.past-day:hover .card-header { filter: grayscale(0.4); } .menu-card.past-day:hover .menu-item:not(.ordered) { opacity: 0.8; filter: grayscale(0.4); } /* Past ordered items get no special frame or shadow, but remain visually distinct by staying fully opaque (via the :not(.ordered) selector above) */ .menu-item.today-ordered { border: 2px solid #8b5cf6; box-shadow: 0 0 30px rgba(139, 92, 246, 0.6); border-radius: 8px; padding: 1rem; margin: 0 0 1.5rem 0; background: var(--bg-card); position: relative; z-index: 5; animation: pulse-glow-strong 3s infinite; } @keyframes pulse-glow-strong { 0% { box-shadow: 0 0 20px rgba(139, 92, 246, 0.4); } 50% { box-shadow: 0 0 40px rgba(139, 92, 246, 0.8); } 100% { box-shadow: 0 0 20px rgba(139, 92, 246, 0.4); } } .menu-card:hover { box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); } .card-header { padding: 1rem 1.25rem; border-bottom: 1px solid var(--border-color); display: flex; justify-content: space-between; align-items: baseline; background-color: var(--bg-card); /* Removed border-radius: 12px 12px 0 0; .menu-card\'s overflow: clip will round the corners initially. When sticky at the top, it will be square and perfectly hide scrolling content! */ /* Sticky within .container scroll area */ position: sticky; top: 0; z-index: 90; } .card-body { padding: 1.25rem; display: grid; grid-template-rows: auto; align-content: start; } .day-name { font-size: 1.125rem; font-weight: 600; } .day-date { font-size: 0.875rem; color: var(--text-secondary); } .empty-state { color: var(--text-secondary); font-style: italic; text-align: center; padding: 1rem; } /* Menu Items */ .menu-item { margin-bottom: 1.5rem; padding-bottom: 1.5rem; border-bottom: 1px solid var(--border-color); } .menu-item:last-child { margin-bottom: 0; padding-bottom: 0; border-bottom: none; } .item-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 0.5rem; gap: 1rem; } .item-name { font-weight: 600; color: var(--text-primary); font-size: 1rem; } .item-price { font-weight: 700; color: var(--accent-color); white-space: nowrap; } .item-desc { font-size: 0.875rem; color: var(--text-secondary); line-height: 1.6; margin-bottom: 0.75rem; white-space: pre-wrap; } .badges { display: flex; gap: 0.5rem; margin-left: auto; flex-wrap: wrap; } .item-status-row { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.75rem; flex-wrap: wrap; } .badge { display: inline-flex; align-items: center; justify-content: center; height: 24px; font-size: 0.75rem; padding: 0 10px; border-radius: 4px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; line-height: normal; white-space: nowrap; } .badge.available { background-color: rgba(16, 185, 129, 0.1); /* Emerald 500 / 10% */ color: var(--success-color); border: 1px solid rgba(16, 185, 129, 0.2); } .badge.sold-out { background-color: rgba(239, 68, 68, 0.1); /* Red 500 / 10% */ color: var(--error-color); border: 1px solid rgba(239, 68, 68, 0.2); } .badge.ordered { background-color: rgba(139, 92, 246, 0.1); /* Violet 500 / 10% */ color: #8b5cf6; border: 1px solid rgba(139, 92, 246, 0.2); gap: 4px; } .badge.ordered .material-icons-round { font-size: 1rem; } /* Loading */ .loading-state { text-align: center; padding: 4rem; color: var(--text-secondary); } .spinner { width: 40px; height: 40px; border: 3px solid var(--border-color); border-top-color: var(--accent-color); border-radius: 50%; margin: 0 auto 1rem; animation: spin 1s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } /* Footer */ .app-footer { flex-shrink: 0; text-align: center; padding: 0.4rem 2rem; color: var(--text-secondary); font-size: 0.8rem; border-top: 1px solid var(--border-color); } /* === Order / Cancel Buttons (inline in status row) === */ .btn-order { display: inline-flex; align-items: center; gap: 4px; padding: 4px 10px; border: none; border-radius: 6px; background: var(--success-color); color: white; font-size: 0.75rem; font-weight: 600; cursor: pointer; transition: all 0.2s ease; font-family: inherit; } .btn-order .material-icons-round { font-size: 16px; } .btn-order:hover:not(:disabled) { filter: brightness(1.15); transform: translateY(-1px); } .btn-order:disabled { opacity: 0.5; cursor: not-allowed; } .btn-order.loading { pointer-events: none; opacity: 0.6; } .btn-order-compact { padding: 2px 4px; gap: 0; } .btn-order-compact .material-icons-round { font-size: 16px; } .btn-cancel { display: inline-flex; align-items: center; justify-content: center; padding: 4px 6px; border: none; border-radius: 6px; background: var(--error-color); color: white; font-size: 0.75rem; cursor: pointer; transition: all 0.2s ease; font-family: inherit; } .btn-cancel .material-icons-round { font-size: 16px; } .btn-cancel:hover:not(:disabled) { filter: brightness(1.15); transform: translateY(-1px); } .btn-cancel:disabled { opacity: 0.5; cursor: not-allowed; } /* Past days: hide action buttons */ .past-day .item-actions { display: none; } /* Order count badge (for multi-orders) */ .order-count-badge { display: inline-flex; align-items: center; justify-content: center; background: rgba(255, 255, 255, 0.3); color: white; font-size: 0.65rem; font-weight: 700; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px; margin-left: 4px; line-height: 1; } /* === Toast Notifications === */ #toast-container { position: fixed; bottom: 20px; right: 20px; z-index: 10000; display: flex; flex-direction: column; gap: 8px; pointer-events: none; } .toast { display: flex; align-items: center; gap: 8px; padding: 10px 16px; border-radius: 8px; font-size: 0.85rem; font-weight: 500; font-family: \'Inter\', sans-serif; color: white; backdrop-filter: blur(10px); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); pointer-events: auto; transform: translateX(120%); opacity: 0; transition: transform 0.3s ease, opacity 0.3s ease; } .toast.show { transform: translateX(0); opacity: 1; } .toast .material-icons-round { font-size: 18px; } .toast-success { background: rgba(5, 150, 105, 0.95); } .toast-error { background: rgba(220, 38, 38, 0.95); } .toast-info { background: rgba(59, 130, 246, 0.95); } /* === Mobile Responsiveness === */ @media (max-width: 600px) { .header-content { flex-direction: column; gap: 1rem; padding: 0.75rem; } .week-nav { width: 100%; justify-content: center; } .nav-pills { width: 100%; justify-content: space-between; } .nav-btn { flex: 1; justify-content: center; padding: 0.5rem; font-size: 0.85rem; } .days-grid { grid-template-columns: 1fr; /* Force single column */ } .main-content { padding: 1rem; } .week-title { font-size: 1.5rem; } /* Adjust toast position for mobile */ .toast-container { bottom: 1rem; right: 1rem; left: 1rem; /* Center on mobile */ width: auto; } .menu-card { margin-bottom: 1rem; } } /* Tighter layout for high column counts (e.g., 5-day landscape) */ @media (min-width: 1024px) { .card-body { padding: 1rem 0.75rem; } .item-header { gap: 0.5rem; } } /* === Flagging & Notification Styles === */ .btn-flag { display: inline-flex; align-items: center; justify-content: center; background: transparent; border: 1px solid var(--text-secondary); color: var(--text-secondary); border-radius: 6px; padding: 4px; cursor: pointer; transition: all 0.2s; margin-right: 0.5rem; width: 28px; height: 28px; } .btn-flag:hover { background: rgba(234, 179, 8, 0.1); /* Yellow-500 / 10% */ color: #eab308; border-color: #eab308; } .btn-flag.active { background: rgba(234, 179, 8, 0.1); color: #eab308; border-color: #eab308; } .btn-flag .material-icons-round { font-size: 1.1rem; } /* Flagged & Sold Out (Yellow Glow) */ .menu-item.flagged-sold-out { border: 1px solid #eab308; box-shadow: 0 0 10px rgba(234, 179, 8, 0.2); border-radius: 8px; padding: 1rem; margin: 0 0 1.5rem 0; background: var(--bg-card); position: relative; z-index: 5; animation: yellow-pulse 3s infinite; } @keyframes yellow-pulse { 0% { box-shadow: 0 0 8px rgba(234, 179, 8, 0.2); } 50% { box-shadow: 0 0 16px rgba(234, 179, 8, 0.5); } 100% { box-shadow: 0 0 8px rgba(234, 179, 8, 0.2); } } /* Flagged & Available (Green Glow) */ .menu-item.flagged-available { border: 2px solid var(--success-color); box-shadow: 0 0 15px rgba(16, 185, 129, 0.3); border-radius: 8px; padding: 1rem; margin: 0 0 1.5rem 0; background: var(--bg-card); position: relative; z-index: 5; animation: green-pulse 3s infinite; } @keyframes green-pulse { 0% { box-shadow: 0 0 10px rgba(16, 185, 129, 0.3); } 50% { box-shadow: 0 0 20px rgba(16, 185, 129, 0.6); } 100% { box-shadow: 0 0 10px rgba(16, 185, 129, 0.3); } } /* Day Header Badges */ .day-header-left { display: flex; align-items: center; gap: 0.75rem; } .menu-code-badge { font-size: 0.75rem; font-weight: 700; color: #8b5cf6; /* Violet 500 */ background-color: rgba(139, 92, 246, 0.15); border: 1px solid rgba(139, 92, 246, 0.3); padding: 2px 6px; border-radius: 6px; line-height: normal; display: inline-block; } /* Detailed Badge Colors */ .nav-badge.badge-violet { background-color: #8b5cf6; } .nav-badge.badge-green { background-color: var(--success-color); } .nav-badge.badge-red { background-color: var(--error-color); } .nav-badge.badge-blue { background-color: var(--accent-color); } /* Day Header Status Colors (User Request) */ .card-header.header-violet { background-color: var(--bg-card); background-image: linear-gradient(rgba(139, 92, 246, 0.15), rgba(139, 92, 246, 0.15)); border-bottom: 2px solid #8b5cf6; } .card-header.header-green { background-color: var(--bg-card); background-image: linear-gradient(rgba(16, 185, 129, 0.15), rgba(16, 185, 129, 0.15)); border-bottom: 2px solid var(--success-color); } .card-header.header-red { background-color: var(--bg-card); background-image: linear-gradient(rgba(239, 68, 68, 0.15), rgba(239, 68, 68, 0.15)); border-bottom: 2px solid var(--error-color); } .card-header.header-violet .day-name, .card-header.header-green .day-name, .card-header.header-red .day-name { font-weight: 700; color: var(--text-primary); /* Ensure text remains standard color */ } /* Update Icon */ .update-icon { display: inline-flex; align-items: center; justify-content: center; margin-left: 8px; background-color: rgba(16, 185, 129, 0.2); /* Green tint */ color: var(--success-color); border-radius: 50%; width: 24px; height: 24px; cursor: pointer; font-size: 14px; transition: all 0.2s; text-decoration: none; animation: pulse 2s infinite; } .update-icon:hover { background-color: var(--success-color); color: white; transform: scale(1.1); } @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.4); } 70% { box-shadow: 0 0 0 6px rgba(16, 185, 129, 0); } 100% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0); } } /* Order Countdown */ #order-countdown { background: rgba(255, 255, 255, 0.1); padding: 0.25rem 0.75rem; border-radius: 99px; font-size: 0.85rem; display: flex; align-items: center; gap: 0.5rem; white-space: nowrap; border: 1px solid var(--border-color); } #order-countdown span { opacity: 0.7; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.5px; } #order-countdown.urgent { background: rgba(239, 68, 68, 0.2); border-color: rgba(239, 68, 68, 0.5); color: #ef4444; animation: pulse-red 2s infinite; } @keyframes pulse-red { 0% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.4); } 70% { box-shadow: 0 0 0 6px rgba(239, 68, 68, 0); } 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0); } } /* Smart Highlights (Blue Glow - matches today-ordered/flagged pattern) */ .menu-item.highlight-glow { border: 2px solid rgba(59, 130, 246, 0.7); box-shadow: 0 0 20px rgba(59, 130, 246, 0.4); border-radius: 8px; padding: 1rem; margin: 0 0 1.5rem 0; background: var(--bg-card); position: relative; z-index: 5; animation: blue-pulse 3s infinite; } @keyframes blue-pulse { 0% { box-shadow: 0 0 15px rgba(59, 130, 246, 0.3); } 50% { box-shadow: 0 0 25px rgba(59, 130, 246, 0.6); } 100% { box-shadow: 0 0 15px rgba(59, 130, 246, 0.3); } } /* Nav Badge with Count */ .nav-badge.has-highlights { background-color: var(--bg-card); /* Neutral background */ color: var(--text-primary); border: 1px solid var(--border-color); padding: 2px 6px; } .nav-badge .highlight-count { color: #3b82f6; /* Blue 500 */ font-weight: 700; margin-left: 4px; } /* Tag Management Modal */ #tags-list { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1rem; min-height: 50px; } /* Tag badges styled consistently with .badge (verfügbar/ausverkauft) */ .tag-badge { display: inline-flex; align-items: center; justify-content: center; height: 24px; font-size: 0.75rem; padding: 0 10px; border-radius: 4px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; line-height: normal; white-space: nowrap; background-color: rgba(59, 130, 246, 0.1); color: #3b82f6; border: 1px solid rgba(59, 130, 246, 0.2); gap: 4px; } .tag-remove { cursor: pointer; opacity: 0.7; font-size: 1.1em; line-height: 1; transition: all 0.2s; } .tag-remove:hover { opacity: 1; color: #ef4444; } .input-group { display: flex; gap: 0.5rem; } .input-group input { flex: 1; padding: 0.75rem; background: var(--bg-body); border: 1px solid var(--border-color); color: var(--text-primary); border-radius: 8px; font-family: inherit; } /* Add tag button - styled like .btn-order with nav-btn.active color */ #btn-add-tag { display: inline-flex; align-items: center; gap: 4px; padding: 0.5rem 1rem; border: none; border-radius: 6px; background: var(--accent-color); color: white; font-size: 0.8rem; font-weight: 600; cursor: pointer; transition: all 0.2s ease; font-family: inherit; white-space: nowrap; } #btn-add-tag:hover { filter: brightness(1.15); transform: translateY(-1px); } .matched-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; /* Space between tags and title */ margin-top: -5px; /* Pull closer to header */ } .tag-badge-small { display: inline-flex; align-items: center; font-size: 0.7rem; padding: 2px 8px; border-radius: 4px; background: rgba(59, 130, 246, 0.15); color: #60a5fa; border: 1px solid rgba(59, 130, 246, 0.3); font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; } [data-theme="light"] .tag-badge-small { background: rgba(37, 99, 235, 0.1); color: #2563eb; border: 1px solid rgba(37, 99, 235, 0.2); } /* Installer Changelog */ .changelog-container ul { padding-left: 1.5rem; margin: 0.5rem 0; } .changelog-container li { margin-bottom: 0.4rem; line-height: 1.5; } .changelog-container h3 { margin-top: 1.5rem; margin-bottom: 0.5rem; font-size: 1.1em; color: var(--accent-color); } /* === Version Menu === */ .version-tag { cursor: pointer; transition: opacity 0.2s ease, text-decoration 0.2s ease; } .version-tag:hover { opacity: 1 !important; text-decoration: underline; } .version-list { list-style: none; padding: 0; margin: 0; } .version-item { display: flex; justify-content: space-between; align-items: center; padding: 10px 14px; border-radius: 8px; margin-bottom: 4px; transition: background 0.2s; } .version-item:hover { background: rgba(100, 116, 139, 0.08); } .version-item.current { background: rgba(2, 154, 168, 0.1); border: 1px solid rgba(2, 154, 168, 0.25); } [data-theme="dark"] .version-item:hover { background: rgba(255, 255, 255, 0.05); } [data-theme="dark"] .version-item.current { background: rgba(96, 165, 250, 0.12); border: 1px solid rgba(96, 165, 250, 0.25); } .version-info { display: flex; align-items: center; gap: 10px; } .badge-current { font-size: 0.75rem; font-weight: 600; color: var(--success-color); padding: 2px 8px; border-radius: 4px; background: rgba(5, 150, 105, 0.1); } .badge-new { font-size: 0.75rem; font-weight: 600; color: #029aa8; padding: 2px 8px; border-radius: 4px; background: rgba(2, 154, 168, 0.1); } [data-theme="dark"] .badge-new { color: #60a5fa; background: rgba(96, 165, 250, 0.12); } .install-link { font-size: 0.8rem; font-weight: 500; padding: 4px 12px; border-radius: 6px; background: rgba(2, 154, 168, 0.1); color: #029aa8; text-decoration: none; border: 1px solid rgba(2, 154, 168, 0.25); transition: all 0.2s; white-space: nowrap; } .install-link:hover { background: rgba(2, 154, 168, 0.2); border-color: rgba(2, 154, 168, 0.4); } [data-theme="dark"] .install-link { color: #60a5fa; background: rgba(96, 165, 250, 0.12); border: 1px solid rgba(96, 165, 250, 0.25); } [data-theme="dark"] .install-link:hover { background: rgba(96, 165, 250, 0.2); border-color: rgba(96, 165, 250, 0.4); } .dev-toggle { padding: 10px 14px; border-radius: 8px; background: rgba(100, 116, 139, 0.05); border: 1px solid var(--border-color); } .dev-toggle input[type="checkbox"] { accent-color: #029aa8; width: 16px; height: 16px; } [data-theme="dark"] .dev-toggle input[type="checkbox"] { accent-color: #60a5fa; } ';document.head.appendChild(s); // Inject JS logic var sc=document.createElement('script'); -sc.textContent="(()=>{\"use strict\";var e={367(e,t,n){n.d(t,{A0:()=>v,Aq:()=>g,BM:()=>S,Et:()=>E,Gb:()=>u,H:()=>b,KG:()=>T,N4:()=>p,P0:()=>H,PQ:()=>y,VL:()=>D,Y1:()=>L,g8:()=>w,i_:()=>c,m9:()=>O,oL:()=>k,wH:()=>h});var a=n(901),o=n(413),s=n(521),i=n(672),r=n(842),l=n(646);let d=null;function c(){if(!a.gX)try{const e=localStorage.getItem(\"AkitaStores\");if(e){const t=JSON.parse(e);t.auth&&t.auth.token&&((0,a.O5)(t.auth.token),localStorage.setItem(s.LS.AUTH_TOKEN,t.auth.token),t.auth.user&&((0,a.lt)(t.auth.user.id||\"unknown\"),localStorage.setItem(s.LS.CURRENT_USER,t.auth.user.id||\"unknown\"),t.auth.user.firstName&&localStorage.setItem(s.LS.FIRST_NAME,t.auth.user.firstName),t.auth.user.lastName&&localStorage.setItem(s.LS.LAST_NAME,t.auth.user.lastName)))}}catch(e){console.warn(\"Failed to parse AkitaStores:\",e)}(0,a.O5)(localStorage.getItem(s.LS.AUTH_TOKEN)),(0,a.lt)(localStorage.getItem(s.LS.CURRENT_USER));const e=localStorage.getItem(s.LS.FIRST_NAME),t=document.getElementById(\"btn-login-open\"),n=document.getElementById(\"user-info\"),o=document.getElementById(\"user-id-display\");a.gX?(t.classList.add(\"hidden\"),n.classList.remove(\"hidden\"),o.textContent=e||(a.Ny?`User ${a.Ny}`:(0,l.t)(\"loggedIn\")),u()):(t.classList.remove(\"hidden\"),n.classList.add(\"hidden\"),o.textContent=\"\"),(0,r.OR)()}async function u(){if(a.gX)try{const e=await fetch(`${s.tE}/user/orders/?venue=${s.eW}&ordering=-created&limit=50`,{headers:(0,i.H)(a.gX)}),t=await e.json();if(e.ok){const e=new Map,n=t.results||[];for(const t of n){if(9===t.order_state)continue;const n=t.date.split(\"T\")[0];for(const a of t.items||[]){const o=`${n}_${a.article}`;e.has(o)||e.set(o,[]),e.get(o).push(t.id)}}(0,a.di)(e),(0,r.OR)(),(0,r.gJ)()}}catch(e){console.error(\"Error fetching orders:\",e)}}async function g(){const e=document.getElementById(\"history-loading\"),t=document.getElementById(\"history-content\"),n=document.getElementById(\"history-progress-fill\"),o=document.getElementById(\"history-progress-text\");let r=[];if(d)r=d;else{const e=localStorage.getItem(s.LS.HISTORY_CACHE);if(e)try{r=JSON.parse(e),d=r}catch(e){console.warn(\"History cache parse error\",e)}}if(r.length>0&&m(r),!a.gX)return;0===r.length&&(t.innerHTML=\"\",e.classList.remove(\"hidden\")),n.style.width=\"0%\",o.textContent=r.length>0?(0,l.t)(\"historyLoadingDelta\"):(0,l.t)(\"historyLoadingFull\"),r.length>0&&e.classList.remove(\"hidden\");let c=r.length>0?`${s.tE}/user/orders/?venue=${s.eW}&ordering=-created&limit=5`:`${s.tE}/user/orders/?venue=${s.eW}&ordering=-created&limit=50`,u=[],g=0,h=0===r.length,p=!1;try{for(;c&&!p;){const e=await fetch(c,{headers:(0,i.H)(a.gX)});if(!e.ok)throw new Error(`Fetch failed: ${e.status}`);const t=await e.json();t.count&&0===g&&(g=t.count);const s=t.results||[];for(const e of s){const t=r.findIndex(t=>t.id===e.id);if(!h&&-1!==t){const n=r[t];if(n.updated===e.updated&&n.order_state===e.order_state){p=!0;break}}u.push(e)}if(!p&&h)if(g>0){const e=Math.round(u.length/g*100);n.style.width=`${e}%`,o.textContent=`${(0,l.t)(\"historyLoadingItem\")} ${u.length} ${(0,l.t)(\"historyLoadingOf\")} ${g}...`}else o.textContent=`${(0,l.t)(\"historyLoadingItem\")} ${u.length}...`;else p||(o.textContent=`${u.length} ${(0,l.t)(\"historyLoadingNew\")}`);c=p?null:t.next}if(u.length>0){const e=new Map(r.map(e=>[e.id,e]));for(const t of u)e.set(t.id,t);const t=Array.from(e.values());t.sort((e,t)=>new Date(t.created)-new Date(e.created)),d=t;try{localStorage.setItem(s.LS.HISTORY_CACHE,JSON.stringify(t))}catch(e){console.warn(\"History cache write error\",e)}m(d)}}catch(e){console.error(\"Error in history sync:\",e),0===r.length?t.innerHTML=`

${(0,l.t)(\"historyLoadError\")}

`:H((0,l.t)(\"bgSyncFailed\"),\"error\")}finally{e.classList.add(\"hidden\")}}function m(e){const t=document.getElementById(\"history-content\");if(!e||0===e.length)return void(t.innerHTML=`

${(0,l.t)(\"noOrders\")}

`);const n={};e.forEach(e=>{const t=new Date(e.date),s=t.getFullYear(),i=t.getMonth(),r=`${s}-${i.toString().padStart(2,\"0\")}`,l=\"en\"===a.Kl?\"en-US\":\"de-AT\",d=t.toLocaleString(l,{month:\"long\"}),c=(0,o.sn)(t);n[s]||(n[s]={year:s,months:{}}),n[s].months[r]||(n[s].months[r]={name:d,year:s,monthIndex:i,count:0,total:0,weeks:{}}),n[s].months[r].weeks[c]||(n[s].months[r].weeks[c]={label:\"en\"===a.Kl?`CW ${c}`:`KW ${c}`,items:[],count:0,total:0});(e.items||[]).forEach(t=>{const a=parseFloat(t.price||e.total||0);n[s].months[r].weeks[c].items.push({date:e.date,name:t.name||\"Men\u00fc\",price:a,state:e.order_state}),9!==e.order_state&&(n[s].months[r].weeks[c].count++,n[s].months[r].weeks[c].total+=a,n[s].months[r].count++,n[s].months[r].total+=a)})}),t.innerHTML=\"\";Object.keys(n).sort((e,t)=>t-e).forEach(e=>{const o=n[e],s=document.createElement(\"div\");s.className=\"history-year-group\";const i=document.createElement(\"h2\");i.className=\"history-year-header\",i.textContent=o.year,s.appendChild(i);Object.keys(o.months).sort((e,t)=>t.localeCompare(e)).forEach(e=>{const t=o.months[e],n=document.createElement(\"div\");n.className=\"history-month-group\";const i=document.createElement(\"div\");i.className=\"history-month-header\",i.setAttribute(\"tabindex\",\"0\"),i.setAttribute(\"role\",\"button\"),i.setAttribute(\"aria-expanded\",\"false\"),i.setAttribute(\"title\",(0,l.t)(\"historyMonthToggle\"));const r=document.createElement(\"div\");r.style.display=\"flex\",r.style.flexDirection=\"column\",r.style.gap=\"4px\";const d=document.createElement(\"span\");d.textContent=t.name,r.appendChild(d);const c=document.createElement(\"div\");c.className=\"history-month-summary\";const u=document.createElement(\"span\");u.innerHTML=`${t.count} ${(0,l.t)(\"orders\")} • \u20ac${t.total.toFixed(2)}`,c.appendChild(u),r.appendChild(c),i.appendChild(r);const g=document.createElement(\"span\");g.className=\"material-icons-round\",g.textContent=\"expand_more\",i.appendChild(g),i.addEventListener(\"click\",()=>{const e=i.parentElement;e.classList.contains(\"open\")?(e.classList.remove(\"open\"),i.setAttribute(\"aria-expanded\",\"false\")):(e.classList.add(\"open\"),i.setAttribute(\"aria-expanded\",\"true\"))}),n.appendChild(i);const m=document.createElement(\"div\");m.className=\"history-month-content\";Object.keys(t.weeks).sort((e,t)=>parseInt(t)-parseInt(e)).forEach(e=>{const n=t.weeks[e],o=document.createElement(\"div\");o.className=\"history-week-group\";const s=document.createElement(\"div\");s.className=\"history-week-header\";const i=document.createElement(\"strong\");i.textContent=n.label,s.appendChild(i);const r=document.createElement(\"span\");r.innerHTML=`${n.count} ${(0,l.t)(\"orders\")} • \u20ac${n.total.toFixed(2)}`,s.appendChild(r),o.appendChild(s),n.items.forEach(e=>{const t=new Date(e.date),n=\"en\"===a.Kl?\"en-US\":\"de-AT\",s=t.toLocaleDateString(n,{weekday:\"short\",day:\"2-digit\",month:\"2-digit\"}),i=document.createElement(\"div\");i.className=\"history-item\",9===e.state&&i.classList.add(\"history-item-cancelled\");const r=document.createElement(\"div\");r.style.fontSize=\"0.85rem\",r.style.color=\"var(--text-secondary)\",r.textContent=s,i.appendChild(r);const d=document.createElement(\"div\");d.className=\"history-item-details\";const c=document.createElement(\"span\");c.className=\"history-item-name\",c.textContent=e.name,d.appendChild(c);const u=document.createElement(\"div\"),g=document.createElement(\"span\");g.className=\"history-item-status\",9===e.state?g.textContent=(0,l.t)(\"stateCancelled\"):8===e.state?g.textContent=(0,l.t)(\"stateCompleted\"):g.textContent=(0,l.t)(\"stateTransferred\"),u.appendChild(g),d.appendChild(u),i.appendChild(d);const m=document.createElement(\"div\");m.className=\"history-item-price\",9===e.state&&m.classList.add(\"history-item-price-cancelled\"),m.textContent=`\u20ac${e.price.toFixed(2)}`,i.appendChild(m),o.appendChild(i)}),m.appendChild(o)}),n.appendChild(m),s.appendChild(n)}),t.appendChild(s)})}async function h(e,t,n,o,r){if(a.gX)try{const c=await fetch(`${s.tE}/auth/user/`,{headers:(0,i.H)(a.gX)});if(!c.ok)return void H(\"Fehler: Benutzerdaten konnten nicht geladen werden\",\"error\");const g=await c.json(),m=(new Date).toISOString(),h={uuid:crypto.randomUUID(),created:m,updated:m,order_type:7,items:[{article:t,course_group:null,modifiers:[],uuid:crypto.randomUUID(),name:n,description:r||\"\",price:String(parseFloat(o)),amount:1,vat:\"10.00\",comment:\"\"}],table:null,total:parseFloat(o),tip:0,currency:\"EUR\",venue:s.eW,states:[],order_state:1,date:`${e}T10:30:00Z`,payment_method:\"payroll\",customer:{first_name:g.first_name,last_name:g.last_name,email:g.email,newsletter:!1},preorder:!0,delivery_fee:0,cash_box_table_name:null,take_away:!1},p=await fetch(`${s.tE}/user/orders/`,{method:\"POST\",headers:(0,i.H)(a.gX),body:JSON.stringify(h)});if(p.ok||201===p.status)H(`${(0,l.t)(\"orderSuccess\")}: ${n}`,\"success\"),d=null,await u();else{const e=await p.json();H(`Fehler: ${e.detail||e.non_field_errors?.[0]||\"Bestellung fehlgeschlagen\"}`,\"error\")}}catch(e){console.error(\"Order error:\",e),H(\"Netzwerkfehler bei Bestellung\",\"error\")}}async function p(e,t,n){if(!a.gX)return;const o=`${e}_${t}`,r=a.L.get(o);if(!r||0===r.length)return;const c=r[r.length-1];try{const e=await fetch(`${s.tE}/user/orders/${c}/cancel/`,{method:\"PATCH\",headers:(0,i.H)(a.gX),body:JSON.stringify({})});if(e.ok)H(`${(0,l.t)(\"cancelSuccess\")}: ${n}`,\"success\"),d=null,await u();else{H(`Fehler: ${(await e.json()).detail||\"Stornierung fehlgeschlagen\"}`,\"error\")}}catch(e){console.error(\"Cancel error:\",e),H(\"Netzwerkfehler bei Stornierung\",\"error\")}}function f(){localStorage.setItem(\"kantine_flags\",JSON.stringify([...a.BY]))}async function v(){if(0===a.BY.size)return;const e=a.gX||s.f9,t=new Set;for(const e of a.BY){const[n]=e.split(\"_\");t.add(n)}let n=!1;const o=document.getElementById(\"alarm-bell\");o&&o.classList.add(\"refreshing\");try{for(const o of t)try{const t=await fetch(`${s.tE}/venues/${s.eW}/menu/${s.YU}/${o}/`,{headers:(0,i.H)(e)});if(!t.ok)continue;const r=(await t.json()).results||[],l=new Map;for(const e of r)if(e.items&&Array.isArray(e.items))for(const t of e.items)l.set(t.id,t);for(let e of a.p_){if(!e.days)continue;const t=e.days.find(e=>e.date===o);if(t&&t.items)for(let e=0;e0;s.available=e||t,s.availableAmount=parseInt(r.available_amount)||0,s.amountTracking=!1!==r.amount_tracking,n=!0}}}}catch(e){console.error(\"Error refreshing flag date\",o,e)}n&&B(),localStorage.setItem(\"kantine_flagged_items_last_checked\",(new Date).toISOString()),(0,r.Mb)(),(0,r.OR)(),H(`${a.BY.size} ${1===a.BY.size?(0,l.t)(\"menuSingular\"):(0,l.t)(\"menuPlural\")} ${(0,l.t)(\"menuChecked\")}`,\"info\")}finally{o&&o.classList.remove(\"refreshing\")}}function y(e,t,n,o){const s=`${e}_${t}`;let i=!1;a.BY.has(s)?(a.BY.delete(s),H(`${(0,l.t)(\"flagRemoved\")} ${n}`,\"success\")):(a.BY.add(s),i=!0,H(`${(0,l.t)(\"flagActivated\")} ${n}`,\"success\"),\"default\"===Notification.permission&&Notification.requestPermission()),f(),(0,r.Mb)(),(0,r.OR)(),i&&v()}function b(){const e=new Date,t=e.toISOString().split(\"T\")[0];let n=!1;for(const o of[...a.BY]){const[s]=o.split(\"_\");let i=!1;if(s=t&&(i=!0)}i&&(a.BY.delete(o),n=!0)}n&&f()}function w(){a.K8||a.gX&&(0,a.cc)(setInterval(()=>async function(){if(0===a.BY.size||!a.gX)return;for(const e of a.BY){const[t,n]=e.split(\"_\"),o=parseInt(n);try{const e=await fetch(`${s.tE}/venues/${s.eW}/menu/${s.YU}/${t}/`,{headers:(0,i.H)(a.gX)});if(!e.ok)continue;const n=(await e.json()).results||[];let r=null;for(const e of n)if(e.items&&(r=e.items.find(e=>e.id===o||e.article===o),r))break;if(r){if(!1===r.amount_tracking||parseInt(r.available_amount)>0){const e=r.name||\"Unbekannt\";H(`${e} ist jetzt verf\u00fcgbar!`,\"success\"),\"granted\"===Notification.permission&&new Notification(\"Kantine Wrapper\",{body:`${e} ist jetzt verf\u00fcgbar!`,icon:\"\ud83c\udf7d\ufe0f\"}),O()}}}catch(t){console.error(`Poll error for ${e}:`,t),await new Promise(e=>setTimeout(e,200))}}localStorage.setItem(\"kantine_flagged_items_last_checked\",(new Date).toISOString()),(0,r.Mb)()}(),s.fv))}function E(){a.K8&&(clearInterval(a.K8),(0,a.cc)(null))}function A(){localStorage.setItem(\"kantine_highlightTags\",JSON.stringify(a.yz)),(0,r.OR)(),(0,r.gJ)()}function k(e){if((e=e.trim().toLowerCase())&&!a.yz.includes(e)){const t=[...a.yz,e];return(0,a.iw)(t),A(),!0}return!1}function L(){const e=document.getElementById(\"tags-list\");e.innerHTML=\"\",a.yz.forEach(t=>{const n=document.createElement(\"span\");n.className=\"tag-badge\",n.innerHTML=`${t} ×`,e.appendChild(n)}),e.querySelectorAll(\".tag-remove\").forEach(e=>{e.addEventListener(\"click\",e=>{!function(e){const t=a.yz.filter(t=>t!==e);(0,a.iw)(t),A()}(e.target.dataset.tag),L()})})}function S(e){return e?(e=e.toLowerCase(),a.yz.filter(t=>e.includes(t))):[]}const I=\"kantine_menuCache\",C=\"kantine_menuCacheTs\";function B(){try{localStorage.setItem(I,JSON.stringify(a.p_)),localStorage.setItem(C,(new Date).toISOString())}catch(e){console.warn(\"Failed to cache menu data:\",e)}}function T(){try{const e=localStorage.getItem(I),t=localStorage.getItem(C);if(e){(0,a.tn)(JSON.parse(e)),(0,a.Xt)((0,o.sn)(new Date)),(0,a.pK)((new Date).getFullYear()),(0,r.OR)(),(0,r.gJ)(),(0,r.Mb)(),t&&N(t);try{const e=new Set;a.p_.forEach(t=>{(t.days||[]).forEach(t=>{(t.items||[]).forEach(t=>{let n=(t.description||\"\").replace(/\\s+/g,\" \").trim();n&&n.includes(\" / \")&&e.add(n)})})})}catch(e){}return!0}}catch(e){console.warn(\"Failed to load cached menu:\",e)}return!1}function D(){const e=localStorage.getItem(C);if(!e)return!1;if(Date.now()-new Date(e).getTime()>36e5)return!1;const t=(0,o.sn)(new Date),n=(0,o.Ao)(new Date);return a.p_.some(e=>e.weekNumber===t&&e.year===n&&e.days&&e.days.length>0)}async function O(){const e=document.getElementById(\"loading\"),t=document.getElementById(\"progress-modal\"),l=document.getElementById(\"progress-fill\"),d=document.getElementById(\"progress-percent\"),u=document.getElementById(\"progress-message\");e.classList.remove(\"hidden\");const g=a.gX||s.f9;try{t.classList.remove(\"hidden\"),u.textContent=\"Hole verf\u00fcgbare Daten...\",l.style.width=\"0%\",d.textContent=\"0%\";const e=await fetch(`${s.tE}/venues/${s.eW}/menu/dates/`,{headers:(0,i.H)(g)});if(!e.ok)throw new Error(`Failed to fetch dates: ${e.status}`);let n=(await e.json()).results||[];const m=new Date;m.setDate(m.getDate()-7);const h=m.toISOString().split(\"T\")[0];n=n.filter(e=>e.date>=h).sort((e,t)=>e.date.localeCompare(t.date)).slice(0,30);const p=n.length;u.textContent=`${p} Tage gefunden. Lade Details...`;const f=[];let v=0;const y=5;for(let e=0;e{const t=e.date;let n=null;try{const a=await fetch(`${s.tE}/venues/${s.eW}/menu/${s.YU}/${t}/`,{headers:(0,i.H)(g)});if(a.ok){const o=(await a.json()).results||[];let s=[];for(const e of o)e.items&&Array.isArray(e.items)&&(s=s.concat(e.items));s.length>0&&(n={date:t,menu_items:s,orders:e.orders||[]})}}catch(e){console.error(`Failed to fetch details for ${t}:`,e)}finally{v++;const e=Math.round(v/p*100);l.style.width=`${e}%`,d.textContent=`${e}%`,u.textContent=`Lade Men\u00fc f\u00fcr ${t}...`}return n}));for(const e of a)e&&f.push(e)}const b=new Map;a.p_&&a.p_.length>0&&a.p_.forEach(e=>{const t=`${e.year}-${e.weekNumber}`;try{b.set(t,{year:e.year,weekNumber:e.weekNumber,days:e.days?e.days.map(e=>({...e,items:e.items?[...e.items]:[]})):[]})}catch(e){console.warn(\"Error hydrating week:\",e)}});for(const e of f){const t=new Date(e.date),n=(0,o.sn)(t),a=(0,o.Ao)(t),s=`${a}-${n}`;b.has(s)||b.set(s,{year:a,weekNumber:n,days:[]});const i=b.get(s),r=t.toLocaleDateString(\"en-US\",{weekday:\"long\"}),l=new Date(e.date);l.setHours(10,0,0,0);const d={date:e.date,weekday:r,orderCutoff:l.toISOString(),items:e.menu_items.map(t=>{const n=!1===t.amount_tracking,a=parseInt(t.available_amount)>0;return{id:`${e.date}_${t.id}`,articleId:t.id,name:t.name||\"Unknown\",description:t.description||\"\",price:parseFloat(t.price)||0,available:n||a,availableAmount:parseInt(t.available_amount)||0,amountTracking:!1!==t.amount_tracking}})},c=i.days.findIndex(t=>t.date===e.date);c>=0?i.days[c]=d:i.days.push(d)}const w=Array.from(b.values()).sort((e,t)=>e.year!==t.year?e.year-t.year:e.weekNumber-t.weekNumber);w.forEach(e=>{e.days&&e.days.sort((e,t)=>e.date.localeCompare(t.date))}),(0,a.tn)(w),B(),N((new Date).toISOString()),(0,a.Xt)((0,o.sn)(new Date)),(0,a.pK)((new Date).getFullYear()),c(),(0,r.OR)(),(0,r.gJ)(),(0,r.Mb)(),u.textContent=\"Fertig!\",setTimeout(()=>t.classList.add(\"hidden\"),500)}catch(e){console.error(\"Error fetching menu:\",e),t.classList.add(\"hidden\"),Promise.resolve().then(n.bind(n,842)).then(t=>{t.showErrorModal(\"Keine Verbindung\",`Die Men\u00fcdaten konnten nicht geladen werden. M\u00f6glicherweise besteht keine Verbindung zur API oder zur Bessa-Webseite.

${(0,o.ZD)(e.message)}`,\"Zur Original-Seite\",\"https://web.bessa.app/knapp-kantine\")})}finally{e.classList.add(\"hidden\")}}let M=null,x=null;function N(e){const t=document.getElementById(\"last-updated-subtitle\");if(e){M=e,localStorage.setItem(\"kantine_last_updated\",e),localStorage.setItem(\"kantine_last_checked\",e);try{const n=new Date(e),a=n.toLocaleTimeString(\"de-DE\",{hour:\"2-digit\",minute:\"2-digit\"}),s=n.toLocaleDateString(\"de-DE\",{day:\"2-digit\",month:\"2-digit\"}),i=(0,o.gs)(n);t.textContent=`Aktualisiert: ${s} ${a} (${i})`}catch(e){t.textContent=\"\"}x||(x=setInterval(()=>{M&&(N(M),(0,r.Mb)())},6e4))}}function H(e,t=\"info\"){let n=document.getElementById(\"toast-container\");n||(n=document.createElement(\"div\"),n.id=\"toast-container\",document.body.appendChild(n));const a=document.createElement(\"div\");a.className=`toast toast-${t}`;const s=\"success\"===t?\"check_circle\":\"error\"===t?\"error\":\"info\";a.innerHTML=`${s}${(0,o.ZD)(e)}`,n.appendChild(a),requestAnimationFrame(()=>a.classList.add(\"show\")),setTimeout(()=>{a.classList.remove(\"show\"),setTimeout(()=>a.remove(),300)},3e3)}},672(e,t,n){n.d(t,{H:()=>o,O:()=>s});var a=n(521);function o(e){return{Authorization:`Token ${e||a.f9}`,Accept:\"application/json\",\"Content-Type\":\"application/json\",\"X-Client-Version\":a.fZ}}function s(){return{Accept:\"application/vnd.github.v3+json\"}}},521(e,t,n){n.d(t,{LS:()=>g,YU:()=>r,d_:()=>u,eW:()=>i,f9:()=>o,fZ:()=>s,fv:()=>l,pe:()=>c,tE:()=>a});const a=\"https://api.bessa.app/v1\",o=\"c3418725e95a9f90e3645cbc846b4d67c7c66131\",s=\"v1.6.17\",i=591,r=7,l=3e5,d=\"TauNeutrino/kantine-overview\",c=`https://api.github.com/repos/${d}`,u=`https://htmlpreview.github.io/?https://github.com/${d}/blob`,g={AUTH_TOKEN:\"kantine_authToken\",CURRENT_USER:\"kantine_currentUser\",FIRST_NAME:\"kantine_firstName\",LAST_NAME:\"kantine_lastName\",LANG:\"kantine_lang\",FLAGS:\"kantine_flags\",FLAGGED_LAST_CHECKED:\"kantine_flagged_items_last_checked\",LAST_CHECKED:\"kantine_last_checked\",MENU_CACHE:\"kantine_menuCache\",MENU_CACHE_TS:\"kantine_menuCacheTs\",HISTORY_CACHE:\"kantine_history_cache\",HIGHLIGHT_TAGS:\"kantine_highlightTags\",LAST_UPDATED:\"kantine_last_updated\",VERSION_CACHE:\"kantine_version_cache\",DEV_MODE:\"kantine_dev_mode\"}},646(e,t,n){n.d(t,{t:()=>s});var a=n(901);const o={de:{thisWeek:\"Diese Woche\",nextWeek:\"N\u00e4chste Woche\",nextWeekTooltipDefault:\"Men\u00fc n\u00e4chster Woche anzeigen\",thisWeekTooltip:\"Men\u00fc dieser Woche anzeigen\",appTitle:\"Kantinen \u00dcbersicht\",updatedAt:\"Aktualisiert\",langTooltip:\"Sprache der Men\u00fcbeschreibung\",weekLabel:\"Woche\",refresh:\"Men\u00fcdaten neu laden\",history:\"Bestellhistorie\",highlights:\"Pers\u00f6nliche Highlights verwalten\",themeTooltip:\"Erscheinungsbild (Hell/Dunkel) wechseln\",login:\"Anmelden\",loginTooltip:\"Mit Bessa.app Account anmelden\",logout:\"Abmelden\",logoutTooltip:\"Von Bessa.app abmelden\",loginTitle:\"Login\",employeeId:\"Mitarbeiternummer\",employeeIdPlaceholder:\"z.B. 2041\",employeeIdHelp:\"Deine offizielle Knapp Mitarbeiternummer.\",password:\"Passwort\",passwordPlaceholder:\"Bessa Passwort\",passwordHelp:\"Das Passwort f\u00fcr deinen Bessa Account.\",loginButton:\"Einloggen\",loggingIn:\"Wird eingeloggt...\",highlightsTitle:\"Meine Highlights\",highlightsDesc:\"Markiere Men\u00fcs automatisch, wenn sie diese Schlagw\u00f6rter enthalten.\",tagInputPlaceholder:\"z.B. Schnitzel, Vegetarisch...\",tagInputTooltip:\"Neues Schlagwort zum Hervorheben eingeben\",addTag:\"Hinzuf\u00fcgen\",addTagTooltip:\"Schlagwort zur Liste hinzuf\u00fcgen\",removeTagTooltip:\"Schlagwort entfernen\",historyTitle:\"Bestellhistorie\",loadingHistory:\"Lade Historie...\",noOrders:\"Keine Bestellungen gefunden.\",orders:\"Bestellungen\",historyMonthToggle:\"Klicken, um die Bestellungen f\u00fcr diesen Monat ein-/auszublenden\",available:\"Verf\u00fcgbar\",soldOut:\"Ausverkauft\",ordered:\"Bestellt\",orderButton:\"Bestellen\",orderAgainTooltip:\"nochmal bestellen\",orderTooltip:\"bestellen\",cancelOrder:\"Bestellung stornieren\",cancelOneOrder:\"Eine Bestellung stornieren\",flagActivate:\"Benachrichtigen wenn verf\u00fcgbar\",flagDeactivate:\"Benachrichtigung deaktivieren\",alarmTooltipNone:\"Keine beobachteten Men\u00fcs\",alarmLastChecked:\"Zuletzt gepr\u00fcft\",versionsTitle:\"\ud83d\udce6 Versionen\",currentVersion:\"Aktuell\",devModeLabel:\"Dev-Mode (alle Tags anzeigen)\",loadingVersions:\"Lade Versionen...\",noVersions:\"Keine Versionen gefunden.\",installed:\"\u2713 Installiert\",newVersion:\"\u2b06 Neu!\",installLink:\"Installieren\",reportBug:\"Fehler melden\",reportBugTooltip:\"Melde einen Fehler auf GitHub\",featureRequest:\"Feature vorschlagen\",featureRequestTooltip:\"Schlage ein neues Feature auf GitHub vor\",clearCache:\"Lokalen Cache leeren\",clearCacheTooltip:\"L\u00f6scht alle lokalen Daten & erzwingt einen Neuladen\",clearCacheConfirm:\"M\u00f6chtest du wirklich alle lokalen Daten (inkl. Login-Session, Cache und Einstellungen) l\u00f6schen? Die Seite wird danach neu geladen.\",versionMenuTooltip:\"Klick f\u00fcr Versionsmen\u00fc\",progressTitle:\"Men\u00fcdaten aktualisieren\",progressInit:\"Initialisierung...\",noMenuData:\"Keine Men\u00fcdaten f\u00fcr KW\",noMenuDataHint:\"Versuchen Sie eine andere Woche oder schauen Sie sp\u00e4ter vorbei.\",costLabel:\"Gesamt\",orderDeadline:\"Bestellschluss\",flagRemoved:\"Flag entfernt f\u00fcr\",flagActivated:\"Benachrichtigung aktiviert f\u00fcr\",menuChecked:\"gepr\u00fcft\",menuSingular:\"Men\u00fc\",menuPlural:\"Men\u00fcs\",newMenuDataAvailable:\"Neue Men\u00fcdaten f\u00fcr n\u00e4chste Woche verf\u00fcgbar!\",orderSuccess:\"Bestellt\",cancelSuccess:\"Storniert\",bgSyncFailed:\"Hintergrund-Synchronisation fehlgeschlagen\",historyLoadError:\"Fehler beim Laden der Historie.\",historyLoadingFull:\"Lade Bestellhistorie...\",historyLoadingDelta:\"Suche nach neuen Bestellungen...\",historyLoadingItem:\"Lade Bestellung\",historyLoadingOf:\"von\",historyLoadingNew:\"neue/ge\u00e4nderte Bestellungen gefunden...\",badgeOrdered:\"bestellt\",badgeOrderable:\"bestellbar\",badgeTotal:\"gesamt\",badgeHighlights:\"Highlights gefunden\",stateCancelled:\"Storniert\",stateCompleted:\"Abgeschlossen\",stateTransferred:\"\u00dcbertragen\",close:\"Schlie\u00dfen\",noConnection:\"Keine Verbindung\",toOriginalPage:\"Zur Original-Seite\",loggedIn:\"Angemeldet\"},en:{thisWeek:\"This Week\",nextWeek:\"Next Week\",nextWeekTooltipDefault:\"Show next week's menu\",thisWeekTooltip:\"Show this week's menu\",appTitle:\"Canteen Overview\",updatedAt:\"Updated\",langTooltip:\"Menu description language\",weekLabel:\"Week\",refresh:\"Reload menu data\",history:\"Order history\",highlights:\"Manage personal highlights\",themeTooltip:\"Toggle appearance (Light/Dark)\",login:\"Sign in\",loginTooltip:\"Sign in with Bessa.app account\",logout:\"Sign out\",logoutTooltip:\"Sign out from Bessa.app\",loginTitle:\"Login\",employeeId:\"Employee ID\",employeeIdPlaceholder:\"e.g. 2041\",employeeIdHelp:\"Your official Knapp employee number.\",password:\"Password\",passwordPlaceholder:\"Bessa password\",passwordHelp:\"The password for your Bessa account.\",loginButton:\"Log in\",loggingIn:\"Logging in...\",highlightsTitle:\"My Highlights\",highlightsDesc:\"Automatically highlight menus containing these keywords.\",tagInputPlaceholder:\"e.g. Schnitzel, Vegetarian...\",tagInputTooltip:\"Enter new keyword to highlight\",addTag:\"Add\",addTagTooltip:\"Add keyword to list\",removeTagTooltip:\"Remove keyword\",historyTitle:\"Order History\",loadingHistory:\"Loading history...\",noOrders:\"No orders found.\",orders:\"Orders\",historyMonthToggle:\"Click to expand/collapse orders for this month\",available:\"Available\",soldOut:\"Sold out\",ordered:\"Ordered\",orderButton:\"Order\",orderAgainTooltip:\"order again\",orderTooltip:\"order\",cancelOrder:\"Cancel order\",cancelOneOrder:\"Cancel one order\",flagActivate:\"Notify when available\",flagDeactivate:\"Deactivate notification\",alarmTooltipNone:\"No flagged menus\",alarmLastChecked:\"Last checked\",versionsTitle:\"\ud83d\udce6 Versions\",currentVersion:\"Current\",devModeLabel:\"Dev mode (show all tags)\",loadingVersions:\"Loading versions...\",noVersions:\"No versions found.\",installed:\"\u2713 Installed\",newVersion:\"\u2b06 New!\",installLink:\"Install\",reportBug:\"Report a bug\",reportBugTooltip:\"Report a bug on GitHub\",featureRequest:\"Request a feature\",featureRequestTooltip:\"Suggest a new feature on GitHub\",clearCache:\"Clear local cache\",clearCacheTooltip:\"Deletes all local data & forces a reload\",clearCacheConfirm:\"Do you really want to delete all local data (including login session, cache, and settings)? The page will reload afterwards.\",versionMenuTooltip:\"Click for version menu\",progressTitle:\"Updating menu data\",progressInit:\"Initializing...\",noMenuData:\"No menu data for CW\",noMenuDataHint:\"Try another week or check back later.\",costLabel:\"Total\",orderDeadline:\"Order deadline\",flagRemoved:\"Flag removed for\",flagActivated:\"Notification activated for\",menuChecked:\"checked\",menuSingular:\"menu\",menuPlural:\"menus\",newMenuDataAvailable:\"New menu data available for next week!\",orderSuccess:\"Ordered\",cancelSuccess:\"Cancelled\",bgSyncFailed:\"Background synchronisation failed\",historyLoadError:\"Error loading history.\",historyLoadingFull:\"Loading order history...\",historyLoadingDelta:\"Checking for new orders...\",historyLoadingItem:\"Loading order\",historyLoadingOf:\"of\",historyLoadingNew:\"new/updated orders found...\",badgeOrdered:\"ordered\",badgeOrderable:\"orderable\",badgeTotal:\"total\",badgeHighlights:\"highlights found\",stateCancelled:\"Cancelled\",stateCompleted:\"Completed\",stateTransferred:\"Transferred\",close:\"Close\",noConnection:\"No connection\",toOriginalPage:\"Go to original page\",loggedIn:\"Logged in\"}};function s(e){const t=\"en\"===a.Kl?\"en\":\"de\";return o[t][e]||o.de[e]||e}},901(e,t,n){n.d(t,{BT:()=>i,BY:()=>g,K8:()=>m,Kl:()=>h,L:()=>u,Ny:()=>c,O5:()=>b,UD:()=>S,Xt:()=>v,cc:()=>A,di:()=>E,gX:()=>d,iw:()=>k,lt:()=>w,pK:()=>y,p_:()=>s,qo:()=>L,sw:()=>l,tn:()=>f,vW:()=>r,yz:()=>p});var a=n(413),o=n(521);let s=[],i=(0,a.sn)(new Date),r=(new Date).getFullYear(),l=\"this-week\",d=localStorage.getItem(o.LS.AUTH_TOKEN),c=localStorage.getItem(o.LS.CURRENT_USER),u=new Map,g=new Set(JSON.parse(localStorage.getItem(o.LS.FLAGS)||\"[]\")),m=null,h=localStorage.getItem(o.LS.LANG)||\"de\",p=JSON.parse(localStorage.getItem(o.LS.HIGHLIGHT_TAGS)||\"[]\");function f(e){s=e}function v(e){i=e}function y(e){r=e}function b(e){d=e}function w(e){c=e}function E(e){u=e}function A(e){m=e}function k(e){p=e}function L(e){\"this-week\"===e||\"next-week\"===e?l=e:console.warn(`[state] Invalid displayMode: \"${e}\". Ignoring.`)}function S(e){[\"de\",\"en\",\"all\"].includes(e)?h=e:console.warn(`[state] Invalid langMode: \"${e}\". Ignoring.`)}},842(e,t,n){n.d(t,{Gk:()=>m,Mb:()=>v,OR:()=>c,Ux:()=>g,gJ:()=>d,showErrorModal:()=>f});var a=n(901),o=n(413),s=n(521),i=n(672),r=n(367),l=n(646);function d(){const e=document.getElementById(\"btn-next-week\");let t=a.BT+1,n=a.vW;t>52&&(t=1,n++);const o=a.p_.find(e=>e.weekNumber===t&&e.year===n);let s=0,i=0,d=0,c=0;o&&o.days&&o.days.forEach(e=>{if(e.items&&e.items.length>0){s++;const t=e.items.some(e=>e.available);t&&i++;let n=!1;e.items.forEach(t=>{const o=t.articleId||parseInt(t.id.split(\"_\")[1]),s=`${e.date}_${o}`;a.L.has(s)&&a.L.get(s).length>0&&(n=!0)}),n&&d++;const o=new Date(e.date).getDay();o>=1&&o<=4&&t&&!n&&c++}});const u=e.querySelector(\".nav-badge\");if(u&&u.remove(),s>0){let a=0;o&&o.days&&o.days.forEach(e=>{e.items.forEach(e=>{const t=(0,r.BM)(e.name),n=(0,r.BM)(e.description);(t.length>0||n.length>0)&&a++})});let u=[`${d} ${(0,l.t)(\"badgeOrdered\")} / ${i} ${(0,l.t)(\"badgeOrderable\")} / ${s} ${(0,l.t)(\"badgeTotal\")}`];if(a>0&&u.push(`${a} ${(0,l.t)(\"badgeHighlights\")}`),e.title=u.join(\" \u2022 \"),c>0){e.classList.add(\"new-week-available\");const a=`kantine_notified_nextweek_${n}_${t}`;localStorage.getItem(a)||(localStorage.setItem(a,\"true\"),(0,r.P0)((0,l.t)(\"newMenuDataAvailable\"),\"info\"))}else e.classList.remove(\"new-week-available\")}else e.title=(0,l.t)(\"nextWeekTooltipDefault\"),e.classList.remove(\"new-week-available\")}function c(){const e=document.getElementById(\"menu-container\");if(!e)return;e.innerHTML=\"\";let t=a.BT,n=a.vW;\"next-week\"===a.sw&&(t++,t>52&&(t=1,n++));const s=a.p_.flatMap(e=>e.days||[]).filter(e=>{const a=new Date(e.date);return(0,o.sn)(a)===t&&(0,o.Ao)(a)===n});if(0===s.length)return e.innerHTML=`\\n
\\n

${(0,l.t)(\"noMenuData\")} ${t} (${n}).

\\n ${(0,l.t)(\"noMenuDataHint\")}\\n
`,void document.getElementById(\"weekly-cost-display\").classList.add(\"hidden\");!function(e){let t=0;e&&e.length>0&&e.forEach(e=>{e.items&&e.items.forEach(n=>{const o=n.articleId||parseInt(n.id.split(\"_\")[1]),s=`${e.date}_${o}`,i=a.L.get(s)||[];i.length>0&&(t+=n.price*i.length)})});const n=document.getElementById(\"weekly-cost-display\");t>0?(n.innerHTML=`shopping_bag ${(0,l.t)(\"costLabel\")}: ${t.toFixed(2).replace(\".\",\",\")} \u20ac`,n.classList.remove(\"hidden\")):n.classList.add(\"hidden\")}(s);const i=document.getElementById(\"header-week-info\"),d=\"this-week\"===a.sw?(0,l.t)(\"thisWeek\"):(0,l.t)(\"nextWeek\");i.innerHTML=`\\n
${d}
\\n
${(0,l.t)(\"weekLabel\")} ${t} \u2022 ${n}
`;const c=document.createElement(\"div\");c.className=\"days-grid\",s.sort((e,t)=>e.date.localeCompare(t.date));s.filter(e=>{const t=new Date(e.date).getDay();return 0!==t&&6!==t}).forEach(e=>{const t=function(e){if(!e.items||0===e.items.length)return null;const t=document.createElement(\"div\");t.className=\"menu-card\";const n=new Date,s=new Date(e.date);let i=!1;if(e.orderCutoff)i=n>=new Date(e.orderCutoff);else{const t=new Date;t.setHours(0,0,0,0);const n=new Date(e.date);n.setHours(0,0,0,0),i=n{const n=t.articleId||parseInt(t.id.split(\"_\")[1]),o=`${e.date}_${n}`,s=(a.L.get(o)||[]).length;if(s>0){const e=t.name.match(/([M][1-9][Ff]?)/);if(e){let t=e[1];s>1&&(t+=\"+\"),d.push(t)}}});const c=document.createElement(\"div\");c.className=\"card-header\";const u=s.toLocaleDateString(\"de-DE\",{day:\"2-digit\",month:\"2-digit\"}),g=d.reduce((e,t)=>e+`${t}`,\"\");let m=\"\";const h=e.items&&e.items.some(t=>{const n=t.articleId||parseInt(t.id.split(\"_\")[1]),o=`${e.date}_${n}`;return a.L.has(o)&&a.L.get(o).length>0}),p=e.items&&e.items.some(e=>e.available);m=h?\"header-violet\":p&&!i?\"header-green\":\"header-red\";m&&c.classList.add(m);c.innerHTML=`\\n
\\n ${(0,o.FS)(e.weekday)}\\n
${g}
\\n
\\n ${u}`,t.appendChild(c);const f=document.createElement(\"div\");f.className=\"card-body\";const v=(new Date).toISOString().split(\"T\")[0],y=e.date===v,b=[...e.items].sort((t,n)=>{if(y){const o=t.articleId||parseInt(t.id.split(\"_\")[1]),s=n.articleId||parseInt(n.id.split(\"_\")[1]),i=a.L.has(`${e.date}_${o}`),r=a.L.has(`${e.date}_${s}`);if(i&&!r)return-1;if(!i&&r)return 1}return t.name.localeCompare(n.name)});return b.forEach(t=>{const s=document.createElement(\"div\");s.className=\"menu-item\";const d=t.articleId||parseInt(t.id.split(\"_\")[1]),c=`${e.date}_${d}`,u=(a.L.get(c)||[]).length;let g=\"\";g=t.available?t.amountTracking?`${(0,l.t)(\"available\")} (${t.availableAmount})`:`${(0,l.t)(\"available\")}`:`${(0,l.t)(\"soldOut\")}`;let m=\"\";if(u>0){const t=u>1?`${u}`:\"\";m=`check_circle ${(0,l.t)(\"ordered\")}${t}`,s.classList.add(\"ordered\"),new Date(e.date).toDateString()===n.toDateString()&&s.classList.add(\"today-ordered\")}const h=`${e.date}_${d}`,p=a.BY.has(h);p&&s.classList.add(t.available?\"flagged-available\":\"flagged-sold-out\");const v=[...new Set([...(0,r.BM)(t.name),...(0,r.BM)(t.description)])];v.length>0&&s.classList.add(\"highlight-glow\");let y=\"\",b=\"\",w=\"\";if(a.gX&&!i){const n=p?\"notifications_active\":\"notifications_none\",a=p?\"btn-flag active\":\"btn-flag\",s=p?(0,l.t)(\"flagDeactivate\"):(0,l.t)(\"flagActivate\");if(t.available&&!p||(w=``),t.available&&(y=u>0?``:``),u>0){const n=1===u?\"close\":\"remove\",a=1===u?(0,l.t)(\"cancelOrder\"):(0,l.t)(\"cancelOneOrder\");b=``}}let E=\"\";if(v.length>0){E=`
${v.reduce((e,t)=>e+`star${(0,o.ZD)(t)}`,\"\")}
`}s.innerHTML=`\\n
\\n ${(0,o.ZD)(t.name)}\\n ${t.price.toFixed(2)} \u20ac\\n
\\n
\\n ${m}\\n ${b}\\n ${y}\\n ${w}\\n
${g}
\\n
\\n ${E}\\n

${(0,o.ZD)((0,o.PC)(t.description))}

`;const A=s.querySelector(\".btn-order\");A&&A.addEventListener(\"click\",e=>{e.stopPropagation();const t=e.currentTarget;t.disabled=!0,t.classList.add(\"loading\"),(0,r.wH)(t.dataset.date,parseInt(t.dataset.article),t.dataset.name,parseFloat(t.dataset.price),t.dataset.desc||\"\").finally(()=>{t.disabled=!1,t.classList.remove(\"loading\")})});const k=s.querySelector(\".btn-cancel\");k&&k.addEventListener(\"click\",e=>{e.stopPropagation();const t=e.currentTarget;t.disabled=!0,(0,r.N4)(t.dataset.date,parseInt(t.dataset.article),t.dataset.name).finally(()=>{t.disabled=!1})});const L=s.querySelector(\".btn-flag\");L&&L.addEventListener(\"click\",e=>{e.stopPropagation();const t=e.currentTarget;(0,r.PQ)(t.dataset.date,parseInt(t.dataset.article),t.dataset.name,t.dataset.cutoff)}),f.appendChild(s)}),t.appendChild(f),t}(e);t&&c.appendChild(t)}),e.appendChild(c),setTimeout(()=>function(e){const t=e.querySelectorAll(\".menu-card\");if(0===t.length)return;let n=0;t.forEach(e=>{n=Math.max(n,e.querySelectorAll(\".menu-item\").length)});for(let e=0;e{const o=t.querySelectorAll(\".menu-item\");o[e]&&(o[e].style.height=\"auto\",n=Math.max(n,o[e].offsetHeight),a.push(o[e]))}),a.forEach(e=>{e.style.height=`${n}px`})}}(c),0)}async function u(e){const t=e?`${s.pe}/tags?per_page=20`:`${s.pe}/releases?per_page=20`,n=await fetch(t,{headers:(0,i.O)()});if(!n.ok){if(403===n.status)throw new Error(\"API Rate Limit erreicht (403). Bitte sp\u00e4ter erneut versuchen.\");throw new Error(`GitHub API ${n.status}`)}return(await n.json()).map(t=>{const n=e?t.name:t.tag_name;return{tag:n,name:e?n:t.name||n,url:`${s.d_}/${n}/dist/install.html`,body:t.body||\"\"}})}async function g(){const e=\"true\"===localStorage.getItem(s.LS.DEV_MODE);try{const t=await u(e);if(!t.length)return;localStorage.setItem(s.LS.VERSION_CACHE,JSON.stringify({timestamp:Date.now(),devMode:e,versions:t}));const n=t[0].tag;if(!(0,o.U4)(n,\"v1.6.17\"))return;const a=document.querySelector(\".header-left h1\");if(a&&!a.querySelector(\".update-icon\")){const e=document.createElement(\"a\");e.className=\"update-icon\",e.href=t[0].url,e.target=\"_blank\",e.innerHTML=\"\ud83c\udd95\",e.title=`Update: ${n} \u2014 Klick zum Installieren`,e.style.cssText=\"margin-left:8px;font-size:1em;text-decoration:none;cursor:pointer;vertical-align:middle;\",a.appendChild(e)}}catch(e){console.warn(\"[Kantine] Version check failed:\",e)}}function m(){const e=document.getElementById(\"version-modal\"),t=document.getElementById(\"version-list-container\"),n=document.getElementById(\"dev-mode-toggle\"),a=\"v1.6.17\";if(!e)return;e.classList.remove(\"hidden\");const i=document.getElementById(\"version-current\");i&&(i.textContent=a);const r=\"true\"===localStorage.getItem(s.LS.DEV_MODE);async function l(e){const i=n.checked;function r(e){if(!e||!e.length)return void(t.innerHTML='

Keine Versionen gefunden.

');t.innerHTML='
    ';const n=t.querySelector(\".version-list\");e.forEach(e=>{const t=e.tag===a,s=(0,o.U4)(e.tag,a),i=document.createElement(\"li\");i.className=\"version-item\"+(t?\" current\":\"\");let r=\"\";t?r='\u2713 Installiert':s&&(r='\u2b06 Neu!');let l=\"\";t||(l=`Installieren`),i.innerHTML=`\\n
    \\n ${(0,o.ZD)(e.tag)}\\n ${r}\\n
    \\n ${l}\\n `,n.appendChild(i)})}t.innerHTML='

    Lade Versionen...

    ';try{const e=localStorage.getItem(s.LS.VERSION_CACHE);let t=null;if(e)try{t=JSON.parse(e)}catch(e){}t&&t.devMode===i&&t.versions&&r(t.versions);const n=await u(i),a=JSON.stringify(n);a!==(t?JSON.stringify(t.versions):\"\")&&(localStorage.setItem(s.LS.VERSION_CACHE,JSON.stringify({timestamp:Date.now(),devMode:i,versions:n})),r(n))}catch(e){t.innerHTML=`

    Fehler: ${(0,o.ZD)(e.message)}

    `}}n.checked=r,l(),n.onchange=()=>{localStorage.setItem(s.LS.DEV_MODE,n.checked),localStorage.removeItem(s.LS.VERSION_CACHE),l()}}function h(){if(!a.gX||!a.Ny)return void p();const e=new Date,t=e.getDay();if(0===t||6===t)return void p();const n=e.toISOString().split(\"T\")[0];let o=!1;for(const e of a.L.keys())if(e.startsWith(n)){o=!0;break}if(o)return void p();const s=new Date;s.setHours(10,0,0,0);const i=s-e;if(i<=0)return void p();const r=Math.floor(i/36e5),d=Math.floor(i%36e5/6e4),c=document.querySelector(\".header-center-wrapper\");if(!c)return;let u=document.getElementById(\"order-countdown\");if(u||(u=document.createElement(\"div\"),u.id=\"order-countdown\",c.insertBefore(u,c.firstChild)),u.innerHTML=`${(0,l.t)(\"orderDeadline\")}: ${r}h ${d}m`,i<36e5){u.classList.add(\"urgent\");const e=`kantine_notified_${n}`;localStorage.getItem(e)||(\"granted\"===Notification.permission?new Notification(\"Kantine: Bestellschluss naht!\",{body:\"Du hast heute noch nichts bestellt. Nur noch 1 Stunde!\",icon:\"\u23f3\"}):\"default\"===Notification.permission&&Notification.requestPermission(),localStorage.setItem(e,\"true\"))}else u.classList.remove(\"urgent\")}function p(){const e=document.getElementById(\"order-countdown\");e&&e.remove()}function f(e,t,n,a){const s=\"error-modal\";let i=document.getElementById(s);i&&i.remove(),i=document.createElement(\"div\"),i.id=s,i.className=\"modal hidden\",i.innerHTML=`\\n
    \\n
    \\n

    \\n signal_wifi_off\\n ${(0,o.ZD)(e)}\\n

    \\n
    \\n
    \\n

    ${t}

    \\n
    \\n \\n
    \\n
    \\n
    \\n `,document.body.appendChild(i),document.getElementById(\"btn-error-redirect\").addEventListener(\"click\",()=>{window.location.href=a}),requestAnimationFrame(()=>{i.classList.remove(\"hidden\")})}function v(){const e=document.getElementById(\"alarm-bell\"),t=document.getElementById(\"alarm-bell-icon\");if(!e||!t)return;if(0===a.BY.size)return e.classList.add(\"hidden\"),e.style.display=\"none\",t.style.color=\"var(--text-secondary)\",void(t.style.textShadow=\"none\");e.classList.remove(\"hidden\"),e.style.display=\"inline-flex\";let n=!1;for(const e of a.p_)if(e.days){for(const t of e.days)if(t.items){for(const e of t.items)if(e.available&&a.BY.has(e.id)){n=!0;break}if(n)break}if(n)break}const i=localStorage.getItem(s.LS.LAST_CHECKED),r=localStorage.getItem(s.LS.FLAGGED_LAST_CHECKED);let d=0;i&&(d=Math.max(d,new Date(i).getTime())),r&&(d=Math.max(d,new Date(r).getTime()));let c=\"gerade eben\";if(0===d){const e=(new Date).toISOString();localStorage.setItem(s.LS.LAST_CHECKED,e),d=new Date(e).getTime()}c=(0,o.gs)(new Date(d)),e.title=`${(0,l.t)(\"alarmLastChecked\")}: ${c}`,n?(t.style.color=\"#10b981\",t.style.textShadow=\"0 0 10px rgba(16, 185, 129, 0.4)\"):(t.style.color=\"#f59e0b\",t.style.textShadow=\"0 0 10px rgba(245, 158, 11, 0.4)\")}setInterval(h,6e4),setTimeout(h,1e3)},413(e,t,n){n.d(t,{Ao:()=>s,FS:()=>i,PC:()=>g,U4:()=>l,ZD:()=>r,gs:()=>d,sn:()=>o});var a=n(901);function o(e){const t=new Date(Date.UTC(e.getFullYear(),e.getMonth(),e.getDate())),n=t.getUTCDay()||7;t.setUTCDate(t.getUTCDate()+4-n);const a=new Date(Date.UTC(t.getUTCFullYear(),0,1));return Math.ceil(((t-a)/864e5+1)/7)}function s(e){const t=new Date(e.getTime());return t.setDate(t.getDate()+3-(t.getDay()+6)%7),t.getFullYear()}function i(e){if(\"en\"===a.Kl)return e;return{Monday:\"Montag\",Tuesday:\"Dienstag\",Wednesday:\"Mittwoch\",Thursday:\"Donnerstag\",Friday:\"Freitag\",Saturday:\"Samstag\",Sunday:\"Sonntag\"}[e]||e}function r(e){const t=document.createElement(\"div\");return t.textContent=e||\"\",t.innerHTML}function l(e,t){if(!e||!t)return!1;const n=e.replace(/^v/,\"\").split(\".\").map(Number),a=t.replace(/^v/,\"\").split(\".\").map(Number);for(let e=0;e(a[e]||0))return!0;if((n[e]||0)<(a[e]||0))return!1}return!1}function d(e){const t=Date.now()-e.getTime(),n=Math.floor(t/6e4);if(n<1)return\"gerade eben\";if(1===n)return\"vor 1 min.\";if(n<60)return`vor ${n} min.`;const a=Math.floor(n/60);return 1===a?\"vor 1 Std.\":`vor ${a} Std.`}const c=[\"apfel\",\"achtung\",\"aubergine\",\"auflauf\",\"beere\",\"blumenkohl\",\"bohne\",\"braten\",\"brokkoli\",\"brot\",\"brust\",\"br\u00f6tchen\",\"butter\",\"chili\",\"dessert\",\"dip\",\"eier\",\"eintopf\",\"eis\",\"erbse\",\"erdbeer\",\"essig\",\"filet\",\"fisch\",\"fisole\",\"fleckerl\",\"fleisch\",\"fl\u00fcgel\",\"frucht\",\"f\u00fcr\",\"gebraten\",\"gem\u00fcse\",\"gew\u00fcrz\",\"gratin\",\"grie\u00df\",\"gulasch\",\"gurke\",\"himbeer\",\"honig\",\"huhn\",\"h\u00e4hnchen\",\"jambalaya\",\"joghurt\",\"karotte\",\"kartoffel\",\"keule\",\"kirsch\",\"knacker\",\"knoblauch\",\"kn\u00f6del\",\"kompott\",\"kraut\",\"kr\u00e4uter\",\"kuchen\",\"k\u00e4se\",\"k\u00fcrbis\",\"lauch\",\"mandel\",\"milch\",\"mild\",\"mit\",\"mohn\",\"most\",\"m\u00f6hre\",\"natur\",\"nockerl\",\"nudel\",\"nuss\",\"nu\u00df\",\"obst\",\"oder\",\"olive\",\"paprika\",\"pfanne\",\"pfannkuchen\",\"pfeffer\",\"pikant\",\"pilz\",\"plunder\",\"p\u00fcree\",\"ragout\",\"rahm\",\"reis\",\"rind\",\"sahne\",\"salami\",\"salat\",\"salz\",\"sauer\",\"scharf\",\"schinken\",\"schnitte\",\"schnitzel\",\"schoko\",\"schupf\",\"schwein\",\"sellerie\",\"senf\",\"sosse\",\"so\u00dfe\",\"spargel\",\"sp\u00e4tzle\",\"speck\",\"spie\u00df\",\"spinat\",\"steak\",\"suppe\",\"s\u00fc\u00df\",\"tofu\",\"tomate\",\"topfen\",\"torte\",\"tr\u00fcffel\",\"und\",\"vanille\",\"vogerl\",\"vom\",\"wien\",\"wurst\",\"zucchini\",\"zum\",\"zur\",\"zwiebel\",\"\u00f6l\"],u=[\"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 g(e){if(\"all\"===a.Kl)return e||\"\";const t=function(e){if(!e)return{de:\"\",en:\"\",raw:\"\"};let t=e.replace(/(?:\\(|(?:\\/|\\s|^))([A-Z,]+)\\)\\s*(?=\\S)(?!\\s*\\/)/g,\"($1)\\n\u2022 \");function n(e){let t=0,n=0;return e.forEach(e=>{const a=e.toLowerCase().replace(/[^a-z\u00e4\u00f6\u00fc\u00df]/g,\"\");if(a){let o=0,s=0;c.includes(a)?o=a.length:c.forEach(e=>{a.includes(e)&&e.length>o&&(o=e.length)}),u.includes(a)?s=a.length:u.forEach(e=>{a.includes(e)&&e.length>s&&(s=e.length)}),o>0&&(t+=o/a.length),s>0&&(n+=s/a.length),/^[A-Z\u00c4\u00d6\u00dc]/.test(e)&&(t+=.5)}}),{de:t,en:n}}function a(e){const t=e.trim().split(/\\s+/);if(t.length<2)return{enPart:e,nextDe:\"\"};let a=-1,o=-9999;for(let e=1;er.de||r.en>0,m=l.de+c>l.en;g&&m&&u>o&&(o=u,a=e)}return-1!==a?{enPart:t.slice(0,a).join(\" \"),nextDe:t.slice(a).join(\" \")}:{enPart:e,nextDe:\"\"}}t.startsWith(\"\u2022 \")||(t=\"\u2022 \"+t);const o=/(.*?)(?:\\(|(?:\\/|\\s|^))([A-Z,]+)\\)\\s*(?!\\s*[/])/g;let s;const i=[];let r=0;for(;null!==(s=o.exec(e));)s.index>r&&i.push(e.substring(r,s.index).trim()),i.push(s[0].trim()),r=o.lastIndex;r=2){const e=i[0].trim();let t=i.slice(1).join(\" / \").trim();const n=a(t);if(n.nextDe){l.push(e+o),d.push(n.enPart+o);const t=n.nextDe+o;l.push(t),d.push(t)}else{const n=t+o,a=e.includes(o.trim())?e:e+o;l.push(a),d.push(n)}}else{const e=a(n);e.nextDe?(d.push(e.enPart+o),l.push(e.nextDe+o)):(l.push(n+o),d.push(n+o))}}let g=l.join(\"\\n\u2022 \");l.length>0&&!g.startsWith(\"\u2022 \")&&(g=\"\u2022 \"+g);let m=d.join(\"\\n\u2022 \");return d.length>0&&!m.startsWith(\"\u2022 \")&&(m=\"\u2022 \"+m),{de:g,en:m,raw:t}}(e);return\"en\"===a.Kl?t.en||t.raw:t.de||t.raw}}},t={};function n(a){var o=t[a];if(void 0!==o)return o.exports;var s=t[a]={exports:{}};return e[a](s,s.exports,n),s.exports}n.d=(e,t)=>{for(var a in t)n.o(t,a)&&!n.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var a=n(901);var o=n(367),s=n(842),i=n(521),r=n(672),l=n(646);if(!window.__KANTINE_LOADED){window.__KANTINE_LOADED=!0,function(){document.title=\"Kantine Weekly Menu\",document.querySelectorAll&&document.querySelectorAll('link[rel*=\"icon\"]').forEach(e=>e.remove());const e=document.createElement(\"link\");if(e.rel=\"icon\",e.type=\"image/png\",e.href=\"data:image/png;base64,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\",document.head.appendChild(e),!document.querySelector('link[href*=\"fonts.googleapis.com/css2?family=Inter\"]')){const e=document.createElement(\"link\");e.rel=\"stylesheet\",e.href=\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap\",document.head.appendChild(e)}if(!document.querySelector('link[href*=\"Material+Icons+Round\"]')){const e=document.createElement(\"link\");e.rel=\"stylesheet\",e.href=\"https://fonts.googleapis.com/icon?family=Material+Icons+Round\",document.head.appendChild(e)}const t=`\\n
    \\n
    \\n
    \\n
    \\n \"Logo\"\\n
    \\n

    Kantinen \u00dcbersicht v1.6.17

    \\n
    \\n
    \\n
    \\n \\n \\n
    \\n \\n
    \\n
    \\n
    \\n \\n \\n \\n
    \\n
    \\n
    \\n
    \\n
    \\n \\n \\n \\n \\n \\n
    \\n person\\n \\n \\n
    \\n
    \\n
    \\n
    \\n\\n
    \\n
    \\n
    \\n

    Login

    \\n \\n
    \\n
    \\n
    \\n \\n \\n Deine offizielle Knapp Mitarbeiternummer.\\n
    \\n
    \\n \\n \\n Das Passwort f\u00fcr deinen Bessa Account.\\n
    \\n
    \\n
    \\n \\n
    \\n
    \\n
    \\n
    \\n\\n
    \\n
    \\n
    \\n

    Men\u00fcdaten aktualisieren

    \\n
    \\n
    \\n
    \\n
    \\n
    \\n
    \\n
    0%
    \\n
    \\n

    Initialisierung...

    \\n
    \\n
    \\n
    \\n\\n
    \\n
    \\n
    \\n

    Meine Highlights

    \\n \\n
    \\n
    \\n

    \\n Markiere Men\u00fcs automatisch, wenn sie diese Schlagw\u00f6rter enthalten.\\n

    \\n
    \\n \\n \\n
    \\n
    \\n
    \\n
    \\n
    \\n\\n
    \\n
    \\n
    \\n

    Bestellhistorie

    \\n \\n
    \\n
    \\n
    \\n

    Lade Historie...

    \\n
    \\n
    \\n
    \\n
    \\n
    \\n
    \\n
    \\n
    \\n
    \\n
    \\n
    \\n\\n
    \\n
    \\n
    \\n

    \ud83d\udce6 Versionen

    \\n \\n
    \\n
    \\n
    \\n Aktuell: v1.6.17\\n
    \\n
    \\n \\n
    \\n
    \\n

    Lade Versionen...

    \\n
    \\n
    \\n \\n bug_report Fehler melden\\n \\n \\n lightbulb Feature vorschlagen\\n \\n \\n
    \\n
    \\n
    \\n
    \\n\\n
    \\n
    \\n update\\n Gerade aktualisiert\\n
    \\n
    \\n
    \\n

    Lade Men\u00fcdaten...

    \\n
    \\n
    \\n
    \\n\\n
    \\n

    Jetzt Bessa Einfach! • Knapp-Kantine Wrapper • ${(new Date).getFullYear()} by Kaufi \ud83d\ude03\ud83d\udc4d mit Hilfe von KI \ud83e\udd16

    \\n
    \\n
    `;document.body.innerHTML=t}(),function(){const e=document.getElementById(\"btn-this-week\"),t=document.getElementById(\"btn-next-week\"),n=document.getElementById(\"btn-refresh\"),d=document.getElementById(\"theme-toggle\"),c=document.getElementById(\"btn-login-open\"),u=document.getElementById(\"btn-login-close\"),g=document.getElementById(\"btn-logout\"),m=document.getElementById(\"login-form\"),h=document.getElementById(\"login-modal\"),p=document.getElementById(\"btn-highlights\"),f=document.getElementById(\"highlights-modal\"),v=document.getElementById(\"btn-highlights-close\"),y=document.getElementById(\"btn-add-tag\"),b=document.getElementById(\"tag-input\"),w=document.getElementById(\"btn-history\"),E=document.getElementById(\"history-modal\"),A=document.getElementById(\"btn-history-close\");document.querySelectorAll(\".lang-btn\").forEach(e=>{e.addEventListener(\"click\",()=>{(0,a.UD)(e.dataset.lang),localStorage.setItem(i.LS.LANG,e.dataset.lang),document.querySelectorAll(\".lang-btn\").forEach(e=>e.classList.remove(\"active\")),e.classList.add(\"active\"),function(){const e=document.getElementById(\"btn-this-week\"),t=document.getElementById(\"btn-next-week\");e&&(e.textContent=(0,l.t)(\"thisWeek\"),e.title=(0,l.t)(\"thisWeekTooltip\")),t&&(t.textContent=(0,l.t)(\"nextWeek\"));const n=document.querySelector(\".header-left h1\");if(n){const e=n.querySelector(\".version-tag\"),t=n.querySelector(\".update-icon\");n.textContent=(0,l.t)(\"appTitle\")+\" \",e&&n.appendChild(e),t&&n.appendChild(t)}const o=document.getElementById(\"btn-refresh\");o&&o.setAttribute(\"aria-label\",(0,l.t)(\"refresh\")),o&&(o.title=(0,l.t)(\"refresh\"));const i=document.getElementById(\"btn-history\");i&&i.setAttribute(\"aria-label\",(0,l.t)(\"history\")),i&&(i.title=(0,l.t)(\"history\"));const r=document.getElementById(\"btn-highlights\");r&&r.setAttribute(\"aria-label\",(0,l.t)(\"highlights\")),r&&(r.title=(0,l.t)(\"highlights\"));const d=document.getElementById(\"theme-toggle\");d&&(d.title=(0,l.t)(\"themeTooltip\"));const c=document.getElementById(\"btn-login-open\");if(c){c.title=(0,l.t)(\"loginTooltip\");const e=c.querySelector(\"span:last-child\");e&&!e.classList.contains(\"material-icons-round\")&&(e.textContent=(0,l.t)(\"login\"))}const u=document.getElementById(\"btn-logout\");u&&(u.title=(0,l.t)(\"logoutTooltip\"));const g=document.getElementById(\"lang-toggle\");g&&(g.title=(0,l.t)(\"langTooltip\"));const m=document.querySelector(\"#highlights-modal .modal-header h2\");m&&(m.textContent=(0,l.t)(\"highlightsTitle\"));const h=document.querySelector(\"#highlights-modal .modal-body > p\");h&&(h.textContent=(0,l.t)(\"highlightsDesc\"));const p=document.getElementById(\"tag-input\");p&&(p.placeholder=(0,l.t)(\"tagInputPlaceholder\"),p.title=(0,l.t)(\"tagInputTooltip\"));const f=document.getElementById(\"btn-add-tag\");f&&(f.textContent=(0,l.t)(\"addTag\"),f.title=(0,l.t)(\"addTagTooltip\"));const v=document.querySelector(\"#history-modal .modal-header h2\");v&&(v.textContent=(0,l.t)(\"historyTitle\"));const y=document.querySelector(\"#login-modal .modal-header h2\");y&&(y.textContent=(0,l.t)(\"loginTitle\"));const b=document.getElementById(\"alarm-bell\");b&&0===a.BY.size&&(b.title=(0,l.t)(\"alarmTooltipNone\")),(0,s.OR)(),(0,s.gJ)(),(0,s.Mb)()}()})}),p&&p.addEventListener(\"click\",()=>{(0,o.Y1)(),f.classList.remove(\"hidden\")}),v&&v.addEventListener(\"click\",()=>{f.classList.add(\"hidden\")}),w.addEventListener(\"click\",()=>{a.gX?(E.classList.remove(\"hidden\"),(0,o.Aq)()):h.classList.remove(\"hidden\")}),A.addEventListener(\"click\",()=>{E.classList.add(\"hidden\")}),window.addEventListener(\"click\",e=>{e.target===E&&E.classList.add(\"hidden\"),e.target===f&&f.classList.add(\"hidden\")});const k=document.querySelector(\".version-tag\"),L=document.getElementById(\"version-modal\"),S=document.getElementById(\"btn-version-close\");k&&k.addEventListener(\"click\",e=>{e.preventDefault(),e.stopPropagation(),(0,s.Gk)()}),S&&S.addEventListener(\"click\",()=>{L.classList.add(\"hidden\")});const I=document.getElementById(\"btn-clear-cache\");I&&I.addEventListener(\"click\",()=>{confirm(\"M\u00f6chtest du wirklich alle lokalen Daten (inkl. Login-Session, Cache und Einstellungen) l\u00f6schen? Die Seite wird danach neu geladen.\")&&(Object.keys(localStorage).forEach(e=>{e.startsWith(\"kantine_\")&&localStorage.removeItem(e)}),window.location.reload())}),window.addEventListener(\"click\",e=>{e.target===L&&L.classList.add(\"hidden\")}),y.addEventListener(\"click\",()=>{const e=b.value;(0,o.oL)(e)&&(b.value=\"\",(0,o.Y1)())}),b.addEventListener(\"keypress\",e=>{\"Enter\"===e.key&&y.click()});const C=localStorage.getItem(\"theme\"),B=window.matchMedia(\"(prefers-color-scheme: dark)\").matches,T=d.querySelector(\".theme-icon\");\"dark\"===C||!C&&B?(document.documentElement.setAttribute(\"data-theme\",\"dark\"),T.textContent=\"dark_mode\"):(document.documentElement.setAttribute(\"data-theme\",\"light\"),T.textContent=\"light_mode\"),d.addEventListener(\"click\",()=>{const e=\"dark\"===document.documentElement.getAttribute(\"data-theme\")?\"light\":\"dark\";document.documentElement.setAttribute(\"data-theme\",e),localStorage.setItem(\"theme\",e),T.textContent=\"dark\"===e?\"dark_mode\":\"light_mode\"}),e.addEventListener(\"click\",()=>{\"this-week\"!==a.sw&&((0,a.qo)(\"this-week\"),e.classList.add(\"active\"),t.classList.remove(\"active\"),(0,s.OR)())}),t.addEventListener(\"click\",()=>{t.classList.remove(\"new-week-available\"),\"next-week\"!==a.sw&&((0,a.qo)(\"next-week\"),t.classList.add(\"active\"),e.classList.remove(\"active\"),(0,s.OR)())}),n.addEventListener(\"click\",()=>{a.gX?(0,o.m9)():h.classList.remove(\"hidden\")});const D=document.getElementById(\"alarm-bell\");D&&D.addEventListener(\"click\",()=>{(0,o.A0)()}),c.addEventListener(\"click\",()=>{h.classList.remove(\"hidden\"),document.getElementById(\"login-error\").classList.add(\"hidden\"),m.reset()}),u.addEventListener(\"click\",()=>{h.classList.add(\"hidden\")}),window.addEventListener(\"click\",e=>{e.target===h&&h.classList.add(\"hidden\")}),m.addEventListener(\"submit\",async e=>{e.preventDefault();const t=document.getElementById(\"employee-id\").value.trim(),n=document.getElementById(\"password\").value,s=document.getElementById(\"login-error\"),l=m.querySelector('button[type=\"submit\"]'),d=l.textContent;l.disabled=!0,l.textContent=\"Wird eingeloggt...\";try{const e=`knapp-${t}@bessa.app`,l=await fetch(`${i.tE}/auth/login/`,{method:\"POST\",headers:(0,r.H)(i.f9),body:JSON.stringify({email:e,password:n})}),d=await l.json();if(l.ok){(0,a.O5)(d.key),(0,a.lt)(t),localStorage.setItem(i.LS.AUTH_TOKEN,d.key),localStorage.setItem(i.LS.CURRENT_USER,t);try{const e=await fetch(`${i.tE}/auth/user/`,{headers:(0,r.H)(d.key)});if(e.ok){const t=await e.json();t.first_name&&localStorage.setItem(i.LS.FIRST_NAME,t.first_name),t.last_name&&localStorage.setItem(i.LS.LAST_NAME,t.last_name)}}catch(e){console.error(\"Failed to fetch user info:\",e)}(0,o.i_)(),h.classList.add(\"hidden\"),(0,o.Gb)(),m.reset(),(0,o.g8)(),(0,o.m9)()}else s.textContent=d.non_field_errors?.[0]||d.error||\"Login fehlgeschlagen\",s.classList.remove(\"hidden\")}catch(e){console.error(\"Login error:\",e),s.textContent=\"Ein Fehler ist aufgetreten\",s.classList.remove(\"hidden\")}finally{l.disabled=!1,l.textContent=d}}),g.addEventListener(\"click\",()=>{localStorage.removeItem(i.LS.AUTH_TOKEN),localStorage.removeItem(i.LS.CURRENT_USER),localStorage.removeItem(i.LS.FIRST_NAME),localStorage.removeItem(i.LS.LAST_NAME),(0,a.O5)(null),(0,a.lt)(null),(0,a.di)(new Map),(0,o.Et)(),(0,o.i_)(),(0,s.OR)()})}(),(0,o.i_)(),(0,o.H)();(0,o.KG)()?(document.getElementById(\"loading\").classList.add(\"hidden\"),(0,o.VL)()||(0,o.m9)()):(0,o.m9)(),a.gX&&(0,o.g8)(),(0,s.Ux)(),setInterval(s.Ux,36e5)}})();\n"; +sc.textContent="(()=>{\"use strict\";var e={367(e,t,n){n.d(t,{A0:()=>v,Aq:()=>g,BM:()=>S,Et:()=>E,Gb:()=>u,H:()=>b,KG:()=>T,N4:()=>p,P0:()=>H,PQ:()=>y,VL:()=>D,Y1:()=>L,g8:()=>w,i_:()=>c,m9:()=>O,oL:()=>k,wH:()=>h});var a=n(901),o=n(413),s=n(521),i=n(672),r=n(842),l=n(646);let d=null;function c(){if(!a.gX)try{const e=localStorage.getItem(\"AkitaStores\");if(e){const t=JSON.parse(e);t.auth&&t.auth.token&&((0,a.O5)(t.auth.token),localStorage.setItem(s.LS.AUTH_TOKEN,t.auth.token),t.auth.user&&((0,a.lt)(t.auth.user.id||\"unknown\"),localStorage.setItem(s.LS.CURRENT_USER,t.auth.user.id||\"unknown\"),t.auth.user.firstName&&localStorage.setItem(s.LS.FIRST_NAME,t.auth.user.firstName),t.auth.user.lastName&&localStorage.setItem(s.LS.LAST_NAME,t.auth.user.lastName)))}}catch(e){console.warn(\"Failed to parse AkitaStores:\",e)}(0,a.O5)(localStorage.getItem(s.LS.AUTH_TOKEN)),(0,a.lt)(localStorage.getItem(s.LS.CURRENT_USER));const e=localStorage.getItem(s.LS.FIRST_NAME),t=document.getElementById(\"btn-login-open\"),n=document.getElementById(\"user-info\"),o=document.getElementById(\"user-id-display\");a.gX?(t.classList.add(\"hidden\"),n.classList.remove(\"hidden\"),o.textContent=e||(a.Ny?`User ${a.Ny}`:(0,l.t)(\"loggedIn\")),u()):(t.classList.remove(\"hidden\"),n.classList.add(\"hidden\"),o.textContent=\"\"),(0,r.OR)()}async function u(){if(a.gX)try{const e=await fetch(`${s.tE}/user/orders/?venue=${s.eW}&ordering=-created&limit=50`,{headers:(0,i.H)(a.gX)}),t=await e.json();if(e.ok){const e=new Map,n=t.results||[];for(const t of n){if(9===t.order_state)continue;const n=t.date.split(\"T\")[0];for(const a of t.items||[]){const o=`${n}_${a.article}`;e.has(o)||e.set(o,[]),e.get(o).push(t.id)}}(0,a.di)(e),(0,r.OR)(),(0,r.gJ)()}}catch(e){console.error(\"Error fetching orders:\",e)}}async function g(){const e=document.getElementById(\"history-loading\"),t=document.getElementById(\"history-content\"),n=document.getElementById(\"history-progress-fill\"),o=document.getElementById(\"history-progress-text\");let r=[];if(d)r=d;else{const e=localStorage.getItem(s.LS.HISTORY_CACHE);if(e)try{r=JSON.parse(e),d=r}catch(e){console.warn(\"History cache parse error\",e)}}if(r.length>0&&m(r),!a.gX)return;0===r.length&&(t.innerHTML=\"\",e.classList.remove(\"hidden\")),n.style.width=\"0%\",o.textContent=r.length>0?(0,l.t)(\"historyLoadingDelta\"):(0,l.t)(\"historyLoadingFull\"),r.length>0&&e.classList.remove(\"hidden\");let c=r.length>0?`${s.tE}/user/orders/?venue=${s.eW}&ordering=-created&limit=5`:`${s.tE}/user/orders/?venue=${s.eW}&ordering=-created&limit=50`,u=[],g=0,h=0===r.length,p=!1;try{for(;c&&!p;){const e=await fetch(c,{headers:(0,i.H)(a.gX)});if(!e.ok)throw new Error(`Fetch failed: ${e.status}`);const t=await e.json();t.count&&0===g&&(g=t.count);const s=t.results||[];for(const e of s){const t=r.findIndex(t=>t.id===e.id);if(!h&&-1!==t){const n=r[t];if(n.updated===e.updated&&n.order_state===e.order_state){p=!0;break}}u.push(e)}if(!p&&h)if(g>0){const e=Math.round(u.length/g*100);n.style.width=`${e}%`,o.textContent=`${(0,l.t)(\"historyLoadingItem\")} ${u.length} ${(0,l.t)(\"historyLoadingOf\")} ${g}...`}else o.textContent=`${(0,l.t)(\"historyLoadingItem\")} ${u.length}...`;else p||(o.textContent=`${u.length} ${(0,l.t)(\"historyLoadingNew\")}`);c=p?null:t.next}if(u.length>0){const e=new Map(r.map(e=>[e.id,e]));for(const t of u)e.set(t.id,t);const t=Array.from(e.values());t.sort((e,t)=>new Date(t.created)-new Date(e.created)),d=t;try{localStorage.setItem(s.LS.HISTORY_CACHE,JSON.stringify(t))}catch(e){console.warn(\"History cache write error\",e)}m(d)}}catch(e){console.error(\"Error in history sync:\",e),0===r.length?t.innerHTML=`

    ${(0,l.t)(\"historyLoadError\")}

    `:H((0,l.t)(\"bgSyncFailed\"),\"error\")}finally{e.classList.add(\"hidden\")}}function m(e){const t=document.getElementById(\"history-content\");if(!e||0===e.length)return void(t.innerHTML=`

    ${(0,l.t)(\"noOrders\")}

    `);const n={};e.forEach(e=>{const t=new Date(e.date),s=t.getFullYear(),i=t.getMonth(),r=`${s}-${i.toString().padStart(2,\"0\")}`,l=\"en\"===a.Kl?\"en-US\":\"de-AT\",d=t.toLocaleString(l,{month:\"long\"}),c=(0,o.sn)(t);n[s]||(n[s]={year:s,months:{}}),n[s].months[r]||(n[s].months[r]={name:d,year:s,monthIndex:i,count:0,total:0,weeks:{}}),n[s].months[r].weeks[c]||(n[s].months[r].weeks[c]={label:\"en\"===a.Kl?`CW ${c}`:`KW ${c}`,items:[],count:0,total:0});(e.items||[]).forEach(t=>{const a=parseFloat(t.price||e.total||0);n[s].months[r].weeks[c].items.push({date:e.date,name:t.name||\"Men\u00fc\",price:a,state:e.order_state}),9!==e.order_state&&(n[s].months[r].weeks[c].count++,n[s].months[r].weeks[c].total+=a,n[s].months[r].count++,n[s].months[r].total+=a)})}),t.innerHTML=\"\";Object.keys(n).sort((e,t)=>t-e).forEach(e=>{const o=n[e],s=document.createElement(\"div\");s.className=\"history-year-group\";const i=document.createElement(\"h2\");i.className=\"history-year-header\",i.textContent=o.year,s.appendChild(i);Object.keys(o.months).sort((e,t)=>t.localeCompare(e)).forEach(e=>{const t=o.months[e],n=document.createElement(\"div\");n.className=\"history-month-group\";const i=document.createElement(\"div\");i.className=\"history-month-header\",i.setAttribute(\"tabindex\",\"0\"),i.setAttribute(\"role\",\"button\"),i.setAttribute(\"aria-expanded\",\"false\"),i.setAttribute(\"title\",(0,l.t)(\"historyMonthToggle\"));const r=document.createElement(\"div\");r.style.display=\"flex\",r.style.flexDirection=\"column\",r.style.gap=\"4px\";const d=document.createElement(\"span\");d.textContent=t.name,r.appendChild(d);const c=document.createElement(\"div\");c.className=\"history-month-summary\";const u=document.createElement(\"span\");u.innerHTML=`${t.count} ${(0,l.t)(\"orders\")} • \u20ac${t.total.toFixed(2)}`,c.appendChild(u),r.appendChild(c),i.appendChild(r);const g=document.createElement(\"span\");g.className=\"material-icons-round\",g.textContent=\"expand_more\",i.appendChild(g),i.addEventListener(\"click\",()=>{const e=i.parentElement;e.classList.contains(\"open\")?(e.classList.remove(\"open\"),i.setAttribute(\"aria-expanded\",\"false\")):(e.classList.add(\"open\"),i.setAttribute(\"aria-expanded\",\"true\"))}),n.appendChild(i);const m=document.createElement(\"div\");m.className=\"history-month-content\";Object.keys(t.weeks).sort((e,t)=>parseInt(t)-parseInt(e)).forEach(e=>{const n=t.weeks[e],o=document.createElement(\"div\");o.className=\"history-week-group\";const s=document.createElement(\"div\");s.className=\"history-week-header\";const i=document.createElement(\"strong\");i.textContent=n.label,s.appendChild(i);const r=document.createElement(\"span\");r.innerHTML=`${n.count} ${(0,l.t)(\"orders\")} • \u20ac${n.total.toFixed(2)}`,s.appendChild(r),o.appendChild(s),n.items.forEach(e=>{const t=new Date(e.date),n=\"en\"===a.Kl?\"en-US\":\"de-AT\",s=t.toLocaleDateString(n,{weekday:\"short\",day:\"2-digit\",month:\"2-digit\"}),i=document.createElement(\"div\");i.className=\"history-item\",9===e.state&&i.classList.add(\"history-item-cancelled\");const r=document.createElement(\"div\");r.style.fontSize=\"0.85rem\",r.style.color=\"var(--text-secondary)\",r.textContent=s,i.appendChild(r);const d=document.createElement(\"div\");d.className=\"history-item-details\";const c=document.createElement(\"span\");c.className=\"history-item-name\",c.textContent=e.name,d.appendChild(c);const u=document.createElement(\"div\"),g=document.createElement(\"span\");g.className=\"history-item-status\",9===e.state?g.textContent=(0,l.t)(\"stateCancelled\"):8===e.state?g.textContent=(0,l.t)(\"stateCompleted\"):g.textContent=(0,l.t)(\"stateTransferred\"),u.appendChild(g),d.appendChild(u),i.appendChild(d);const m=document.createElement(\"div\");m.className=\"history-item-price\",9===e.state&&m.classList.add(\"history-item-price-cancelled\"),m.textContent=`\u20ac${e.price.toFixed(2)}`,i.appendChild(m),o.appendChild(i)}),m.appendChild(o)}),n.appendChild(m),s.appendChild(n)}),t.appendChild(s)})}async function h(e,t,n,o,r){if(a.gX)try{const c=await fetch(`${s.tE}/auth/user/`,{headers:(0,i.H)(a.gX)});if(!c.ok)return void H(\"Fehler: Benutzerdaten konnten nicht geladen werden\",\"error\");const g=await c.json(),m=(new Date).toISOString(),h={uuid:crypto.randomUUID(),created:m,updated:m,order_type:7,items:[{article:t,course_group:null,modifiers:[],uuid:crypto.randomUUID(),name:n,description:r||\"\",price:String(parseFloat(o)),amount:1,vat:\"10.00\",comment:\"\"}],table:null,total:parseFloat(o),tip:0,currency:\"EUR\",venue:s.eW,states:[],order_state:1,date:`${e}T10:30:00Z`,payment_method:\"payroll\",customer:{first_name:g.first_name,last_name:g.last_name,email:g.email,newsletter:!1},preorder:!0,delivery_fee:0,cash_box_table_name:null,take_away:!1},p=await fetch(`${s.tE}/user/orders/`,{method:\"POST\",headers:(0,i.H)(a.gX),body:JSON.stringify(h)});if(p.ok||201===p.status)H(`${(0,l.t)(\"orderSuccess\")}: ${n}`,\"success\"),d=null,await u();else{const e=await p.json();H(`Fehler: ${e.detail||e.non_field_errors?.[0]||\"Bestellung fehlgeschlagen\"}`,\"error\")}}catch(e){console.error(\"Order error:\",e),H(\"Netzwerkfehler bei Bestellung\",\"error\")}}async function p(e,t,n){if(!a.gX)return;const o=`${e}_${t}`,r=a.L.get(o);if(!r||0===r.length)return;const c=r[r.length-1];try{const e=await fetch(`${s.tE}/user/orders/${c}/cancel/`,{method:\"PATCH\",headers:(0,i.H)(a.gX),body:JSON.stringify({})});if(e.ok)H(`${(0,l.t)(\"cancelSuccess\")}: ${n}`,\"success\"),d=null,await u();else{H(`Fehler: ${(await e.json()).detail||\"Stornierung fehlgeschlagen\"}`,\"error\")}}catch(e){console.error(\"Cancel error:\",e),H(\"Netzwerkfehler bei Stornierung\",\"error\")}}function f(){localStorage.setItem(\"kantine_flags\",JSON.stringify([...a.BY]))}async function v(){if(0===a.BY.size)return;const e=a.gX||s.f9,t=new Set;for(const e of a.BY){const[n]=e.split(\"_\");t.add(n)}let n=!1;const o=document.getElementById(\"alarm-bell\");o&&o.classList.add(\"refreshing\");try{for(const o of t)try{const t=await fetch(`${s.tE}/venues/${s.eW}/menu/${s.YU}/${o}/`,{headers:(0,i.H)(e)});if(!t.ok)continue;const r=(await t.json()).results||[],l=new Map;for(const e of r)if(e.items&&Array.isArray(e.items))for(const t of e.items)l.set(t.id,t);for(let e of a.p_){if(!e.days)continue;const t=e.days.find(e=>e.date===o);if(t&&t.items)for(let e=0;e0;s.available=e||t,s.availableAmount=parseInt(r.available_amount)||0,s.amountTracking=!1!==r.amount_tracking,n=!0}}}}catch(e){console.error(\"Error refreshing flag date\",o,e)}n&&B(),localStorage.setItem(\"kantine_flagged_items_last_checked\",(new Date).toISOString()),(0,r.Mb)(),(0,r.OR)(),H(`${a.BY.size} ${1===a.BY.size?(0,l.t)(\"menuSingular\"):(0,l.t)(\"menuPlural\")} ${(0,l.t)(\"menuChecked\")}`,\"info\")}finally{o&&o.classList.remove(\"refreshing\")}}function y(e,t,n,o){const s=`${e}_${t}`;let i=!1;a.BY.has(s)?(a.BY.delete(s),H(`${(0,l.t)(\"flagRemoved\")} ${n}`,\"success\")):(a.BY.add(s),i=!0,H(`${(0,l.t)(\"flagActivated\")} ${n}`,\"success\"),\"default\"===Notification.permission&&Notification.requestPermission()),f(),(0,r.Mb)(),(0,r.OR)(),i&&v()}function b(){const e=new Date,t=e.toISOString().split(\"T\")[0];let n=!1;for(const o of[...a.BY]){const[s]=o.split(\"_\");let i=!1;if(s=t&&(i=!0)}i&&(a.BY.delete(o),n=!0)}n&&f()}function w(){a.K8||a.gX&&(0,a.cc)(setInterval(()=>async function(){if(0===a.BY.size||!a.gX)return;for(const e of a.BY){const[t,n]=e.split(\"_\"),o=parseInt(n);try{const e=await fetch(`${s.tE}/venues/${s.eW}/menu/${s.YU}/${t}/`,{headers:(0,i.H)(a.gX)});if(!e.ok)continue;const n=(await e.json()).results||[];let r=null;for(const e of n)if(e.items&&(r=e.items.find(e=>e.id===o||e.article===o),r))break;if(r){if(!1===r.amount_tracking||parseInt(r.available_amount)>0){const e=r.name||\"Unbekannt\";H(`${e} ist jetzt verf\u00fcgbar!`,\"success\"),\"granted\"===Notification.permission&&new Notification(\"Kantine Wrapper\",{body:`${e} ist jetzt verf\u00fcgbar!`,icon:\"\ud83c\udf7d\ufe0f\"}),O()}}}catch(t){console.error(`Poll error for ${e}:`,t),await new Promise(e=>setTimeout(e,200))}}localStorage.setItem(\"kantine_flagged_items_last_checked\",(new Date).toISOString()),(0,r.Mb)()}(),s.fv))}function E(){a.K8&&(clearInterval(a.K8),(0,a.cc)(null))}function A(){localStorage.setItem(\"kantine_highlightTags\",JSON.stringify(a.yz)),(0,r.OR)(),(0,r.gJ)()}function k(e){if((e=e.trim().toLowerCase())&&!a.yz.includes(e)){const t=[...a.yz,e];return(0,a.iw)(t),A(),!0}return!1}function L(){const e=document.getElementById(\"tags-list\");e.innerHTML=\"\",a.yz.forEach(t=>{const n=document.createElement(\"span\");n.className=\"tag-badge\",n.innerHTML=`${t} ×`,e.appendChild(n)}),e.querySelectorAll(\".tag-remove\").forEach(e=>{e.addEventListener(\"click\",e=>{!function(e){const t=a.yz.filter(t=>t!==e);(0,a.iw)(t),A()}(e.target.dataset.tag),L()})})}function S(e){return e?(e=e.toLowerCase(),a.yz.filter(t=>e.includes(t))):[]}const I=\"kantine_menuCache\",C=\"kantine_menuCacheTs\";function B(){try{localStorage.setItem(I,JSON.stringify(a.p_)),localStorage.setItem(C,(new Date).toISOString())}catch(e){console.warn(\"Failed to cache menu data:\",e)}}function T(){try{const e=localStorage.getItem(I),t=localStorage.getItem(C);if(e){(0,a.tn)(JSON.parse(e)),(0,a.Xt)((0,o.sn)(new Date)),(0,a.pK)((new Date).getFullYear()),(0,r.OR)(),(0,r.gJ)(),(0,r.Mb)(),t&&N(t);try{const e=new Set;a.p_.forEach(t=>{(t.days||[]).forEach(t=>{(t.items||[]).forEach(t=>{let n=(t.description||\"\").replace(/\\s+/g,\" \").trim();n&&n.includes(\" / \")&&e.add(n)})})})}catch(e){}return!0}}catch(e){console.warn(\"Failed to load cached menu:\",e)}return!1}function D(){const e=localStorage.getItem(C);if(!e)return!1;if(Date.now()-new Date(e).getTime()>36e5)return!1;const t=(0,o.sn)(new Date),n=(0,o.Ao)(new Date);return a.p_.some(e=>e.weekNumber===t&&e.year===n&&e.days&&e.days.length>0)}async function O(){const e=document.getElementById(\"loading\"),t=document.getElementById(\"progress-modal\"),l=document.getElementById(\"progress-fill\"),d=document.getElementById(\"progress-percent\"),u=document.getElementById(\"progress-message\");e.classList.remove(\"hidden\");const g=a.gX||s.f9;try{t.classList.remove(\"hidden\"),u.textContent=\"Hole verf\u00fcgbare Daten...\",l.style.width=\"0%\",d.textContent=\"0%\";const e=await fetch(`${s.tE}/venues/${s.eW}/menu/dates/`,{headers:(0,i.H)(g)});if(!e.ok)throw new Error(`Failed to fetch dates: ${e.status}`);let n=(await e.json()).results||[];const m=new Date;m.setDate(m.getDate()-7);const h=m.toISOString().split(\"T\")[0];n=n.filter(e=>e.date>=h).sort((e,t)=>e.date.localeCompare(t.date)).slice(0,30);const p=n.length;u.textContent=`${p} Tage gefunden. Lade Details...`;const f=[];let v=0;const y=5;for(let e=0;e{const t=e.date;let n=null;try{const a=await fetch(`${s.tE}/venues/${s.eW}/menu/${s.YU}/${t}/`,{headers:(0,i.H)(g)});if(a.ok){const o=(await a.json()).results||[];let s=[];for(const e of o)e.items&&Array.isArray(e.items)&&(s=s.concat(e.items));s.length>0&&(n={date:t,menu_items:s,orders:e.orders||[]})}}catch(e){console.error(`Failed to fetch details for ${t}:`,e)}finally{v++;const e=Math.round(v/p*100);l.style.width=`${e}%`,d.textContent=`${e}%`,u.textContent=`Lade Men\u00fc f\u00fcr ${t}...`}return n}));for(const e of a)e&&f.push(e)}const b=new Map;a.p_&&a.p_.length>0&&a.p_.forEach(e=>{const t=`${e.year}-${e.weekNumber}`;try{b.set(t,{year:e.year,weekNumber:e.weekNumber,days:e.days?e.days.map(e=>({...e,items:e.items?[...e.items]:[]})):[]})}catch(e){console.warn(\"Error hydrating week:\",e)}});for(const e of f){const t=new Date(e.date),n=(0,o.sn)(t),a=(0,o.Ao)(t),s=`${a}-${n}`;b.has(s)||b.set(s,{year:a,weekNumber:n,days:[]});const i=b.get(s),r=t.toLocaleDateString(\"en-US\",{weekday:\"long\"}),l=new Date(e.date);l.setHours(10,0,0,0);const d={date:e.date,weekday:r,orderCutoff:l.toISOString(),items:e.menu_items.map(t=>{const n=!1===t.amount_tracking,a=parseInt(t.available_amount)>0;return{id:`${e.date}_${t.id}`,articleId:t.id,name:t.name||\"Unknown\",description:t.description||\"\",price:parseFloat(t.price)||0,available:n||a,availableAmount:parseInt(t.available_amount)||0,amountTracking:!1!==t.amount_tracking}})},c=i.days.findIndex(t=>t.date===e.date);c>=0?i.days[c]=d:i.days.push(d)}const w=Array.from(b.values()).sort((e,t)=>e.year!==t.year?e.year-t.year:e.weekNumber-t.weekNumber);w.forEach(e=>{e.days&&e.days.sort((e,t)=>e.date.localeCompare(t.date))}),(0,a.tn)(w),B(),N((new Date).toISOString()),(0,a.Xt)((0,o.sn)(new Date)),(0,a.pK)((new Date).getFullYear()),c(),(0,r.OR)(),(0,r.gJ)(),(0,r.Mb)(),u.textContent=\"Fertig!\",setTimeout(()=>t.classList.add(\"hidden\"),500)}catch(e){console.error(\"Error fetching menu:\",e),t.classList.add(\"hidden\"),Promise.resolve().then(n.bind(n,842)).then(t=>{t.showErrorModal(\"Keine Verbindung\",`Die Men\u00fcdaten konnten nicht geladen werden. M\u00f6glicherweise besteht keine Verbindung zur API oder zur Bessa-Webseite.

    ${(0,o.ZD)(e.message)}`,\"Zur Original-Seite\",\"https://web.bessa.app/knapp-kantine\")})}finally{e.classList.add(\"hidden\")}}let M=null,x=null;function N(e){const t=document.getElementById(\"last-updated-subtitle\");if(e){M=e,localStorage.setItem(\"kantine_last_updated\",e),localStorage.setItem(\"kantine_last_checked\",e);try{const n=new Date(e),a=n.toLocaleTimeString(\"de-DE\",{hour:\"2-digit\",minute:\"2-digit\"}),s=n.toLocaleDateString(\"de-DE\",{day:\"2-digit\",month:\"2-digit\"}),i=(0,o.gs)(n);t.textContent=`Aktualisiert: ${s} ${a} (${i})`}catch(e){t.textContent=\"\"}x||(x=setInterval(()=>{M&&(N(M),(0,r.Mb)())},6e4))}}function H(e,t=\"info\"){let n=document.getElementById(\"toast-container\");n||(n=document.createElement(\"div\"),n.id=\"toast-container\",document.body.appendChild(n));const a=document.createElement(\"div\");a.className=`toast toast-${t}`;const s=\"success\"===t?\"check_circle\":\"error\"===t?\"error\":\"info\";a.innerHTML=`${s}${(0,o.ZD)(e)}`,n.appendChild(a),requestAnimationFrame(()=>a.classList.add(\"show\")),setTimeout(()=>{a.classList.remove(\"show\"),setTimeout(()=>a.remove(),300)},3e3)}},672(e,t,n){n.d(t,{H:()=>o,O:()=>s});var a=n(521);function o(e){return{Authorization:`Token ${e||a.f9}`,Accept:\"application/json\",\"Content-Type\":\"application/json\",\"X-Client-Version\":a.fZ}}function s(){return{Accept:\"application/vnd.github.v3+json\"}}},521(e,t,n){n.d(t,{LS:()=>g,YU:()=>r,d_:()=>u,eW:()=>i,f9:()=>o,fZ:()=>s,fv:()=>l,pe:()=>c,tE:()=>a});const a=\"https://api.bessa.app/v1\",o=\"c3418725e95a9f90e3645cbc846b4d67c7c66131\",s=\"v1.6.18\",i=591,r=7,l=3e5,d=\"TauNeutrino/kantine-overview\",c=`https://api.github.com/repos/${d}`,u=`https://htmlpreview.github.io/?https://github.com/${d}/blob`,g={AUTH_TOKEN:\"kantine_authToken\",CURRENT_USER:\"kantine_currentUser\",FIRST_NAME:\"kantine_firstName\",LAST_NAME:\"kantine_lastName\",LANG:\"kantine_lang\",FLAGS:\"kantine_flags\",FLAGGED_LAST_CHECKED:\"kantine_flagged_items_last_checked\",LAST_CHECKED:\"kantine_last_checked\",MENU_CACHE:\"kantine_menuCache\",MENU_CACHE_TS:\"kantine_menuCacheTs\",HISTORY_CACHE:\"kantine_history_cache\",HIGHLIGHT_TAGS:\"kantine_highlightTags\",LAST_UPDATED:\"kantine_last_updated\",VERSION_CACHE:\"kantine_version_cache\",DEV_MODE:\"kantine_dev_mode\"}},646(e,t,n){n.d(t,{t:()=>s});var a=n(901);const o={de:{thisWeek:\"Diese Woche\",nextWeek:\"N\u00e4chste Woche\",nextWeekTooltipDefault:\"Men\u00fc n\u00e4chster Woche anzeigen\",thisWeekTooltip:\"Men\u00fc dieser Woche anzeigen\",appTitle:\"Kantinen \u00dcbersicht\",updatedAt:\"Aktualisiert\",langTooltip:\"Sprache der Men\u00fcbeschreibung\",weekLabel:\"Woche\",refresh:\"Men\u00fcdaten neu laden\",history:\"Bestellhistorie\",highlights:\"Pers\u00f6nliche Highlights verwalten\",themeTooltip:\"Erscheinungsbild (Hell/Dunkel) wechseln\",login:\"Anmelden\",loginTooltip:\"Mit Bessa.app Account anmelden\",logout:\"Abmelden\",logoutTooltip:\"Von Bessa.app abmelden\",loginTitle:\"Login\",employeeId:\"Mitarbeiternummer\",employeeIdPlaceholder:\"z.B. 2041\",employeeIdHelp:\"Deine offizielle Knapp Mitarbeiternummer.\",password:\"Passwort\",passwordPlaceholder:\"Bessa Passwort\",passwordHelp:\"Das Passwort f\u00fcr deinen Bessa Account.\",loginButton:\"Einloggen\",loggingIn:\"Wird eingeloggt...\",highlightsTitle:\"Meine Highlights\",highlightsDesc:\"Markiere Men\u00fcs automatisch, wenn sie diese Schlagw\u00f6rter enthalten.\",tagInputPlaceholder:\"z.B. Schnitzel, Vegetarisch...\",tagInputTooltip:\"Neues Schlagwort zum Hervorheben eingeben\",addTag:\"Hinzuf\u00fcgen\",addTagTooltip:\"Schlagwort zur Liste hinzuf\u00fcgen\",removeTagTooltip:\"Schlagwort entfernen\",historyTitle:\"Bestellhistorie\",loadingHistory:\"Lade Historie...\",noOrders:\"Keine Bestellungen gefunden.\",orders:\"Bestellungen\",historyMonthToggle:\"Klicken, um die Bestellungen f\u00fcr diesen Monat ein-/auszublenden\",available:\"Verf\u00fcgbar\",soldOut:\"Ausverkauft\",ordered:\"Bestellt\",orderButton:\"Bestellen\",orderAgainTooltip:\"nochmal bestellen\",orderTooltip:\"bestellen\",cancelOrder:\"Bestellung stornieren\",cancelOneOrder:\"Eine Bestellung stornieren\",flagActivate:\"Benachrichtigen wenn verf\u00fcgbar\",flagDeactivate:\"Benachrichtigung deaktivieren\",alarmTooltipNone:\"Keine beobachteten Men\u00fcs\",alarmLastChecked:\"Zuletzt gepr\u00fcft\",versionsTitle:\"\ud83d\udce6 Versionen\",currentVersion:\"Aktuell\",devModeLabel:\"Dev-Mode (alle Tags anzeigen)\",loadingVersions:\"Lade Versionen...\",noVersions:\"Keine Versionen gefunden.\",installed:\"\u2713 Installiert\",newVersion:\"\u2b06 Neu!\",installLink:\"Installieren\",reportBug:\"Fehler melden\",reportBugTooltip:\"Melde einen Fehler auf GitHub\",featureRequest:\"Feature vorschlagen\",featureRequestTooltip:\"Schlage ein neues Feature auf GitHub vor\",clearCache:\"Lokalen Cache leeren\",clearCacheTooltip:\"L\u00f6scht alle lokalen Daten & erzwingt einen Neuladen\",clearCacheConfirm:\"M\u00f6chtest du wirklich alle lokalen Daten (inkl. Login-Session, Cache und Einstellungen) l\u00f6schen? Die Seite wird danach neu geladen.\",versionMenuTooltip:\"Klick f\u00fcr Versionsmen\u00fc\",progressTitle:\"Men\u00fcdaten aktualisieren\",progressInit:\"Initialisierung...\",noMenuData:\"Keine Men\u00fcdaten f\u00fcr KW\",noMenuDataHint:\"Versuchen Sie eine andere Woche oder schauen Sie sp\u00e4ter vorbei.\",costLabel:\"Gesamt\",orderDeadline:\"Bestellschluss\",flagRemoved:\"Flag entfernt f\u00fcr\",flagActivated:\"Benachrichtigung aktiviert f\u00fcr\",menuChecked:\"gepr\u00fcft\",menuSingular:\"Men\u00fc\",menuPlural:\"Men\u00fcs\",newMenuDataAvailable:\"Neue Men\u00fcdaten f\u00fcr n\u00e4chste Woche verf\u00fcgbar!\",orderSuccess:\"Bestellt\",cancelSuccess:\"Storniert\",bgSyncFailed:\"Hintergrund-Synchronisation fehlgeschlagen\",historyLoadError:\"Fehler beim Laden der Historie.\",historyLoadingFull:\"Lade Bestellhistorie...\",historyLoadingDelta:\"Suche nach neuen Bestellungen...\",historyLoadingItem:\"Lade Bestellung\",historyLoadingOf:\"von\",historyLoadingNew:\"neue/ge\u00e4nderte Bestellungen gefunden...\",badgeOrdered:\"bestellt\",badgeOrderable:\"bestellbar\",badgeTotal:\"gesamt\",badgeHighlights:\"Highlights gefunden\",stateCancelled:\"Storniert\",stateCompleted:\"Abgeschlossen\",stateTransferred:\"\u00dcbertragen\",close:\"Schlie\u00dfen\",noConnection:\"Keine Verbindung\",toOriginalPage:\"Zur Original-Seite\",loggedIn:\"Angemeldet\"},en:{thisWeek:\"This Week\",nextWeek:\"Next Week\",nextWeekTooltipDefault:\"Show next week's menu\",thisWeekTooltip:\"Show this week's menu\",appTitle:\"Canteen Overview\",updatedAt:\"Updated\",langTooltip:\"Menu description language\",weekLabel:\"Week\",refresh:\"Reload menu data\",history:\"Order history\",highlights:\"Manage personal highlights\",themeTooltip:\"Toggle appearance (Light/Dark)\",login:\"Sign in\",loginTooltip:\"Sign in with Bessa.app account\",logout:\"Sign out\",logoutTooltip:\"Sign out from Bessa.app\",loginTitle:\"Login\",employeeId:\"Employee ID\",employeeIdPlaceholder:\"e.g. 2041\",employeeIdHelp:\"Your official Knapp employee number.\",password:\"Password\",passwordPlaceholder:\"Bessa password\",passwordHelp:\"The password for your Bessa account.\",loginButton:\"Log in\",loggingIn:\"Logging in...\",highlightsTitle:\"My Highlights\",highlightsDesc:\"Automatically highlight menus containing these keywords.\",tagInputPlaceholder:\"e.g. Schnitzel, Vegetarian...\",tagInputTooltip:\"Enter new keyword to highlight\",addTag:\"Add\",addTagTooltip:\"Add keyword to list\",removeTagTooltip:\"Remove keyword\",historyTitle:\"Order History\",loadingHistory:\"Loading history...\",noOrders:\"No orders found.\",orders:\"Orders\",historyMonthToggle:\"Click to expand/collapse orders for this month\",available:\"Available\",soldOut:\"Sold out\",ordered:\"Ordered\",orderButton:\"Order\",orderAgainTooltip:\"order again\",orderTooltip:\"order\",cancelOrder:\"Cancel order\",cancelOneOrder:\"Cancel one order\",flagActivate:\"Notify when available\",flagDeactivate:\"Deactivate notification\",alarmTooltipNone:\"No flagged menus\",alarmLastChecked:\"Last checked\",versionsTitle:\"\ud83d\udce6 Versions\",currentVersion:\"Current\",devModeLabel:\"Dev mode (show all tags)\",loadingVersions:\"Loading versions...\",noVersions:\"No versions found.\",installed:\"\u2713 Installed\",newVersion:\"\u2b06 New!\",installLink:\"Install\",reportBug:\"Report a bug\",reportBugTooltip:\"Report a bug on GitHub\",featureRequest:\"Request a feature\",featureRequestTooltip:\"Suggest a new feature on GitHub\",clearCache:\"Clear local cache\",clearCacheTooltip:\"Deletes all local data & forces a reload\",clearCacheConfirm:\"Do you really want to delete all local data (including login session, cache, and settings)? The page will reload afterwards.\",versionMenuTooltip:\"Click for version menu\",progressTitle:\"Updating menu data\",progressInit:\"Initializing...\",noMenuData:\"No menu data for CW\",noMenuDataHint:\"Try another week or check back later.\",costLabel:\"Total\",orderDeadline:\"Order deadline\",flagRemoved:\"Flag removed for\",flagActivated:\"Notification activated for\",menuChecked:\"checked\",menuSingular:\"menu\",menuPlural:\"menus\",newMenuDataAvailable:\"New menu data available for next week!\",orderSuccess:\"Ordered\",cancelSuccess:\"Cancelled\",bgSyncFailed:\"Background synchronisation failed\",historyLoadError:\"Error loading history.\",historyLoadingFull:\"Loading order history...\",historyLoadingDelta:\"Checking for new orders...\",historyLoadingItem:\"Loading order\",historyLoadingOf:\"of\",historyLoadingNew:\"new/updated orders found...\",badgeOrdered:\"ordered\",badgeOrderable:\"orderable\",badgeTotal:\"total\",badgeHighlights:\"highlights found\",stateCancelled:\"Cancelled\",stateCompleted:\"Completed\",stateTransferred:\"Transferred\",close:\"Close\",noConnection:\"No connection\",toOriginalPage:\"Go to original page\",loggedIn:\"Logged in\"}};function s(e){const t=\"en\"===a.Kl?\"en\":\"de\";return o[t][e]||o.de[e]||e}},901(e,t,n){n.d(t,{BT:()=>i,BY:()=>g,K8:()=>m,Kl:()=>h,L:()=>u,Ny:()=>c,O5:()=>b,UD:()=>S,Xt:()=>v,cc:()=>A,di:()=>E,gX:()=>d,iw:()=>k,lt:()=>w,pK:()=>y,p_:()=>s,qo:()=>L,sw:()=>l,tn:()=>f,vW:()=>r,yz:()=>p});var a=n(413),o=n(521);let s=[],i=(0,a.sn)(new Date),r=(new Date).getFullYear(),l=\"this-week\",d=localStorage.getItem(o.LS.AUTH_TOKEN),c=localStorage.getItem(o.LS.CURRENT_USER),u=new Map,g=new Set(JSON.parse(localStorage.getItem(o.LS.FLAGS)||\"[]\")),m=null,h=localStorage.getItem(o.LS.LANG)||\"de\",p=JSON.parse(localStorage.getItem(o.LS.HIGHLIGHT_TAGS)||\"[]\");function f(e){s=e}function v(e){i=e}function y(e){r=e}function b(e){d=e}function w(e){c=e}function E(e){u=e}function A(e){m=e}function k(e){p=e}function L(e){\"this-week\"===e||\"next-week\"===e?l=e:console.warn(`[state] Invalid displayMode: \"${e}\". Ignoring.`)}function S(e){[\"de\",\"en\",\"all\"].includes(e)?h=e:console.warn(`[state] Invalid langMode: \"${e}\". Ignoring.`)}},842(e,t,n){n.d(t,{Gk:()=>m,Mb:()=>v,OR:()=>c,Ux:()=>g,gJ:()=>d,showErrorModal:()=>f});var a=n(901),o=n(413),s=n(521),i=n(672),r=n(367),l=n(646);function d(){const e=document.getElementById(\"btn-next-week\");let t=a.BT+1,n=a.vW;t>52&&(t=1,n++);const o=a.p_.find(e=>e.weekNumber===t&&e.year===n);let s=0,i=0,d=0,c=0;o&&o.days&&o.days.forEach(e=>{if(e.items&&e.items.length>0){s++;const t=e.items.some(e=>e.available);t&&i++;let n=!1;e.items.forEach(t=>{const o=t.articleId||parseInt(t.id.split(\"_\")[1]),s=`${e.date}_${o}`;a.L.has(s)&&a.L.get(s).length>0&&(n=!0)}),n&&d++;const o=new Date(e.date).getDay();o>=1&&o<=4&&t&&!n&&c++}});const u=e.querySelector(\".nav-badge\");if(u&&u.remove(),s>0){let a=0;o&&o.days&&o.days.forEach(e=>{e.items.forEach(e=>{const t=(0,r.BM)(e.name),n=(0,r.BM)(e.description);(t.length>0||n.length>0)&&a++})});let u=[`${d} ${(0,l.t)(\"badgeOrdered\")} / ${i} ${(0,l.t)(\"badgeOrderable\")} / ${s} ${(0,l.t)(\"badgeTotal\")}`];if(a>0&&u.push(`${a} ${(0,l.t)(\"badgeHighlights\")}`),e.title=u.join(\" \u2022 \"),c>0){e.classList.add(\"new-week-available\");const a=`kantine_notified_nextweek_${n}_${t}`;localStorage.getItem(a)||(localStorage.setItem(a,\"true\"),(0,r.P0)((0,l.t)(\"newMenuDataAvailable\"),\"info\"))}else e.classList.remove(\"new-week-available\")}else e.title=(0,l.t)(\"nextWeekTooltipDefault\"),e.classList.remove(\"new-week-available\")}function c(){const e=document.getElementById(\"menu-container\");if(!e)return;e.innerHTML=\"\";let t=a.BT,n=a.vW;\"next-week\"===a.sw&&(t++,t>52&&(t=1,n++));const s=a.p_.flatMap(e=>e.days||[]).filter(e=>{const a=new Date(e.date);return(0,o.sn)(a)===t&&(0,o.Ao)(a)===n});if(0===s.length)return e.innerHTML=`\\n
    \\n

    ${(0,l.t)(\"noMenuData\")} ${t} (${n}).

    \\n ${(0,l.t)(\"noMenuDataHint\")}\\n
    `,void document.getElementById(\"weekly-cost-display\").classList.add(\"hidden\");!function(e){let t=0;e&&e.length>0&&e.forEach(e=>{e.items&&e.items.forEach(n=>{const o=n.articleId||parseInt(n.id.split(\"_\")[1]),s=`${e.date}_${o}`,i=a.L.get(s)||[];i.length>0&&(t+=n.price*i.length)})});const n=document.getElementById(\"weekly-cost-display\");t>0?(n.innerHTML=`shopping_bag ${(0,l.t)(\"costLabel\")}: ${t.toFixed(2).replace(\".\",\",\")} \u20ac`,n.classList.remove(\"hidden\")):n.classList.add(\"hidden\")}(s);const i=document.getElementById(\"header-week-info\"),d=\"this-week\"===a.sw?(0,l.t)(\"thisWeek\"):(0,l.t)(\"nextWeek\");i.innerHTML=`\\n
    ${d}
    \\n
    ${(0,l.t)(\"weekLabel\")} ${t} \u2022 ${n}
    `;const c=document.createElement(\"div\");c.className=\"days-grid\",s.sort((e,t)=>e.date.localeCompare(t.date));s.filter(e=>{const t=new Date(e.date).getDay();return 0!==t&&6!==t}).forEach(e=>{const t=function(e){if(!e.items||0===e.items.length)return null;const t=document.createElement(\"div\");t.className=\"menu-card\";const n=new Date,s=new Date(e.date);let i=!1;if(e.orderCutoff)i=n>=new Date(e.orderCutoff);else{const t=new Date;t.setHours(0,0,0,0);const n=new Date(e.date);n.setHours(0,0,0,0),i=n{const n=t.articleId||parseInt(t.id.split(\"_\")[1]),o=`${e.date}_${n}`,s=(a.L.get(o)||[]).length;if(s>0){const e=t.name.match(/([M][1-9][Ff]?)/);if(e){let t=e[1];s>1&&(t+=\"+\"),d.push(t)}}});const c=document.createElement(\"div\");c.className=\"card-header\";const u=s.toLocaleDateString(\"de-DE\",{day:\"2-digit\",month:\"2-digit\"}),g=d.reduce((e,t)=>e+`${t}`,\"\");let m=\"\";const h=e.items&&e.items.some(t=>{const n=t.articleId||parseInt(t.id.split(\"_\")[1]),o=`${e.date}_${n}`;return a.L.has(o)&&a.L.get(o).length>0}),p=e.items&&e.items.some(e=>e.available);m=h?\"header-violet\":p&&!i?\"header-green\":\"header-red\";m&&c.classList.add(m);c.innerHTML=`\\n
    \\n ${(0,o.FS)(e.weekday)}\\n
    ${g}
    \\n
    \\n ${u}`,t.appendChild(c);const f=document.createElement(\"div\");f.className=\"card-body\";const v=(new Date).toISOString().split(\"T\")[0],y=e.date===v,b=[...e.items].sort((t,n)=>{if(y){const o=t.articleId||parseInt(t.id.split(\"_\")[1]),s=n.articleId||parseInt(n.id.split(\"_\")[1]),i=a.L.has(`${e.date}_${o}`),r=a.L.has(`${e.date}_${s}`);if(i&&!r)return-1;if(!i&&r)return 1}return t.name.localeCompare(n.name)});return b.forEach(t=>{const s=document.createElement(\"div\");s.className=\"menu-item\";const d=t.articleId||parseInt(t.id.split(\"_\")[1]),c=`${e.date}_${d}`,u=(a.L.get(c)||[]).length;let g=\"\";g=t.available?t.amountTracking?`${(0,l.t)(\"available\")} (${t.availableAmount})`:`${(0,l.t)(\"available\")}`:`${(0,l.t)(\"soldOut\")}`;let m=\"\";if(u>0){const t=u>1?`${u}`:\"\";m=`check_circle ${(0,l.t)(\"ordered\")}${t}`,s.classList.add(\"ordered\"),new Date(e.date).toDateString()===n.toDateString()&&s.classList.add(\"today-ordered\")}const h=`${e.date}_${d}`,p=a.BY.has(h);p&&s.classList.add(t.available?\"flagged-available\":\"flagged-sold-out\");const v=[...new Set([...(0,r.BM)(t.name),...(0,r.BM)(t.description)])];v.length>0&&s.classList.add(\"highlight-glow\");let y=\"\",b=\"\",w=\"\";if(a.gX&&!i){const n=p?\"notifications_active\":\"notifications_none\",a=p?\"btn-flag active\":\"btn-flag\",s=p?(0,l.t)(\"flagDeactivate\"):(0,l.t)(\"flagActivate\");if(t.available&&!p||(w=``),t.available&&(y=u>0?``:``),u>0){const n=1===u?\"close\":\"remove\",a=1===u?(0,l.t)(\"cancelOrder\"):(0,l.t)(\"cancelOneOrder\");b=``}}let E=\"\";if(v.length>0){E=`
    ${v.reduce((e,t)=>e+`star${(0,o.ZD)(t)}`,\"\")}
    `}s.innerHTML=`\\n
    \\n ${(0,o.ZD)(t.name)}\\n ${t.price.toFixed(2)} \u20ac\\n
    \\n
    \\n ${m}\\n ${b}\\n ${y}\\n ${w}\\n
    ${g}
    \\n
    \\n ${E}\\n

    ${(0,o.ZD)((0,o.PC)(t.description))}

    `;const A=s.querySelector(\".btn-order\");A&&A.addEventListener(\"click\",e=>{e.stopPropagation();const t=e.currentTarget;t.disabled=!0,t.classList.add(\"loading\"),(0,r.wH)(t.dataset.date,parseInt(t.dataset.article),t.dataset.name,parseFloat(t.dataset.price),t.dataset.desc||\"\").finally(()=>{t.disabled=!1,t.classList.remove(\"loading\")})});const k=s.querySelector(\".btn-cancel\");k&&k.addEventListener(\"click\",e=>{e.stopPropagation();const t=e.currentTarget;t.disabled=!0,(0,r.N4)(t.dataset.date,parseInt(t.dataset.article),t.dataset.name).finally(()=>{t.disabled=!1})});const L=s.querySelector(\".btn-flag\");L&&L.addEventListener(\"click\",e=>{e.stopPropagation();const t=e.currentTarget;(0,r.PQ)(t.dataset.date,parseInt(t.dataset.article),t.dataset.name,t.dataset.cutoff)}),f.appendChild(s)}),t.appendChild(f),t}(e);t&&c.appendChild(t)}),e.appendChild(c),setTimeout(()=>function(e){const t=e.querySelectorAll(\".menu-card\");if(0===t.length)return;let n=0;t.forEach(e=>{n=Math.max(n,e.querySelectorAll(\".menu-item\").length)});for(let e=0;e{const o=t.querySelectorAll(\".menu-item\");o[e]&&(o[e].style.height=\"auto\",n=Math.max(n,o[e].offsetHeight),a.push(o[e]))}),a.forEach(e=>{e.style.height=`${n}px`})}}(c),0)}async function u(e){const t=e?`${s.pe}/tags?per_page=20`:`${s.pe}/releases?per_page=20`,n=await fetch(t,{headers:(0,i.O)()});if(!n.ok){if(403===n.status)throw new Error(\"API Rate Limit erreicht (403). Bitte sp\u00e4ter erneut versuchen.\");throw new Error(`GitHub API ${n.status}`)}return(await n.json()).map(t=>{const n=e?t.name:t.tag_name;return{tag:n,name:e?n:t.name||n,url:`${s.d_}/${n}/dist/install.html`,body:t.body||\"\"}})}async function g(){const e=\"true\"===localStorage.getItem(s.LS.DEV_MODE);try{const t=await u(e);if(!t.length)return;localStorage.setItem(s.LS.VERSION_CACHE,JSON.stringify({timestamp:Date.now(),devMode:e,versions:t}));const n=t[0].tag;if(!(0,o.U4)(n,\"v1.6.18\"))return;const a=document.querySelector(\".header-left h1\");if(a&&!a.querySelector(\".update-icon\")){const e=document.createElement(\"a\");e.className=\"update-icon\",e.href=t[0].url,e.target=\"_blank\",e.innerHTML=\"\ud83c\udd95\",e.title=`Update: ${n} \u2014 Klick zum Installieren`,e.style.cssText=\"margin-left:8px;font-size:1em;text-decoration:none;cursor:pointer;vertical-align:middle;\",a.appendChild(e)}}catch(e){console.warn(\"[Kantine] Version check failed:\",e)}}function m(){const e=document.getElementById(\"version-modal\"),t=document.getElementById(\"version-list-container\"),n=document.getElementById(\"dev-mode-toggle\"),a=\"v1.6.18\";if(!e)return;e.classList.remove(\"hidden\");const i=document.getElementById(\"version-current\");i&&(i.textContent=a);const r=\"true\"===localStorage.getItem(s.LS.DEV_MODE);async function l(e){const i=n.checked;function r(e){if(!e||!e.length)return void(t.innerHTML='

    Keine Versionen gefunden.

    ');t.innerHTML='
      ';const n=t.querySelector(\".version-list\");e.forEach(e=>{const t=e.tag===a,s=(0,o.U4)(e.tag,a),i=document.createElement(\"li\");i.className=\"version-item\"+(t?\" current\":\"\");let r=\"\";t?r='\u2713 Installiert':s&&(r='\u2b06 Neu!');let l=\"\";t||(l=`Installieren`),i.innerHTML=`\\n
      \\n ${(0,o.ZD)(e.tag)}\\n ${r}\\n
      \\n ${l}\\n `,n.appendChild(i)})}t.innerHTML='

      Lade Versionen...

      ';try{const e=localStorage.getItem(s.LS.VERSION_CACHE);let t=null;if(e)try{t=JSON.parse(e)}catch(e){}t&&t.devMode===i&&t.versions&&r(t.versions);const n=await u(i),a=JSON.stringify(n);a!==(t?JSON.stringify(t.versions):\"\")&&(localStorage.setItem(s.LS.VERSION_CACHE,JSON.stringify({timestamp:Date.now(),devMode:i,versions:n})),r(n))}catch(e){t.innerHTML=`

      Fehler: ${(0,o.ZD)(e.message)}

      `}}n.checked=r,l(),n.onchange=()=>{localStorage.setItem(s.LS.DEV_MODE,n.checked),localStorage.removeItem(s.LS.VERSION_CACHE),l()}}function h(){if(!a.gX||!a.Ny)return void p();const e=new Date,t=e.getDay();if(0===t||6===t)return void p();const n=e.toISOString().split(\"T\")[0];let o=!1;for(const e of a.L.keys())if(e.startsWith(n)){o=!0;break}if(o)return void p();const s=new Date;s.setHours(10,0,0,0);const i=s-e;if(i<=0)return void p();const r=Math.floor(i/36e5),d=Math.floor(i%36e5/6e4),c=document.querySelector(\".header-center-wrapper\");if(!c)return;let u=document.getElementById(\"order-countdown\");if(u||(u=document.createElement(\"div\"),u.id=\"order-countdown\",c.insertBefore(u,c.firstChild)),u.innerHTML=`${(0,l.t)(\"orderDeadline\")}: ${r}h ${d}m`,i<36e5){u.classList.add(\"urgent\");const e=`kantine_notified_${n}`;localStorage.getItem(e)||(\"granted\"===Notification.permission?new Notification(\"Kantine: Bestellschluss naht!\",{body:\"Du hast heute noch nichts bestellt. Nur noch 1 Stunde!\",icon:\"\u23f3\"}):\"default\"===Notification.permission&&Notification.requestPermission(),localStorage.setItem(e,\"true\"))}else u.classList.remove(\"urgent\")}function p(){const e=document.getElementById(\"order-countdown\");e&&e.remove()}function f(e,t,n,a){const s=\"error-modal\";let i=document.getElementById(s);i&&i.remove(),i=document.createElement(\"div\"),i.id=s,i.className=\"modal hidden\",i.innerHTML=`\\n
      \\n
      \\n

      \\n signal_wifi_off\\n ${(0,o.ZD)(e)}\\n

      \\n
      \\n
      \\n

      ${t}

      \\n
      \\n \\n
      \\n
      \\n
      \\n `,document.body.appendChild(i),document.getElementById(\"btn-error-redirect\").addEventListener(\"click\",()=>{window.location.href=a}),requestAnimationFrame(()=>{i.classList.remove(\"hidden\")})}function v(){const e=document.getElementById(\"alarm-bell\"),t=document.getElementById(\"alarm-bell-icon\");if(!e||!t)return;if(0===a.BY.size)return e.classList.add(\"hidden\"),e.style.display=\"none\",t.style.color=\"var(--text-secondary)\",void(t.style.textShadow=\"none\");e.classList.remove(\"hidden\"),e.style.display=\"inline-flex\";let n=!1;for(const e of a.p_)if(e.days){for(const t of e.days)if(t.items){for(const e of t.items)if(e.available&&a.BY.has(e.id)){n=!0;break}if(n)break}if(n)break}const i=localStorage.getItem(s.LS.LAST_CHECKED),r=localStorage.getItem(s.LS.FLAGGED_LAST_CHECKED);let d=0;i&&(d=Math.max(d,new Date(i).getTime())),r&&(d=Math.max(d,new Date(r).getTime()));let c=\"gerade eben\";if(0===d){const e=(new Date).toISOString();localStorage.setItem(s.LS.LAST_CHECKED,e),d=new Date(e).getTime()}c=(0,o.gs)(new Date(d)),e.title=`${(0,l.t)(\"alarmLastChecked\")}: ${c}`,n?(t.style.color=\"#10b981\",t.style.textShadow=\"0 0 10px rgba(16, 185, 129, 0.4)\"):(t.style.color=\"#f59e0b\",t.style.textShadow=\"0 0 10px rgba(245, 158, 11, 0.4)\")}setInterval(h,6e4),setTimeout(h,1e3)},413(e,t,n){n.d(t,{Ao:()=>s,FS:()=>i,PC:()=>g,U4:()=>l,ZD:()=>r,gs:()=>d,sn:()=>o});var a=n(901);function o(e){const t=new Date(Date.UTC(e.getFullYear(),e.getMonth(),e.getDate())),n=t.getUTCDay()||7;t.setUTCDate(t.getUTCDate()+4-n);const a=new Date(Date.UTC(t.getUTCFullYear(),0,1));return Math.ceil(((t-a)/864e5+1)/7)}function s(e){const t=new Date(e.getTime());return t.setDate(t.getDate()+3-(t.getDay()+6)%7),t.getFullYear()}function i(e){if(\"en\"===a.Kl)return e;return{Monday:\"Montag\",Tuesday:\"Dienstag\",Wednesday:\"Mittwoch\",Thursday:\"Donnerstag\",Friday:\"Freitag\",Saturday:\"Samstag\",Sunday:\"Sonntag\"}[e]||e}function r(e){const t=document.createElement(\"div\");return t.textContent=e||\"\",t.innerHTML}function l(e,t){if(!e||!t)return!1;const n=e.replace(/^v/,\"\").split(\".\").map(Number),a=t.replace(/^v/,\"\").split(\".\").map(Number);for(let e=0;e(a[e]||0))return!0;if((n[e]||0)<(a[e]||0))return!1}return!1}function d(e){const t=Date.now()-e.getTime(),n=Math.floor(t/6e4);if(n<1)return\"gerade eben\";if(1===n)return\"vor 1 min.\";if(n<60)return`vor ${n} min.`;const a=Math.floor(n/60);return 1===a?\"vor 1 Std.\":`vor ${a} Std.`}const c=[\"apfel\",\"achtung\",\"aubergine\",\"auflauf\",\"beere\",\"blumenkohl\",\"bohne\",\"braten\",\"brokkoli\",\"brot\",\"brust\",\"br\u00f6tchen\",\"butter\",\"chili\",\"dessert\",\"dip\",\"eier\",\"eintopf\",\"eis\",\"erbse\",\"erdbeer\",\"essig\",\"filet\",\"fisch\",\"fisole\",\"fleckerl\",\"fleisch\",\"fl\u00fcgel\",\"frucht\",\"f\u00fcr\",\"gebraten\",\"gem\u00fcse\",\"gew\u00fcrz\",\"gratin\",\"grie\u00df\",\"gulasch\",\"gurke\",\"himbeer\",\"honig\",\"huhn\",\"h\u00e4hnchen\",\"jambalaya\",\"joghurt\",\"karotte\",\"kartoffel\",\"keule\",\"kirsch\",\"knacker\",\"knoblauch\",\"kn\u00f6del\",\"kompott\",\"kraut\",\"kr\u00e4uter\",\"kuchen\",\"k\u00e4se\",\"k\u00fcrbis\",\"lauch\",\"mandel\",\"milch\",\"mild\",\"mit\",\"mohn\",\"most\",\"m\u00f6hre\",\"natur\",\"nockerl\",\"nudel\",\"nuss\",\"nu\u00df\",\"obst\",\"oder\",\"olive\",\"paprika\",\"pfanne\",\"pfannkuchen\",\"pfeffer\",\"pikant\",\"pilz\",\"plunder\",\"p\u00fcree\",\"ragout\",\"rahm\",\"reis\",\"rind\",\"sahne\",\"salami\",\"salat\",\"salz\",\"sauer\",\"scharf\",\"schinken\",\"schnitte\",\"schnitzel\",\"schoko\",\"schupf\",\"schwein\",\"sellerie\",\"senf\",\"sosse\",\"so\u00dfe\",\"spargel\",\"sp\u00e4tzle\",\"speck\",\"spie\u00df\",\"spinat\",\"steak\",\"suppe\",\"s\u00fc\u00df\",\"tofu\",\"tomate\",\"topfen\",\"torte\",\"tr\u00fcffel\",\"und\",\"vanille\",\"vogerl\",\"vom\",\"wien\",\"wurst\",\"zucchini\",\"zum\",\"zur\",\"zwiebel\",\"\u00f6l\"],u=[\"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 g(e){if(\"all\"===a.Kl)return e||\"\";const t=function(e){if(!e)return{de:\"\",en:\"\",raw:\"\"};let t=e.replace(/(?:\\(|(?:\\/|\\s|^))([A-Z,]+)\\)\\s*(?=\\S)(?!\\s*\\/)/g,\"($1)\\n\u2022 \");function n(e){let t=0,n=0;return e.forEach(e=>{const a=e.toLowerCase().replace(/[^a-z\u00e4\u00f6\u00fc\u00df]/g,\"\");if(a){let o=0,s=0;c.includes(a)?o=a.length:c.forEach(e=>{a.includes(e)&&e.length>o&&(o=e.length)}),u.includes(a)?s=a.length:u.forEach(e=>{a.includes(e)&&e.length>s&&(s=e.length)}),o>0&&(t+=o/a.length),s>0&&(n+=s/a.length),/^[A-Z\u00c4\u00d6\u00dc]/.test(e)&&(t+=.5)}}),{de:t,en:n}}function a(e){const t=e.trim().split(/\\s+/);if(t.length<2)return{enPart:e,nextDe:\"\"};let a=-1,o=-9999;for(let e=1;er.de||r.en>0,m=l.de+c>l.en;g&&m&&u>o&&(o=u,a=e)}return-1!==a?{enPart:t.slice(0,a).join(\" \"),nextDe:t.slice(a).join(\" \")}:{enPart:e,nextDe:\"\"}}t.startsWith(\"\u2022 \")||(t=\"\u2022 \"+t);const o=/(.*?)(?:\\(|(?:\\/|\\s|^))([A-Z,]+)\\)\\s*(?!\\s*[/])/g;let s;const i=[];let r=0;for(;null!==(s=o.exec(e));)s.index>r&&i.push(e.substring(r,s.index).trim()),i.push(s[0].trim()),r=o.lastIndex;r=2){const e=i[0].trim();let t=i.slice(1).join(\" / \").trim();const n=a(t);if(n.nextDe){l.push(e+o),d.push(n.enPart+o);const t=n.nextDe+o;l.push(t),d.push(t)}else{const n=t+o,a=e.includes(o.trim())?e:e+o;l.push(a),d.push(n)}}else{const e=a(n);e.nextDe?(d.push(e.enPart+o),l.push(e.nextDe+o)):(l.push(n+o),d.push(n+o))}}let g=l.join(\"\\n\u2022 \");l.length>0&&!g.startsWith(\"\u2022 \")&&(g=\"\u2022 \"+g);let m=d.join(\"\\n\u2022 \");return d.length>0&&!m.startsWith(\"\u2022 \")&&(m=\"\u2022 \"+m),{de:g,en:m,raw:t}}(e);return\"en\"===a.Kl?t.en||t.raw:t.de||t.raw}}},t={};function n(a){var o=t[a];if(void 0!==o)return o.exports;var s=t[a]={exports:{}};return e[a](s,s.exports,n),s.exports}n.d=(e,t)=>{for(var a in t)n.o(t,a)&&!n.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var a=n(901);var o=n(367),s=n(842),i=n(521),r=n(672),l=n(646);if(!window.__KANTINE_LOADED){window.__KANTINE_LOADED=!0,function(){document.title=\"Kantine Weekly Menu\",document.querySelectorAll&&document.querySelectorAll('link[rel*=\"icon\"]').forEach(e=>e.remove());const e=document.createElement(\"link\");if(e.rel=\"icon\",e.type=\"image/png\",e.href=\"data:image/png;base64,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\",document.head.appendChild(e),!document.querySelector('link[href*=\"fonts.googleapis.com/css2?family=Inter\"]')){const e=document.createElement(\"link\");e.rel=\"stylesheet\",e.href=\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap\",document.head.appendChild(e)}if(!document.querySelector('link[href*=\"Material+Icons+Round\"]')){const e=document.createElement(\"link\");e.rel=\"stylesheet\",e.href=\"https://fonts.googleapis.com/icon?family=Material+Icons+Round\",document.head.appendChild(e)}const t=`\\n
      \\n
      \\n
      \\n
      \\n \"Logo\"\\n
      \\n

      Kantinen \u00dcbersicht v1.6.18

      \\n
      \\n
      \\n
      \\n \\n \\n
      \\n \\n
      \\n
      \\n
      \\n \\n \\n \\n
      \\n
      \\n
      \\n
      \\n
      \\n \\n \\n \\n \\n \\n
      \\n person\\n \\n \\n
      \\n
      \\n
      \\n
      \\n\\n
      \\n
      \\n
      \\n

      Login

      \\n \\n
      \\n
      \\n
      \\n \\n \\n Deine offizielle Knapp Mitarbeiternummer.\\n
      \\n
      \\n \\n \\n Das Passwort f\u00fcr deinen Bessa Account.\\n
      \\n
      \\n
      \\n \\n
      \\n
      \\n
      \\n
      \\n\\n
      \\n
      \\n
      \\n

      Men\u00fcdaten aktualisieren

      \\n
      \\n
      \\n
      \\n
      \\n
      \\n
      \\n
      0%
      \\n
      \\n

      Initialisierung...

      \\n
      \\n
      \\n
      \\n\\n
      \\n
      \\n
      \\n

      Meine Highlights

      \\n \\n
      \\n
      \\n

      \\n Markiere Men\u00fcs automatisch, wenn sie diese Schlagw\u00f6rter enthalten.\\n

      \\n
      \\n \\n \\n
      \\n
      \\n
      \\n
      \\n
      \\n\\n
      \\n
      \\n
      \\n

      Bestellhistorie

      \\n \\n
      \\n
      \\n
      \\n

      Lade Historie...

      \\n
      \\n
      \\n
      \\n
      \\n
      \\n
      \\n
      \\n
      \\n
      \\n
      \\n
      \\n\\n
      \\n
      \\n
      \\n

      \ud83d\udce6 Versionen

      \\n \\n
      \\n
      \\n
      \\n Aktuell: v1.6.18\\n
      \\n
      \\n \\n
      \\n
      \\n

      Lade Versionen...

      \\n
      \\n
      \\n \\n bug_report Fehler melden\\n \\n \\n lightbulb Feature vorschlagen\\n \\n \\n
      \\n
      \\n
      \\n
      \\n\\n
      \\n
      \\n update\\n Gerade aktualisiert\\n
      \\n
      \\n
      \\n

      Lade Men\u00fcdaten...

      \\n
      \\n
      \\n
      \\n\\n
      \\n

      Jetzt Bessa Einfach! • Knapp-Kantine Wrapper • ${(new Date).getFullYear()} by Kaufi \ud83d\ude03\ud83d\udc4d mit Hilfe von KI \ud83e\udd16

      \\n
      \\n
      `;document.body.innerHTML=t}(),function(){const e=document.getElementById(\"btn-this-week\"),t=document.getElementById(\"btn-next-week\"),n=document.getElementById(\"btn-refresh\"),d=document.getElementById(\"theme-toggle\"),c=document.getElementById(\"btn-login-open\"),u=document.getElementById(\"btn-login-close\"),g=document.getElementById(\"btn-logout\"),m=document.getElementById(\"login-form\"),h=document.getElementById(\"login-modal\"),p=document.getElementById(\"btn-highlights\"),f=document.getElementById(\"highlights-modal\"),v=document.getElementById(\"btn-highlights-close\"),y=document.getElementById(\"btn-add-tag\"),b=document.getElementById(\"tag-input\"),w=document.getElementById(\"btn-history\"),E=document.getElementById(\"history-modal\"),A=document.getElementById(\"btn-history-close\");document.querySelectorAll(\".lang-btn\").forEach(e=>{e.addEventListener(\"click\",()=>{(0,a.UD)(e.dataset.lang),localStorage.setItem(i.LS.LANG,e.dataset.lang),document.querySelectorAll(\".lang-btn\").forEach(e=>e.classList.remove(\"active\")),e.classList.add(\"active\"),function(){const e=document.getElementById(\"btn-this-week\"),t=document.getElementById(\"btn-next-week\");e&&(e.textContent=(0,l.t)(\"thisWeek\"),e.title=(0,l.t)(\"thisWeekTooltip\")),t&&(t.textContent=(0,l.t)(\"nextWeek\"));const n=document.querySelector(\".header-left h1\");if(n){const e=n.querySelector(\".version-tag\"),t=n.querySelector(\".update-icon\");n.textContent=(0,l.t)(\"appTitle\")+\" \",e&&n.appendChild(e),t&&n.appendChild(t)}const o=document.getElementById(\"btn-refresh\");o&&o.setAttribute(\"aria-label\",(0,l.t)(\"refresh\")),o&&(o.title=(0,l.t)(\"refresh\"));const i=document.getElementById(\"btn-history\");i&&i.setAttribute(\"aria-label\",(0,l.t)(\"history\")),i&&(i.title=(0,l.t)(\"history\"));const r=document.getElementById(\"btn-highlights\");r&&r.setAttribute(\"aria-label\",(0,l.t)(\"highlights\")),r&&(r.title=(0,l.t)(\"highlights\"));const d=document.getElementById(\"theme-toggle\");d&&(d.title=(0,l.t)(\"themeTooltip\"));const c=document.getElementById(\"btn-login-open\");if(c){c.title=(0,l.t)(\"loginTooltip\");const e=c.querySelector(\"span:last-child\");e&&!e.classList.contains(\"material-icons-round\")&&(e.textContent=(0,l.t)(\"login\"))}const u=document.getElementById(\"btn-logout\");u&&(u.title=(0,l.t)(\"logoutTooltip\"));const g=document.getElementById(\"lang-toggle\");g&&(g.title=(0,l.t)(\"langTooltip\"));const m=document.querySelector(\"#highlights-modal .modal-header h2\");m&&(m.textContent=(0,l.t)(\"highlightsTitle\"));const h=document.querySelector(\"#highlights-modal .modal-body > p\");h&&(h.textContent=(0,l.t)(\"highlightsDesc\"));const p=document.getElementById(\"tag-input\");p&&(p.placeholder=(0,l.t)(\"tagInputPlaceholder\"),p.title=(0,l.t)(\"tagInputTooltip\"));const f=document.getElementById(\"btn-add-tag\");f&&(f.textContent=(0,l.t)(\"addTag\"),f.title=(0,l.t)(\"addTagTooltip\"));const v=document.querySelector(\"#history-modal .modal-header h2\");v&&(v.textContent=(0,l.t)(\"historyTitle\"));const y=document.querySelector(\"#login-modal .modal-header h2\");y&&(y.textContent=(0,l.t)(\"loginTitle\"));const b=document.getElementById(\"alarm-bell\");b&&0===a.BY.size&&(b.title=(0,l.t)(\"alarmTooltipNone\")),(0,s.OR)(),(0,s.gJ)(),(0,s.Mb)()}()})}),p&&p.addEventListener(\"click\",()=>{(0,o.Y1)(),f.classList.remove(\"hidden\")}),v&&v.addEventListener(\"click\",()=>{f.classList.add(\"hidden\")}),w.addEventListener(\"click\",()=>{a.gX?(E.classList.remove(\"hidden\"),(0,o.Aq)()):h.classList.remove(\"hidden\")}),A.addEventListener(\"click\",()=>{E.classList.add(\"hidden\")}),window.addEventListener(\"click\",e=>{e.target===E&&E.classList.add(\"hidden\"),e.target===f&&f.classList.add(\"hidden\")});const k=document.querySelector(\".version-tag\"),L=document.getElementById(\"version-modal\"),S=document.getElementById(\"btn-version-close\");k&&k.addEventListener(\"click\",e=>{e.preventDefault(),e.stopPropagation(),(0,s.Gk)()}),S&&S.addEventListener(\"click\",()=>{L.classList.add(\"hidden\")});const I=document.getElementById(\"btn-clear-cache\");I&&I.addEventListener(\"click\",()=>{confirm(\"M\u00f6chtest du wirklich alle lokalen Daten (inkl. Login-Session, Cache und Einstellungen) l\u00f6schen? Die Seite wird danach neu geladen.\")&&(Object.keys(localStorage).forEach(e=>{e.startsWith(\"kantine_\")&&localStorage.removeItem(e)}),window.location.reload())}),window.addEventListener(\"click\",e=>{e.target===L&&L.classList.add(\"hidden\")}),y.addEventListener(\"click\",()=>{const e=b.value;(0,o.oL)(e)&&(b.value=\"\",(0,o.Y1)())}),b.addEventListener(\"keypress\",e=>{\"Enter\"===e.key&&y.click()});const C=localStorage.getItem(\"theme\"),B=window.matchMedia(\"(prefers-color-scheme: dark)\").matches,T=d.querySelector(\".theme-icon\");\"dark\"===C||!C&&B?(document.documentElement.setAttribute(\"data-theme\",\"dark\"),T.textContent=\"dark_mode\"):(document.documentElement.setAttribute(\"data-theme\",\"light\"),T.textContent=\"light_mode\"),d.addEventListener(\"click\",()=>{const e=\"dark\"===document.documentElement.getAttribute(\"data-theme\")?\"light\":\"dark\";document.documentElement.setAttribute(\"data-theme\",e),localStorage.setItem(\"theme\",e),T.textContent=\"dark\"===e?\"dark_mode\":\"light_mode\"}),e.addEventListener(\"click\",()=>{\"this-week\"!==a.sw&&((0,a.qo)(\"this-week\"),e.classList.add(\"active\"),t.classList.remove(\"active\"),(0,s.OR)())}),t.addEventListener(\"click\",()=>{t.classList.remove(\"new-week-available\"),\"next-week\"!==a.sw&&((0,a.qo)(\"next-week\"),t.classList.add(\"active\"),e.classList.remove(\"active\"),(0,s.OR)())}),n.addEventListener(\"click\",()=>{a.gX?(0,o.m9)():h.classList.remove(\"hidden\")});const D=document.getElementById(\"alarm-bell\");D&&D.addEventListener(\"click\",()=>{(0,o.A0)()}),c.addEventListener(\"click\",()=>{h.classList.remove(\"hidden\"),document.getElementById(\"login-error\").classList.add(\"hidden\"),m.reset()}),u.addEventListener(\"click\",()=>{h.classList.add(\"hidden\")}),window.addEventListener(\"click\",e=>{e.target===h&&h.classList.add(\"hidden\")}),m.addEventListener(\"submit\",async e=>{e.preventDefault();const t=document.getElementById(\"employee-id\").value.trim(),n=document.getElementById(\"password\").value,s=document.getElementById(\"login-error\"),l=m.querySelector('button[type=\"submit\"]'),d=l.textContent;l.disabled=!0,l.textContent=\"Wird eingeloggt...\";try{const e=`knapp-${t}@bessa.app`,l=await fetch(`${i.tE}/auth/login/`,{method:\"POST\",headers:(0,r.H)(i.f9),body:JSON.stringify({email:e,password:n})}),d=await l.json();if(l.ok){(0,a.O5)(d.key),(0,a.lt)(t),localStorage.setItem(i.LS.AUTH_TOKEN,d.key),localStorage.setItem(i.LS.CURRENT_USER,t);try{const e=await fetch(`${i.tE}/auth/user/`,{headers:(0,r.H)(d.key)});if(e.ok){const t=await e.json();t.first_name&&localStorage.setItem(i.LS.FIRST_NAME,t.first_name),t.last_name&&localStorage.setItem(i.LS.LAST_NAME,t.last_name)}}catch(e){console.error(\"Failed to fetch user info:\",e)}(0,o.i_)(),h.classList.add(\"hidden\"),(0,o.Gb)(),m.reset(),(0,o.g8)(),(0,o.m9)()}else s.textContent=d.non_field_errors?.[0]||d.error||\"Login fehlgeschlagen\",s.classList.remove(\"hidden\")}catch(e){console.error(\"Login error:\",e),s.textContent=\"Ein Fehler ist aufgetreten\",s.classList.remove(\"hidden\")}finally{l.disabled=!1,l.textContent=d}}),g.addEventListener(\"click\",()=>{localStorage.removeItem(i.LS.AUTH_TOKEN),localStorage.removeItem(i.LS.CURRENT_USER),localStorage.removeItem(i.LS.FIRST_NAME),localStorage.removeItem(i.LS.LAST_NAME),(0,a.O5)(null),(0,a.lt)(null),(0,a.di)(new Map),(0,o.Et)(),(0,o.i_)(),(0,s.OR)()})}(),(0,o.i_)(),(0,o.H)();(0,o.KG)()?(document.getElementById(\"loading\").classList.add(\"hidden\"),(0,o.VL)()||(0,o.m9)()):(0,o.m9)(),a.gX&&(0,o.g8)(),(0,s.Ux)(),setInterval(s.Ux,36e5)}})();\n"; document.head.appendChild(sc); })(); diff --git a/dist/bookmarklet.txt b/dist/bookmarklet.txt index 29a8a6f..e05952c 100755 --- a/dist/bookmarklet.txt +++ b/dist/bookmarklet.txt @@ -1 +1 @@ -javascript:javascript:(function(){ if(window.__KANTINE_LOADED){alert('Kantine Wrapper already loaded!');return;} var s=document.createElement('style');s.textContent=':root { /* Premium Slate/Gray-Blue Palette - Light Mode */ --bg-body: #f1f5f9; /* Slate 100 */ --bg-card: #ffffff; --text-primary: #334155; /* Slate 700 */ --text-secondary: #64748b; --accent-color: #0f172a; /* Slate 900 (High contrast) */ --border-color: #cbd5e1; /* Slate 300 */ --banner-bg: #e2e8f0; --banner-text: #1e293b; --success-color: #059669; --error-color: #dc2626; --card-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.05), 0 2px 4px -2px rgb(0 0 0 / 0.05); --header-bg: rgba(255, 255, 255, 0.9); --header-border: 1px solid rgba(203, 213, 225, 0.6); } [data-theme="dark"] { /* Premium Slate/Gray-Blue Palette - Dark Mode */ --bg-body: #1e293b; /* Deep Slate Gray (Requested) */ --bg-card: #334155; /* Slate 700 */ --text-primary: #f8fafc; /* Slate 50 */ --text-secondary: #cbd5e1; /* Slate 300 */ --accent-color: #60a5fa; /* Blue 400 */ --border-color: #475569; /* Slate 600 */ --banner-bg: #475569; --banner-text: #e2e8f0; --header-bg: rgba(30, 41, 59, 0.9); --header-border: 1px solid rgba(71, 85, 105, 0.6); --card-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.4); } * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: \'Inter\', system-ui, -apple-system, sans-serif; background-color: var(--bg-body); color: var(--text-primary); transition: background-color 0.3s ease, color 0.3s ease; line-height: 1.5; -webkit-font-smoothing: antialiased; } /* Fix scrolling bug: Reset html/body styles from host page */ /* IMPORTANT: html must NOT have overflow set, or it creates a scroll container that breaks position: sticky */ html { height: auto !important; min-height: 100% !important; overflow: visible !important; position: static !important; margin: 0 !important; padding: 0 !important; } body { height: auto !important; min-height: 100% !important; overflow-x: clip !important; /* clip prevents horizontal overflow without breaking sticky */ overflow-y: visible !important; position: static !important; margin: 0 !important; padding: 0 !important; } /* Header */ .app-header { flex-shrink: 0; z-index: 100; backdrop-filter: blur(12px); background-color: var(--header-bg); border-bottom: var(--header-border); padding: 1rem 0; } .header-content { width: 100%; /* Full width */ padding: 0 2rem; /* Comfortable padding */ display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 1rem; } .brand { display: flex; align-items: center; gap: 0.75rem; } .brand-text { display: flex; flex-direction: column; } .brand h1 { font-size: 1.25rem; font-weight: 700; letter-spacing: -0.025em; margin-bottom: 0; } .subtitle { font-size: 0.85rem; color: var(--text-secondary); font-weight: 400; margin-left: 2px; } .logo-icon { font-size: 1.5rem; color: var(--accent-color); } /* Controls */ .controls { display: flex; align-items: center; gap: 1.5rem; justify-self: end; } /* Header Week Info (centered) */ .header-week-info { text-align: center; line-height: 1.3; } .header-center-wrapper { display: flex; flex-direction: row; align-items: center; gap: 1.5rem; justify-content: center; } .header-week-title { font-size: 1.1rem; font-weight: 600; color: var(--text-primary); } .header-week-subtitle { font-size: 0.85rem; color: var(--text-secondary); } /* Language Toggle (FR-100) */ .lang-toggle { display: inline-flex; gap: 0; border-radius: 6px; overflow: hidden; border: 1px solid var(--border-color); background: var(--bg-card); } .lang-btn { padding: 3px 10px; font-size: 0.7rem; font-weight: 600; letter-spacing: 0.03em; background: transparent; color: var(--text-secondary); border: none; cursor: pointer; transition: all 0.2s; } .lang-btn:hover { color: var(--text-primary); background: rgba(100, 116, 139, 0.1); } .lang-btn.active { background: var(--accent-color); color: white; } .nav-group { display: flex; background-color: var(--bg-card); border: 1px solid var(--border-color); padding: 0.25rem; border-radius: 8px; } .nav-btn { background: none; border: none; padding: 0.5rem 1rem; font-size: 0.875rem; font-weight: 500; color: var(--text-secondary); cursor: pointer; border-radius: 6px; transition: all 0.2s; display: flex; align-items: center; gap: 0.5rem; } .nav-btn:hover { color: var(--text-primary); background-color: rgba(100, 116, 139, 0.1); } .nav-btn.active { background-color: var(--accent-color); color: white; } /* Notification state for Next Week */ .nav-btn.new-week-available { animation: goldPulse 2s infinite; border-color: #f59e0b; color: var(--accent-color); } .nav-btn.new-week-available.active { color: white; } @keyframes goldPulse { 0% { box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.7); } 70% { box-shadow: 0 0 0 10px rgba(245, 158, 11, 0); } 100% { box-shadow: 0 0 0 0 rgba(245, 158, 11, 0); } } /* Badge for nav buttons (day count indicator) */ .nav-badge { background-color: var(--error-color); color: white; font-size: 0.75rem; font-weight: 600; padding: 0 6px; border-radius: 10px; min-width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center; margin-left: 8px; gap: 3px; line-height: 1; } .nav-badge .orderable { color: #fff; font-weight: 800; } .nav-badge .separator { opacity: 0.6; font-weight: 400; } .nav-badge .total { opacity: 0.8; font-weight: 400; } .nav-btn.active .nav-badge { background: rgba(255, 255, 255, 0.3); } /* Primary style for Login Button to match header */ #btn-login-open { background-color: var(--accent-color); color: white; padding: 0.5rem 1.25rem; border-radius: 8px; font-weight: 600; letter-spacing: 0.025em; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } #btn-login-open:hover { background-color: #334155; /* Slightly lighter than slate-900 */ transform: translateY(-1px); box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } /* User Badge Button (Login) */ .user-badge-btn { display: flex; align-items: center; gap: 8px; padding: 6px 12px; background: var(--bg-card); border: 1px solid var(--border-color); border-radius: 20px; font-size: 0.9rem; font-weight: 500; color: var(--text-primary); cursor: pointer; transition: all 0.2s; } .user-badge-btn:hover { background: rgba(100, 116, 139, 0.1); border-color: var(--accent-color); } .user-badge-btn .material-icons-round { font-size: 1.25rem; color: var(--accent-color); } .icon-btn { background: none; border: none; color: var(--text-primary); cursor: pointer; padding: 0.5rem; border-radius: 50%; transition: background-color 0.2s; display: flex; align-items: center; justify-content: center; } .icon-btn:hover { background-color: rgba(100, 116, 139, 0.1); } /* Refresh button animation */ #btn-refresh.refreshing .material-icons-round, #alarm-bell.refreshing .material-icons-round { animation: rotate 1s linear infinite; } @keyframes rotate { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } /* Progress Modal */ .progress-container { margin-bottom: 1.5rem; } .progress-bar { width: 100%; height: 8px; background-color: var(--border-color); border-radius: 4px; overflow: hidden; margin-bottom: 0.75rem; } .progress-fill { height: 100%; background: linear-gradient(90deg, var(--accent-color) 0%, #60a5fa 100%); width: 0%; transition: width 0.3s ease; border-radius: 4px; } .progress-percent { text-align: center; font-size: 1.5rem; font-weight: 700; color: var(--text-primary); margin-bottom: 0.5rem; } .progress-message { text-align: center; color: var(--text-secondary); font-size: 0.9rem; font-weight: 500; } .weekly-cost { background-color: rgba(59, 130, 246, 0.1); /* Blue tint */ color: var(--accent-color); padding: 0.4rem 0.8rem; border-radius: 8px; font-weight: 600; font-size: 0.9rem; display: flex; align-items: center; gap: 0.5rem; border: 1px solid rgba(59, 130, 246, 0.2); } .weekly-cost .material-icons-round { font-size: 18px; } /* Container - flex column, full width so child scrollbar is at edge */ .container { flex: 1; width: 100%; overflow: hidden; padding: 0 0 0 0; /* Only top padding, no horizontal so child fills width */ display: flex; flex-direction: column; } /* Add horizontal padding to direct children of container to maintain layout */ .container>*:not(.menu-grid) { padding-left: 2rem; padding-right: 2rem; } /* Banner */ .banner { background-color: var(--banner-bg); color: var(--banner-text); padding: 0.75rem 1rem; border-radius: 8px; display: flex; align-items: center; gap: 0.5rem; margin-bottom: 2rem; font-size: 0.875rem; font-weight: 500; border: 1px solid var(--border-color); max-width: fit-content; } /* User Badge */ .user-badge { display: flex; align-items: center; gap: 8px; padding: 6px 12px; background: var(--bg-card); /* Changed from --surface */ border: 1px solid var(--border-color); /* Changed from --border */ border-radius: 20px; font-size: 0.9rem; font-weight: 500; } .icon-btn-small { background: none; border: none; padding: 4px; cursor: pointer; color: var(--text-secondary); /* Changed from --text-muted */ display: flex; align-items: center; justify-content: center; border-radius: 50%; transition: all 0.2s; } .icon-btn-small:hover { color: var(--error-color); /* Changed from --danger */ background: rgba(239, 68, 68, 0.1); } /* Modal */ .modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); backdrop-filter: blur(4px); display: flex; align-items: center; justify-content: center; z-index: 1000; transition: all 0.3s; } .modal.hidden { opacity: 0; pointer-events: none; } .modal-content { background: var(--bg-card); width: 90%; max-width: 400px; border-radius: 16px; box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); overflow: hidden; animation: modalSlide 0.3s ease-out; } /* History Modal specific */ .history-modal-content { max-width: 600px; max-height: 85vh; display: flex; flex-direction: column; } .history-modal-content .modal-body { overflow-y: auto; padding: 0; /* Padding is handled by inner elements */ } /* History Styles */ .history-year-group { margin-bottom: 16px; } .history-year-header { background: var(--bg-card); padding: 12px 20px; margin: 0; font-size: 1.2rem; font-weight: 700; color: var(--text-primary); border-bottom: 2px solid var(--border-color); position: sticky; top: 0; z-index: 12; } .history-month-group { border-bottom: 1px solid var(--border-color); } .history-month-header { display: flex; justify-content: space-between; align-items: center; padding: 14px 20px; margin: 0; font-size: 1.05rem; font-weight: 600; color: var(--text-primary); background: var(--bg-body); cursor: pointer; transition: background 0.2s; } .history-month-header:hover { background: var(--border-color); /* Slight hover effect */ } .history-month-summary { display: flex; align-items: center; gap: 12px; font-size: 0.95rem; color: var(--text-secondary); } .history-month-content { display: none; /* Collapsed by default */ background: var(--bg-card); } .history-month-group.open .history-month-content { display: block; /* Expanded when open class is present */ } .history-month-group.open .history-month-header .material-icons-round { transform: rotate(180deg); } .history-month-header .material-icons-round { transition: transform 0.3s; font-size: 20px; } .history-week-group { padding: 12px 20px; border-bottom: 1px dashed var(--border-color); } .history-week-group:last-child { border-bottom: none; } .history-week-header { display: flex; justify-content: space-between; align-items: center; font-size: 0.9rem; font-weight: 600; color: var(--text-secondary); margin-bottom: 10px; } .history-week-summary { font-size: 0.85rem; font-weight: 500; background: rgba(100, 116, 139, 0.1); padding: 4px 10px; border-radius: 12px; } .history-items { display: flex; flex-direction: column; gap: 8px; } .history-item { display: grid; grid-template-columns: 50px 1fr auto; align-items: center; gap: 12px; padding: 10px 12px; background: var(--bg-body); border-radius: 8px; border: 1px solid var(--border-color); } .history-item-date { font-size: 0.85rem; color: var(--text-secondary); font-weight: 500; } .history-item-details { display: flex; flex-direction: column; gap: 4px; } .history-item-name { font-size: 0.95rem; font-weight: 500; color: var(--text-primary); } .history-item-price { font-weight: 600; color: var(--text-primary); } .history-item-status { font-size: 0.8rem; font-weight: 600; color: var(--text-primary); text-transform: uppercase; letter-spacing: 0.5px; } .history-item-cancelled { opacity: 0.5; filter: grayscale(1); } .history-item-price-cancelled { text-decoration: line-through; color: var(--text-secondary); } @keyframes modalSlide { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } .modal-header { display: flex; align-items: center; justify-content: space-between; padding: 20px; border-bottom: 1px solid var(--border-color); } .modal-header h2 { margin: 0; font-size: 1.25rem; } .modal-body { padding: 20px; } #login-form { padding: 20px; } .form-group { margin-bottom: 20px; } .form-group label { display: block; margin-bottom: 6px; font-weight: 500; font-size: 0.9rem; } .form-group input { width: 100%; padding: 10px 12px; border: 1px solid var(--border-color); /* Changed from --border */ border-radius: 8px; background: var(--bg-body); /* Changed from --bg */ color: var(--text-primary); /* Changed from --text */ font-family: inherit; transition: border-color 0.2s; } .form-group input:focus { outline: none; border-color: var(--accent-color); /* Changed from --primary */ } .help-text { display: block; margin-top: 4px; color: var(--text-secondary); /* Changed from --text-muted */ font-size: 0.75rem; } .error-msg { margin-bottom: 16px; padding: 10px; background: rgba(239, 68, 68, 0.1); color: var(--error-color); /* Changed from --danger */ border-radius: 8px; font-size: 0.85rem; text-align: center; } .modal-actions { margin-top: 24px; } .btn-primary.wide { width: 100%; justify-content: center; } .hidden { display: none !important; } /* Menu Grid Container */ .menu-grid { display: flex; flex-direction: column; flex: 1; overflow: hidden; gap: 1rem; } .week-section { margin-bottom: 2rem; } .week-header { margin-bottom: 1.5rem; border-bottom: 1px solid var(--border-color); padding-bottom: 1rem; text-align: center; } .week-title { font-size: 1.75rem; font-weight: 700; color: var(--text-primary); } .week-range { color: var(--text-secondary); font-size: 0.9rem; margin-top: 0.25rem; } /* Full-viewport layout: header + scrollable content + footer */ #kantine-wrapper { display: flex; flex-direction: column; height: 100vh; height: 100dvh; /* Dynamic viewport height for mobile browsers */ overflow: hidden; } .days-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 0.5rem; flex: 1; overflow-y: auto; /* This is the scroll container at the window edge */ align-content: start; padding: 0 2rem 2rem 2rem; } /* Card */ .menu-card { background-color: var(--bg-card); border-radius: 12px; border: 1px solid var(--border-color); box-shadow: var(--card-shadow); overflow: clip; /* Clips scrolling content behind sticky header */ transition: box-shadow 0.2s ease; display: flex; flex-direction: column; } /* Past Day Styling - Target specific elements so ordered items can remain visible AND preserve sticky context */ /* We MUST apply filter/opacity to children, not the parent .menu-card, or else position: sticky breaks */ /* Header keeps fully opaque background to hide scrolling items, only grayscales */ .menu-card.past-day .card-header { filter: grayscale(0.8); transition: filter 0.3s; } /* Items become semi-transparent */ .menu-card.past-day .menu-item:not(.ordered) { opacity: 0.6; filter: grayscale(0.8); transition: opacity 0.3s, filter 0.3s; } .menu-card.past-day:hover .card-header { filter: grayscale(0.4); } .menu-card.past-day:hover .menu-item:not(.ordered) { opacity: 0.8; filter: grayscale(0.4); } /* Past ordered items get no special frame or shadow, but remain visually distinct by staying fully opaque (via the :not(.ordered) selector above) */ .menu-item.today-ordered { border: 2px solid #8b5cf6; box-shadow: 0 0 30px rgba(139, 92, 246, 0.6); border-radius: 8px; padding: 1rem; margin: 0 -1rem 1.5rem -1rem; background: var(--bg-card); position: relative; z-index: 5; animation: pulse-glow-strong 3s infinite; } @keyframes pulse-glow-strong { 0% { box-shadow: 0 0 20px rgba(139, 92, 246, 0.4); } 50% { box-shadow: 0 0 40px rgba(139, 92, 246, 0.8); } 100% { box-shadow: 0 0 20px rgba(139, 92, 246, 0.4); } } .menu-card:hover { box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); } .card-header { padding: 1rem 1.25rem; border-bottom: 1px solid var(--border-color); display: flex; justify-content: space-between; align-items: baseline; background-color: var(--bg-card); /* Removed border-radius: 12px 12px 0 0; .menu-card\'s overflow: clip will round the corners initially. When sticky at the top, it will be square and perfectly hide scrolling content! */ /* Sticky within .container scroll area */ position: sticky; top: 0; z-index: 90; } .card-body { padding: 1.25rem; display: grid; grid-template-rows: auto; align-content: start; } .day-name { font-size: 1.125rem; font-weight: 600; } .day-date { font-size: 0.875rem; color: var(--text-secondary); } .empty-state { color: var(--text-secondary); font-style: italic; text-align: center; padding: 1rem; } /* Menu Items */ .menu-item { margin-bottom: 1.5rem; padding-bottom: 1.5rem; border-bottom: 1px solid var(--border-color); } .menu-item:last-child { margin-bottom: 0; padding-bottom: 0; border-bottom: none; } .item-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 0.5rem; gap: 1rem; } .item-name { font-weight: 600; color: var(--text-primary); font-size: 1rem; } .item-price { font-weight: 700; color: var(--accent-color); white-space: nowrap; } .item-desc { font-size: 0.875rem; color: var(--text-secondary); line-height: 1.6; margin-bottom: 0.75rem; white-space: pre-wrap; } .badges { display: flex; gap: 0.5rem; margin-left: auto; flex-wrap: wrap; } .item-status-row { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.75rem; flex-wrap: wrap; } .badge { display: inline-flex; align-items: center; justify-content: center; height: 24px; font-size: 0.75rem; padding: 0 10px; border-radius: 4px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; line-height: normal; white-space: nowrap; } .badge.available { background-color: rgba(16, 185, 129, 0.1); /* Emerald 500 / 10% */ color: var(--success-color); border: 1px solid rgba(16, 185, 129, 0.2); } .badge.sold-out { background-color: rgba(239, 68, 68, 0.1); /* Red 500 / 10% */ color: var(--error-color); border: 1px solid rgba(239, 68, 68, 0.2); } .badge.ordered { background-color: rgba(139, 92, 246, 0.1); /* Violet 500 / 10% */ color: #8b5cf6; border: 1px solid rgba(139, 92, 246, 0.2); gap: 4px; } .badge.ordered .material-icons-round { font-size: 1rem; } /* Loading */ .loading-state { text-align: center; padding: 4rem; color: var(--text-secondary); } .spinner { width: 40px; height: 40px; border: 3px solid var(--border-color); border-top-color: var(--accent-color); border-radius: 50%; margin: 0 auto 1rem; animation: spin 1s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } /* Footer */ .app-footer { flex-shrink: 0; text-align: center; padding: 0.4rem 2rem; color: var(--text-secondary); font-size: 0.8rem; border-top: 1px solid var(--border-color); } /* === Order / Cancel Buttons (inline in status row) === */ .btn-order { display: inline-flex; align-items: center; gap: 4px; padding: 4px 10px; border: none; border-radius: 6px; background: var(--success-color); color: white; font-size: 0.75rem; font-weight: 600; cursor: pointer; transition: all 0.2s ease; font-family: inherit; } .btn-order .material-icons-round { font-size: 16px; } .btn-order:hover:not(:disabled) { filter: brightness(1.15); transform: translateY(-1px); } .btn-order:disabled { opacity: 0.5; cursor: not-allowed; } .btn-order.loading { pointer-events: none; opacity: 0.6; } .btn-order-compact { padding: 2px 4px; gap: 0; } .btn-order-compact .material-icons-round { font-size: 16px; } .btn-cancel { display: inline-flex; align-items: center; justify-content: center; padding: 4px 6px; border: none; border-radius: 6px; background: var(--error-color); color: white; font-size: 0.75rem; cursor: pointer; transition: all 0.2s ease; font-family: inherit; } .btn-cancel .material-icons-round { font-size: 16px; } .btn-cancel:hover:not(:disabled) { filter: brightness(1.15); transform: translateY(-1px); } .btn-cancel:disabled { opacity: 0.5; cursor: not-allowed; } /* Past days: hide action buttons */ .past-day .item-actions { display: none; } /* Order count badge (for multi-orders) */ .order-count-badge { display: inline-flex; align-items: center; justify-content: center; background: rgba(255, 255, 255, 0.3); color: white; font-size: 0.65rem; font-weight: 700; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px; margin-left: 4px; line-height: 1; } /* === Toast Notifications === */ #toast-container { position: fixed; bottom: 20px; right: 20px; z-index: 10000; display: flex; flex-direction: column; gap: 8px; pointer-events: none; } .toast { display: flex; align-items: center; gap: 8px; padding: 10px 16px; border-radius: 8px; font-size: 0.85rem; font-weight: 500; font-family: \'Inter\', sans-serif; color: white; backdrop-filter: blur(10px); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); pointer-events: auto; transform: translateX(120%); opacity: 0; transition: transform 0.3s ease, opacity 0.3s ease; } .toast.show { transform: translateX(0); opacity: 1; } .toast .material-icons-round { font-size: 18px; } .toast-success { background: rgba(5, 150, 105, 0.95); } .toast-error { background: rgba(220, 38, 38, 0.95); } .toast-info { background: rgba(59, 130, 246, 0.95); } /* === Mobile Responsiveness === */ @media (max-width: 600px) { .header-content { flex-direction: column; gap: 1rem; padding: 0.75rem; } .week-nav { width: 100%; justify-content: center; } .nav-pills { width: 100%; justify-content: space-between; } .nav-btn { flex: 1; justify-content: center; padding: 0.5rem; font-size: 0.85rem; } .days-grid { grid-template-columns: 1fr; /* Force single column */ } .main-content { padding: 1rem; } .week-title { font-size: 1.5rem; } /* Adjust toast position for mobile */ .toast-container { bottom: 1rem; right: 1rem; left: 1rem; /* Center on mobile */ width: auto; } .menu-card { margin-bottom: 1rem; } } /* Tighter layout for high column counts (e.g., 5-day landscape) */ @media (min-width: 1024px) { .card-body { padding: 1rem 0.75rem; } .item-header { gap: 0.5rem; } } /* === Flagging & Notification Styles === */ .btn-flag { display: inline-flex; align-items: center; justify-content: center; background: transparent; border: 1px solid var(--text-secondary); color: var(--text-secondary); border-radius: 6px; padding: 4px; cursor: pointer; transition: all 0.2s; margin-right: 0.5rem; width: 28px; height: 28px; } .btn-flag:hover { background: rgba(234, 179, 8, 0.1); /* Yellow-500 / 10% */ color: #eab308; border-color: #eab308; } .btn-flag.active { background: rgba(234, 179, 8, 0.1); color: #eab308; border-color: #eab308; } .btn-flag .material-icons-round { font-size: 1.1rem; } /* Flagged & Sold Out (Yellow Glow) */ .menu-item.flagged-sold-out { border: 1px solid #eab308; box-shadow: 0 0 10px rgba(234, 179, 8, 0.2); border-radius: 8px; padding: 1rem; margin: 0 -1rem 1.5rem -1rem; background: var(--bg-card); position: relative; z-index: 5; animation: yellow-pulse 3s infinite; } @keyframes yellow-pulse { 0% { box-shadow: 0 0 8px rgba(234, 179, 8, 0.2); } 50% { box-shadow: 0 0 16px rgba(234, 179, 8, 0.5); } 100% { box-shadow: 0 0 8px rgba(234, 179, 8, 0.2); } } /* Flagged & Available (Green Glow) */ .menu-item.flagged-available { border: 2px solid var(--success-color); box-shadow: 0 0 15px rgba(16, 185, 129, 0.3); border-radius: 8px; padding: 1rem; margin: 0 -1rem 1.5rem -1rem; background: var(--bg-card); position: relative; z-index: 5; animation: green-pulse 3s infinite; } @keyframes green-pulse { 0% { box-shadow: 0 0 10px rgba(16, 185, 129, 0.3); } 50% { box-shadow: 0 0 20px rgba(16, 185, 129, 0.6); } 100% { box-shadow: 0 0 10px rgba(16, 185, 129, 0.3); } } /* Day Header Badges */ .day-header-left { display: flex; align-items: center; gap: 0.75rem; } .menu-code-badge { font-size: 0.75rem; font-weight: 700; color: #8b5cf6; /* Violet 500 */ background-color: rgba(139, 92, 246, 0.15); border: 1px solid rgba(139, 92, 246, 0.3); padding: 2px 6px; border-radius: 6px; line-height: normal; display: inline-block; } /* Detailed Badge Colors */ .nav-badge.badge-violet { background-color: #8b5cf6; } .nav-badge.badge-green { background-color: var(--success-color); } .nav-badge.badge-red { background-color: var(--error-color); } .nav-badge.badge-blue { background-color: var(--accent-color); } /* Day Header Status Colors (User Request) */ .card-header.header-violet { background-color: var(--bg-card); background-image: linear-gradient(rgba(139, 92, 246, 0.15), rgba(139, 92, 246, 0.15)); border-bottom: 2px solid #8b5cf6; } .card-header.header-green { background-color: var(--bg-card); background-image: linear-gradient(rgba(16, 185, 129, 0.15), rgba(16, 185, 129, 0.15)); border-bottom: 2px solid var(--success-color); } .card-header.header-red { background-color: var(--bg-card); background-image: linear-gradient(rgba(239, 68, 68, 0.15), rgba(239, 68, 68, 0.15)); border-bottom: 2px solid var(--error-color); } .card-header.header-violet .day-name, .card-header.header-green .day-name, .card-header.header-red .day-name { font-weight: 700; color: var(--text-primary); /* Ensure text remains standard color */ } /* Update Icon */ .update-icon { display: inline-flex; align-items: center; justify-content: center; margin-left: 8px; background-color: rgba(16, 185, 129, 0.2); /* Green tint */ color: var(--success-color); border-radius: 50%; width: 24px; height: 24px; cursor: pointer; font-size: 14px; transition: all 0.2s; text-decoration: none; animation: pulse 2s infinite; } .update-icon:hover { background-color: var(--success-color); color: white; transform: scale(1.1); } @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.4); } 70% { box-shadow: 0 0 0 6px rgba(16, 185, 129, 0); } 100% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0); } } /* Order Countdown */ #order-countdown { background: rgba(255, 255, 255, 0.1); padding: 0.25rem 0.75rem; border-radius: 99px; font-size: 0.85rem; display: flex; align-items: center; gap: 0.5rem; white-space: nowrap; border: 1px solid var(--border-color); } #order-countdown span { opacity: 0.7; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.5px; } #order-countdown.urgent { background: rgba(239, 68, 68, 0.2); border-color: rgba(239, 68, 68, 0.5); color: #ef4444; animation: pulse-red 2s infinite; } @keyframes pulse-red { 0% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.4); } 70% { box-shadow: 0 0 0 6px rgba(239, 68, 68, 0); } 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0); } } /* Smart Highlights (Blue Glow - matches today-ordered/flagged pattern) */ .menu-item.highlight-glow { border: 2px solid rgba(59, 130, 246, 0.7); box-shadow: 0 0 20px rgba(59, 130, 246, 0.4); border-radius: 8px; padding: 1rem; margin: 0 -1rem 1.5rem -1rem; background: var(--bg-card); position: relative; z-index: 5; animation: blue-pulse 3s infinite; } @keyframes blue-pulse { 0% { box-shadow: 0 0 15px rgba(59, 130, 246, 0.3); } 50% { box-shadow: 0 0 25px rgba(59, 130, 246, 0.6); } 100% { box-shadow: 0 0 15px rgba(59, 130, 246, 0.3); } } /* Nav Badge with Count */ .nav-badge.has-highlights { background-color: var(--bg-card); /* Neutral background */ color: var(--text-primary); border: 1px solid var(--border-color); padding: 2px 6px; } .nav-badge .highlight-count { color: #3b82f6; /* Blue 500 */ font-weight: 700; margin-left: 4px; } /* Tag Management Modal */ #tags-list { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1rem; min-height: 50px; } /* Tag badges styled consistently with .badge (verfügbar/ausverkauft) */ .tag-badge { display: inline-flex; align-items: center; justify-content: center; height: 24px; font-size: 0.75rem; padding: 0 10px; border-radius: 4px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; line-height: normal; white-space: nowrap; background-color: rgba(59, 130, 246, 0.1); color: #3b82f6; border: 1px solid rgba(59, 130, 246, 0.2); gap: 4px; } .tag-remove { cursor: pointer; opacity: 0.7; font-size: 1.1em; line-height: 1; transition: all 0.2s; } .tag-remove:hover { opacity: 1; color: #ef4444; } .input-group { display: flex; gap: 0.5rem; } .input-group input { flex: 1; padding: 0.75rem; background: var(--bg-body); border: 1px solid var(--border-color); color: var(--text-primary); border-radius: 8px; font-family: inherit; } /* Add tag button - styled like .btn-order with nav-btn.active color */ #btn-add-tag { display: inline-flex; align-items: center; gap: 4px; padding: 0.5rem 1rem; border: none; border-radius: 6px; background: var(--accent-color); color: white; font-size: 0.8rem; font-weight: 600; cursor: pointer; transition: all 0.2s ease; font-family: inherit; white-space: nowrap; } #btn-add-tag:hover { filter: brightness(1.15); transform: translateY(-1px); } .matched-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; /* Space between tags and title */ margin-top: -5px; /* Pull closer to header */ } .tag-badge-small { display: inline-flex; align-items: center; font-size: 0.7rem; padding: 2px 8px; border-radius: 4px; background: rgba(59, 130, 246, 0.15); color: #60a5fa; border: 1px solid rgba(59, 130, 246, 0.3); font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; } [data-theme="light"] .tag-badge-small { background: rgba(37, 99, 235, 0.1); color: #2563eb; border: 1px solid rgba(37, 99, 235, 0.2); } /* Installer Changelog */ .changelog-container ul { padding-left: 1.5rem; margin: 0.5rem 0; } .changelog-container li { margin-bottom: 0.4rem; line-height: 1.5; } .changelog-container h3 { margin-top: 1.5rem; margin-bottom: 0.5rem; font-size: 1.1em; color: var(--accent-color); } /* === Version Menu === */ .version-tag { cursor: pointer; transition: opacity 0.2s ease, text-decoration 0.2s ease; } .version-tag:hover { opacity: 1 !important; text-decoration: underline; } .version-list { list-style: none; padding: 0; margin: 0; } .version-item { display: flex; justify-content: space-between; align-items: center; padding: 10px 14px; border-radius: 8px; margin-bottom: 4px; transition: background 0.2s; } .version-item:hover { background: rgba(100, 116, 139, 0.08); } .version-item.current { background: rgba(2, 154, 168, 0.1); border: 1px solid rgba(2, 154, 168, 0.25); } [data-theme="dark"] .version-item:hover { background: rgba(255, 255, 255, 0.05); } [data-theme="dark"] .version-item.current { background: rgba(96, 165, 250, 0.12); border: 1px solid rgba(96, 165, 250, 0.25); } .version-info { display: flex; align-items: center; gap: 10px; } .badge-current { font-size: 0.75rem; font-weight: 600; color: var(--success-color); padding: 2px 8px; border-radius: 4px; background: rgba(5, 150, 105, 0.1); } .badge-new { font-size: 0.75rem; font-weight: 600; color: #029aa8; padding: 2px 8px; border-radius: 4px; background: rgba(2, 154, 168, 0.1); } [data-theme="dark"] .badge-new { color: #60a5fa; background: rgba(96, 165, 250, 0.12); } .install-link { font-size: 0.8rem; font-weight: 500; padding: 4px 12px; border-radius: 6px; background: rgba(2, 154, 168, 0.1); color: #029aa8; text-decoration: none; border: 1px solid rgba(2, 154, 168, 0.25); transition: all 0.2s; white-space: nowrap; } .install-link:hover { background: rgba(2, 154, 168, 0.2); border-color: rgba(2, 154, 168, 0.4); } [data-theme="dark"] .install-link { color: #60a5fa; background: rgba(96, 165, 250, 0.12); border: 1px solid rgba(96, 165, 250, 0.25); } [data-theme="dark"] .install-link:hover { background: rgba(96, 165, 250, 0.2); border-color: rgba(96, 165, 250, 0.4); } .dev-toggle { padding: 10px 14px; border-radius: 8px; background: rgba(100, 116, 139, 0.05); border: 1px solid var(--border-color); } .dev-toggle input[type="checkbox"] { accent-color: #029aa8; width: 16px; height: 16px; } [data-theme="dark"] .dev-toggle input[type="checkbox"] { accent-color: #60a5fa; } ';document.head.appendChild(s); // Inject JS logic var sc=document.createElement('script'); sc.textContent="(()=>{\"use strict\";var e={367(e,t,n){n.d(t,{A0:()=>v,Aq:()=>g,BM:()=>S,Et:()=>E,Gb:()=>u,H:()=>b,KG:()=>T,N4:()=>p,P0:()=>H,PQ:()=>y,VL:()=>D,Y1:()=>L,g8:()=>w,i_:()=>c,m9:()=>O,oL:()=>k,wH:()=>h});var a=n(901),o=n(413),s=n(521),i=n(672),r=n(842),l=n(646);let d=null;function c(){if(!a.gX)try{const e=localStorage.getItem(\"AkitaStores\");if(e){const t=JSON.parse(e);t.auth&&t.auth.token&&((0,a.O5)(t.auth.token),localStorage.setItem(s.LS.AUTH_TOKEN,t.auth.token),t.auth.user&&((0,a.lt)(t.auth.user.id||\"unknown\"),localStorage.setItem(s.LS.CURRENT_USER,t.auth.user.id||\"unknown\"),t.auth.user.firstName&&localStorage.setItem(s.LS.FIRST_NAME,t.auth.user.firstName),t.auth.user.lastName&&localStorage.setItem(s.LS.LAST_NAME,t.auth.user.lastName)))}}catch(e){console.warn(\"Failed to parse AkitaStores:\",e)}(0,a.O5)(localStorage.getItem(s.LS.AUTH_TOKEN)),(0,a.lt)(localStorage.getItem(s.LS.CURRENT_USER));const e=localStorage.getItem(s.LS.FIRST_NAME),t=document.getElementById(\"btn-login-open\"),n=document.getElementById(\"user-info\"),o=document.getElementById(\"user-id-display\");a.gX?(t.classList.add(\"hidden\"),n.classList.remove(\"hidden\"),o.textContent=e||(a.Ny?`User ${a.Ny}`:(0,l.t)(\"loggedIn\")),u()):(t.classList.remove(\"hidden\"),n.classList.add(\"hidden\"),o.textContent=\"\"),(0,r.OR)()}async function u(){if(a.gX)try{const e=await fetch(`${s.tE}/user/orders/?venue=${s.eW}&ordering=-created&limit=50`,{headers:(0,i.H)(a.gX)}),t=await e.json();if(e.ok){const e=new Map,n=t.results||[];for(const t of n){if(9===t.order_state)continue;const n=t.date.split(\"T\")[0];for(const a of t.items||[]){const o=`${n}_${a.article}`;e.has(o)||e.set(o,[]),e.get(o).push(t.id)}}(0,a.di)(e),(0,r.OR)(),(0,r.gJ)()}}catch(e){console.error(\"Error fetching orders:\",e)}}async function g(){const e=document.getElementById(\"history-loading\"),t=document.getElementById(\"history-content\"),n=document.getElementById(\"history-progress-fill\"),o=document.getElementById(\"history-progress-text\");let r=[];if(d)r=d;else{const e=localStorage.getItem(s.LS.HISTORY_CACHE);if(e)try{r=JSON.parse(e),d=r}catch(e){console.warn(\"History cache parse error\",e)}}if(r.length>0&&m(r),!a.gX)return;0===r.length&&(t.innerHTML=\"\",e.classList.remove(\"hidden\")),n.style.width=\"0%\",o.textContent=r.length>0?(0,l.t)(\"historyLoadingDelta\"):(0,l.t)(\"historyLoadingFull\"),r.length>0&&e.classList.remove(\"hidden\");let c=r.length>0?`${s.tE}/user/orders/?venue=${s.eW}&ordering=-created&limit=5`:`${s.tE}/user/orders/?venue=${s.eW}&ordering=-created&limit=50`,u=[],g=0,h=0===r.length,p=!1;try{for(;c&&!p;){const e=await fetch(c,{headers:(0,i.H)(a.gX)});if(!e.ok)throw new Error(`Fetch failed: ${e.status}`);const t=await e.json();t.count&&0===g&&(g=t.count);const s=t.results||[];for(const e of s){const t=r.findIndex(t=>t.id===e.id);if(!h&&-1!==t){const n=r[t];if(n.updated===e.updated&&n.order_state===e.order_state){p=!0;break}}u.push(e)}if(!p&&h)if(g>0){const e=Math.round(u.length/g*100);n.style.width=`${e}%`,o.textContent=`${(0,l.t)(\"historyLoadingItem\")} ${u.length} ${(0,l.t)(\"historyLoadingOf\")} ${g}...`}else o.textContent=`${(0,l.t)(\"historyLoadingItem\")} ${u.length}...`;else p||(o.textContent=`${u.length} ${(0,l.t)(\"historyLoadingNew\")}`);c=p?null:t.next}if(u.length>0){const e=new Map(r.map(e=>[e.id,e]));for(const t of u)e.set(t.id,t);const t=Array.from(e.values());t.sort((e,t)=>new Date(t.created)-new Date(e.created)),d=t;try{localStorage.setItem(s.LS.HISTORY_CACHE,JSON.stringify(t))}catch(e){console.warn(\"History cache write error\",e)}m(d)}}catch(e){console.error(\"Error in history sync:\",e),0===r.length?t.innerHTML=`

      ${(0,l.t)(\"historyLoadError\")}

      `:H((0,l.t)(\"bgSyncFailed\"),\"error\")}finally{e.classList.add(\"hidden\")}}function m(e){const t=document.getElementById(\"history-content\");if(!e||0===e.length)return void(t.innerHTML=`

      ${(0,l.t)(\"noOrders\")}

      `);const n={};e.forEach(e=>{const t=new Date(e.date),s=t.getFullYear(),i=t.getMonth(),r=`${s}-${i.toString().padStart(2,\"0\")}`,l=\"en\"===a.Kl?\"en-US\":\"de-AT\",d=t.toLocaleString(l,{month:\"long\"}),c=(0,o.sn)(t);n[s]||(n[s]={year:s,months:{}}),n[s].months[r]||(n[s].months[r]={name:d,year:s,monthIndex:i,count:0,total:0,weeks:{}}),n[s].months[r].weeks[c]||(n[s].months[r].weeks[c]={label:\"en\"===a.Kl?`CW ${c}`:`KW ${c}`,items:[],count:0,total:0});(e.items||[]).forEach(t=>{const a=parseFloat(t.price||e.total||0);n[s].months[r].weeks[c].items.push({date:e.date,name:t.name||\"Men\u00fc\",price:a,state:e.order_state}),9!==e.order_state&&(n[s].months[r].weeks[c].count++,n[s].months[r].weeks[c].total+=a,n[s].months[r].count++,n[s].months[r].total+=a)})}),t.innerHTML=\"\";Object.keys(n).sort((e,t)=>t-e).forEach(e=>{const o=n[e],s=document.createElement(\"div\");s.className=\"history-year-group\";const i=document.createElement(\"h2\");i.className=\"history-year-header\",i.textContent=o.year,s.appendChild(i);Object.keys(o.months).sort((e,t)=>t.localeCompare(e)).forEach(e=>{const t=o.months[e],n=document.createElement(\"div\");n.className=\"history-month-group\";const i=document.createElement(\"div\");i.className=\"history-month-header\",i.setAttribute(\"tabindex\",\"0\"),i.setAttribute(\"role\",\"button\"),i.setAttribute(\"aria-expanded\",\"false\"),i.setAttribute(\"title\",(0,l.t)(\"historyMonthToggle\"));const r=document.createElement(\"div\");r.style.display=\"flex\",r.style.flexDirection=\"column\",r.style.gap=\"4px\";const d=document.createElement(\"span\");d.textContent=t.name,r.appendChild(d);const c=document.createElement(\"div\");c.className=\"history-month-summary\";const u=document.createElement(\"span\");u.innerHTML=`${t.count} ${(0,l.t)(\"orders\")} • \u20ac${t.total.toFixed(2)}`,c.appendChild(u),r.appendChild(c),i.appendChild(r);const g=document.createElement(\"span\");g.className=\"material-icons-round\",g.textContent=\"expand_more\",i.appendChild(g),i.addEventListener(\"click\",()=>{const e=i.parentElement;e.classList.contains(\"open\")?(e.classList.remove(\"open\"),i.setAttribute(\"aria-expanded\",\"false\")):(e.classList.add(\"open\"),i.setAttribute(\"aria-expanded\",\"true\"))}),n.appendChild(i);const m=document.createElement(\"div\");m.className=\"history-month-content\";Object.keys(t.weeks).sort((e,t)=>parseInt(t)-parseInt(e)).forEach(e=>{const n=t.weeks[e],o=document.createElement(\"div\");o.className=\"history-week-group\";const s=document.createElement(\"div\");s.className=\"history-week-header\";const i=document.createElement(\"strong\");i.textContent=n.label,s.appendChild(i);const r=document.createElement(\"span\");r.innerHTML=`${n.count} ${(0,l.t)(\"orders\")} • \u20ac${n.total.toFixed(2)}`,s.appendChild(r),o.appendChild(s),n.items.forEach(e=>{const t=new Date(e.date),n=\"en\"===a.Kl?\"en-US\":\"de-AT\",s=t.toLocaleDateString(n,{weekday:\"short\",day:\"2-digit\",month:\"2-digit\"}),i=document.createElement(\"div\");i.className=\"history-item\",9===e.state&&i.classList.add(\"history-item-cancelled\");const r=document.createElement(\"div\");r.style.fontSize=\"0.85rem\",r.style.color=\"var(--text-secondary)\",r.textContent=s,i.appendChild(r);const d=document.createElement(\"div\");d.className=\"history-item-details\";const c=document.createElement(\"span\");c.className=\"history-item-name\",c.textContent=e.name,d.appendChild(c);const u=document.createElement(\"div\"),g=document.createElement(\"span\");g.className=\"history-item-status\",9===e.state?g.textContent=(0,l.t)(\"stateCancelled\"):8===e.state?g.textContent=(0,l.t)(\"stateCompleted\"):g.textContent=(0,l.t)(\"stateTransferred\"),u.appendChild(g),d.appendChild(u),i.appendChild(d);const m=document.createElement(\"div\");m.className=\"history-item-price\",9===e.state&&m.classList.add(\"history-item-price-cancelled\"),m.textContent=`\u20ac${e.price.toFixed(2)}`,i.appendChild(m),o.appendChild(i)}),m.appendChild(o)}),n.appendChild(m),s.appendChild(n)}),t.appendChild(s)})}async function h(e,t,n,o,r){if(a.gX)try{const c=await fetch(`${s.tE}/auth/user/`,{headers:(0,i.H)(a.gX)});if(!c.ok)return void H(\"Fehler: Benutzerdaten konnten nicht geladen werden\",\"error\");const g=await c.json(),m=(new Date).toISOString(),h={uuid:crypto.randomUUID(),created:m,updated:m,order_type:7,items:[{article:t,course_group:null,modifiers:[],uuid:crypto.randomUUID(),name:n,description:r||\"\",price:String(parseFloat(o)),amount:1,vat:\"10.00\",comment:\"\"}],table:null,total:parseFloat(o),tip:0,currency:\"EUR\",venue:s.eW,states:[],order_state:1,date:`${e}T10:30:00Z`,payment_method:\"payroll\",customer:{first_name:g.first_name,last_name:g.last_name,email:g.email,newsletter:!1},preorder:!0,delivery_fee:0,cash_box_table_name:null,take_away:!1},p=await fetch(`${s.tE}/user/orders/`,{method:\"POST\",headers:(0,i.H)(a.gX),body:JSON.stringify(h)});if(p.ok||201===p.status)H(`${(0,l.t)(\"orderSuccess\")}: ${n}`,\"success\"),d=null,await u();else{const e=await p.json();H(`Fehler: ${e.detail||e.non_field_errors?.[0]||\"Bestellung fehlgeschlagen\"}`,\"error\")}}catch(e){console.error(\"Order error:\",e),H(\"Netzwerkfehler bei Bestellung\",\"error\")}}async function p(e,t,n){if(!a.gX)return;const o=`${e}_${t}`,r=a.L.get(o);if(!r||0===r.length)return;const c=r[r.length-1];try{const e=await fetch(`${s.tE}/user/orders/${c}/cancel/`,{method:\"PATCH\",headers:(0,i.H)(a.gX),body:JSON.stringify({})});if(e.ok)H(`${(0,l.t)(\"cancelSuccess\")}: ${n}`,\"success\"),d=null,await u();else{H(`Fehler: ${(await e.json()).detail||\"Stornierung fehlgeschlagen\"}`,\"error\")}}catch(e){console.error(\"Cancel error:\",e),H(\"Netzwerkfehler bei Stornierung\",\"error\")}}function f(){localStorage.setItem(\"kantine_flags\",JSON.stringify([...a.BY]))}async function v(){if(0===a.BY.size)return;const e=a.gX||s.f9,t=new Set;for(const e of a.BY){const[n]=e.split(\"_\");t.add(n)}let n=!1;const o=document.getElementById(\"alarm-bell\");o&&o.classList.add(\"refreshing\");try{for(const o of t)try{const t=await fetch(`${s.tE}/venues/${s.eW}/menu/${s.YU}/${o}/`,{headers:(0,i.H)(e)});if(!t.ok)continue;const r=(await t.json()).results||[],l=new Map;for(const e of r)if(e.items&&Array.isArray(e.items))for(const t of e.items)l.set(t.id,t);for(let e of a.p_){if(!e.days)continue;const t=e.days.find(e=>e.date===o);if(t&&t.items)for(let e=0;e0;s.available=e||t,s.availableAmount=parseInt(r.available_amount)||0,s.amountTracking=!1!==r.amount_tracking,n=!0}}}}catch(e){console.error(\"Error refreshing flag date\",o,e)}n&&B(),localStorage.setItem(\"kantine_flagged_items_last_checked\",(new Date).toISOString()),(0,r.Mb)(),(0,r.OR)(),H(`${a.BY.size} ${1===a.BY.size?(0,l.t)(\"menuSingular\"):(0,l.t)(\"menuPlural\")} ${(0,l.t)(\"menuChecked\")}`,\"info\")}finally{o&&o.classList.remove(\"refreshing\")}}function y(e,t,n,o){const s=`${e}_${t}`;let i=!1;a.BY.has(s)?(a.BY.delete(s),H(`${(0,l.t)(\"flagRemoved\")} ${n}`,\"success\")):(a.BY.add(s),i=!0,H(`${(0,l.t)(\"flagActivated\")} ${n}`,\"success\"),\"default\"===Notification.permission&&Notification.requestPermission()),f(),(0,r.Mb)(),(0,r.OR)(),i&&v()}function b(){const e=new Date,t=e.toISOString().split(\"T\")[0];let n=!1;for(const o of[...a.BY]){const[s]=o.split(\"_\");let i=!1;if(s=t&&(i=!0)}i&&(a.BY.delete(o),n=!0)}n&&f()}function w(){a.K8||a.gX&&(0,a.cc)(setInterval(()=>async function(){if(0===a.BY.size||!a.gX)return;for(const e of a.BY){const[t,n]=e.split(\"_\"),o=parseInt(n);try{const e=await fetch(`${s.tE}/venues/${s.eW}/menu/${s.YU}/${t}/`,{headers:(0,i.H)(a.gX)});if(!e.ok)continue;const n=(await e.json()).results||[];let r=null;for(const e of n)if(e.items&&(r=e.items.find(e=>e.id===o||e.article===o),r))break;if(r){if(!1===r.amount_tracking||parseInt(r.available_amount)>0){const e=r.name||\"Unbekannt\";H(`${e} ist jetzt verf\u00fcgbar!`,\"success\"),\"granted\"===Notification.permission&&new Notification(\"Kantine Wrapper\",{body:`${e} ist jetzt verf\u00fcgbar!`,icon:\"\ud83c\udf7d\ufe0f\"}),O()}}}catch(t){console.error(`Poll error for ${e}:`,t),await new Promise(e=>setTimeout(e,200))}}localStorage.setItem(\"kantine_flagged_items_last_checked\",(new Date).toISOString()),(0,r.Mb)()}(),s.fv))}function E(){a.K8&&(clearInterval(a.K8),(0,a.cc)(null))}function A(){localStorage.setItem(\"kantine_highlightTags\",JSON.stringify(a.yz)),(0,r.OR)(),(0,r.gJ)()}function k(e){if((e=e.trim().toLowerCase())&&!a.yz.includes(e)){const t=[...a.yz,e];return(0,a.iw)(t),A(),!0}return!1}function L(){const e=document.getElementById(\"tags-list\");e.innerHTML=\"\",a.yz.forEach(t=>{const n=document.createElement(\"span\");n.className=\"tag-badge\",n.innerHTML=`${t} ×`,e.appendChild(n)}),e.querySelectorAll(\".tag-remove\").forEach(e=>{e.addEventListener(\"click\",e=>{!function(e){const t=a.yz.filter(t=>t!==e);(0,a.iw)(t),A()}(e.target.dataset.tag),L()})})}function S(e){return e?(e=e.toLowerCase(),a.yz.filter(t=>e.includes(t))):[]}const I=\"kantine_menuCache\",C=\"kantine_menuCacheTs\";function B(){try{localStorage.setItem(I,JSON.stringify(a.p_)),localStorage.setItem(C,(new Date).toISOString())}catch(e){console.warn(\"Failed to cache menu data:\",e)}}function T(){try{const e=localStorage.getItem(I),t=localStorage.getItem(C);if(e){(0,a.tn)(JSON.parse(e)),(0,a.Xt)((0,o.sn)(new Date)),(0,a.pK)((new Date).getFullYear()),(0,r.OR)(),(0,r.gJ)(),(0,r.Mb)(),t&&N(t);try{const e=new Set;a.p_.forEach(t=>{(t.days||[]).forEach(t=>{(t.items||[]).forEach(t=>{let n=(t.description||\"\").replace(/\\s+/g,\" \").trim();n&&n.includes(\" / \")&&e.add(n)})})})}catch(e){}return!0}}catch(e){console.warn(\"Failed to load cached menu:\",e)}return!1}function D(){const e=localStorage.getItem(C);if(!e)return!1;if(Date.now()-new Date(e).getTime()>36e5)return!1;const t=(0,o.sn)(new Date),n=(0,o.Ao)(new Date);return a.p_.some(e=>e.weekNumber===t&&e.year===n&&e.days&&e.days.length>0)}async function O(){const e=document.getElementById(\"loading\"),t=document.getElementById(\"progress-modal\"),l=document.getElementById(\"progress-fill\"),d=document.getElementById(\"progress-percent\"),u=document.getElementById(\"progress-message\");e.classList.remove(\"hidden\");const g=a.gX||s.f9;try{t.classList.remove(\"hidden\"),u.textContent=\"Hole verf\u00fcgbare Daten...\",l.style.width=\"0%\",d.textContent=\"0%\";const e=await fetch(`${s.tE}/venues/${s.eW}/menu/dates/`,{headers:(0,i.H)(g)});if(!e.ok)throw new Error(`Failed to fetch dates: ${e.status}`);let n=(await e.json()).results||[];const m=new Date;m.setDate(m.getDate()-7);const h=m.toISOString().split(\"T\")[0];n=n.filter(e=>e.date>=h).sort((e,t)=>e.date.localeCompare(t.date)).slice(0,30);const p=n.length;u.textContent=`${p} Tage gefunden. Lade Details...`;const f=[];let v=0;const y=5;for(let e=0;e{const t=e.date;let n=null;try{const a=await fetch(`${s.tE}/venues/${s.eW}/menu/${s.YU}/${t}/`,{headers:(0,i.H)(g)});if(a.ok){const o=(await a.json()).results||[];let s=[];for(const e of o)e.items&&Array.isArray(e.items)&&(s=s.concat(e.items));s.length>0&&(n={date:t,menu_items:s,orders:e.orders||[]})}}catch(e){console.error(`Failed to fetch details for ${t}:`,e)}finally{v++;const e=Math.round(v/p*100);l.style.width=`${e}%`,d.textContent=`${e}%`,u.textContent=`Lade Men\u00fc f\u00fcr ${t}...`}return n}));for(const e of a)e&&f.push(e)}const b=new Map;a.p_&&a.p_.length>0&&a.p_.forEach(e=>{const t=`${e.year}-${e.weekNumber}`;try{b.set(t,{year:e.year,weekNumber:e.weekNumber,days:e.days?e.days.map(e=>({...e,items:e.items?[...e.items]:[]})):[]})}catch(e){console.warn(\"Error hydrating week:\",e)}});for(const e of f){const t=new Date(e.date),n=(0,o.sn)(t),a=(0,o.Ao)(t),s=`${a}-${n}`;b.has(s)||b.set(s,{year:a,weekNumber:n,days:[]});const i=b.get(s),r=t.toLocaleDateString(\"en-US\",{weekday:\"long\"}),l=new Date(e.date);l.setHours(10,0,0,0);const d={date:e.date,weekday:r,orderCutoff:l.toISOString(),items:e.menu_items.map(t=>{const n=!1===t.amount_tracking,a=parseInt(t.available_amount)>0;return{id:`${e.date}_${t.id}`,articleId:t.id,name:t.name||\"Unknown\",description:t.description||\"\",price:parseFloat(t.price)||0,available:n||a,availableAmount:parseInt(t.available_amount)||0,amountTracking:!1!==t.amount_tracking}})},c=i.days.findIndex(t=>t.date===e.date);c>=0?i.days[c]=d:i.days.push(d)}const w=Array.from(b.values()).sort((e,t)=>e.year!==t.year?e.year-t.year:e.weekNumber-t.weekNumber);w.forEach(e=>{e.days&&e.days.sort((e,t)=>e.date.localeCompare(t.date))}),(0,a.tn)(w),B(),N((new Date).toISOString()),(0,a.Xt)((0,o.sn)(new Date)),(0,a.pK)((new Date).getFullYear()),c(),(0,r.OR)(),(0,r.gJ)(),(0,r.Mb)(),u.textContent=\"Fertig!\",setTimeout(()=>t.classList.add(\"hidden\"),500)}catch(e){console.error(\"Error fetching menu:\",e),t.classList.add(\"hidden\"),Promise.resolve().then(n.bind(n,842)).then(t=>{t.showErrorModal(\"Keine Verbindung\",`Die Men\u00fcdaten konnten nicht geladen werden. M\u00f6glicherweise besteht keine Verbindung zur API oder zur Bessa-Webseite.

      ${(0,o.ZD)(e.message)}`,\"Zur Original-Seite\",\"https://web.bessa.app/knapp-kantine\")})}finally{e.classList.add(\"hidden\")}}let M=null,x=null;function N(e){const t=document.getElementById(\"last-updated-subtitle\");if(e){M=e,localStorage.setItem(\"kantine_last_updated\",e),localStorage.setItem(\"kantine_last_checked\",e);try{const n=new Date(e),a=n.toLocaleTimeString(\"de-DE\",{hour:\"2-digit\",minute:\"2-digit\"}),s=n.toLocaleDateString(\"de-DE\",{day:\"2-digit\",month:\"2-digit\"}),i=(0,o.gs)(n);t.textContent=`Aktualisiert: ${s} ${a} (${i})`}catch(e){t.textContent=\"\"}x||(x=setInterval(()=>{M&&(N(M),(0,r.Mb)())},6e4))}}function H(e,t=\"info\"){let n=document.getElementById(\"toast-container\");n||(n=document.createElement(\"div\"),n.id=\"toast-container\",document.body.appendChild(n));const a=document.createElement(\"div\");a.className=`toast toast-${t}`;const s=\"success\"===t?\"check_circle\":\"error\"===t?\"error\":\"info\";a.innerHTML=`${s}${(0,o.ZD)(e)}`,n.appendChild(a),requestAnimationFrame(()=>a.classList.add(\"show\")),setTimeout(()=>{a.classList.remove(\"show\"),setTimeout(()=>a.remove(),300)},3e3)}},672(e,t,n){n.d(t,{H:()=>o,O:()=>s});var a=n(521);function o(e){return{Authorization:`Token ${e||a.f9}`,Accept:\"application/json\",\"Content-Type\":\"application/json\",\"X-Client-Version\":a.fZ}}function s(){return{Accept:\"application/vnd.github.v3+json\"}}},521(e,t,n){n.d(t,{LS:()=>g,YU:()=>r,d_:()=>u,eW:()=>i,f9:()=>o,fZ:()=>s,fv:()=>l,pe:()=>c,tE:()=>a});const a=\"https://api.bessa.app/v1\",o=\"c3418725e95a9f90e3645cbc846b4d67c7c66131\",s=\"v1.6.17\",i=591,r=7,l=3e5,d=\"TauNeutrino/kantine-overview\",c=`https://api.github.com/repos/${d}`,u=`https://htmlpreview.github.io/?https://github.com/${d}/blob`,g={AUTH_TOKEN:\"kantine_authToken\",CURRENT_USER:\"kantine_currentUser\",FIRST_NAME:\"kantine_firstName\",LAST_NAME:\"kantine_lastName\",LANG:\"kantine_lang\",FLAGS:\"kantine_flags\",FLAGGED_LAST_CHECKED:\"kantine_flagged_items_last_checked\",LAST_CHECKED:\"kantine_last_checked\",MENU_CACHE:\"kantine_menuCache\",MENU_CACHE_TS:\"kantine_menuCacheTs\",HISTORY_CACHE:\"kantine_history_cache\",HIGHLIGHT_TAGS:\"kantine_highlightTags\",LAST_UPDATED:\"kantine_last_updated\",VERSION_CACHE:\"kantine_version_cache\",DEV_MODE:\"kantine_dev_mode\"}},646(e,t,n){n.d(t,{t:()=>s});var a=n(901);const o={de:{thisWeek:\"Diese Woche\",nextWeek:\"N\u00e4chste Woche\",nextWeekTooltipDefault:\"Men\u00fc n\u00e4chster Woche anzeigen\",thisWeekTooltip:\"Men\u00fc dieser Woche anzeigen\",appTitle:\"Kantinen \u00dcbersicht\",updatedAt:\"Aktualisiert\",langTooltip:\"Sprache der Men\u00fcbeschreibung\",weekLabel:\"Woche\",refresh:\"Men\u00fcdaten neu laden\",history:\"Bestellhistorie\",highlights:\"Pers\u00f6nliche Highlights verwalten\",themeTooltip:\"Erscheinungsbild (Hell/Dunkel) wechseln\",login:\"Anmelden\",loginTooltip:\"Mit Bessa.app Account anmelden\",logout:\"Abmelden\",logoutTooltip:\"Von Bessa.app abmelden\",loginTitle:\"Login\",employeeId:\"Mitarbeiternummer\",employeeIdPlaceholder:\"z.B. 2041\",employeeIdHelp:\"Deine offizielle Knapp Mitarbeiternummer.\",password:\"Passwort\",passwordPlaceholder:\"Bessa Passwort\",passwordHelp:\"Das Passwort f\u00fcr deinen Bessa Account.\",loginButton:\"Einloggen\",loggingIn:\"Wird eingeloggt...\",highlightsTitle:\"Meine Highlights\",highlightsDesc:\"Markiere Men\u00fcs automatisch, wenn sie diese Schlagw\u00f6rter enthalten.\",tagInputPlaceholder:\"z.B. Schnitzel, Vegetarisch...\",tagInputTooltip:\"Neues Schlagwort zum Hervorheben eingeben\",addTag:\"Hinzuf\u00fcgen\",addTagTooltip:\"Schlagwort zur Liste hinzuf\u00fcgen\",removeTagTooltip:\"Schlagwort entfernen\",historyTitle:\"Bestellhistorie\",loadingHistory:\"Lade Historie...\",noOrders:\"Keine Bestellungen gefunden.\",orders:\"Bestellungen\",historyMonthToggle:\"Klicken, um die Bestellungen f\u00fcr diesen Monat ein-/auszublenden\",available:\"Verf\u00fcgbar\",soldOut:\"Ausverkauft\",ordered:\"Bestellt\",orderButton:\"Bestellen\",orderAgainTooltip:\"nochmal bestellen\",orderTooltip:\"bestellen\",cancelOrder:\"Bestellung stornieren\",cancelOneOrder:\"Eine Bestellung stornieren\",flagActivate:\"Benachrichtigen wenn verf\u00fcgbar\",flagDeactivate:\"Benachrichtigung deaktivieren\",alarmTooltipNone:\"Keine beobachteten Men\u00fcs\",alarmLastChecked:\"Zuletzt gepr\u00fcft\",versionsTitle:\"\ud83d\udce6 Versionen\",currentVersion:\"Aktuell\",devModeLabel:\"Dev-Mode (alle Tags anzeigen)\",loadingVersions:\"Lade Versionen...\",noVersions:\"Keine Versionen gefunden.\",installed:\"\u2713 Installiert\",newVersion:\"\u2b06 Neu!\",installLink:\"Installieren\",reportBug:\"Fehler melden\",reportBugTooltip:\"Melde einen Fehler auf GitHub\",featureRequest:\"Feature vorschlagen\",featureRequestTooltip:\"Schlage ein neues Feature auf GitHub vor\",clearCache:\"Lokalen Cache leeren\",clearCacheTooltip:\"L\u00f6scht alle lokalen Daten & erzwingt einen Neuladen\",clearCacheConfirm:\"M\u00f6chtest du wirklich alle lokalen Daten (inkl. Login-Session, Cache und Einstellungen) l\u00f6schen? Die Seite wird danach neu geladen.\",versionMenuTooltip:\"Klick f\u00fcr Versionsmen\u00fc\",progressTitle:\"Men\u00fcdaten aktualisieren\",progressInit:\"Initialisierung...\",noMenuData:\"Keine Men\u00fcdaten f\u00fcr KW\",noMenuDataHint:\"Versuchen Sie eine andere Woche oder schauen Sie sp\u00e4ter vorbei.\",costLabel:\"Gesamt\",orderDeadline:\"Bestellschluss\",flagRemoved:\"Flag entfernt f\u00fcr\",flagActivated:\"Benachrichtigung aktiviert f\u00fcr\",menuChecked:\"gepr\u00fcft\",menuSingular:\"Men\u00fc\",menuPlural:\"Men\u00fcs\",newMenuDataAvailable:\"Neue Men\u00fcdaten f\u00fcr n\u00e4chste Woche verf\u00fcgbar!\",orderSuccess:\"Bestellt\",cancelSuccess:\"Storniert\",bgSyncFailed:\"Hintergrund-Synchronisation fehlgeschlagen\",historyLoadError:\"Fehler beim Laden der Historie.\",historyLoadingFull:\"Lade Bestellhistorie...\",historyLoadingDelta:\"Suche nach neuen Bestellungen...\",historyLoadingItem:\"Lade Bestellung\",historyLoadingOf:\"von\",historyLoadingNew:\"neue/ge\u00e4nderte Bestellungen gefunden...\",badgeOrdered:\"bestellt\",badgeOrderable:\"bestellbar\",badgeTotal:\"gesamt\",badgeHighlights:\"Highlights gefunden\",stateCancelled:\"Storniert\",stateCompleted:\"Abgeschlossen\",stateTransferred:\"\u00dcbertragen\",close:\"Schlie\u00dfen\",noConnection:\"Keine Verbindung\",toOriginalPage:\"Zur Original-Seite\",loggedIn:\"Angemeldet\"},en:{thisWeek:\"This Week\",nextWeek:\"Next Week\",nextWeekTooltipDefault:\"Show next week's menu\",thisWeekTooltip:\"Show this week's menu\",appTitle:\"Canteen Overview\",updatedAt:\"Updated\",langTooltip:\"Menu description language\",weekLabel:\"Week\",refresh:\"Reload menu data\",history:\"Order history\",highlights:\"Manage personal highlights\",themeTooltip:\"Toggle appearance (Light/Dark)\",login:\"Sign in\",loginTooltip:\"Sign in with Bessa.app account\",logout:\"Sign out\",logoutTooltip:\"Sign out from Bessa.app\",loginTitle:\"Login\",employeeId:\"Employee ID\",employeeIdPlaceholder:\"e.g. 2041\",employeeIdHelp:\"Your official Knapp employee number.\",password:\"Password\",passwordPlaceholder:\"Bessa password\",passwordHelp:\"The password for your Bessa account.\",loginButton:\"Log in\",loggingIn:\"Logging in...\",highlightsTitle:\"My Highlights\",highlightsDesc:\"Automatically highlight menus containing these keywords.\",tagInputPlaceholder:\"e.g. Schnitzel, Vegetarian...\",tagInputTooltip:\"Enter new keyword to highlight\",addTag:\"Add\",addTagTooltip:\"Add keyword to list\",removeTagTooltip:\"Remove keyword\",historyTitle:\"Order History\",loadingHistory:\"Loading history...\",noOrders:\"No orders found.\",orders:\"Orders\",historyMonthToggle:\"Click to expand/collapse orders for this month\",available:\"Available\",soldOut:\"Sold out\",ordered:\"Ordered\",orderButton:\"Order\",orderAgainTooltip:\"order again\",orderTooltip:\"order\",cancelOrder:\"Cancel order\",cancelOneOrder:\"Cancel one order\",flagActivate:\"Notify when available\",flagDeactivate:\"Deactivate notification\",alarmTooltipNone:\"No flagged menus\",alarmLastChecked:\"Last checked\",versionsTitle:\"\ud83d\udce6 Versions\",currentVersion:\"Current\",devModeLabel:\"Dev mode (show all tags)\",loadingVersions:\"Loading versions...\",noVersions:\"No versions found.\",installed:\"\u2713 Installed\",newVersion:\"\u2b06 New!\",installLink:\"Install\",reportBug:\"Report a bug\",reportBugTooltip:\"Report a bug on GitHub\",featureRequest:\"Request a feature\",featureRequestTooltip:\"Suggest a new feature on GitHub\",clearCache:\"Clear local cache\",clearCacheTooltip:\"Deletes all local data & forces a reload\",clearCacheConfirm:\"Do you really want to delete all local data (including login session, cache, and settings)? The page will reload afterwards.\",versionMenuTooltip:\"Click for version menu\",progressTitle:\"Updating menu data\",progressInit:\"Initializing...\",noMenuData:\"No menu data for CW\",noMenuDataHint:\"Try another week or check back later.\",costLabel:\"Total\",orderDeadline:\"Order deadline\",flagRemoved:\"Flag removed for\",flagActivated:\"Notification activated for\",menuChecked:\"checked\",menuSingular:\"menu\",menuPlural:\"menus\",newMenuDataAvailable:\"New menu data available for next week!\",orderSuccess:\"Ordered\",cancelSuccess:\"Cancelled\",bgSyncFailed:\"Background synchronisation failed\",historyLoadError:\"Error loading history.\",historyLoadingFull:\"Loading order history...\",historyLoadingDelta:\"Checking for new orders...\",historyLoadingItem:\"Loading order\",historyLoadingOf:\"of\",historyLoadingNew:\"new/updated orders found...\",badgeOrdered:\"ordered\",badgeOrderable:\"orderable\",badgeTotal:\"total\",badgeHighlights:\"highlights found\",stateCancelled:\"Cancelled\",stateCompleted:\"Completed\",stateTransferred:\"Transferred\",close:\"Close\",noConnection:\"No connection\",toOriginalPage:\"Go to original page\",loggedIn:\"Logged in\"}};function s(e){const t=\"en\"===a.Kl?\"en\":\"de\";return o[t][e]||o.de[e]||e}},901(e,t,n){n.d(t,{BT:()=>i,BY:()=>g,K8:()=>m,Kl:()=>h,L:()=>u,Ny:()=>c,O5:()=>b,UD:()=>S,Xt:()=>v,cc:()=>A,di:()=>E,gX:()=>d,iw:()=>k,lt:()=>w,pK:()=>y,p_:()=>s,qo:()=>L,sw:()=>l,tn:()=>f,vW:()=>r,yz:()=>p});var a=n(413),o=n(521);let s=[],i=(0,a.sn)(new Date),r=(new Date).getFullYear(),l=\"this-week\",d=localStorage.getItem(o.LS.AUTH_TOKEN),c=localStorage.getItem(o.LS.CURRENT_USER),u=new Map,g=new Set(JSON.parse(localStorage.getItem(o.LS.FLAGS)||\"[]\")),m=null,h=localStorage.getItem(o.LS.LANG)||\"de\",p=JSON.parse(localStorage.getItem(o.LS.HIGHLIGHT_TAGS)||\"[]\");function f(e){s=e}function v(e){i=e}function y(e){r=e}function b(e){d=e}function w(e){c=e}function E(e){u=e}function A(e){m=e}function k(e){p=e}function L(e){\"this-week\"===e||\"next-week\"===e?l=e:console.warn(`[state] Invalid displayMode: \"${e}\". Ignoring.`)}function S(e){[\"de\",\"en\",\"all\"].includes(e)?h=e:console.warn(`[state] Invalid langMode: \"${e}\". Ignoring.`)}},842(e,t,n){n.d(t,{Gk:()=>m,Mb:()=>v,OR:()=>c,Ux:()=>g,gJ:()=>d,showErrorModal:()=>f});var a=n(901),o=n(413),s=n(521),i=n(672),r=n(367),l=n(646);function d(){const e=document.getElementById(\"btn-next-week\");let t=a.BT+1,n=a.vW;t>52&&(t=1,n++);const o=a.p_.find(e=>e.weekNumber===t&&e.year===n);let s=0,i=0,d=0,c=0;o&&o.days&&o.days.forEach(e=>{if(e.items&&e.items.length>0){s++;const t=e.items.some(e=>e.available);t&&i++;let n=!1;e.items.forEach(t=>{const o=t.articleId||parseInt(t.id.split(\"_\")[1]),s=`${e.date}_${o}`;a.L.has(s)&&a.L.get(s).length>0&&(n=!0)}),n&&d++;const o=new Date(e.date).getDay();o>=1&&o<=4&&t&&!n&&c++}});const u=e.querySelector(\".nav-badge\");if(u&&u.remove(),s>0){let a=0;o&&o.days&&o.days.forEach(e=>{e.items.forEach(e=>{const t=(0,r.BM)(e.name),n=(0,r.BM)(e.description);(t.length>0||n.length>0)&&a++})});let u=[`${d} ${(0,l.t)(\"badgeOrdered\")} / ${i} ${(0,l.t)(\"badgeOrderable\")} / ${s} ${(0,l.t)(\"badgeTotal\")}`];if(a>0&&u.push(`${a} ${(0,l.t)(\"badgeHighlights\")}`),e.title=u.join(\" \u2022 \"),c>0){e.classList.add(\"new-week-available\");const a=`kantine_notified_nextweek_${n}_${t}`;localStorage.getItem(a)||(localStorage.setItem(a,\"true\"),(0,r.P0)((0,l.t)(\"newMenuDataAvailable\"),\"info\"))}else e.classList.remove(\"new-week-available\")}else e.title=(0,l.t)(\"nextWeekTooltipDefault\"),e.classList.remove(\"new-week-available\")}function c(){const e=document.getElementById(\"menu-container\");if(!e)return;e.innerHTML=\"\";let t=a.BT,n=a.vW;\"next-week\"===a.sw&&(t++,t>52&&(t=1,n++));const s=a.p_.flatMap(e=>e.days||[]).filter(e=>{const a=new Date(e.date);return(0,o.sn)(a)===t&&(0,o.Ao)(a)===n});if(0===s.length)return e.innerHTML=`\\n
      \\n

      ${(0,l.t)(\"noMenuData\")} ${t} (${n}).

      \\n ${(0,l.t)(\"noMenuDataHint\")}\\n
      `,void document.getElementById(\"weekly-cost-display\").classList.add(\"hidden\");!function(e){let t=0;e&&e.length>0&&e.forEach(e=>{e.items&&e.items.forEach(n=>{const o=n.articleId||parseInt(n.id.split(\"_\")[1]),s=`${e.date}_${o}`,i=a.L.get(s)||[];i.length>0&&(t+=n.price*i.length)})});const n=document.getElementById(\"weekly-cost-display\");t>0?(n.innerHTML=`shopping_bag ${(0,l.t)(\"costLabel\")}: ${t.toFixed(2).replace(\".\",\",\")} \u20ac`,n.classList.remove(\"hidden\")):n.classList.add(\"hidden\")}(s);const i=document.getElementById(\"header-week-info\"),d=\"this-week\"===a.sw?(0,l.t)(\"thisWeek\"):(0,l.t)(\"nextWeek\");i.innerHTML=`\\n
      ${d}
      \\n
      ${(0,l.t)(\"weekLabel\")} ${t} \u2022 ${n}
      `;const c=document.createElement(\"div\");c.className=\"days-grid\",s.sort((e,t)=>e.date.localeCompare(t.date));s.filter(e=>{const t=new Date(e.date).getDay();return 0!==t&&6!==t}).forEach(e=>{const t=function(e){if(!e.items||0===e.items.length)return null;const t=document.createElement(\"div\");t.className=\"menu-card\";const n=new Date,s=new Date(e.date);let i=!1;if(e.orderCutoff)i=n>=new Date(e.orderCutoff);else{const t=new Date;t.setHours(0,0,0,0);const n=new Date(e.date);n.setHours(0,0,0,0),i=n{const n=t.articleId||parseInt(t.id.split(\"_\")[1]),o=`${e.date}_${n}`,s=(a.L.get(o)||[]).length;if(s>0){const e=t.name.match(/([M][1-9][Ff]?)/);if(e){let t=e[1];s>1&&(t+=\"+\"),d.push(t)}}});const c=document.createElement(\"div\");c.className=\"card-header\";const u=s.toLocaleDateString(\"de-DE\",{day:\"2-digit\",month:\"2-digit\"}),g=d.reduce((e,t)=>e+`${t}`,\"\");let m=\"\";const h=e.items&&e.items.some(t=>{const n=t.articleId||parseInt(t.id.split(\"_\")[1]),o=`${e.date}_${n}`;return a.L.has(o)&&a.L.get(o).length>0}),p=e.items&&e.items.some(e=>e.available);m=h?\"header-violet\":p&&!i?\"header-green\":\"header-red\";m&&c.classList.add(m);c.innerHTML=`\\n
      \\n ${(0,o.FS)(e.weekday)}\\n
      ${g}
      \\n
      \\n ${u}`,t.appendChild(c);const f=document.createElement(\"div\");f.className=\"card-body\";const v=(new Date).toISOString().split(\"T\")[0],y=e.date===v,b=[...e.items].sort((t,n)=>{if(y){const o=t.articleId||parseInt(t.id.split(\"_\")[1]),s=n.articleId||parseInt(n.id.split(\"_\")[1]),i=a.L.has(`${e.date}_${o}`),r=a.L.has(`${e.date}_${s}`);if(i&&!r)return-1;if(!i&&r)return 1}return t.name.localeCompare(n.name)});return b.forEach(t=>{const s=document.createElement(\"div\");s.className=\"menu-item\";const d=t.articleId||parseInt(t.id.split(\"_\")[1]),c=`${e.date}_${d}`,u=(a.L.get(c)||[]).length;let g=\"\";g=t.available?t.amountTracking?`${(0,l.t)(\"available\")} (${t.availableAmount})`:`${(0,l.t)(\"available\")}`:`${(0,l.t)(\"soldOut\")}`;let m=\"\";if(u>0){const t=u>1?`${u}`:\"\";m=`check_circle ${(0,l.t)(\"ordered\")}${t}`,s.classList.add(\"ordered\"),new Date(e.date).toDateString()===n.toDateString()&&s.classList.add(\"today-ordered\")}const h=`${e.date}_${d}`,p=a.BY.has(h);p&&s.classList.add(t.available?\"flagged-available\":\"flagged-sold-out\");const v=[...new Set([...(0,r.BM)(t.name),...(0,r.BM)(t.description)])];v.length>0&&s.classList.add(\"highlight-glow\");let y=\"\",b=\"\",w=\"\";if(a.gX&&!i){const n=p?\"notifications_active\":\"notifications_none\",a=p?\"btn-flag active\":\"btn-flag\",s=p?(0,l.t)(\"flagDeactivate\"):(0,l.t)(\"flagActivate\");if(t.available&&!p||(w=``),t.available&&(y=u>0?``:``),u>0){const n=1===u?\"close\":\"remove\",a=1===u?(0,l.t)(\"cancelOrder\"):(0,l.t)(\"cancelOneOrder\");b=``}}let E=\"\";if(v.length>0){E=`
      ${v.reduce((e,t)=>e+`star${(0,o.ZD)(t)}`,\"\")}
      `}s.innerHTML=`\\n
      \\n ${(0,o.ZD)(t.name)}\\n ${t.price.toFixed(2)} \u20ac\\n
      \\n
      \\n ${m}\\n ${b}\\n ${y}\\n ${w}\\n
      ${g}
      \\n
      \\n ${E}\\n

      ${(0,o.ZD)((0,o.PC)(t.description))}

      `;const A=s.querySelector(\".btn-order\");A&&A.addEventListener(\"click\",e=>{e.stopPropagation();const t=e.currentTarget;t.disabled=!0,t.classList.add(\"loading\"),(0,r.wH)(t.dataset.date,parseInt(t.dataset.article),t.dataset.name,parseFloat(t.dataset.price),t.dataset.desc||\"\").finally(()=>{t.disabled=!1,t.classList.remove(\"loading\")})});const k=s.querySelector(\".btn-cancel\");k&&k.addEventListener(\"click\",e=>{e.stopPropagation();const t=e.currentTarget;t.disabled=!0,(0,r.N4)(t.dataset.date,parseInt(t.dataset.article),t.dataset.name).finally(()=>{t.disabled=!1})});const L=s.querySelector(\".btn-flag\");L&&L.addEventListener(\"click\",e=>{e.stopPropagation();const t=e.currentTarget;(0,r.PQ)(t.dataset.date,parseInt(t.dataset.article),t.dataset.name,t.dataset.cutoff)}),f.appendChild(s)}),t.appendChild(f),t}(e);t&&c.appendChild(t)}),e.appendChild(c),setTimeout(()=>function(e){const t=e.querySelectorAll(\".menu-card\");if(0===t.length)return;let n=0;t.forEach(e=>{n=Math.max(n,e.querySelectorAll(\".menu-item\").length)});for(let e=0;e{const o=t.querySelectorAll(\".menu-item\");o[e]&&(o[e].style.height=\"auto\",n=Math.max(n,o[e].offsetHeight),a.push(o[e]))}),a.forEach(e=>{e.style.height=`${n}px`})}}(c),0)}async function u(e){const t=e?`${s.pe}/tags?per_page=20`:`${s.pe}/releases?per_page=20`,n=await fetch(t,{headers:(0,i.O)()});if(!n.ok){if(403===n.status)throw new Error(\"API Rate Limit erreicht (403). Bitte sp\u00e4ter erneut versuchen.\");throw new Error(`GitHub API ${n.status}`)}return(await n.json()).map(t=>{const n=e?t.name:t.tag_name;return{tag:n,name:e?n:t.name||n,url:`${s.d_}/${n}/dist/install.html`,body:t.body||\"\"}})}async function g(){const e=\"true\"===localStorage.getItem(s.LS.DEV_MODE);try{const t=await u(e);if(!t.length)return;localStorage.setItem(s.LS.VERSION_CACHE,JSON.stringify({timestamp:Date.now(),devMode:e,versions:t}));const n=t[0].tag;if(!(0,o.U4)(n,\"v1.6.17\"))return;const a=document.querySelector(\".header-left h1\");if(a&&!a.querySelector(\".update-icon\")){const e=document.createElement(\"a\");e.className=\"update-icon\",e.href=t[0].url,e.target=\"_blank\",e.innerHTML=\"\ud83c\udd95\",e.title=`Update: ${n} \u2014 Klick zum Installieren`,e.style.cssText=\"margin-left:8px;font-size:1em;text-decoration:none;cursor:pointer;vertical-align:middle;\",a.appendChild(e)}}catch(e){console.warn(\"[Kantine] Version check failed:\",e)}}function m(){const e=document.getElementById(\"version-modal\"),t=document.getElementById(\"version-list-container\"),n=document.getElementById(\"dev-mode-toggle\"),a=\"v1.6.17\";if(!e)return;e.classList.remove(\"hidden\");const i=document.getElementById(\"version-current\");i&&(i.textContent=a);const r=\"true\"===localStorage.getItem(s.LS.DEV_MODE);async function l(e){const i=n.checked;function r(e){if(!e||!e.length)return void(t.innerHTML='

      Keine Versionen gefunden.

      ');t.innerHTML='
        ';const n=t.querySelector(\".version-list\");e.forEach(e=>{const t=e.tag===a,s=(0,o.U4)(e.tag,a),i=document.createElement(\"li\");i.className=\"version-item\"+(t?\" current\":\"\");let r=\"\";t?r='\u2713 Installiert':s&&(r='\u2b06 Neu!');let l=\"\";t||(l=`Installieren`),i.innerHTML=`\\n
        \\n ${(0,o.ZD)(e.tag)}\\n ${r}\\n
        \\n ${l}\\n `,n.appendChild(i)})}t.innerHTML='

        Lade Versionen...

        ';try{const e=localStorage.getItem(s.LS.VERSION_CACHE);let t=null;if(e)try{t=JSON.parse(e)}catch(e){}t&&t.devMode===i&&t.versions&&r(t.versions);const n=await u(i),a=JSON.stringify(n);a!==(t?JSON.stringify(t.versions):\"\")&&(localStorage.setItem(s.LS.VERSION_CACHE,JSON.stringify({timestamp:Date.now(),devMode:i,versions:n})),r(n))}catch(e){t.innerHTML=`

        Fehler: ${(0,o.ZD)(e.message)}

        `}}n.checked=r,l(),n.onchange=()=>{localStorage.setItem(s.LS.DEV_MODE,n.checked),localStorage.removeItem(s.LS.VERSION_CACHE),l()}}function h(){if(!a.gX||!a.Ny)return void p();const e=new Date,t=e.getDay();if(0===t||6===t)return void p();const n=e.toISOString().split(\"T\")[0];let o=!1;for(const e of a.L.keys())if(e.startsWith(n)){o=!0;break}if(o)return void p();const s=new Date;s.setHours(10,0,0,0);const i=s-e;if(i<=0)return void p();const r=Math.floor(i/36e5),d=Math.floor(i%36e5/6e4),c=document.querySelector(\".header-center-wrapper\");if(!c)return;let u=document.getElementById(\"order-countdown\");if(u||(u=document.createElement(\"div\"),u.id=\"order-countdown\",c.insertBefore(u,c.firstChild)),u.innerHTML=`${(0,l.t)(\"orderDeadline\")}: ${r}h ${d}m`,i<36e5){u.classList.add(\"urgent\");const e=`kantine_notified_${n}`;localStorage.getItem(e)||(\"granted\"===Notification.permission?new Notification(\"Kantine: Bestellschluss naht!\",{body:\"Du hast heute noch nichts bestellt. Nur noch 1 Stunde!\",icon:\"\u23f3\"}):\"default\"===Notification.permission&&Notification.requestPermission(),localStorage.setItem(e,\"true\"))}else u.classList.remove(\"urgent\")}function p(){const e=document.getElementById(\"order-countdown\");e&&e.remove()}function f(e,t,n,a){const s=\"error-modal\";let i=document.getElementById(s);i&&i.remove(),i=document.createElement(\"div\"),i.id=s,i.className=\"modal hidden\",i.innerHTML=`\\n
        \\n
        \\n

        \\n signal_wifi_off\\n ${(0,o.ZD)(e)}\\n

        \\n
        \\n
        \\n

        ${t}

        \\n
        \\n \\n
        \\n
        \\n
        \\n `,document.body.appendChild(i),document.getElementById(\"btn-error-redirect\").addEventListener(\"click\",()=>{window.location.href=a}),requestAnimationFrame(()=>{i.classList.remove(\"hidden\")})}function v(){const e=document.getElementById(\"alarm-bell\"),t=document.getElementById(\"alarm-bell-icon\");if(!e||!t)return;if(0===a.BY.size)return e.classList.add(\"hidden\"),e.style.display=\"none\",t.style.color=\"var(--text-secondary)\",void(t.style.textShadow=\"none\");e.classList.remove(\"hidden\"),e.style.display=\"inline-flex\";let n=!1;for(const e of a.p_)if(e.days){for(const t of e.days)if(t.items){for(const e of t.items)if(e.available&&a.BY.has(e.id)){n=!0;break}if(n)break}if(n)break}const i=localStorage.getItem(s.LS.LAST_CHECKED),r=localStorage.getItem(s.LS.FLAGGED_LAST_CHECKED);let d=0;i&&(d=Math.max(d,new Date(i).getTime())),r&&(d=Math.max(d,new Date(r).getTime()));let c=\"gerade eben\";if(0===d){const e=(new Date).toISOString();localStorage.setItem(s.LS.LAST_CHECKED,e),d=new Date(e).getTime()}c=(0,o.gs)(new Date(d)),e.title=`${(0,l.t)(\"alarmLastChecked\")}: ${c}`,n?(t.style.color=\"#10b981\",t.style.textShadow=\"0 0 10px rgba(16, 185, 129, 0.4)\"):(t.style.color=\"#f59e0b\",t.style.textShadow=\"0 0 10px rgba(245, 158, 11, 0.4)\")}setInterval(h,6e4),setTimeout(h,1e3)},413(e,t,n){n.d(t,{Ao:()=>s,FS:()=>i,PC:()=>g,U4:()=>l,ZD:()=>r,gs:()=>d,sn:()=>o});var a=n(901);function o(e){const t=new Date(Date.UTC(e.getFullYear(),e.getMonth(),e.getDate())),n=t.getUTCDay()||7;t.setUTCDate(t.getUTCDate()+4-n);const a=new Date(Date.UTC(t.getUTCFullYear(),0,1));return Math.ceil(((t-a)/864e5+1)/7)}function s(e){const t=new Date(e.getTime());return t.setDate(t.getDate()+3-(t.getDay()+6)%7),t.getFullYear()}function i(e){if(\"en\"===a.Kl)return e;return{Monday:\"Montag\",Tuesday:\"Dienstag\",Wednesday:\"Mittwoch\",Thursday:\"Donnerstag\",Friday:\"Freitag\",Saturday:\"Samstag\",Sunday:\"Sonntag\"}[e]||e}function r(e){const t=document.createElement(\"div\");return t.textContent=e||\"\",t.innerHTML}function l(e,t){if(!e||!t)return!1;const n=e.replace(/^v/,\"\").split(\".\").map(Number),a=t.replace(/^v/,\"\").split(\".\").map(Number);for(let e=0;e(a[e]||0))return!0;if((n[e]||0)<(a[e]||0))return!1}return!1}function d(e){const t=Date.now()-e.getTime(),n=Math.floor(t/6e4);if(n<1)return\"gerade eben\";if(1===n)return\"vor 1 min.\";if(n<60)return`vor ${n} min.`;const a=Math.floor(n/60);return 1===a?\"vor 1 Std.\":`vor ${a} Std.`}const c=[\"apfel\",\"achtung\",\"aubergine\",\"auflauf\",\"beere\",\"blumenkohl\",\"bohne\",\"braten\",\"brokkoli\",\"brot\",\"brust\",\"br\u00f6tchen\",\"butter\",\"chili\",\"dessert\",\"dip\",\"eier\",\"eintopf\",\"eis\",\"erbse\",\"erdbeer\",\"essig\",\"filet\",\"fisch\",\"fisole\",\"fleckerl\",\"fleisch\",\"fl\u00fcgel\",\"frucht\",\"f\u00fcr\",\"gebraten\",\"gem\u00fcse\",\"gew\u00fcrz\",\"gratin\",\"grie\u00df\",\"gulasch\",\"gurke\",\"himbeer\",\"honig\",\"huhn\",\"h\u00e4hnchen\",\"jambalaya\",\"joghurt\",\"karotte\",\"kartoffel\",\"keule\",\"kirsch\",\"knacker\",\"knoblauch\",\"kn\u00f6del\",\"kompott\",\"kraut\",\"kr\u00e4uter\",\"kuchen\",\"k\u00e4se\",\"k\u00fcrbis\",\"lauch\",\"mandel\",\"milch\",\"mild\",\"mit\",\"mohn\",\"most\",\"m\u00f6hre\",\"natur\",\"nockerl\",\"nudel\",\"nuss\",\"nu\u00df\",\"obst\",\"oder\",\"olive\",\"paprika\",\"pfanne\",\"pfannkuchen\",\"pfeffer\",\"pikant\",\"pilz\",\"plunder\",\"p\u00fcree\",\"ragout\",\"rahm\",\"reis\",\"rind\",\"sahne\",\"salami\",\"salat\",\"salz\",\"sauer\",\"scharf\",\"schinken\",\"schnitte\",\"schnitzel\",\"schoko\",\"schupf\",\"schwein\",\"sellerie\",\"senf\",\"sosse\",\"so\u00dfe\",\"spargel\",\"sp\u00e4tzle\",\"speck\",\"spie\u00df\",\"spinat\",\"steak\",\"suppe\",\"s\u00fc\u00df\",\"tofu\",\"tomate\",\"topfen\",\"torte\",\"tr\u00fcffel\",\"und\",\"vanille\",\"vogerl\",\"vom\",\"wien\",\"wurst\",\"zucchini\",\"zum\",\"zur\",\"zwiebel\",\"\u00f6l\"],u=[\"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 g(e){if(\"all\"===a.Kl)return e||\"\";const t=function(e){if(!e)return{de:\"\",en:\"\",raw:\"\"};let t=e.replace(/(?:\\(|(?:\\/|\\s|^))([A-Z,]+)\\)\\s*(?=\\S)(?!\\s*\\/)/g,\"($1)\\n\u2022 \");function n(e){let t=0,n=0;return e.forEach(e=>{const a=e.toLowerCase().replace(/[^a-z\u00e4\u00f6\u00fc\u00df]/g,\"\");if(a){let o=0,s=0;c.includes(a)?o=a.length:c.forEach(e=>{a.includes(e)&&e.length>o&&(o=e.length)}),u.includes(a)?s=a.length:u.forEach(e=>{a.includes(e)&&e.length>s&&(s=e.length)}),o>0&&(t+=o/a.length),s>0&&(n+=s/a.length),/^[A-Z\u00c4\u00d6\u00dc]/.test(e)&&(t+=.5)}}),{de:t,en:n}}function a(e){const t=e.trim().split(/\\s+/);if(t.length<2)return{enPart:e,nextDe:\"\"};let a=-1,o=-9999;for(let e=1;er.de||r.en>0,m=l.de+c>l.en;g&&m&&u>o&&(o=u,a=e)}return-1!==a?{enPart:t.slice(0,a).join(\" \"),nextDe:t.slice(a).join(\" \")}:{enPart:e,nextDe:\"\"}}t.startsWith(\"\u2022 \")||(t=\"\u2022 \"+t);const o=/(.*?)(?:\\(|(?:\\/|\\s|^))([A-Z,]+)\\)\\s*(?!\\s*[/])/g;let s;const i=[];let r=0;for(;null!==(s=o.exec(e));)s.index>r&&i.push(e.substring(r,s.index).trim()),i.push(s[0].trim()),r=o.lastIndex;r=2){const e=i[0].trim();let t=i.slice(1).join(\" / \").trim();const n=a(t);if(n.nextDe){l.push(e+o),d.push(n.enPart+o);const t=n.nextDe+o;l.push(t),d.push(t)}else{const n=t+o,a=e.includes(o.trim())?e:e+o;l.push(a),d.push(n)}}else{const e=a(n);e.nextDe?(d.push(e.enPart+o),l.push(e.nextDe+o)):(l.push(n+o),d.push(n+o))}}let g=l.join(\"\\n\u2022 \");l.length>0&&!g.startsWith(\"\u2022 \")&&(g=\"\u2022 \"+g);let m=d.join(\"\\n\u2022 \");return d.length>0&&!m.startsWith(\"\u2022 \")&&(m=\"\u2022 \"+m),{de:g,en:m,raw:t}}(e);return\"en\"===a.Kl?t.en||t.raw:t.de||t.raw}}},t={};function n(a){var o=t[a];if(void 0!==o)return o.exports;var s=t[a]={exports:{}};return e[a](s,s.exports,n),s.exports}n.d=(e,t)=>{for(var a in t)n.o(t,a)&&!n.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var a=n(901);var o=n(367),s=n(842),i=n(521),r=n(672),l=n(646);if(!window.__KANTINE_LOADED){window.__KANTINE_LOADED=!0,function(){document.title=\"Kantine Weekly Menu\",document.querySelectorAll&&document.querySelectorAll('link[rel*=\"icon\"]').forEach(e=>e.remove());const e=document.createElement(\"link\");if(e.rel=\"icon\",e.type=\"image/png\",e.href=\"data:image/png;base64,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\",document.head.appendChild(e),!document.querySelector('link[href*=\"fonts.googleapis.com/css2?family=Inter\"]')){const e=document.createElement(\"link\");e.rel=\"stylesheet\",e.href=\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap\",document.head.appendChild(e)}if(!document.querySelector('link[href*=\"Material+Icons+Round\"]')){const e=document.createElement(\"link\");e.rel=\"stylesheet\",e.href=\"https://fonts.googleapis.com/icon?family=Material+Icons+Round\",document.head.appendChild(e)}const t=`\\n
        \\n
        \\n
        \\n
        \\n \"Logo\"\\n
        \\n

        Kantinen \u00dcbersicht v1.6.17

        \\n
        \\n
        \\n
        \\n \\n \\n
        \\n \\n
        \\n
        \\n
        \\n \\n \\n \\n
        \\n
        \\n
        \\n
        \\n
        \\n \\n \\n \\n \\n \\n
        \\n person\\n \\n \\n
        \\n
        \\n
        \\n
        \\n\\n
        \\n
        \\n
        \\n

        Login

        \\n \\n
        \\n
        \\n
        \\n \\n \\n Deine offizielle Knapp Mitarbeiternummer.\\n
        \\n
        \\n \\n \\n Das Passwort f\u00fcr deinen Bessa Account.\\n
        \\n
        \\n
        \\n \\n
        \\n
        \\n
        \\n
        \\n\\n
        \\n
        \\n
        \\n

        Men\u00fcdaten aktualisieren

        \\n
        \\n
        \\n
        \\n
        \\n
        \\n
        \\n
        0%
        \\n
        \\n

        Initialisierung...

        \\n
        \\n
        \\n
        \\n\\n
        \\n
        \\n
        \\n

        Meine Highlights

        \\n \\n
        \\n
        \\n

        \\n Markiere Men\u00fcs automatisch, wenn sie diese Schlagw\u00f6rter enthalten.\\n

        \\n
        \\n \\n \\n
        \\n
        \\n
        \\n
        \\n
        \\n\\n
        \\n
        \\n
        \\n

        Bestellhistorie

        \\n \\n
        \\n
        \\n
        \\n

        Lade Historie...

        \\n
        \\n
        \\n
        \\n
        \\n
        \\n
        \\n
        \\n
        \\n
        \\n
        \\n
        \\n\\n
        \\n
        \\n
        \\n

        \ud83d\udce6 Versionen

        \\n \\n
        \\n
        \\n
        \\n Aktuell: v1.6.17\\n
        \\n
        \\n \\n
        \\n
        \\n

        Lade Versionen...

        \\n
        \\n
        \\n \\n bug_report Fehler melden\\n \\n \\n lightbulb Feature vorschlagen\\n \\n \\n
        \\n
        \\n
        \\n
        \\n\\n
        \\n
        \\n update\\n Gerade aktualisiert\\n
        \\n
        \\n
        \\n

        Lade Men\u00fcdaten...

        \\n
        \\n
        \\n
        \\n\\n
        \\n

        Jetzt Bessa Einfach! • Knapp-Kantine Wrapper • ${(new Date).getFullYear()} by Kaufi \ud83d\ude03\ud83d\udc4d mit Hilfe von KI \ud83e\udd16

        \\n
        \\n
        `;document.body.innerHTML=t}(),function(){const e=document.getElementById(\"btn-this-week\"),t=document.getElementById(\"btn-next-week\"),n=document.getElementById(\"btn-refresh\"),d=document.getElementById(\"theme-toggle\"),c=document.getElementById(\"btn-login-open\"),u=document.getElementById(\"btn-login-close\"),g=document.getElementById(\"btn-logout\"),m=document.getElementById(\"login-form\"),h=document.getElementById(\"login-modal\"),p=document.getElementById(\"btn-highlights\"),f=document.getElementById(\"highlights-modal\"),v=document.getElementById(\"btn-highlights-close\"),y=document.getElementById(\"btn-add-tag\"),b=document.getElementById(\"tag-input\"),w=document.getElementById(\"btn-history\"),E=document.getElementById(\"history-modal\"),A=document.getElementById(\"btn-history-close\");document.querySelectorAll(\".lang-btn\").forEach(e=>{e.addEventListener(\"click\",()=>{(0,a.UD)(e.dataset.lang),localStorage.setItem(i.LS.LANG,e.dataset.lang),document.querySelectorAll(\".lang-btn\").forEach(e=>e.classList.remove(\"active\")),e.classList.add(\"active\"),function(){const e=document.getElementById(\"btn-this-week\"),t=document.getElementById(\"btn-next-week\");e&&(e.textContent=(0,l.t)(\"thisWeek\"),e.title=(0,l.t)(\"thisWeekTooltip\")),t&&(t.textContent=(0,l.t)(\"nextWeek\"));const n=document.querySelector(\".header-left h1\");if(n){const e=n.querySelector(\".version-tag\"),t=n.querySelector(\".update-icon\");n.textContent=(0,l.t)(\"appTitle\")+\" \",e&&n.appendChild(e),t&&n.appendChild(t)}const o=document.getElementById(\"btn-refresh\");o&&o.setAttribute(\"aria-label\",(0,l.t)(\"refresh\")),o&&(o.title=(0,l.t)(\"refresh\"));const i=document.getElementById(\"btn-history\");i&&i.setAttribute(\"aria-label\",(0,l.t)(\"history\")),i&&(i.title=(0,l.t)(\"history\"));const r=document.getElementById(\"btn-highlights\");r&&r.setAttribute(\"aria-label\",(0,l.t)(\"highlights\")),r&&(r.title=(0,l.t)(\"highlights\"));const d=document.getElementById(\"theme-toggle\");d&&(d.title=(0,l.t)(\"themeTooltip\"));const c=document.getElementById(\"btn-login-open\");if(c){c.title=(0,l.t)(\"loginTooltip\");const e=c.querySelector(\"span:last-child\");e&&!e.classList.contains(\"material-icons-round\")&&(e.textContent=(0,l.t)(\"login\"))}const u=document.getElementById(\"btn-logout\");u&&(u.title=(0,l.t)(\"logoutTooltip\"));const g=document.getElementById(\"lang-toggle\");g&&(g.title=(0,l.t)(\"langTooltip\"));const m=document.querySelector(\"#highlights-modal .modal-header h2\");m&&(m.textContent=(0,l.t)(\"highlightsTitle\"));const h=document.querySelector(\"#highlights-modal .modal-body > p\");h&&(h.textContent=(0,l.t)(\"highlightsDesc\"));const p=document.getElementById(\"tag-input\");p&&(p.placeholder=(0,l.t)(\"tagInputPlaceholder\"),p.title=(0,l.t)(\"tagInputTooltip\"));const f=document.getElementById(\"btn-add-tag\");f&&(f.textContent=(0,l.t)(\"addTag\"),f.title=(0,l.t)(\"addTagTooltip\"));const v=document.querySelector(\"#history-modal .modal-header h2\");v&&(v.textContent=(0,l.t)(\"historyTitle\"));const y=document.querySelector(\"#login-modal .modal-header h2\");y&&(y.textContent=(0,l.t)(\"loginTitle\"));const b=document.getElementById(\"alarm-bell\");b&&0===a.BY.size&&(b.title=(0,l.t)(\"alarmTooltipNone\")),(0,s.OR)(),(0,s.gJ)(),(0,s.Mb)()}()})}),p&&p.addEventListener(\"click\",()=>{(0,o.Y1)(),f.classList.remove(\"hidden\")}),v&&v.addEventListener(\"click\",()=>{f.classList.add(\"hidden\")}),w.addEventListener(\"click\",()=>{a.gX?(E.classList.remove(\"hidden\"),(0,o.Aq)()):h.classList.remove(\"hidden\")}),A.addEventListener(\"click\",()=>{E.classList.add(\"hidden\")}),window.addEventListener(\"click\",e=>{e.target===E&&E.classList.add(\"hidden\"),e.target===f&&f.classList.add(\"hidden\")});const k=document.querySelector(\".version-tag\"),L=document.getElementById(\"version-modal\"),S=document.getElementById(\"btn-version-close\");k&&k.addEventListener(\"click\",e=>{e.preventDefault(),e.stopPropagation(),(0,s.Gk)()}),S&&S.addEventListener(\"click\",()=>{L.classList.add(\"hidden\")});const I=document.getElementById(\"btn-clear-cache\");I&&I.addEventListener(\"click\",()=>{confirm(\"M\u00f6chtest du wirklich alle lokalen Daten (inkl. Login-Session, Cache und Einstellungen) l\u00f6schen? Die Seite wird danach neu geladen.\")&&(Object.keys(localStorage).forEach(e=>{e.startsWith(\"kantine_\")&&localStorage.removeItem(e)}),window.location.reload())}),window.addEventListener(\"click\",e=>{e.target===L&&L.classList.add(\"hidden\")}),y.addEventListener(\"click\",()=>{const e=b.value;(0,o.oL)(e)&&(b.value=\"\",(0,o.Y1)())}),b.addEventListener(\"keypress\",e=>{\"Enter\"===e.key&&y.click()});const C=localStorage.getItem(\"theme\"),B=window.matchMedia(\"(prefers-color-scheme: dark)\").matches,T=d.querySelector(\".theme-icon\");\"dark\"===C||!C&&B?(document.documentElement.setAttribute(\"data-theme\",\"dark\"),T.textContent=\"dark_mode\"):(document.documentElement.setAttribute(\"data-theme\",\"light\"),T.textContent=\"light_mode\"),d.addEventListener(\"click\",()=>{const e=\"dark\"===document.documentElement.getAttribute(\"data-theme\")?\"light\":\"dark\";document.documentElement.setAttribute(\"data-theme\",e),localStorage.setItem(\"theme\",e),T.textContent=\"dark\"===e?\"dark_mode\":\"light_mode\"}),e.addEventListener(\"click\",()=>{\"this-week\"!==a.sw&&((0,a.qo)(\"this-week\"),e.classList.add(\"active\"),t.classList.remove(\"active\"),(0,s.OR)())}),t.addEventListener(\"click\",()=>{t.classList.remove(\"new-week-available\"),\"next-week\"!==a.sw&&((0,a.qo)(\"next-week\"),t.classList.add(\"active\"),e.classList.remove(\"active\"),(0,s.OR)())}),n.addEventListener(\"click\",()=>{a.gX?(0,o.m9)():h.classList.remove(\"hidden\")});const D=document.getElementById(\"alarm-bell\");D&&D.addEventListener(\"click\",()=>{(0,o.A0)()}),c.addEventListener(\"click\",()=>{h.classList.remove(\"hidden\"),document.getElementById(\"login-error\").classList.add(\"hidden\"),m.reset()}),u.addEventListener(\"click\",()=>{h.classList.add(\"hidden\")}),window.addEventListener(\"click\",e=>{e.target===h&&h.classList.add(\"hidden\")}),m.addEventListener(\"submit\",async e=>{e.preventDefault();const t=document.getElementById(\"employee-id\").value.trim(),n=document.getElementById(\"password\").value,s=document.getElementById(\"login-error\"),l=m.querySelector('button[type=\"submit\"]'),d=l.textContent;l.disabled=!0,l.textContent=\"Wird eingeloggt...\";try{const e=`knapp-${t}@bessa.app`,l=await fetch(`${i.tE}/auth/login/`,{method:\"POST\",headers:(0,r.H)(i.f9),body:JSON.stringify({email:e,password:n})}),d=await l.json();if(l.ok){(0,a.O5)(d.key),(0,a.lt)(t),localStorage.setItem(i.LS.AUTH_TOKEN,d.key),localStorage.setItem(i.LS.CURRENT_USER,t);try{const e=await fetch(`${i.tE}/auth/user/`,{headers:(0,r.H)(d.key)});if(e.ok){const t=await e.json();t.first_name&&localStorage.setItem(i.LS.FIRST_NAME,t.first_name),t.last_name&&localStorage.setItem(i.LS.LAST_NAME,t.last_name)}}catch(e){console.error(\"Failed to fetch user info:\",e)}(0,o.i_)(),h.classList.add(\"hidden\"),(0,o.Gb)(),m.reset(),(0,o.g8)(),(0,o.m9)()}else s.textContent=d.non_field_errors?.[0]||d.error||\"Login fehlgeschlagen\",s.classList.remove(\"hidden\")}catch(e){console.error(\"Login error:\",e),s.textContent=\"Ein Fehler ist aufgetreten\",s.classList.remove(\"hidden\")}finally{l.disabled=!1,l.textContent=d}}),g.addEventListener(\"click\",()=>{localStorage.removeItem(i.LS.AUTH_TOKEN),localStorage.removeItem(i.LS.CURRENT_USER),localStorage.removeItem(i.LS.FIRST_NAME),localStorage.removeItem(i.LS.LAST_NAME),(0,a.O5)(null),(0,a.lt)(null),(0,a.di)(new Map),(0,o.Et)(),(0,o.i_)(),(0,s.OR)()})}(),(0,o.i_)(),(0,o.H)();(0,o.KG)()?(document.getElementById(\"loading\").classList.add(\"hidden\"),(0,o.VL)()||(0,o.m9)()):(0,o.m9)(),a.gX&&(0,o.g8)(),(0,s.Ux)(),setInterval(s.Ux,36e5)}})();\n"; document.head.appendChild(sc); })(); +javascript:javascript:(function(){ if(window.__KANTINE_LOADED){alert('Kantine Wrapper already loaded!');return;} var s=document.createElement('style');s.textContent=':root { /* Premium Slate/Gray-Blue Palette - Light Mode */ --bg-body: #f1f5f9; /* Slate 100 */ --bg-card: #ffffff; --text-primary: #334155; /* Slate 700 */ --text-secondary: #64748b; --accent-color: #0f172a; /* Slate 900 (High contrast) */ --border-color: #cbd5e1; /* Slate 300 */ --banner-bg: #e2e8f0; --banner-text: #1e293b; --success-color: #059669; --error-color: #dc2626; --card-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.05), 0 2px 4px -2px rgb(0 0 0 / 0.05); --header-bg: rgba(255, 255, 255, 0.9); --header-border: 1px solid rgba(203, 213, 225, 0.6); } [data-theme="dark"] { /* Premium Slate/Gray-Blue Palette - Dark Mode */ --bg-body: #1e293b; /* Deep Slate Gray (Requested) */ --bg-card: #334155; /* Slate 700 */ --text-primary: #f8fafc; /* Slate 50 */ --text-secondary: #cbd5e1; /* Slate 300 */ --accent-color: #60a5fa; /* Blue 400 */ --border-color: #475569; /* Slate 600 */ --banner-bg: #475569; --banner-text: #e2e8f0; --header-bg: rgba(30, 41, 59, 0.9); --header-border: 1px solid rgba(71, 85, 105, 0.6); --card-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.4); } * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: \'Inter\', system-ui, -apple-system, sans-serif; background-color: var(--bg-body); color: var(--text-primary); transition: background-color 0.3s ease, color 0.3s ease; line-height: 1.5; -webkit-font-smoothing: antialiased; } /* Fix scrolling bug: Reset html/body styles from host page */ /* IMPORTANT: html must NOT have overflow set, or it creates a scroll container that breaks position: sticky */ html { height: auto !important; min-height: 100% !important; overflow: visible !important; position: static !important; margin: 0 !important; padding: 0 !important; } body { height: auto !important; min-height: 100% !important; overflow-x: clip !important; /* clip prevents horizontal overflow without breaking sticky */ overflow-y: visible !important; position: static !important; margin: 0 !important; padding: 0 !important; } /* Header */ .app-header { flex-shrink: 0; z-index: 100; backdrop-filter: blur(12px); background-color: var(--header-bg); border-bottom: var(--header-border); padding: 1rem 0; } .header-content { width: 100%; /* Full width */ padding: 0 2rem; /* Comfortable padding */ display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 1rem; } .brand { display: flex; align-items: center; gap: 0.75rem; } .brand-text { display: flex; flex-direction: column; } .brand h1 { font-size: 1.25rem; font-weight: 700; letter-spacing: -0.025em; margin-bottom: 0; } .subtitle { font-size: 0.85rem; color: var(--text-secondary); font-weight: 400; margin-left: 2px; } .logo-icon { font-size: 1.5rem; color: var(--accent-color); } /* Controls */ .controls { display: flex; align-items: center; gap: 1.5rem; justify-self: end; } /* Header Week Info (centered) */ .header-week-info { text-align: center; line-height: 1.3; } .header-center-wrapper { display: flex; flex-direction: row; align-items: center; gap: 1.5rem; justify-content: center; } .header-week-title { font-size: 1.1rem; font-weight: 600; color: var(--text-primary); } .header-week-subtitle { font-size: 0.85rem; color: var(--text-secondary); } /* Language Toggle (FR-100) */ .lang-toggle { display: inline-flex; gap: 0; border-radius: 6px; overflow: hidden; border: 1px solid var(--border-color); background: var(--bg-card); } .lang-btn { padding: 3px 10px; font-size: 0.7rem; font-weight: 600; letter-spacing: 0.03em; background: transparent; color: var(--text-secondary); border: none; cursor: pointer; transition: all 0.2s; } .lang-btn:hover { color: var(--text-primary); background: rgba(100, 116, 139, 0.1); } .lang-btn.active { background: var(--accent-color); color: white; } .nav-group { display: flex; background-color: var(--bg-card); border: 1px solid var(--border-color); padding: 0.25rem; border-radius: 8px; } .nav-btn { background: none; border: none; padding: 0.5rem 1rem; font-size: 0.875rem; font-weight: 500; color: var(--text-secondary); cursor: pointer; border-radius: 6px; transition: all 0.2s; display: flex; align-items: center; gap: 0.5rem; } .nav-btn:hover { color: var(--text-primary); background-color: rgba(100, 116, 139, 0.1); } .nav-btn.active { background-color: var(--accent-color); color: white; } /* Notification state for Next Week */ .nav-btn.new-week-available { animation: goldPulse 2s infinite; border-color: #f59e0b; color: var(--accent-color); } .nav-btn.new-week-available.active { color: white; } @keyframes goldPulse { 0% { box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.7); } 70% { box-shadow: 0 0 0 10px rgba(245, 158, 11, 0); } 100% { box-shadow: 0 0 0 0 rgba(245, 158, 11, 0); } } /* Badge for nav buttons (day count indicator) */ .nav-badge { background-color: var(--error-color); color: white; font-size: 0.75rem; font-weight: 600; padding: 0 6px; border-radius: 10px; min-width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center; margin-left: 8px; gap: 3px; line-height: 1; } .nav-badge .orderable { color: #fff; font-weight: 800; } .nav-badge .separator { opacity: 0.6; font-weight: 400; } .nav-badge .total { opacity: 0.8; font-weight: 400; } .nav-btn.active .nav-badge { background: rgba(255, 255, 255, 0.3); } /* Primary style for Login Button to match header */ #btn-login-open { background-color: var(--accent-color); color: white; padding: 0.5rem 1.25rem; border-radius: 8px; font-weight: 600; letter-spacing: 0.025em; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } #btn-login-open:hover { background-color: #334155; /* Slightly lighter than slate-900 */ transform: translateY(-1px); box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } /* User Badge Button (Login) */ .user-badge-btn { display: flex; align-items: center; gap: 8px; padding: 6px 12px; background: var(--bg-card); border: 1px solid var(--border-color); border-radius: 20px; font-size: 0.9rem; font-weight: 500; color: var(--text-primary); cursor: pointer; transition: all 0.2s; } .user-badge-btn:hover { background: rgba(100, 116, 139, 0.1); border-color: var(--accent-color); } .user-badge-btn .material-icons-round { font-size: 1.25rem; color: var(--accent-color); } .icon-btn { background: none; border: none; color: var(--text-primary); cursor: pointer; padding: 0.5rem; border-radius: 50%; transition: background-color 0.2s; display: flex; align-items: center; justify-content: center; } .icon-btn:hover { background-color: rgba(100, 116, 139, 0.1); } /* Refresh button animation */ #btn-refresh.refreshing .material-icons-round, #alarm-bell.refreshing .material-icons-round { animation: rotate 1s linear infinite; } @keyframes rotate { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } /* Progress Modal */ .progress-container { margin-bottom: 1.5rem; } .progress-bar { width: 100%; height: 8px; background-color: var(--border-color); border-radius: 4px; overflow: hidden; margin-bottom: 0.75rem; } .progress-fill { height: 100%; background: linear-gradient(90deg, var(--accent-color) 0%, #60a5fa 100%); width: 0%; transition: width 0.3s ease; border-radius: 4px; } .progress-percent { text-align: center; font-size: 1.5rem; font-weight: 700; color: var(--text-primary); margin-bottom: 0.5rem; } .progress-message { text-align: center; color: var(--text-secondary); font-size: 0.9rem; font-weight: 500; } .weekly-cost { background-color: rgba(59, 130, 246, 0.1); /* Blue tint */ color: var(--accent-color); padding: 0.4rem 0.8rem; border-radius: 8px; font-weight: 600; font-size: 0.9rem; display: flex; align-items: center; gap: 0.5rem; border: 1px solid rgba(59, 130, 246, 0.2); } .weekly-cost .material-icons-round { font-size: 18px; } /* Container - flex column, full width so child scrollbar is at edge */ .container { flex: 1; width: 100%; overflow: hidden; padding: 0 0 0 0; /* Only top padding, no horizontal so child fills width */ display: flex; flex-direction: column; } /* Add horizontal padding to direct children of container to maintain layout */ .container>*:not(.menu-grid) { padding-left: 2rem; padding-right: 2rem; } /* Banner */ .banner { background-color: var(--banner-bg); color: var(--banner-text); padding: 0.75rem 1rem; border-radius: 8px; display: flex; align-items: center; gap: 0.5rem; margin-bottom: 2rem; font-size: 0.875rem; font-weight: 500; border: 1px solid var(--border-color); max-width: fit-content; } /* User Badge */ .user-badge { display: flex; align-items: center; gap: 8px; padding: 6px 12px; background: var(--bg-card); /* Changed from --surface */ border: 1px solid var(--border-color); /* Changed from --border */ border-radius: 20px; font-size: 0.9rem; font-weight: 500; } .icon-btn-small { background: none; border: none; padding: 4px; cursor: pointer; color: var(--text-secondary); /* Changed from --text-muted */ display: flex; align-items: center; justify-content: center; border-radius: 50%; transition: all 0.2s; } .icon-btn-small:hover { color: var(--error-color); /* Changed from --danger */ background: rgba(239, 68, 68, 0.1); } /* Modal */ .modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); backdrop-filter: blur(4px); display: flex; align-items: center; justify-content: center; z-index: 1000; transition: all 0.3s; } .modal.hidden { opacity: 0; pointer-events: none; } .modal-content { background: var(--bg-card); width: 90%; max-width: 400px; border-radius: 16px; box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); overflow: hidden; animation: modalSlide 0.3s ease-out; } /* History Modal specific */ .history-modal-content { max-width: 600px; max-height: 85vh; display: flex; flex-direction: column; } .history-modal-content .modal-body { overflow-y: auto; padding: 0; /* Padding is handled by inner elements */ } /* History Styles */ .history-year-group { margin-bottom: 16px; } .history-year-header { background: var(--bg-card); padding: 12px 20px; margin: 0; font-size: 1.2rem; font-weight: 700; color: var(--text-primary); border-bottom: 2px solid var(--border-color); position: sticky; top: 0; z-index: 12; } .history-month-group { border-bottom: 1px solid var(--border-color); } .history-month-header { display: flex; justify-content: space-between; align-items: center; padding: 14px 20px; margin: 0; font-size: 1.05rem; font-weight: 600; color: var(--text-primary); background: var(--bg-body); cursor: pointer; transition: background 0.2s; } .history-month-header:hover { background: var(--border-color); /* Slight hover effect */ } .history-month-summary { display: flex; align-items: center; gap: 12px; font-size: 0.95rem; color: var(--text-secondary); } .history-month-content { display: none; /* Collapsed by default */ background: var(--bg-card); } .history-month-group.open .history-month-content { display: block; /* Expanded when open class is present */ } .history-month-group.open .history-month-header .material-icons-round { transform: rotate(180deg); } .history-month-header .material-icons-round { transition: transform 0.3s; font-size: 20px; } .history-week-group { padding: 12px 20px; border-bottom: 1px dashed var(--border-color); } .history-week-group:last-child { border-bottom: none; } .history-week-header { display: flex; justify-content: space-between; align-items: center; font-size: 0.9rem; font-weight: 600; color: var(--text-secondary); margin-bottom: 10px; } .history-week-summary { font-size: 0.85rem; font-weight: 500; background: rgba(100, 116, 139, 0.1); padding: 4px 10px; border-radius: 12px; } .history-items { display: flex; flex-direction: column; gap: 8px; } .history-item { display: grid; grid-template-columns: 50px 1fr auto; align-items: center; gap: 12px; padding: 10px 12px; background: var(--bg-body); border-radius: 8px; border: 1px solid var(--border-color); } .history-item-date { font-size: 0.85rem; color: var(--text-secondary); font-weight: 500; } .history-item-details { display: flex; flex-direction: column; gap: 4px; } .history-item-name { font-size: 0.95rem; font-weight: 500; color: var(--text-primary); } .history-item-price { font-weight: 600; color: var(--text-primary); } .history-item-status { font-size: 0.8rem; font-weight: 600; color: var(--text-primary); text-transform: uppercase; letter-spacing: 0.5px; } .history-item-cancelled { opacity: 0.5; filter: grayscale(1); } .history-item-price-cancelled { text-decoration: line-through; color: var(--text-secondary); } @keyframes modalSlide { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } .modal-header { display: flex; align-items: center; justify-content: space-between; padding: 20px; border-bottom: 1px solid var(--border-color); } .modal-header h2 { margin: 0; font-size: 1.25rem; } .modal-body { padding: 20px; } #login-form { padding: 20px; } .form-group { margin-bottom: 20px; } .form-group label { display: block; margin-bottom: 6px; font-weight: 500; font-size: 0.9rem; } .form-group input { width: 100%; padding: 10px 12px; border: 1px solid var(--border-color); /* Changed from --border */ border-radius: 8px; background: var(--bg-body); /* Changed from --bg */ color: var(--text-primary); /* Changed from --text */ font-family: inherit; transition: border-color 0.2s; } .form-group input:focus { outline: none; border-color: var(--accent-color); /* Changed from --primary */ } .help-text { display: block; margin-top: 4px; color: var(--text-secondary); /* Changed from --text-muted */ font-size: 0.75rem; } .error-msg { margin-bottom: 16px; padding: 10px; background: rgba(239, 68, 68, 0.1); color: var(--error-color); /* Changed from --danger */ border-radius: 8px; font-size: 0.85rem; text-align: center; } .modal-actions { margin-top: 24px; } .btn-primary.wide { width: 100%; justify-content: center; } .hidden { display: none !important; } /* Menu Grid Container */ .menu-grid { display: flex; flex-direction: column; flex: 1; overflow: hidden; gap: 1rem; } .week-section { margin-bottom: 2rem; } .week-header { margin-bottom: 1.5rem; border-bottom: 1px solid var(--border-color); padding-bottom: 1rem; text-align: center; } .week-title { font-size: 1.75rem; font-weight: 700; color: var(--text-primary); } .week-range { color: var(--text-secondary); font-size: 0.9rem; margin-top: 0.25rem; } /* Full-viewport layout: header + scrollable content + footer */ #kantine-wrapper { display: flex; flex-direction: column; height: 100vh; height: 100dvh; /* Dynamic viewport height for mobile browsers */ overflow: hidden; } .days-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 0.5rem; flex: 1; overflow-y: auto; /* This is the scroll container at the window edge */ align-content: start; padding: 0 2rem 2rem 2rem; } /* Card */ .menu-card { background-color: var(--bg-card); border-radius: 12px; border: 1px solid var(--border-color); box-shadow: var(--card-shadow); overflow: clip; /* Clips scrolling content behind sticky header */ transition: box-shadow 0.2s ease; display: flex; flex-direction: column; } /* Past Day Styling - Target specific elements so ordered items can remain visible AND preserve sticky context */ /* We MUST apply filter/opacity to children, not the parent .menu-card, or else position: sticky breaks */ /* Header keeps fully opaque background to hide scrolling items, only grayscales */ .menu-card.past-day .card-header { filter: grayscale(0.8); transition: filter 0.3s; } /* Items become semi-transparent */ .menu-card.past-day .menu-item:not(.ordered) { opacity: 0.6; filter: grayscale(0.8); transition: opacity 0.3s, filter 0.3s; } .menu-card.past-day:hover .card-header { filter: grayscale(0.4); } .menu-card.past-day:hover .menu-item:not(.ordered) { opacity: 0.8; filter: grayscale(0.4); } /* Past ordered items get no special frame or shadow, but remain visually distinct by staying fully opaque (via the :not(.ordered) selector above) */ .menu-item.today-ordered { border: 2px solid #8b5cf6; box-shadow: 0 0 30px rgba(139, 92, 246, 0.6); border-radius: 8px; padding: 1rem; margin: 0 0 1.5rem 0; background: var(--bg-card); position: relative; z-index: 5; animation: pulse-glow-strong 3s infinite; } @keyframes pulse-glow-strong { 0% { box-shadow: 0 0 20px rgba(139, 92, 246, 0.4); } 50% { box-shadow: 0 0 40px rgba(139, 92, 246, 0.8); } 100% { box-shadow: 0 0 20px rgba(139, 92, 246, 0.4); } } .menu-card:hover { box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); } .card-header { padding: 1rem 1.25rem; border-bottom: 1px solid var(--border-color); display: flex; justify-content: space-between; align-items: baseline; background-color: var(--bg-card); /* Removed border-radius: 12px 12px 0 0; .menu-card\'s overflow: clip will round the corners initially. When sticky at the top, it will be square and perfectly hide scrolling content! */ /* Sticky within .container scroll area */ position: sticky; top: 0; z-index: 90; } .card-body { padding: 1.25rem; display: grid; grid-template-rows: auto; align-content: start; } .day-name { font-size: 1.125rem; font-weight: 600; } .day-date { font-size: 0.875rem; color: var(--text-secondary); } .empty-state { color: var(--text-secondary); font-style: italic; text-align: center; padding: 1rem; } /* Menu Items */ .menu-item { margin-bottom: 1.5rem; padding-bottom: 1.5rem; border-bottom: 1px solid var(--border-color); } .menu-item:last-child { margin-bottom: 0; padding-bottom: 0; border-bottom: none; } .item-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 0.5rem; gap: 1rem; } .item-name { font-weight: 600; color: var(--text-primary); font-size: 1rem; } .item-price { font-weight: 700; color: var(--accent-color); white-space: nowrap; } .item-desc { font-size: 0.875rem; color: var(--text-secondary); line-height: 1.6; margin-bottom: 0.75rem; white-space: pre-wrap; } .badges { display: flex; gap: 0.5rem; margin-left: auto; flex-wrap: wrap; } .item-status-row { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.75rem; flex-wrap: wrap; } .badge { display: inline-flex; align-items: center; justify-content: center; height: 24px; font-size: 0.75rem; padding: 0 10px; border-radius: 4px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; line-height: normal; white-space: nowrap; } .badge.available { background-color: rgba(16, 185, 129, 0.1); /* Emerald 500 / 10% */ color: var(--success-color); border: 1px solid rgba(16, 185, 129, 0.2); } .badge.sold-out { background-color: rgba(239, 68, 68, 0.1); /* Red 500 / 10% */ color: var(--error-color); border: 1px solid rgba(239, 68, 68, 0.2); } .badge.ordered { background-color: rgba(139, 92, 246, 0.1); /* Violet 500 / 10% */ color: #8b5cf6; border: 1px solid rgba(139, 92, 246, 0.2); gap: 4px; } .badge.ordered .material-icons-round { font-size: 1rem; } /* Loading */ .loading-state { text-align: center; padding: 4rem; color: var(--text-secondary); } .spinner { width: 40px; height: 40px; border: 3px solid var(--border-color); border-top-color: var(--accent-color); border-radius: 50%; margin: 0 auto 1rem; animation: spin 1s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } /* Footer */ .app-footer { flex-shrink: 0; text-align: center; padding: 0.4rem 2rem; color: var(--text-secondary); font-size: 0.8rem; border-top: 1px solid var(--border-color); } /* === Order / Cancel Buttons (inline in status row) === */ .btn-order { display: inline-flex; align-items: center; gap: 4px; padding: 4px 10px; border: none; border-radius: 6px; background: var(--success-color); color: white; font-size: 0.75rem; font-weight: 600; cursor: pointer; transition: all 0.2s ease; font-family: inherit; } .btn-order .material-icons-round { font-size: 16px; } .btn-order:hover:not(:disabled) { filter: brightness(1.15); transform: translateY(-1px); } .btn-order:disabled { opacity: 0.5; cursor: not-allowed; } .btn-order.loading { pointer-events: none; opacity: 0.6; } .btn-order-compact { padding: 2px 4px; gap: 0; } .btn-order-compact .material-icons-round { font-size: 16px; } .btn-cancel { display: inline-flex; align-items: center; justify-content: center; padding: 4px 6px; border: none; border-radius: 6px; background: var(--error-color); color: white; font-size: 0.75rem; cursor: pointer; transition: all 0.2s ease; font-family: inherit; } .btn-cancel .material-icons-round { font-size: 16px; } .btn-cancel:hover:not(:disabled) { filter: brightness(1.15); transform: translateY(-1px); } .btn-cancel:disabled { opacity: 0.5; cursor: not-allowed; } /* Past days: hide action buttons */ .past-day .item-actions { display: none; } /* Order count badge (for multi-orders) */ .order-count-badge { display: inline-flex; align-items: center; justify-content: center; background: rgba(255, 255, 255, 0.3); color: white; font-size: 0.65rem; font-weight: 700; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px; margin-left: 4px; line-height: 1; } /* === Toast Notifications === */ #toast-container { position: fixed; bottom: 20px; right: 20px; z-index: 10000; display: flex; flex-direction: column; gap: 8px; pointer-events: none; } .toast { display: flex; align-items: center; gap: 8px; padding: 10px 16px; border-radius: 8px; font-size: 0.85rem; font-weight: 500; font-family: \'Inter\', sans-serif; color: white; backdrop-filter: blur(10px); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); pointer-events: auto; transform: translateX(120%); opacity: 0; transition: transform 0.3s ease, opacity 0.3s ease; } .toast.show { transform: translateX(0); opacity: 1; } .toast .material-icons-round { font-size: 18px; } .toast-success { background: rgba(5, 150, 105, 0.95); } .toast-error { background: rgba(220, 38, 38, 0.95); } .toast-info { background: rgba(59, 130, 246, 0.95); } /* === Mobile Responsiveness === */ @media (max-width: 600px) { .header-content { flex-direction: column; gap: 1rem; padding: 0.75rem; } .week-nav { width: 100%; justify-content: center; } .nav-pills { width: 100%; justify-content: space-between; } .nav-btn { flex: 1; justify-content: center; padding: 0.5rem; font-size: 0.85rem; } .days-grid { grid-template-columns: 1fr; /* Force single column */ } .main-content { padding: 1rem; } .week-title { font-size: 1.5rem; } /* Adjust toast position for mobile */ .toast-container { bottom: 1rem; right: 1rem; left: 1rem; /* Center on mobile */ width: auto; } .menu-card { margin-bottom: 1rem; } } /* Tighter layout for high column counts (e.g., 5-day landscape) */ @media (min-width: 1024px) { .card-body { padding: 1rem 0.75rem; } .item-header { gap: 0.5rem; } } /* === Flagging & Notification Styles === */ .btn-flag { display: inline-flex; align-items: center; justify-content: center; background: transparent; border: 1px solid var(--text-secondary); color: var(--text-secondary); border-radius: 6px; padding: 4px; cursor: pointer; transition: all 0.2s; margin-right: 0.5rem; width: 28px; height: 28px; } .btn-flag:hover { background: rgba(234, 179, 8, 0.1); /* Yellow-500 / 10% */ color: #eab308; border-color: #eab308; } .btn-flag.active { background: rgba(234, 179, 8, 0.1); color: #eab308; border-color: #eab308; } .btn-flag .material-icons-round { font-size: 1.1rem; } /* Flagged & Sold Out (Yellow Glow) */ .menu-item.flagged-sold-out { border: 1px solid #eab308; box-shadow: 0 0 10px rgba(234, 179, 8, 0.2); border-radius: 8px; padding: 1rem; margin: 0 0 1.5rem 0; background: var(--bg-card); position: relative; z-index: 5; animation: yellow-pulse 3s infinite; } @keyframes yellow-pulse { 0% { box-shadow: 0 0 8px rgba(234, 179, 8, 0.2); } 50% { box-shadow: 0 0 16px rgba(234, 179, 8, 0.5); } 100% { box-shadow: 0 0 8px rgba(234, 179, 8, 0.2); } } /* Flagged & Available (Green Glow) */ .menu-item.flagged-available { border: 2px solid var(--success-color); box-shadow: 0 0 15px rgba(16, 185, 129, 0.3); border-radius: 8px; padding: 1rem; margin: 0 0 1.5rem 0; background: var(--bg-card); position: relative; z-index: 5; animation: green-pulse 3s infinite; } @keyframes green-pulse { 0% { box-shadow: 0 0 10px rgba(16, 185, 129, 0.3); } 50% { box-shadow: 0 0 20px rgba(16, 185, 129, 0.6); } 100% { box-shadow: 0 0 10px rgba(16, 185, 129, 0.3); } } /* Day Header Badges */ .day-header-left { display: flex; align-items: center; gap: 0.75rem; } .menu-code-badge { font-size: 0.75rem; font-weight: 700; color: #8b5cf6; /* Violet 500 */ background-color: rgba(139, 92, 246, 0.15); border: 1px solid rgba(139, 92, 246, 0.3); padding: 2px 6px; border-radius: 6px; line-height: normal; display: inline-block; } /* Detailed Badge Colors */ .nav-badge.badge-violet { background-color: #8b5cf6; } .nav-badge.badge-green { background-color: var(--success-color); } .nav-badge.badge-red { background-color: var(--error-color); } .nav-badge.badge-blue { background-color: var(--accent-color); } /* Day Header Status Colors (User Request) */ .card-header.header-violet { background-color: var(--bg-card); background-image: linear-gradient(rgba(139, 92, 246, 0.15), rgba(139, 92, 246, 0.15)); border-bottom: 2px solid #8b5cf6; } .card-header.header-green { background-color: var(--bg-card); background-image: linear-gradient(rgba(16, 185, 129, 0.15), rgba(16, 185, 129, 0.15)); border-bottom: 2px solid var(--success-color); } .card-header.header-red { background-color: var(--bg-card); background-image: linear-gradient(rgba(239, 68, 68, 0.15), rgba(239, 68, 68, 0.15)); border-bottom: 2px solid var(--error-color); } .card-header.header-violet .day-name, .card-header.header-green .day-name, .card-header.header-red .day-name { font-weight: 700; color: var(--text-primary); /* Ensure text remains standard color */ } /* Update Icon */ .update-icon { display: inline-flex; align-items: center; justify-content: center; margin-left: 8px; background-color: rgba(16, 185, 129, 0.2); /* Green tint */ color: var(--success-color); border-radius: 50%; width: 24px; height: 24px; cursor: pointer; font-size: 14px; transition: all 0.2s; text-decoration: none; animation: pulse 2s infinite; } .update-icon:hover { background-color: var(--success-color); color: white; transform: scale(1.1); } @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.4); } 70% { box-shadow: 0 0 0 6px rgba(16, 185, 129, 0); } 100% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0); } } /* Order Countdown */ #order-countdown { background: rgba(255, 255, 255, 0.1); padding: 0.25rem 0.75rem; border-radius: 99px; font-size: 0.85rem; display: flex; align-items: center; gap: 0.5rem; white-space: nowrap; border: 1px solid var(--border-color); } #order-countdown span { opacity: 0.7; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.5px; } #order-countdown.urgent { background: rgba(239, 68, 68, 0.2); border-color: rgba(239, 68, 68, 0.5); color: #ef4444; animation: pulse-red 2s infinite; } @keyframes pulse-red { 0% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.4); } 70% { box-shadow: 0 0 0 6px rgba(239, 68, 68, 0); } 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0); } } /* Smart Highlights (Blue Glow - matches today-ordered/flagged pattern) */ .menu-item.highlight-glow { border: 2px solid rgba(59, 130, 246, 0.7); box-shadow: 0 0 20px rgba(59, 130, 246, 0.4); border-radius: 8px; padding: 1rem; margin: 0 0 1.5rem 0; background: var(--bg-card); position: relative; z-index: 5; animation: blue-pulse 3s infinite; } @keyframes blue-pulse { 0% { box-shadow: 0 0 15px rgba(59, 130, 246, 0.3); } 50% { box-shadow: 0 0 25px rgba(59, 130, 246, 0.6); } 100% { box-shadow: 0 0 15px rgba(59, 130, 246, 0.3); } } /* Nav Badge with Count */ .nav-badge.has-highlights { background-color: var(--bg-card); /* Neutral background */ color: var(--text-primary); border: 1px solid var(--border-color); padding: 2px 6px; } .nav-badge .highlight-count { color: #3b82f6; /* Blue 500 */ font-weight: 700; margin-left: 4px; } /* Tag Management Modal */ #tags-list { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1rem; min-height: 50px; } /* Tag badges styled consistently with .badge (verfügbar/ausverkauft) */ .tag-badge { display: inline-flex; align-items: center; justify-content: center; height: 24px; font-size: 0.75rem; padding: 0 10px; border-radius: 4px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; line-height: normal; white-space: nowrap; background-color: rgba(59, 130, 246, 0.1); color: #3b82f6; border: 1px solid rgba(59, 130, 246, 0.2); gap: 4px; } .tag-remove { cursor: pointer; opacity: 0.7; font-size: 1.1em; line-height: 1; transition: all 0.2s; } .tag-remove:hover { opacity: 1; color: #ef4444; } .input-group { display: flex; gap: 0.5rem; } .input-group input { flex: 1; padding: 0.75rem; background: var(--bg-body); border: 1px solid var(--border-color); color: var(--text-primary); border-radius: 8px; font-family: inherit; } /* Add tag button - styled like .btn-order with nav-btn.active color */ #btn-add-tag { display: inline-flex; align-items: center; gap: 4px; padding: 0.5rem 1rem; border: none; border-radius: 6px; background: var(--accent-color); color: white; font-size: 0.8rem; font-weight: 600; cursor: pointer; transition: all 0.2s ease; font-family: inherit; white-space: nowrap; } #btn-add-tag:hover { filter: brightness(1.15); transform: translateY(-1px); } .matched-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; /* Space between tags and title */ margin-top: -5px; /* Pull closer to header */ } .tag-badge-small { display: inline-flex; align-items: center; font-size: 0.7rem; padding: 2px 8px; border-radius: 4px; background: rgba(59, 130, 246, 0.15); color: #60a5fa; border: 1px solid rgba(59, 130, 246, 0.3); font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; } [data-theme="light"] .tag-badge-small { background: rgba(37, 99, 235, 0.1); color: #2563eb; border: 1px solid rgba(37, 99, 235, 0.2); } /* Installer Changelog */ .changelog-container ul { padding-left: 1.5rem; margin: 0.5rem 0; } .changelog-container li { margin-bottom: 0.4rem; line-height: 1.5; } .changelog-container h3 { margin-top: 1.5rem; margin-bottom: 0.5rem; font-size: 1.1em; color: var(--accent-color); } /* === Version Menu === */ .version-tag { cursor: pointer; transition: opacity 0.2s ease, text-decoration 0.2s ease; } .version-tag:hover { opacity: 1 !important; text-decoration: underline; } .version-list { list-style: none; padding: 0; margin: 0; } .version-item { display: flex; justify-content: space-between; align-items: center; padding: 10px 14px; border-radius: 8px; margin-bottom: 4px; transition: background 0.2s; } .version-item:hover { background: rgba(100, 116, 139, 0.08); } .version-item.current { background: rgba(2, 154, 168, 0.1); border: 1px solid rgba(2, 154, 168, 0.25); } [data-theme="dark"] .version-item:hover { background: rgba(255, 255, 255, 0.05); } [data-theme="dark"] .version-item.current { background: rgba(96, 165, 250, 0.12); border: 1px solid rgba(96, 165, 250, 0.25); } .version-info { display: flex; align-items: center; gap: 10px; } .badge-current { font-size: 0.75rem; font-weight: 600; color: var(--success-color); padding: 2px 8px; border-radius: 4px; background: rgba(5, 150, 105, 0.1); } .badge-new { font-size: 0.75rem; font-weight: 600; color: #029aa8; padding: 2px 8px; border-radius: 4px; background: rgba(2, 154, 168, 0.1); } [data-theme="dark"] .badge-new { color: #60a5fa; background: rgba(96, 165, 250, 0.12); } .install-link { font-size: 0.8rem; font-weight: 500; padding: 4px 12px; border-radius: 6px; background: rgba(2, 154, 168, 0.1); color: #029aa8; text-decoration: none; border: 1px solid rgba(2, 154, 168, 0.25); transition: all 0.2s; white-space: nowrap; } .install-link:hover { background: rgba(2, 154, 168, 0.2); border-color: rgba(2, 154, 168, 0.4); } [data-theme="dark"] .install-link { color: #60a5fa; background: rgba(96, 165, 250, 0.12); border: 1px solid rgba(96, 165, 250, 0.25); } [data-theme="dark"] .install-link:hover { background: rgba(96, 165, 250, 0.2); border-color: rgba(96, 165, 250, 0.4); } .dev-toggle { padding: 10px 14px; border-radius: 8px; background: rgba(100, 116, 139, 0.05); border: 1px solid var(--border-color); } .dev-toggle input[type="checkbox"] { accent-color: #029aa8; width: 16px; height: 16px; } [data-theme="dark"] .dev-toggle input[type="checkbox"] { accent-color: #60a5fa; } ';document.head.appendChild(s); // Inject JS logic var sc=document.createElement('script'); sc.textContent="(()=>{\"use strict\";var e={367(e,t,n){n.d(t,{A0:()=>v,Aq:()=>g,BM:()=>S,Et:()=>E,Gb:()=>u,H:()=>b,KG:()=>T,N4:()=>p,P0:()=>H,PQ:()=>y,VL:()=>D,Y1:()=>L,g8:()=>w,i_:()=>c,m9:()=>O,oL:()=>k,wH:()=>h});var a=n(901),o=n(413),s=n(521),i=n(672),r=n(842),l=n(646);let d=null;function c(){if(!a.gX)try{const e=localStorage.getItem(\"AkitaStores\");if(e){const t=JSON.parse(e);t.auth&&t.auth.token&&((0,a.O5)(t.auth.token),localStorage.setItem(s.LS.AUTH_TOKEN,t.auth.token),t.auth.user&&((0,a.lt)(t.auth.user.id||\"unknown\"),localStorage.setItem(s.LS.CURRENT_USER,t.auth.user.id||\"unknown\"),t.auth.user.firstName&&localStorage.setItem(s.LS.FIRST_NAME,t.auth.user.firstName),t.auth.user.lastName&&localStorage.setItem(s.LS.LAST_NAME,t.auth.user.lastName)))}}catch(e){console.warn(\"Failed to parse AkitaStores:\",e)}(0,a.O5)(localStorage.getItem(s.LS.AUTH_TOKEN)),(0,a.lt)(localStorage.getItem(s.LS.CURRENT_USER));const e=localStorage.getItem(s.LS.FIRST_NAME),t=document.getElementById(\"btn-login-open\"),n=document.getElementById(\"user-info\"),o=document.getElementById(\"user-id-display\");a.gX?(t.classList.add(\"hidden\"),n.classList.remove(\"hidden\"),o.textContent=e||(a.Ny?`User ${a.Ny}`:(0,l.t)(\"loggedIn\")),u()):(t.classList.remove(\"hidden\"),n.classList.add(\"hidden\"),o.textContent=\"\"),(0,r.OR)()}async function u(){if(a.gX)try{const e=await fetch(`${s.tE}/user/orders/?venue=${s.eW}&ordering=-created&limit=50`,{headers:(0,i.H)(a.gX)}),t=await e.json();if(e.ok){const e=new Map,n=t.results||[];for(const t of n){if(9===t.order_state)continue;const n=t.date.split(\"T\")[0];for(const a of t.items||[]){const o=`${n}_${a.article}`;e.has(o)||e.set(o,[]),e.get(o).push(t.id)}}(0,a.di)(e),(0,r.OR)(),(0,r.gJ)()}}catch(e){console.error(\"Error fetching orders:\",e)}}async function g(){const e=document.getElementById(\"history-loading\"),t=document.getElementById(\"history-content\"),n=document.getElementById(\"history-progress-fill\"),o=document.getElementById(\"history-progress-text\");let r=[];if(d)r=d;else{const e=localStorage.getItem(s.LS.HISTORY_CACHE);if(e)try{r=JSON.parse(e),d=r}catch(e){console.warn(\"History cache parse error\",e)}}if(r.length>0&&m(r),!a.gX)return;0===r.length&&(t.innerHTML=\"\",e.classList.remove(\"hidden\")),n.style.width=\"0%\",o.textContent=r.length>0?(0,l.t)(\"historyLoadingDelta\"):(0,l.t)(\"historyLoadingFull\"),r.length>0&&e.classList.remove(\"hidden\");let c=r.length>0?`${s.tE}/user/orders/?venue=${s.eW}&ordering=-created&limit=5`:`${s.tE}/user/orders/?venue=${s.eW}&ordering=-created&limit=50`,u=[],g=0,h=0===r.length,p=!1;try{for(;c&&!p;){const e=await fetch(c,{headers:(0,i.H)(a.gX)});if(!e.ok)throw new Error(`Fetch failed: ${e.status}`);const t=await e.json();t.count&&0===g&&(g=t.count);const s=t.results||[];for(const e of s){const t=r.findIndex(t=>t.id===e.id);if(!h&&-1!==t){const n=r[t];if(n.updated===e.updated&&n.order_state===e.order_state){p=!0;break}}u.push(e)}if(!p&&h)if(g>0){const e=Math.round(u.length/g*100);n.style.width=`${e}%`,o.textContent=`${(0,l.t)(\"historyLoadingItem\")} ${u.length} ${(0,l.t)(\"historyLoadingOf\")} ${g}...`}else o.textContent=`${(0,l.t)(\"historyLoadingItem\")} ${u.length}...`;else p||(o.textContent=`${u.length} ${(0,l.t)(\"historyLoadingNew\")}`);c=p?null:t.next}if(u.length>0){const e=new Map(r.map(e=>[e.id,e]));for(const t of u)e.set(t.id,t);const t=Array.from(e.values());t.sort((e,t)=>new Date(t.created)-new Date(e.created)),d=t;try{localStorage.setItem(s.LS.HISTORY_CACHE,JSON.stringify(t))}catch(e){console.warn(\"History cache write error\",e)}m(d)}}catch(e){console.error(\"Error in history sync:\",e),0===r.length?t.innerHTML=`

        ${(0,l.t)(\"historyLoadError\")}

        `:H((0,l.t)(\"bgSyncFailed\"),\"error\")}finally{e.classList.add(\"hidden\")}}function m(e){const t=document.getElementById(\"history-content\");if(!e||0===e.length)return void(t.innerHTML=`

        ${(0,l.t)(\"noOrders\")}

        `);const n={};e.forEach(e=>{const t=new Date(e.date),s=t.getFullYear(),i=t.getMonth(),r=`${s}-${i.toString().padStart(2,\"0\")}`,l=\"en\"===a.Kl?\"en-US\":\"de-AT\",d=t.toLocaleString(l,{month:\"long\"}),c=(0,o.sn)(t);n[s]||(n[s]={year:s,months:{}}),n[s].months[r]||(n[s].months[r]={name:d,year:s,monthIndex:i,count:0,total:0,weeks:{}}),n[s].months[r].weeks[c]||(n[s].months[r].weeks[c]={label:\"en\"===a.Kl?`CW ${c}`:`KW ${c}`,items:[],count:0,total:0});(e.items||[]).forEach(t=>{const a=parseFloat(t.price||e.total||0);n[s].months[r].weeks[c].items.push({date:e.date,name:t.name||\"Men\u00fc\",price:a,state:e.order_state}),9!==e.order_state&&(n[s].months[r].weeks[c].count++,n[s].months[r].weeks[c].total+=a,n[s].months[r].count++,n[s].months[r].total+=a)})}),t.innerHTML=\"\";Object.keys(n).sort((e,t)=>t-e).forEach(e=>{const o=n[e],s=document.createElement(\"div\");s.className=\"history-year-group\";const i=document.createElement(\"h2\");i.className=\"history-year-header\",i.textContent=o.year,s.appendChild(i);Object.keys(o.months).sort((e,t)=>t.localeCompare(e)).forEach(e=>{const t=o.months[e],n=document.createElement(\"div\");n.className=\"history-month-group\";const i=document.createElement(\"div\");i.className=\"history-month-header\",i.setAttribute(\"tabindex\",\"0\"),i.setAttribute(\"role\",\"button\"),i.setAttribute(\"aria-expanded\",\"false\"),i.setAttribute(\"title\",(0,l.t)(\"historyMonthToggle\"));const r=document.createElement(\"div\");r.style.display=\"flex\",r.style.flexDirection=\"column\",r.style.gap=\"4px\";const d=document.createElement(\"span\");d.textContent=t.name,r.appendChild(d);const c=document.createElement(\"div\");c.className=\"history-month-summary\";const u=document.createElement(\"span\");u.innerHTML=`${t.count} ${(0,l.t)(\"orders\")} • \u20ac${t.total.toFixed(2)}`,c.appendChild(u),r.appendChild(c),i.appendChild(r);const g=document.createElement(\"span\");g.className=\"material-icons-round\",g.textContent=\"expand_more\",i.appendChild(g),i.addEventListener(\"click\",()=>{const e=i.parentElement;e.classList.contains(\"open\")?(e.classList.remove(\"open\"),i.setAttribute(\"aria-expanded\",\"false\")):(e.classList.add(\"open\"),i.setAttribute(\"aria-expanded\",\"true\"))}),n.appendChild(i);const m=document.createElement(\"div\");m.className=\"history-month-content\";Object.keys(t.weeks).sort((e,t)=>parseInt(t)-parseInt(e)).forEach(e=>{const n=t.weeks[e],o=document.createElement(\"div\");o.className=\"history-week-group\";const s=document.createElement(\"div\");s.className=\"history-week-header\";const i=document.createElement(\"strong\");i.textContent=n.label,s.appendChild(i);const r=document.createElement(\"span\");r.innerHTML=`${n.count} ${(0,l.t)(\"orders\")} • \u20ac${n.total.toFixed(2)}`,s.appendChild(r),o.appendChild(s),n.items.forEach(e=>{const t=new Date(e.date),n=\"en\"===a.Kl?\"en-US\":\"de-AT\",s=t.toLocaleDateString(n,{weekday:\"short\",day:\"2-digit\",month:\"2-digit\"}),i=document.createElement(\"div\");i.className=\"history-item\",9===e.state&&i.classList.add(\"history-item-cancelled\");const r=document.createElement(\"div\");r.style.fontSize=\"0.85rem\",r.style.color=\"var(--text-secondary)\",r.textContent=s,i.appendChild(r);const d=document.createElement(\"div\");d.className=\"history-item-details\";const c=document.createElement(\"span\");c.className=\"history-item-name\",c.textContent=e.name,d.appendChild(c);const u=document.createElement(\"div\"),g=document.createElement(\"span\");g.className=\"history-item-status\",9===e.state?g.textContent=(0,l.t)(\"stateCancelled\"):8===e.state?g.textContent=(0,l.t)(\"stateCompleted\"):g.textContent=(0,l.t)(\"stateTransferred\"),u.appendChild(g),d.appendChild(u),i.appendChild(d);const m=document.createElement(\"div\");m.className=\"history-item-price\",9===e.state&&m.classList.add(\"history-item-price-cancelled\"),m.textContent=`\u20ac${e.price.toFixed(2)}`,i.appendChild(m),o.appendChild(i)}),m.appendChild(o)}),n.appendChild(m),s.appendChild(n)}),t.appendChild(s)})}async function h(e,t,n,o,r){if(a.gX)try{const c=await fetch(`${s.tE}/auth/user/`,{headers:(0,i.H)(a.gX)});if(!c.ok)return void H(\"Fehler: Benutzerdaten konnten nicht geladen werden\",\"error\");const g=await c.json(),m=(new Date).toISOString(),h={uuid:crypto.randomUUID(),created:m,updated:m,order_type:7,items:[{article:t,course_group:null,modifiers:[],uuid:crypto.randomUUID(),name:n,description:r||\"\",price:String(parseFloat(o)),amount:1,vat:\"10.00\",comment:\"\"}],table:null,total:parseFloat(o),tip:0,currency:\"EUR\",venue:s.eW,states:[],order_state:1,date:`${e}T10:30:00Z`,payment_method:\"payroll\",customer:{first_name:g.first_name,last_name:g.last_name,email:g.email,newsletter:!1},preorder:!0,delivery_fee:0,cash_box_table_name:null,take_away:!1},p=await fetch(`${s.tE}/user/orders/`,{method:\"POST\",headers:(0,i.H)(a.gX),body:JSON.stringify(h)});if(p.ok||201===p.status)H(`${(0,l.t)(\"orderSuccess\")}: ${n}`,\"success\"),d=null,await u();else{const e=await p.json();H(`Fehler: ${e.detail||e.non_field_errors?.[0]||\"Bestellung fehlgeschlagen\"}`,\"error\")}}catch(e){console.error(\"Order error:\",e),H(\"Netzwerkfehler bei Bestellung\",\"error\")}}async function p(e,t,n){if(!a.gX)return;const o=`${e}_${t}`,r=a.L.get(o);if(!r||0===r.length)return;const c=r[r.length-1];try{const e=await fetch(`${s.tE}/user/orders/${c}/cancel/`,{method:\"PATCH\",headers:(0,i.H)(a.gX),body:JSON.stringify({})});if(e.ok)H(`${(0,l.t)(\"cancelSuccess\")}: ${n}`,\"success\"),d=null,await u();else{H(`Fehler: ${(await e.json()).detail||\"Stornierung fehlgeschlagen\"}`,\"error\")}}catch(e){console.error(\"Cancel error:\",e),H(\"Netzwerkfehler bei Stornierung\",\"error\")}}function f(){localStorage.setItem(\"kantine_flags\",JSON.stringify([...a.BY]))}async function v(){if(0===a.BY.size)return;const e=a.gX||s.f9,t=new Set;for(const e of a.BY){const[n]=e.split(\"_\");t.add(n)}let n=!1;const o=document.getElementById(\"alarm-bell\");o&&o.classList.add(\"refreshing\");try{for(const o of t)try{const t=await fetch(`${s.tE}/venues/${s.eW}/menu/${s.YU}/${o}/`,{headers:(0,i.H)(e)});if(!t.ok)continue;const r=(await t.json()).results||[],l=new Map;for(const e of r)if(e.items&&Array.isArray(e.items))for(const t of e.items)l.set(t.id,t);for(let e of a.p_){if(!e.days)continue;const t=e.days.find(e=>e.date===o);if(t&&t.items)for(let e=0;e0;s.available=e||t,s.availableAmount=parseInt(r.available_amount)||0,s.amountTracking=!1!==r.amount_tracking,n=!0}}}}catch(e){console.error(\"Error refreshing flag date\",o,e)}n&&B(),localStorage.setItem(\"kantine_flagged_items_last_checked\",(new Date).toISOString()),(0,r.Mb)(),(0,r.OR)(),H(`${a.BY.size} ${1===a.BY.size?(0,l.t)(\"menuSingular\"):(0,l.t)(\"menuPlural\")} ${(0,l.t)(\"menuChecked\")}`,\"info\")}finally{o&&o.classList.remove(\"refreshing\")}}function y(e,t,n,o){const s=`${e}_${t}`;let i=!1;a.BY.has(s)?(a.BY.delete(s),H(`${(0,l.t)(\"flagRemoved\")} ${n}`,\"success\")):(a.BY.add(s),i=!0,H(`${(0,l.t)(\"flagActivated\")} ${n}`,\"success\"),\"default\"===Notification.permission&&Notification.requestPermission()),f(),(0,r.Mb)(),(0,r.OR)(),i&&v()}function b(){const e=new Date,t=e.toISOString().split(\"T\")[0];let n=!1;for(const o of[...a.BY]){const[s]=o.split(\"_\");let i=!1;if(s=t&&(i=!0)}i&&(a.BY.delete(o),n=!0)}n&&f()}function w(){a.K8||a.gX&&(0,a.cc)(setInterval(()=>async function(){if(0===a.BY.size||!a.gX)return;for(const e of a.BY){const[t,n]=e.split(\"_\"),o=parseInt(n);try{const e=await fetch(`${s.tE}/venues/${s.eW}/menu/${s.YU}/${t}/`,{headers:(0,i.H)(a.gX)});if(!e.ok)continue;const n=(await e.json()).results||[];let r=null;for(const e of n)if(e.items&&(r=e.items.find(e=>e.id===o||e.article===o),r))break;if(r){if(!1===r.amount_tracking||parseInt(r.available_amount)>0){const e=r.name||\"Unbekannt\";H(`${e} ist jetzt verf\u00fcgbar!`,\"success\"),\"granted\"===Notification.permission&&new Notification(\"Kantine Wrapper\",{body:`${e} ist jetzt verf\u00fcgbar!`,icon:\"\ud83c\udf7d\ufe0f\"}),O()}}}catch(t){console.error(`Poll error for ${e}:`,t),await new Promise(e=>setTimeout(e,200))}}localStorage.setItem(\"kantine_flagged_items_last_checked\",(new Date).toISOString()),(0,r.Mb)()}(),s.fv))}function E(){a.K8&&(clearInterval(a.K8),(0,a.cc)(null))}function A(){localStorage.setItem(\"kantine_highlightTags\",JSON.stringify(a.yz)),(0,r.OR)(),(0,r.gJ)()}function k(e){if((e=e.trim().toLowerCase())&&!a.yz.includes(e)){const t=[...a.yz,e];return(0,a.iw)(t),A(),!0}return!1}function L(){const e=document.getElementById(\"tags-list\");e.innerHTML=\"\",a.yz.forEach(t=>{const n=document.createElement(\"span\");n.className=\"tag-badge\",n.innerHTML=`${t} ×`,e.appendChild(n)}),e.querySelectorAll(\".tag-remove\").forEach(e=>{e.addEventListener(\"click\",e=>{!function(e){const t=a.yz.filter(t=>t!==e);(0,a.iw)(t),A()}(e.target.dataset.tag),L()})})}function S(e){return e?(e=e.toLowerCase(),a.yz.filter(t=>e.includes(t))):[]}const I=\"kantine_menuCache\",C=\"kantine_menuCacheTs\";function B(){try{localStorage.setItem(I,JSON.stringify(a.p_)),localStorage.setItem(C,(new Date).toISOString())}catch(e){console.warn(\"Failed to cache menu data:\",e)}}function T(){try{const e=localStorage.getItem(I),t=localStorage.getItem(C);if(e){(0,a.tn)(JSON.parse(e)),(0,a.Xt)((0,o.sn)(new Date)),(0,a.pK)((new Date).getFullYear()),(0,r.OR)(),(0,r.gJ)(),(0,r.Mb)(),t&&N(t);try{const e=new Set;a.p_.forEach(t=>{(t.days||[]).forEach(t=>{(t.items||[]).forEach(t=>{let n=(t.description||\"\").replace(/\\s+/g,\" \").trim();n&&n.includes(\" / \")&&e.add(n)})})})}catch(e){}return!0}}catch(e){console.warn(\"Failed to load cached menu:\",e)}return!1}function D(){const e=localStorage.getItem(C);if(!e)return!1;if(Date.now()-new Date(e).getTime()>36e5)return!1;const t=(0,o.sn)(new Date),n=(0,o.Ao)(new Date);return a.p_.some(e=>e.weekNumber===t&&e.year===n&&e.days&&e.days.length>0)}async function O(){const e=document.getElementById(\"loading\"),t=document.getElementById(\"progress-modal\"),l=document.getElementById(\"progress-fill\"),d=document.getElementById(\"progress-percent\"),u=document.getElementById(\"progress-message\");e.classList.remove(\"hidden\");const g=a.gX||s.f9;try{t.classList.remove(\"hidden\"),u.textContent=\"Hole verf\u00fcgbare Daten...\",l.style.width=\"0%\",d.textContent=\"0%\";const e=await fetch(`${s.tE}/venues/${s.eW}/menu/dates/`,{headers:(0,i.H)(g)});if(!e.ok)throw new Error(`Failed to fetch dates: ${e.status}`);let n=(await e.json()).results||[];const m=new Date;m.setDate(m.getDate()-7);const h=m.toISOString().split(\"T\")[0];n=n.filter(e=>e.date>=h).sort((e,t)=>e.date.localeCompare(t.date)).slice(0,30);const p=n.length;u.textContent=`${p} Tage gefunden. Lade Details...`;const f=[];let v=0;const y=5;for(let e=0;e{const t=e.date;let n=null;try{const a=await fetch(`${s.tE}/venues/${s.eW}/menu/${s.YU}/${t}/`,{headers:(0,i.H)(g)});if(a.ok){const o=(await a.json()).results||[];let s=[];for(const e of o)e.items&&Array.isArray(e.items)&&(s=s.concat(e.items));s.length>0&&(n={date:t,menu_items:s,orders:e.orders||[]})}}catch(e){console.error(`Failed to fetch details for ${t}:`,e)}finally{v++;const e=Math.round(v/p*100);l.style.width=`${e}%`,d.textContent=`${e}%`,u.textContent=`Lade Men\u00fc f\u00fcr ${t}...`}return n}));for(const e of a)e&&f.push(e)}const b=new Map;a.p_&&a.p_.length>0&&a.p_.forEach(e=>{const t=`${e.year}-${e.weekNumber}`;try{b.set(t,{year:e.year,weekNumber:e.weekNumber,days:e.days?e.days.map(e=>({...e,items:e.items?[...e.items]:[]})):[]})}catch(e){console.warn(\"Error hydrating week:\",e)}});for(const e of f){const t=new Date(e.date),n=(0,o.sn)(t),a=(0,o.Ao)(t),s=`${a}-${n}`;b.has(s)||b.set(s,{year:a,weekNumber:n,days:[]});const i=b.get(s),r=t.toLocaleDateString(\"en-US\",{weekday:\"long\"}),l=new Date(e.date);l.setHours(10,0,0,0);const d={date:e.date,weekday:r,orderCutoff:l.toISOString(),items:e.menu_items.map(t=>{const n=!1===t.amount_tracking,a=parseInt(t.available_amount)>0;return{id:`${e.date}_${t.id}`,articleId:t.id,name:t.name||\"Unknown\",description:t.description||\"\",price:parseFloat(t.price)||0,available:n||a,availableAmount:parseInt(t.available_amount)||0,amountTracking:!1!==t.amount_tracking}})},c=i.days.findIndex(t=>t.date===e.date);c>=0?i.days[c]=d:i.days.push(d)}const w=Array.from(b.values()).sort((e,t)=>e.year!==t.year?e.year-t.year:e.weekNumber-t.weekNumber);w.forEach(e=>{e.days&&e.days.sort((e,t)=>e.date.localeCompare(t.date))}),(0,a.tn)(w),B(),N((new Date).toISOString()),(0,a.Xt)((0,o.sn)(new Date)),(0,a.pK)((new Date).getFullYear()),c(),(0,r.OR)(),(0,r.gJ)(),(0,r.Mb)(),u.textContent=\"Fertig!\",setTimeout(()=>t.classList.add(\"hidden\"),500)}catch(e){console.error(\"Error fetching menu:\",e),t.classList.add(\"hidden\"),Promise.resolve().then(n.bind(n,842)).then(t=>{t.showErrorModal(\"Keine Verbindung\",`Die Men\u00fcdaten konnten nicht geladen werden. M\u00f6glicherweise besteht keine Verbindung zur API oder zur Bessa-Webseite.

        ${(0,o.ZD)(e.message)}`,\"Zur Original-Seite\",\"https://web.bessa.app/knapp-kantine\")})}finally{e.classList.add(\"hidden\")}}let M=null,x=null;function N(e){const t=document.getElementById(\"last-updated-subtitle\");if(e){M=e,localStorage.setItem(\"kantine_last_updated\",e),localStorage.setItem(\"kantine_last_checked\",e);try{const n=new Date(e),a=n.toLocaleTimeString(\"de-DE\",{hour:\"2-digit\",minute:\"2-digit\"}),s=n.toLocaleDateString(\"de-DE\",{day:\"2-digit\",month:\"2-digit\"}),i=(0,o.gs)(n);t.textContent=`Aktualisiert: ${s} ${a} (${i})`}catch(e){t.textContent=\"\"}x||(x=setInterval(()=>{M&&(N(M),(0,r.Mb)())},6e4))}}function H(e,t=\"info\"){let n=document.getElementById(\"toast-container\");n||(n=document.createElement(\"div\"),n.id=\"toast-container\",document.body.appendChild(n));const a=document.createElement(\"div\");a.className=`toast toast-${t}`;const s=\"success\"===t?\"check_circle\":\"error\"===t?\"error\":\"info\";a.innerHTML=`${s}${(0,o.ZD)(e)}`,n.appendChild(a),requestAnimationFrame(()=>a.classList.add(\"show\")),setTimeout(()=>{a.classList.remove(\"show\"),setTimeout(()=>a.remove(),300)},3e3)}},672(e,t,n){n.d(t,{H:()=>o,O:()=>s});var a=n(521);function o(e){return{Authorization:`Token ${e||a.f9}`,Accept:\"application/json\",\"Content-Type\":\"application/json\",\"X-Client-Version\":a.fZ}}function s(){return{Accept:\"application/vnd.github.v3+json\"}}},521(e,t,n){n.d(t,{LS:()=>g,YU:()=>r,d_:()=>u,eW:()=>i,f9:()=>o,fZ:()=>s,fv:()=>l,pe:()=>c,tE:()=>a});const a=\"https://api.bessa.app/v1\",o=\"c3418725e95a9f90e3645cbc846b4d67c7c66131\",s=\"v1.6.18\",i=591,r=7,l=3e5,d=\"TauNeutrino/kantine-overview\",c=`https://api.github.com/repos/${d}`,u=`https://htmlpreview.github.io/?https://github.com/${d}/blob`,g={AUTH_TOKEN:\"kantine_authToken\",CURRENT_USER:\"kantine_currentUser\",FIRST_NAME:\"kantine_firstName\",LAST_NAME:\"kantine_lastName\",LANG:\"kantine_lang\",FLAGS:\"kantine_flags\",FLAGGED_LAST_CHECKED:\"kantine_flagged_items_last_checked\",LAST_CHECKED:\"kantine_last_checked\",MENU_CACHE:\"kantine_menuCache\",MENU_CACHE_TS:\"kantine_menuCacheTs\",HISTORY_CACHE:\"kantine_history_cache\",HIGHLIGHT_TAGS:\"kantine_highlightTags\",LAST_UPDATED:\"kantine_last_updated\",VERSION_CACHE:\"kantine_version_cache\",DEV_MODE:\"kantine_dev_mode\"}},646(e,t,n){n.d(t,{t:()=>s});var a=n(901);const o={de:{thisWeek:\"Diese Woche\",nextWeek:\"N\u00e4chste Woche\",nextWeekTooltipDefault:\"Men\u00fc n\u00e4chster Woche anzeigen\",thisWeekTooltip:\"Men\u00fc dieser Woche anzeigen\",appTitle:\"Kantinen \u00dcbersicht\",updatedAt:\"Aktualisiert\",langTooltip:\"Sprache der Men\u00fcbeschreibung\",weekLabel:\"Woche\",refresh:\"Men\u00fcdaten neu laden\",history:\"Bestellhistorie\",highlights:\"Pers\u00f6nliche Highlights verwalten\",themeTooltip:\"Erscheinungsbild (Hell/Dunkel) wechseln\",login:\"Anmelden\",loginTooltip:\"Mit Bessa.app Account anmelden\",logout:\"Abmelden\",logoutTooltip:\"Von Bessa.app abmelden\",loginTitle:\"Login\",employeeId:\"Mitarbeiternummer\",employeeIdPlaceholder:\"z.B. 2041\",employeeIdHelp:\"Deine offizielle Knapp Mitarbeiternummer.\",password:\"Passwort\",passwordPlaceholder:\"Bessa Passwort\",passwordHelp:\"Das Passwort f\u00fcr deinen Bessa Account.\",loginButton:\"Einloggen\",loggingIn:\"Wird eingeloggt...\",highlightsTitle:\"Meine Highlights\",highlightsDesc:\"Markiere Men\u00fcs automatisch, wenn sie diese Schlagw\u00f6rter enthalten.\",tagInputPlaceholder:\"z.B. Schnitzel, Vegetarisch...\",tagInputTooltip:\"Neues Schlagwort zum Hervorheben eingeben\",addTag:\"Hinzuf\u00fcgen\",addTagTooltip:\"Schlagwort zur Liste hinzuf\u00fcgen\",removeTagTooltip:\"Schlagwort entfernen\",historyTitle:\"Bestellhistorie\",loadingHistory:\"Lade Historie...\",noOrders:\"Keine Bestellungen gefunden.\",orders:\"Bestellungen\",historyMonthToggle:\"Klicken, um die Bestellungen f\u00fcr diesen Monat ein-/auszublenden\",available:\"Verf\u00fcgbar\",soldOut:\"Ausverkauft\",ordered:\"Bestellt\",orderButton:\"Bestellen\",orderAgainTooltip:\"nochmal bestellen\",orderTooltip:\"bestellen\",cancelOrder:\"Bestellung stornieren\",cancelOneOrder:\"Eine Bestellung stornieren\",flagActivate:\"Benachrichtigen wenn verf\u00fcgbar\",flagDeactivate:\"Benachrichtigung deaktivieren\",alarmTooltipNone:\"Keine beobachteten Men\u00fcs\",alarmLastChecked:\"Zuletzt gepr\u00fcft\",versionsTitle:\"\ud83d\udce6 Versionen\",currentVersion:\"Aktuell\",devModeLabel:\"Dev-Mode (alle Tags anzeigen)\",loadingVersions:\"Lade Versionen...\",noVersions:\"Keine Versionen gefunden.\",installed:\"\u2713 Installiert\",newVersion:\"\u2b06 Neu!\",installLink:\"Installieren\",reportBug:\"Fehler melden\",reportBugTooltip:\"Melde einen Fehler auf GitHub\",featureRequest:\"Feature vorschlagen\",featureRequestTooltip:\"Schlage ein neues Feature auf GitHub vor\",clearCache:\"Lokalen Cache leeren\",clearCacheTooltip:\"L\u00f6scht alle lokalen Daten & erzwingt einen Neuladen\",clearCacheConfirm:\"M\u00f6chtest du wirklich alle lokalen Daten (inkl. Login-Session, Cache und Einstellungen) l\u00f6schen? Die Seite wird danach neu geladen.\",versionMenuTooltip:\"Klick f\u00fcr Versionsmen\u00fc\",progressTitle:\"Men\u00fcdaten aktualisieren\",progressInit:\"Initialisierung...\",noMenuData:\"Keine Men\u00fcdaten f\u00fcr KW\",noMenuDataHint:\"Versuchen Sie eine andere Woche oder schauen Sie sp\u00e4ter vorbei.\",costLabel:\"Gesamt\",orderDeadline:\"Bestellschluss\",flagRemoved:\"Flag entfernt f\u00fcr\",flagActivated:\"Benachrichtigung aktiviert f\u00fcr\",menuChecked:\"gepr\u00fcft\",menuSingular:\"Men\u00fc\",menuPlural:\"Men\u00fcs\",newMenuDataAvailable:\"Neue Men\u00fcdaten f\u00fcr n\u00e4chste Woche verf\u00fcgbar!\",orderSuccess:\"Bestellt\",cancelSuccess:\"Storniert\",bgSyncFailed:\"Hintergrund-Synchronisation fehlgeschlagen\",historyLoadError:\"Fehler beim Laden der Historie.\",historyLoadingFull:\"Lade Bestellhistorie...\",historyLoadingDelta:\"Suche nach neuen Bestellungen...\",historyLoadingItem:\"Lade Bestellung\",historyLoadingOf:\"von\",historyLoadingNew:\"neue/ge\u00e4nderte Bestellungen gefunden...\",badgeOrdered:\"bestellt\",badgeOrderable:\"bestellbar\",badgeTotal:\"gesamt\",badgeHighlights:\"Highlights gefunden\",stateCancelled:\"Storniert\",stateCompleted:\"Abgeschlossen\",stateTransferred:\"\u00dcbertragen\",close:\"Schlie\u00dfen\",noConnection:\"Keine Verbindung\",toOriginalPage:\"Zur Original-Seite\",loggedIn:\"Angemeldet\"},en:{thisWeek:\"This Week\",nextWeek:\"Next Week\",nextWeekTooltipDefault:\"Show next week's menu\",thisWeekTooltip:\"Show this week's menu\",appTitle:\"Canteen Overview\",updatedAt:\"Updated\",langTooltip:\"Menu description language\",weekLabel:\"Week\",refresh:\"Reload menu data\",history:\"Order history\",highlights:\"Manage personal highlights\",themeTooltip:\"Toggle appearance (Light/Dark)\",login:\"Sign in\",loginTooltip:\"Sign in with Bessa.app account\",logout:\"Sign out\",logoutTooltip:\"Sign out from Bessa.app\",loginTitle:\"Login\",employeeId:\"Employee ID\",employeeIdPlaceholder:\"e.g. 2041\",employeeIdHelp:\"Your official Knapp employee number.\",password:\"Password\",passwordPlaceholder:\"Bessa password\",passwordHelp:\"The password for your Bessa account.\",loginButton:\"Log in\",loggingIn:\"Logging in...\",highlightsTitle:\"My Highlights\",highlightsDesc:\"Automatically highlight menus containing these keywords.\",tagInputPlaceholder:\"e.g. Schnitzel, Vegetarian...\",tagInputTooltip:\"Enter new keyword to highlight\",addTag:\"Add\",addTagTooltip:\"Add keyword to list\",removeTagTooltip:\"Remove keyword\",historyTitle:\"Order History\",loadingHistory:\"Loading history...\",noOrders:\"No orders found.\",orders:\"Orders\",historyMonthToggle:\"Click to expand/collapse orders for this month\",available:\"Available\",soldOut:\"Sold out\",ordered:\"Ordered\",orderButton:\"Order\",orderAgainTooltip:\"order again\",orderTooltip:\"order\",cancelOrder:\"Cancel order\",cancelOneOrder:\"Cancel one order\",flagActivate:\"Notify when available\",flagDeactivate:\"Deactivate notification\",alarmTooltipNone:\"No flagged menus\",alarmLastChecked:\"Last checked\",versionsTitle:\"\ud83d\udce6 Versions\",currentVersion:\"Current\",devModeLabel:\"Dev mode (show all tags)\",loadingVersions:\"Loading versions...\",noVersions:\"No versions found.\",installed:\"\u2713 Installed\",newVersion:\"\u2b06 New!\",installLink:\"Install\",reportBug:\"Report a bug\",reportBugTooltip:\"Report a bug on GitHub\",featureRequest:\"Request a feature\",featureRequestTooltip:\"Suggest a new feature on GitHub\",clearCache:\"Clear local cache\",clearCacheTooltip:\"Deletes all local data & forces a reload\",clearCacheConfirm:\"Do you really want to delete all local data (including login session, cache, and settings)? The page will reload afterwards.\",versionMenuTooltip:\"Click for version menu\",progressTitle:\"Updating menu data\",progressInit:\"Initializing...\",noMenuData:\"No menu data for CW\",noMenuDataHint:\"Try another week or check back later.\",costLabel:\"Total\",orderDeadline:\"Order deadline\",flagRemoved:\"Flag removed for\",flagActivated:\"Notification activated for\",menuChecked:\"checked\",menuSingular:\"menu\",menuPlural:\"menus\",newMenuDataAvailable:\"New menu data available for next week!\",orderSuccess:\"Ordered\",cancelSuccess:\"Cancelled\",bgSyncFailed:\"Background synchronisation failed\",historyLoadError:\"Error loading history.\",historyLoadingFull:\"Loading order history...\",historyLoadingDelta:\"Checking for new orders...\",historyLoadingItem:\"Loading order\",historyLoadingOf:\"of\",historyLoadingNew:\"new/updated orders found...\",badgeOrdered:\"ordered\",badgeOrderable:\"orderable\",badgeTotal:\"total\",badgeHighlights:\"highlights found\",stateCancelled:\"Cancelled\",stateCompleted:\"Completed\",stateTransferred:\"Transferred\",close:\"Close\",noConnection:\"No connection\",toOriginalPage:\"Go to original page\",loggedIn:\"Logged in\"}};function s(e){const t=\"en\"===a.Kl?\"en\":\"de\";return o[t][e]||o.de[e]||e}},901(e,t,n){n.d(t,{BT:()=>i,BY:()=>g,K8:()=>m,Kl:()=>h,L:()=>u,Ny:()=>c,O5:()=>b,UD:()=>S,Xt:()=>v,cc:()=>A,di:()=>E,gX:()=>d,iw:()=>k,lt:()=>w,pK:()=>y,p_:()=>s,qo:()=>L,sw:()=>l,tn:()=>f,vW:()=>r,yz:()=>p});var a=n(413),o=n(521);let s=[],i=(0,a.sn)(new Date),r=(new Date).getFullYear(),l=\"this-week\",d=localStorage.getItem(o.LS.AUTH_TOKEN),c=localStorage.getItem(o.LS.CURRENT_USER),u=new Map,g=new Set(JSON.parse(localStorage.getItem(o.LS.FLAGS)||\"[]\")),m=null,h=localStorage.getItem(o.LS.LANG)||\"de\",p=JSON.parse(localStorage.getItem(o.LS.HIGHLIGHT_TAGS)||\"[]\");function f(e){s=e}function v(e){i=e}function y(e){r=e}function b(e){d=e}function w(e){c=e}function E(e){u=e}function A(e){m=e}function k(e){p=e}function L(e){\"this-week\"===e||\"next-week\"===e?l=e:console.warn(`[state] Invalid displayMode: \"${e}\". Ignoring.`)}function S(e){[\"de\",\"en\",\"all\"].includes(e)?h=e:console.warn(`[state] Invalid langMode: \"${e}\". Ignoring.`)}},842(e,t,n){n.d(t,{Gk:()=>m,Mb:()=>v,OR:()=>c,Ux:()=>g,gJ:()=>d,showErrorModal:()=>f});var a=n(901),o=n(413),s=n(521),i=n(672),r=n(367),l=n(646);function d(){const e=document.getElementById(\"btn-next-week\");let t=a.BT+1,n=a.vW;t>52&&(t=1,n++);const o=a.p_.find(e=>e.weekNumber===t&&e.year===n);let s=0,i=0,d=0,c=0;o&&o.days&&o.days.forEach(e=>{if(e.items&&e.items.length>0){s++;const t=e.items.some(e=>e.available);t&&i++;let n=!1;e.items.forEach(t=>{const o=t.articleId||parseInt(t.id.split(\"_\")[1]),s=`${e.date}_${o}`;a.L.has(s)&&a.L.get(s).length>0&&(n=!0)}),n&&d++;const o=new Date(e.date).getDay();o>=1&&o<=4&&t&&!n&&c++}});const u=e.querySelector(\".nav-badge\");if(u&&u.remove(),s>0){let a=0;o&&o.days&&o.days.forEach(e=>{e.items.forEach(e=>{const t=(0,r.BM)(e.name),n=(0,r.BM)(e.description);(t.length>0||n.length>0)&&a++})});let u=[`${d} ${(0,l.t)(\"badgeOrdered\")} / ${i} ${(0,l.t)(\"badgeOrderable\")} / ${s} ${(0,l.t)(\"badgeTotal\")}`];if(a>0&&u.push(`${a} ${(0,l.t)(\"badgeHighlights\")}`),e.title=u.join(\" \u2022 \"),c>0){e.classList.add(\"new-week-available\");const a=`kantine_notified_nextweek_${n}_${t}`;localStorage.getItem(a)||(localStorage.setItem(a,\"true\"),(0,r.P0)((0,l.t)(\"newMenuDataAvailable\"),\"info\"))}else e.classList.remove(\"new-week-available\")}else e.title=(0,l.t)(\"nextWeekTooltipDefault\"),e.classList.remove(\"new-week-available\")}function c(){const e=document.getElementById(\"menu-container\");if(!e)return;e.innerHTML=\"\";let t=a.BT,n=a.vW;\"next-week\"===a.sw&&(t++,t>52&&(t=1,n++));const s=a.p_.flatMap(e=>e.days||[]).filter(e=>{const a=new Date(e.date);return(0,o.sn)(a)===t&&(0,o.Ao)(a)===n});if(0===s.length)return e.innerHTML=`\\n
        \\n

        ${(0,l.t)(\"noMenuData\")} ${t} (${n}).

        \\n ${(0,l.t)(\"noMenuDataHint\")}\\n
        `,void document.getElementById(\"weekly-cost-display\").classList.add(\"hidden\");!function(e){let t=0;e&&e.length>0&&e.forEach(e=>{e.items&&e.items.forEach(n=>{const o=n.articleId||parseInt(n.id.split(\"_\")[1]),s=`${e.date}_${o}`,i=a.L.get(s)||[];i.length>0&&(t+=n.price*i.length)})});const n=document.getElementById(\"weekly-cost-display\");t>0?(n.innerHTML=`shopping_bag ${(0,l.t)(\"costLabel\")}: ${t.toFixed(2).replace(\".\",\",\")} \u20ac`,n.classList.remove(\"hidden\")):n.classList.add(\"hidden\")}(s);const i=document.getElementById(\"header-week-info\"),d=\"this-week\"===a.sw?(0,l.t)(\"thisWeek\"):(0,l.t)(\"nextWeek\");i.innerHTML=`\\n
        ${d}
        \\n
        ${(0,l.t)(\"weekLabel\")} ${t} \u2022 ${n}
        `;const c=document.createElement(\"div\");c.className=\"days-grid\",s.sort((e,t)=>e.date.localeCompare(t.date));s.filter(e=>{const t=new Date(e.date).getDay();return 0!==t&&6!==t}).forEach(e=>{const t=function(e){if(!e.items||0===e.items.length)return null;const t=document.createElement(\"div\");t.className=\"menu-card\";const n=new Date,s=new Date(e.date);let i=!1;if(e.orderCutoff)i=n>=new Date(e.orderCutoff);else{const t=new Date;t.setHours(0,0,0,0);const n=new Date(e.date);n.setHours(0,0,0,0),i=n{const n=t.articleId||parseInt(t.id.split(\"_\")[1]),o=`${e.date}_${n}`,s=(a.L.get(o)||[]).length;if(s>0){const e=t.name.match(/([M][1-9][Ff]?)/);if(e){let t=e[1];s>1&&(t+=\"+\"),d.push(t)}}});const c=document.createElement(\"div\");c.className=\"card-header\";const u=s.toLocaleDateString(\"de-DE\",{day:\"2-digit\",month:\"2-digit\"}),g=d.reduce((e,t)=>e+`${t}`,\"\");let m=\"\";const h=e.items&&e.items.some(t=>{const n=t.articleId||parseInt(t.id.split(\"_\")[1]),o=`${e.date}_${n}`;return a.L.has(o)&&a.L.get(o).length>0}),p=e.items&&e.items.some(e=>e.available);m=h?\"header-violet\":p&&!i?\"header-green\":\"header-red\";m&&c.classList.add(m);c.innerHTML=`\\n
        \\n ${(0,o.FS)(e.weekday)}\\n
        ${g}
        \\n
        \\n ${u}`,t.appendChild(c);const f=document.createElement(\"div\");f.className=\"card-body\";const v=(new Date).toISOString().split(\"T\")[0],y=e.date===v,b=[...e.items].sort((t,n)=>{if(y){const o=t.articleId||parseInt(t.id.split(\"_\")[1]),s=n.articleId||parseInt(n.id.split(\"_\")[1]),i=a.L.has(`${e.date}_${o}`),r=a.L.has(`${e.date}_${s}`);if(i&&!r)return-1;if(!i&&r)return 1}return t.name.localeCompare(n.name)});return b.forEach(t=>{const s=document.createElement(\"div\");s.className=\"menu-item\";const d=t.articleId||parseInt(t.id.split(\"_\")[1]),c=`${e.date}_${d}`,u=(a.L.get(c)||[]).length;let g=\"\";g=t.available?t.amountTracking?`${(0,l.t)(\"available\")} (${t.availableAmount})`:`${(0,l.t)(\"available\")}`:`${(0,l.t)(\"soldOut\")}`;let m=\"\";if(u>0){const t=u>1?`${u}`:\"\";m=`check_circle ${(0,l.t)(\"ordered\")}${t}`,s.classList.add(\"ordered\"),new Date(e.date).toDateString()===n.toDateString()&&s.classList.add(\"today-ordered\")}const h=`${e.date}_${d}`,p=a.BY.has(h);p&&s.classList.add(t.available?\"flagged-available\":\"flagged-sold-out\");const v=[...new Set([...(0,r.BM)(t.name),...(0,r.BM)(t.description)])];v.length>0&&s.classList.add(\"highlight-glow\");let y=\"\",b=\"\",w=\"\";if(a.gX&&!i){const n=p?\"notifications_active\":\"notifications_none\",a=p?\"btn-flag active\":\"btn-flag\",s=p?(0,l.t)(\"flagDeactivate\"):(0,l.t)(\"flagActivate\");if(t.available&&!p||(w=``),t.available&&(y=u>0?``:``),u>0){const n=1===u?\"close\":\"remove\",a=1===u?(0,l.t)(\"cancelOrder\"):(0,l.t)(\"cancelOneOrder\");b=``}}let E=\"\";if(v.length>0){E=`
        ${v.reduce((e,t)=>e+`star${(0,o.ZD)(t)}`,\"\")}
        `}s.innerHTML=`\\n
        \\n ${(0,o.ZD)(t.name)}\\n ${t.price.toFixed(2)} \u20ac\\n
        \\n
        \\n ${m}\\n ${b}\\n ${y}\\n ${w}\\n
        ${g}
        \\n
        \\n ${E}\\n

        ${(0,o.ZD)((0,o.PC)(t.description))}

        `;const A=s.querySelector(\".btn-order\");A&&A.addEventListener(\"click\",e=>{e.stopPropagation();const t=e.currentTarget;t.disabled=!0,t.classList.add(\"loading\"),(0,r.wH)(t.dataset.date,parseInt(t.dataset.article),t.dataset.name,parseFloat(t.dataset.price),t.dataset.desc||\"\").finally(()=>{t.disabled=!1,t.classList.remove(\"loading\")})});const k=s.querySelector(\".btn-cancel\");k&&k.addEventListener(\"click\",e=>{e.stopPropagation();const t=e.currentTarget;t.disabled=!0,(0,r.N4)(t.dataset.date,parseInt(t.dataset.article),t.dataset.name).finally(()=>{t.disabled=!1})});const L=s.querySelector(\".btn-flag\");L&&L.addEventListener(\"click\",e=>{e.stopPropagation();const t=e.currentTarget;(0,r.PQ)(t.dataset.date,parseInt(t.dataset.article),t.dataset.name,t.dataset.cutoff)}),f.appendChild(s)}),t.appendChild(f),t}(e);t&&c.appendChild(t)}),e.appendChild(c),setTimeout(()=>function(e){const t=e.querySelectorAll(\".menu-card\");if(0===t.length)return;let n=0;t.forEach(e=>{n=Math.max(n,e.querySelectorAll(\".menu-item\").length)});for(let e=0;e{const o=t.querySelectorAll(\".menu-item\");o[e]&&(o[e].style.height=\"auto\",n=Math.max(n,o[e].offsetHeight),a.push(o[e]))}),a.forEach(e=>{e.style.height=`${n}px`})}}(c),0)}async function u(e){const t=e?`${s.pe}/tags?per_page=20`:`${s.pe}/releases?per_page=20`,n=await fetch(t,{headers:(0,i.O)()});if(!n.ok){if(403===n.status)throw new Error(\"API Rate Limit erreicht (403). Bitte sp\u00e4ter erneut versuchen.\");throw new Error(`GitHub API ${n.status}`)}return(await n.json()).map(t=>{const n=e?t.name:t.tag_name;return{tag:n,name:e?n:t.name||n,url:`${s.d_}/${n}/dist/install.html`,body:t.body||\"\"}})}async function g(){const e=\"true\"===localStorage.getItem(s.LS.DEV_MODE);try{const t=await u(e);if(!t.length)return;localStorage.setItem(s.LS.VERSION_CACHE,JSON.stringify({timestamp:Date.now(),devMode:e,versions:t}));const n=t[0].tag;if(!(0,o.U4)(n,\"v1.6.18\"))return;const a=document.querySelector(\".header-left h1\");if(a&&!a.querySelector(\".update-icon\")){const e=document.createElement(\"a\");e.className=\"update-icon\",e.href=t[0].url,e.target=\"_blank\",e.innerHTML=\"\ud83c\udd95\",e.title=`Update: ${n} \u2014 Klick zum Installieren`,e.style.cssText=\"margin-left:8px;font-size:1em;text-decoration:none;cursor:pointer;vertical-align:middle;\",a.appendChild(e)}}catch(e){console.warn(\"[Kantine] Version check failed:\",e)}}function m(){const e=document.getElementById(\"version-modal\"),t=document.getElementById(\"version-list-container\"),n=document.getElementById(\"dev-mode-toggle\"),a=\"v1.6.18\";if(!e)return;e.classList.remove(\"hidden\");const i=document.getElementById(\"version-current\");i&&(i.textContent=a);const r=\"true\"===localStorage.getItem(s.LS.DEV_MODE);async function l(e){const i=n.checked;function r(e){if(!e||!e.length)return void(t.innerHTML='

        Keine Versionen gefunden.

        ');t.innerHTML='
          ';const n=t.querySelector(\".version-list\");e.forEach(e=>{const t=e.tag===a,s=(0,o.U4)(e.tag,a),i=document.createElement(\"li\");i.className=\"version-item\"+(t?\" current\":\"\");let r=\"\";t?r='\u2713 Installiert':s&&(r='\u2b06 Neu!');let l=\"\";t||(l=`Installieren`),i.innerHTML=`\\n
          \\n ${(0,o.ZD)(e.tag)}\\n ${r}\\n
          \\n ${l}\\n `,n.appendChild(i)})}t.innerHTML='

          Lade Versionen...

          ';try{const e=localStorage.getItem(s.LS.VERSION_CACHE);let t=null;if(e)try{t=JSON.parse(e)}catch(e){}t&&t.devMode===i&&t.versions&&r(t.versions);const n=await u(i),a=JSON.stringify(n);a!==(t?JSON.stringify(t.versions):\"\")&&(localStorage.setItem(s.LS.VERSION_CACHE,JSON.stringify({timestamp:Date.now(),devMode:i,versions:n})),r(n))}catch(e){t.innerHTML=`

          Fehler: ${(0,o.ZD)(e.message)}

          `}}n.checked=r,l(),n.onchange=()=>{localStorage.setItem(s.LS.DEV_MODE,n.checked),localStorage.removeItem(s.LS.VERSION_CACHE),l()}}function h(){if(!a.gX||!a.Ny)return void p();const e=new Date,t=e.getDay();if(0===t||6===t)return void p();const n=e.toISOString().split(\"T\")[0];let o=!1;for(const e of a.L.keys())if(e.startsWith(n)){o=!0;break}if(o)return void p();const s=new Date;s.setHours(10,0,0,0);const i=s-e;if(i<=0)return void p();const r=Math.floor(i/36e5),d=Math.floor(i%36e5/6e4),c=document.querySelector(\".header-center-wrapper\");if(!c)return;let u=document.getElementById(\"order-countdown\");if(u||(u=document.createElement(\"div\"),u.id=\"order-countdown\",c.insertBefore(u,c.firstChild)),u.innerHTML=`${(0,l.t)(\"orderDeadline\")}: ${r}h ${d}m`,i<36e5){u.classList.add(\"urgent\");const e=`kantine_notified_${n}`;localStorage.getItem(e)||(\"granted\"===Notification.permission?new Notification(\"Kantine: Bestellschluss naht!\",{body:\"Du hast heute noch nichts bestellt. Nur noch 1 Stunde!\",icon:\"\u23f3\"}):\"default\"===Notification.permission&&Notification.requestPermission(),localStorage.setItem(e,\"true\"))}else u.classList.remove(\"urgent\")}function p(){const e=document.getElementById(\"order-countdown\");e&&e.remove()}function f(e,t,n,a){const s=\"error-modal\";let i=document.getElementById(s);i&&i.remove(),i=document.createElement(\"div\"),i.id=s,i.className=\"modal hidden\",i.innerHTML=`\\n
          \\n
          \\n

          \\n signal_wifi_off\\n ${(0,o.ZD)(e)}\\n

          \\n
          \\n
          \\n

          ${t}

          \\n
          \\n \\n
          \\n
          \\n
          \\n `,document.body.appendChild(i),document.getElementById(\"btn-error-redirect\").addEventListener(\"click\",()=>{window.location.href=a}),requestAnimationFrame(()=>{i.classList.remove(\"hidden\")})}function v(){const e=document.getElementById(\"alarm-bell\"),t=document.getElementById(\"alarm-bell-icon\");if(!e||!t)return;if(0===a.BY.size)return e.classList.add(\"hidden\"),e.style.display=\"none\",t.style.color=\"var(--text-secondary)\",void(t.style.textShadow=\"none\");e.classList.remove(\"hidden\"),e.style.display=\"inline-flex\";let n=!1;for(const e of a.p_)if(e.days){for(const t of e.days)if(t.items){for(const e of t.items)if(e.available&&a.BY.has(e.id)){n=!0;break}if(n)break}if(n)break}const i=localStorage.getItem(s.LS.LAST_CHECKED),r=localStorage.getItem(s.LS.FLAGGED_LAST_CHECKED);let d=0;i&&(d=Math.max(d,new Date(i).getTime())),r&&(d=Math.max(d,new Date(r).getTime()));let c=\"gerade eben\";if(0===d){const e=(new Date).toISOString();localStorage.setItem(s.LS.LAST_CHECKED,e),d=new Date(e).getTime()}c=(0,o.gs)(new Date(d)),e.title=`${(0,l.t)(\"alarmLastChecked\")}: ${c}`,n?(t.style.color=\"#10b981\",t.style.textShadow=\"0 0 10px rgba(16, 185, 129, 0.4)\"):(t.style.color=\"#f59e0b\",t.style.textShadow=\"0 0 10px rgba(245, 158, 11, 0.4)\")}setInterval(h,6e4),setTimeout(h,1e3)},413(e,t,n){n.d(t,{Ao:()=>s,FS:()=>i,PC:()=>g,U4:()=>l,ZD:()=>r,gs:()=>d,sn:()=>o});var a=n(901);function o(e){const t=new Date(Date.UTC(e.getFullYear(),e.getMonth(),e.getDate())),n=t.getUTCDay()||7;t.setUTCDate(t.getUTCDate()+4-n);const a=new Date(Date.UTC(t.getUTCFullYear(),0,1));return Math.ceil(((t-a)/864e5+1)/7)}function s(e){const t=new Date(e.getTime());return t.setDate(t.getDate()+3-(t.getDay()+6)%7),t.getFullYear()}function i(e){if(\"en\"===a.Kl)return e;return{Monday:\"Montag\",Tuesday:\"Dienstag\",Wednesday:\"Mittwoch\",Thursday:\"Donnerstag\",Friday:\"Freitag\",Saturday:\"Samstag\",Sunday:\"Sonntag\"}[e]||e}function r(e){const t=document.createElement(\"div\");return t.textContent=e||\"\",t.innerHTML}function l(e,t){if(!e||!t)return!1;const n=e.replace(/^v/,\"\").split(\".\").map(Number),a=t.replace(/^v/,\"\").split(\".\").map(Number);for(let e=0;e(a[e]||0))return!0;if((n[e]||0)<(a[e]||0))return!1}return!1}function d(e){const t=Date.now()-e.getTime(),n=Math.floor(t/6e4);if(n<1)return\"gerade eben\";if(1===n)return\"vor 1 min.\";if(n<60)return`vor ${n} min.`;const a=Math.floor(n/60);return 1===a?\"vor 1 Std.\":`vor ${a} Std.`}const c=[\"apfel\",\"achtung\",\"aubergine\",\"auflauf\",\"beere\",\"blumenkohl\",\"bohne\",\"braten\",\"brokkoli\",\"brot\",\"brust\",\"br\u00f6tchen\",\"butter\",\"chili\",\"dessert\",\"dip\",\"eier\",\"eintopf\",\"eis\",\"erbse\",\"erdbeer\",\"essig\",\"filet\",\"fisch\",\"fisole\",\"fleckerl\",\"fleisch\",\"fl\u00fcgel\",\"frucht\",\"f\u00fcr\",\"gebraten\",\"gem\u00fcse\",\"gew\u00fcrz\",\"gratin\",\"grie\u00df\",\"gulasch\",\"gurke\",\"himbeer\",\"honig\",\"huhn\",\"h\u00e4hnchen\",\"jambalaya\",\"joghurt\",\"karotte\",\"kartoffel\",\"keule\",\"kirsch\",\"knacker\",\"knoblauch\",\"kn\u00f6del\",\"kompott\",\"kraut\",\"kr\u00e4uter\",\"kuchen\",\"k\u00e4se\",\"k\u00fcrbis\",\"lauch\",\"mandel\",\"milch\",\"mild\",\"mit\",\"mohn\",\"most\",\"m\u00f6hre\",\"natur\",\"nockerl\",\"nudel\",\"nuss\",\"nu\u00df\",\"obst\",\"oder\",\"olive\",\"paprika\",\"pfanne\",\"pfannkuchen\",\"pfeffer\",\"pikant\",\"pilz\",\"plunder\",\"p\u00fcree\",\"ragout\",\"rahm\",\"reis\",\"rind\",\"sahne\",\"salami\",\"salat\",\"salz\",\"sauer\",\"scharf\",\"schinken\",\"schnitte\",\"schnitzel\",\"schoko\",\"schupf\",\"schwein\",\"sellerie\",\"senf\",\"sosse\",\"so\u00dfe\",\"spargel\",\"sp\u00e4tzle\",\"speck\",\"spie\u00df\",\"spinat\",\"steak\",\"suppe\",\"s\u00fc\u00df\",\"tofu\",\"tomate\",\"topfen\",\"torte\",\"tr\u00fcffel\",\"und\",\"vanille\",\"vogerl\",\"vom\",\"wien\",\"wurst\",\"zucchini\",\"zum\",\"zur\",\"zwiebel\",\"\u00f6l\"],u=[\"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 g(e){if(\"all\"===a.Kl)return e||\"\";const t=function(e){if(!e)return{de:\"\",en:\"\",raw:\"\"};let t=e.replace(/(?:\\(|(?:\\/|\\s|^))([A-Z,]+)\\)\\s*(?=\\S)(?!\\s*\\/)/g,\"($1)\\n\u2022 \");function n(e){let t=0,n=0;return e.forEach(e=>{const a=e.toLowerCase().replace(/[^a-z\u00e4\u00f6\u00fc\u00df]/g,\"\");if(a){let o=0,s=0;c.includes(a)?o=a.length:c.forEach(e=>{a.includes(e)&&e.length>o&&(o=e.length)}),u.includes(a)?s=a.length:u.forEach(e=>{a.includes(e)&&e.length>s&&(s=e.length)}),o>0&&(t+=o/a.length),s>0&&(n+=s/a.length),/^[A-Z\u00c4\u00d6\u00dc]/.test(e)&&(t+=.5)}}),{de:t,en:n}}function a(e){const t=e.trim().split(/\\s+/);if(t.length<2)return{enPart:e,nextDe:\"\"};let a=-1,o=-9999;for(let e=1;er.de||r.en>0,m=l.de+c>l.en;g&&m&&u>o&&(o=u,a=e)}return-1!==a?{enPart:t.slice(0,a).join(\" \"),nextDe:t.slice(a).join(\" \")}:{enPart:e,nextDe:\"\"}}t.startsWith(\"\u2022 \")||(t=\"\u2022 \"+t);const o=/(.*?)(?:\\(|(?:\\/|\\s|^))([A-Z,]+)\\)\\s*(?!\\s*[/])/g;let s;const i=[];let r=0;for(;null!==(s=o.exec(e));)s.index>r&&i.push(e.substring(r,s.index).trim()),i.push(s[0].trim()),r=o.lastIndex;r=2){const e=i[0].trim();let t=i.slice(1).join(\" / \").trim();const n=a(t);if(n.nextDe){l.push(e+o),d.push(n.enPart+o);const t=n.nextDe+o;l.push(t),d.push(t)}else{const n=t+o,a=e.includes(o.trim())?e:e+o;l.push(a),d.push(n)}}else{const e=a(n);e.nextDe?(d.push(e.enPart+o),l.push(e.nextDe+o)):(l.push(n+o),d.push(n+o))}}let g=l.join(\"\\n\u2022 \");l.length>0&&!g.startsWith(\"\u2022 \")&&(g=\"\u2022 \"+g);let m=d.join(\"\\n\u2022 \");return d.length>0&&!m.startsWith(\"\u2022 \")&&(m=\"\u2022 \"+m),{de:g,en:m,raw:t}}(e);return\"en\"===a.Kl?t.en||t.raw:t.de||t.raw}}},t={};function n(a){var o=t[a];if(void 0!==o)return o.exports;var s=t[a]={exports:{}};return e[a](s,s.exports,n),s.exports}n.d=(e,t)=>{for(var a in t)n.o(t,a)&&!n.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var a=n(901);var o=n(367),s=n(842),i=n(521),r=n(672),l=n(646);if(!window.__KANTINE_LOADED){window.__KANTINE_LOADED=!0,function(){document.title=\"Kantine Weekly Menu\",document.querySelectorAll&&document.querySelectorAll('link[rel*=\"icon\"]').forEach(e=>e.remove());const e=document.createElement(\"link\");if(e.rel=\"icon\",e.type=\"image/png\",e.href=\"data:image/png;base64,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\",document.head.appendChild(e),!document.querySelector('link[href*=\"fonts.googleapis.com/css2?family=Inter\"]')){const e=document.createElement(\"link\");e.rel=\"stylesheet\",e.href=\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap\",document.head.appendChild(e)}if(!document.querySelector('link[href*=\"Material+Icons+Round\"]')){const e=document.createElement(\"link\");e.rel=\"stylesheet\",e.href=\"https://fonts.googleapis.com/icon?family=Material+Icons+Round\",document.head.appendChild(e)}const t=`\\n
          \\n
          \\n
          \\n
          \\n \"Logo\"\\n
          \\n

          Kantinen \u00dcbersicht v1.6.18

          \\n
          \\n
          \\n
          \\n \\n \\n
          \\n \\n
          \\n
          \\n
          \\n \\n \\n \\n
          \\n
          \\n
          \\n
          \\n
          \\n \\n \\n \\n \\n \\n
          \\n person\\n \\n \\n
          \\n
          \\n
          \\n
          \\n\\n
          \\n
          \\n
          \\n

          Login

          \\n \\n
          \\n
          \\n
          \\n \\n \\n Deine offizielle Knapp Mitarbeiternummer.\\n
          \\n
          \\n \\n \\n Das Passwort f\u00fcr deinen Bessa Account.\\n
          \\n
          \\n
          \\n \\n
          \\n
          \\n
          \\n
          \\n\\n
          \\n
          \\n
          \\n

          Men\u00fcdaten aktualisieren

          \\n
          \\n
          \\n
          \\n
          \\n
          \\n
          \\n
          0%
          \\n
          \\n

          Initialisierung...

          \\n
          \\n
          \\n
          \\n\\n
          \\n
          \\n
          \\n

          Meine Highlights

          \\n \\n
          \\n
          \\n

          \\n Markiere Men\u00fcs automatisch, wenn sie diese Schlagw\u00f6rter enthalten.\\n

          \\n
          \\n \\n \\n
          \\n
          \\n
          \\n
          \\n
          \\n\\n
          \\n
          \\n
          \\n

          Bestellhistorie

          \\n \\n
          \\n
          \\n
          \\n

          Lade Historie...

          \\n
          \\n
          \\n
          \\n
          \\n
          \\n
          \\n
          \\n
          \\n
          \\n
          \\n
          \\n\\n
          \\n
          \\n
          \\n

          \ud83d\udce6 Versionen

          \\n \\n
          \\n
          \\n
          \\n Aktuell: v1.6.18\\n
          \\n
          \\n \\n
          \\n
          \\n

          Lade Versionen...

          \\n
          \\n
          \\n \\n bug_report Fehler melden\\n \\n \\n lightbulb Feature vorschlagen\\n \\n \\n
          \\n
          \\n
          \\n
          \\n\\n
          \\n
          \\n update\\n Gerade aktualisiert\\n
          \\n
          \\n
          \\n

          Lade Men\u00fcdaten...

          \\n
          \\n
          \\n
          \\n\\n
          \\n

          Jetzt Bessa Einfach! • Knapp-Kantine Wrapper • ${(new Date).getFullYear()} by Kaufi \ud83d\ude03\ud83d\udc4d mit Hilfe von KI \ud83e\udd16

          \\n
          \\n
          `;document.body.innerHTML=t}(),function(){const e=document.getElementById(\"btn-this-week\"),t=document.getElementById(\"btn-next-week\"),n=document.getElementById(\"btn-refresh\"),d=document.getElementById(\"theme-toggle\"),c=document.getElementById(\"btn-login-open\"),u=document.getElementById(\"btn-login-close\"),g=document.getElementById(\"btn-logout\"),m=document.getElementById(\"login-form\"),h=document.getElementById(\"login-modal\"),p=document.getElementById(\"btn-highlights\"),f=document.getElementById(\"highlights-modal\"),v=document.getElementById(\"btn-highlights-close\"),y=document.getElementById(\"btn-add-tag\"),b=document.getElementById(\"tag-input\"),w=document.getElementById(\"btn-history\"),E=document.getElementById(\"history-modal\"),A=document.getElementById(\"btn-history-close\");document.querySelectorAll(\".lang-btn\").forEach(e=>{e.addEventListener(\"click\",()=>{(0,a.UD)(e.dataset.lang),localStorage.setItem(i.LS.LANG,e.dataset.lang),document.querySelectorAll(\".lang-btn\").forEach(e=>e.classList.remove(\"active\")),e.classList.add(\"active\"),function(){const e=document.getElementById(\"btn-this-week\"),t=document.getElementById(\"btn-next-week\");e&&(e.textContent=(0,l.t)(\"thisWeek\"),e.title=(0,l.t)(\"thisWeekTooltip\")),t&&(t.textContent=(0,l.t)(\"nextWeek\"));const n=document.querySelector(\".header-left h1\");if(n){const e=n.querySelector(\".version-tag\"),t=n.querySelector(\".update-icon\");n.textContent=(0,l.t)(\"appTitle\")+\" \",e&&n.appendChild(e),t&&n.appendChild(t)}const o=document.getElementById(\"btn-refresh\");o&&o.setAttribute(\"aria-label\",(0,l.t)(\"refresh\")),o&&(o.title=(0,l.t)(\"refresh\"));const i=document.getElementById(\"btn-history\");i&&i.setAttribute(\"aria-label\",(0,l.t)(\"history\")),i&&(i.title=(0,l.t)(\"history\"));const r=document.getElementById(\"btn-highlights\");r&&r.setAttribute(\"aria-label\",(0,l.t)(\"highlights\")),r&&(r.title=(0,l.t)(\"highlights\"));const d=document.getElementById(\"theme-toggle\");d&&(d.title=(0,l.t)(\"themeTooltip\"));const c=document.getElementById(\"btn-login-open\");if(c){c.title=(0,l.t)(\"loginTooltip\");const e=c.querySelector(\"span:last-child\");e&&!e.classList.contains(\"material-icons-round\")&&(e.textContent=(0,l.t)(\"login\"))}const u=document.getElementById(\"btn-logout\");u&&(u.title=(0,l.t)(\"logoutTooltip\"));const g=document.getElementById(\"lang-toggle\");g&&(g.title=(0,l.t)(\"langTooltip\"));const m=document.querySelector(\"#highlights-modal .modal-header h2\");m&&(m.textContent=(0,l.t)(\"highlightsTitle\"));const h=document.querySelector(\"#highlights-modal .modal-body > p\");h&&(h.textContent=(0,l.t)(\"highlightsDesc\"));const p=document.getElementById(\"tag-input\");p&&(p.placeholder=(0,l.t)(\"tagInputPlaceholder\"),p.title=(0,l.t)(\"tagInputTooltip\"));const f=document.getElementById(\"btn-add-tag\");f&&(f.textContent=(0,l.t)(\"addTag\"),f.title=(0,l.t)(\"addTagTooltip\"));const v=document.querySelector(\"#history-modal .modal-header h2\");v&&(v.textContent=(0,l.t)(\"historyTitle\"));const y=document.querySelector(\"#login-modal .modal-header h2\");y&&(y.textContent=(0,l.t)(\"loginTitle\"));const b=document.getElementById(\"alarm-bell\");b&&0===a.BY.size&&(b.title=(0,l.t)(\"alarmTooltipNone\")),(0,s.OR)(),(0,s.gJ)(),(0,s.Mb)()}()})}),p&&p.addEventListener(\"click\",()=>{(0,o.Y1)(),f.classList.remove(\"hidden\")}),v&&v.addEventListener(\"click\",()=>{f.classList.add(\"hidden\")}),w.addEventListener(\"click\",()=>{a.gX?(E.classList.remove(\"hidden\"),(0,o.Aq)()):h.classList.remove(\"hidden\")}),A.addEventListener(\"click\",()=>{E.classList.add(\"hidden\")}),window.addEventListener(\"click\",e=>{e.target===E&&E.classList.add(\"hidden\"),e.target===f&&f.classList.add(\"hidden\")});const k=document.querySelector(\".version-tag\"),L=document.getElementById(\"version-modal\"),S=document.getElementById(\"btn-version-close\");k&&k.addEventListener(\"click\",e=>{e.preventDefault(),e.stopPropagation(),(0,s.Gk)()}),S&&S.addEventListener(\"click\",()=>{L.classList.add(\"hidden\")});const I=document.getElementById(\"btn-clear-cache\");I&&I.addEventListener(\"click\",()=>{confirm(\"M\u00f6chtest du wirklich alle lokalen Daten (inkl. Login-Session, Cache und Einstellungen) l\u00f6schen? Die Seite wird danach neu geladen.\")&&(Object.keys(localStorage).forEach(e=>{e.startsWith(\"kantine_\")&&localStorage.removeItem(e)}),window.location.reload())}),window.addEventListener(\"click\",e=>{e.target===L&&L.classList.add(\"hidden\")}),y.addEventListener(\"click\",()=>{const e=b.value;(0,o.oL)(e)&&(b.value=\"\",(0,o.Y1)())}),b.addEventListener(\"keypress\",e=>{\"Enter\"===e.key&&y.click()});const C=localStorage.getItem(\"theme\"),B=window.matchMedia(\"(prefers-color-scheme: dark)\").matches,T=d.querySelector(\".theme-icon\");\"dark\"===C||!C&&B?(document.documentElement.setAttribute(\"data-theme\",\"dark\"),T.textContent=\"dark_mode\"):(document.documentElement.setAttribute(\"data-theme\",\"light\"),T.textContent=\"light_mode\"),d.addEventListener(\"click\",()=>{const e=\"dark\"===document.documentElement.getAttribute(\"data-theme\")?\"light\":\"dark\";document.documentElement.setAttribute(\"data-theme\",e),localStorage.setItem(\"theme\",e),T.textContent=\"dark\"===e?\"dark_mode\":\"light_mode\"}),e.addEventListener(\"click\",()=>{\"this-week\"!==a.sw&&((0,a.qo)(\"this-week\"),e.classList.add(\"active\"),t.classList.remove(\"active\"),(0,s.OR)())}),t.addEventListener(\"click\",()=>{t.classList.remove(\"new-week-available\"),\"next-week\"!==a.sw&&((0,a.qo)(\"next-week\"),t.classList.add(\"active\"),e.classList.remove(\"active\"),(0,s.OR)())}),n.addEventListener(\"click\",()=>{a.gX?(0,o.m9)():h.classList.remove(\"hidden\")});const D=document.getElementById(\"alarm-bell\");D&&D.addEventListener(\"click\",()=>{(0,o.A0)()}),c.addEventListener(\"click\",()=>{h.classList.remove(\"hidden\"),document.getElementById(\"login-error\").classList.add(\"hidden\"),m.reset()}),u.addEventListener(\"click\",()=>{h.classList.add(\"hidden\")}),window.addEventListener(\"click\",e=>{e.target===h&&h.classList.add(\"hidden\")}),m.addEventListener(\"submit\",async e=>{e.preventDefault();const t=document.getElementById(\"employee-id\").value.trim(),n=document.getElementById(\"password\").value,s=document.getElementById(\"login-error\"),l=m.querySelector('button[type=\"submit\"]'),d=l.textContent;l.disabled=!0,l.textContent=\"Wird eingeloggt...\";try{const e=`knapp-${t}@bessa.app`,l=await fetch(`${i.tE}/auth/login/`,{method:\"POST\",headers:(0,r.H)(i.f9),body:JSON.stringify({email:e,password:n})}),d=await l.json();if(l.ok){(0,a.O5)(d.key),(0,a.lt)(t),localStorage.setItem(i.LS.AUTH_TOKEN,d.key),localStorage.setItem(i.LS.CURRENT_USER,t);try{const e=await fetch(`${i.tE}/auth/user/`,{headers:(0,r.H)(d.key)});if(e.ok){const t=await e.json();t.first_name&&localStorage.setItem(i.LS.FIRST_NAME,t.first_name),t.last_name&&localStorage.setItem(i.LS.LAST_NAME,t.last_name)}}catch(e){console.error(\"Failed to fetch user info:\",e)}(0,o.i_)(),h.classList.add(\"hidden\"),(0,o.Gb)(),m.reset(),(0,o.g8)(),(0,o.m9)()}else s.textContent=d.non_field_errors?.[0]||d.error||\"Login fehlgeschlagen\",s.classList.remove(\"hidden\")}catch(e){console.error(\"Login error:\",e),s.textContent=\"Ein Fehler ist aufgetreten\",s.classList.remove(\"hidden\")}finally{l.disabled=!1,l.textContent=d}}),g.addEventListener(\"click\",()=>{localStorage.removeItem(i.LS.AUTH_TOKEN),localStorage.removeItem(i.LS.CURRENT_USER),localStorage.removeItem(i.LS.FIRST_NAME),localStorage.removeItem(i.LS.LAST_NAME),(0,a.O5)(null),(0,a.lt)(null),(0,a.di)(new Map),(0,o.Et)(),(0,o.i_)(),(0,s.OR)()})}(),(0,o.i_)(),(0,o.H)();(0,o.KG)()?(document.getElementById(\"loading\").classList.add(\"hidden\"),(0,o.VL)()||(0,o.m9)()):(0,o.m9)(),a.gX&&(0,o.g8)(),(0,s.Ux)(),setInterval(s.Ux,36e5)}})();\n"; document.head.appendChild(sc); })(); diff --git a/dist/install.html b/dist/install.html index fb585d6..f55384b 100755 --- a/dist/install.html +++ b/dist/install.html @@ -2,7 +2,7 @@ - Kantine Wrapper Installer (v1.6.17) + Kantine Wrapper Installer (v1.6.18)