diff --git a/backend/app.py b/backend/app.py index 63a877d..b149407 100644 --- a/backend/app.py +++ b/backend/app.py @@ -32,6 +32,7 @@ from routers import ( hermes_ui, maintenance, models, + radar, routing, system, voice, @@ -107,6 +108,7 @@ async def no_cache( app.include_router(health.router) app.include_router(boxwart.router) # Cockpit: Start, Hinweise, Modell-Nutzung, Zeitplan +app.include_router(radar.router) # Modell-Radar: Kandidaten, Nachttests, Übernehmen/Verwerfen app.include_router(models.router) app.include_router(routing.router) app.include_router(system.router) diff --git a/backend/radar_lauf.py b/backend/radar_lauf.py new file mode 100644 index 0000000..40f36b2 --- /dev/null +++ b/backend/radar_lauf.py @@ -0,0 +1,112 @@ +""" +Nächtlicher Lauf des Modell-Radars (Box-Wart, 09/2026) — gestartet von mc2-radar.timer um 00:30. + +Warum ein eigener Einstieg: Der Test lädt ein bis zu ~85 GB großes Modell neben Lucys Hirn. Das +darf nur nachts passieren und muss um 02:30 sicher vorbei sein, weil um 03:00 der NerdQuiz- +Nachtlauf das Hirn braucht. Ablauf: + + 1. Suchen — höchstens einmal am Tag (Merkliste + Entdeckung). + 2. Offene Urteile nachholen („getestet“: damals fehlte die Vergleichsmessung). + 3. Testen — nur im Fenster 00:30–02:30 und höchstens ein neuer Kandidat pro Woche. + +Die Messungen prüfen die Frist selbst. Hängt trotzdem etwas, zieht fünf Minuten nach der Frist die +Notbremse: Kandidaten-Server und Download werden gestoppt, der Prozess endet hart. systemd +(RuntimeMaxSec) ist die letzte Sicherung. Ist nichts fällig, endet der Lauf sofort mit Code 0. +""" + +import logging +import os +import signal +import subprocess +import sys +import threading +import time +from pathlib import Path + +from services import radar + +logging.basicConfig( + level=os.environ.get("MC_LOG_LEVEL", "INFO").upper(), + format="%(asctime)s %(levelname)-7s %(name)s: %(message)s", +) +log = logging.getLogger("radar_lauf") + +NOTBREMSE_S = int(os.environ.get("MC_RADAR_NOTBREMSE_S", "300")) + + +def _beim_beenden(signum, _frame) -> None: + """SIGTERM (systemd stop, RuntimeMaxSec) → normal auslaufen, damit der Kandidaten-Server gestoppt wird.""" + raise SystemExit(f"Signal {signum}") + + +def _notbremse(frist: float) -> threading.Timer: + def ziehen() -> None: + log.error("Radar: Notbremse – %s s nach der Frist läuft noch etwas, der Lauf wird hart beendet.", NOTBREMSE_S) + try: + radar.notstopp() + finally: + os._exit(3) + + bremse = threading.Timer(max(frist - time.time(), 0) + NOTBREMSE_S, ziehen) + bremse.daemon = True + bremse.start() + return bremse + + +NOTIFY = Path(__file__).resolve().parents[1] / "deploy" / "notify.sh" + + +def melde_bestanden(test: dict) -> None: + """Ein bestandener Kandidat wartet auf eine Entscheidung — einmal Bescheid geben, sonst liegt er + unbemerkt herum (Lehre der Pins vom September). notify.sh sammelt Nachtmeldungen für den Morgen.""" + k = radar.lade_stand()["kandidaten"].get(test.get("kandidat")) or {} + rolle = "das Hirn" if test.get("rolle") == "hirn" else "den Coder" + text = (f"{k.get('name') or test.get('kandidat')} hat den Nachttest für {rolle} bestanden. " + f"{str(test.get('zusammenfassung') or '')[:300]} " + "In MC2 unter Modelle kannst du ihn übernehmen oder verwerfen.") + try: + subprocess.run(["bash", str(NOTIFY), "-s", "[Modell-Radar]", text], timeout=120, check=False, + stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + except (OSError, subprocess.SubprocessError): + log.warning("Radar: Meldung über den bestandenen Kandidaten ging nicht raus.", exc_info=True) + + +def main() -> int: + beginn = radar.jetzt() + if radar.suche_faellig(beginn): + try: + ergebnis = radar.suche() + log.info("Radar: Suche – %s neu, %s warten", len(ergebnis.get("neu") or []), ergebnis.get("wartend")) + except Exception: + log.warning("Radar: Suche fehlgeschlagen", exc_info=True) + else: + log.info("Radar: heute schon gesucht.") + + if not radar.im_fenster(radar.jetzt()): + log.info("Radar: außerhalb des Test-Fensters %s–%s, nichts zu testen.", radar.FENSTER_START, + radar.FENSTER_ENDE) + return 0 + + frist = radar.fenster_ende(radar.jetzt()).timestamp() + signal.signal(signal.SIGTERM, _beim_beenden) + bremse = _notbremse(frist) + try: + if (nachgeholt := radar.nachurteilen(frist)): + log.info("Radar: %s offene Urteile nachgeholt.", nachgeholt) + plan = radar.plane_test(radar.lade_stand(), radar.jetzt()) + if not plan.get("kandidat"): + log.info("Radar: nichts fällig (%s).", plan.get("grund")) + return 0 + log.info("Radar: teste %s bis spätestens %s.", plan.get("grund"), radar.FENSTER_ENDE) + test = radar.teste(plan["kandidat"], frist) + if test: + log.info("Radar: %s – %s", test.get("ergebnis"), test.get("zusammenfassung")) + if test.get("ergebnis") == "bestanden": + melde_bestanden(test) + return 0 + finally: + bremse.cancel() + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/backend/routers/radar.py b/backend/routers/radar.py new file mode 100644 index 0000000..867d9b8 --- /dev/null +++ b/backend/routers/radar.py @@ -0,0 +1,44 @@ +""" +Modell-Radar-Schnittstellen (Box-Wart, Umbau 09/2026). + + GET /api/radar Nächster und letzter Test, Kandidaten, Test-Verlauf + POST /api/radar/suche Jetzt suchen (Merkliste + Hugging-Face-Entdeckung) + POST /api/radar/{id}/uebernehmen Bestandenen Kandidaten in Betrieb nehmen (Modell-Tausch) + POST /api/radar/{id}/verwerfen Kandidaten verwerfen (Dateien weg, nie wieder testen) + +Dünn: die Logik liegt in services/radar.py. Getestet wird nur nachts (backend/radar_lauf.py). +""" + +from fastapi import APIRouter, HTTPException +from services import radar + +router = APIRouter(prefix="/api", tags=["radar"]) + + +def _antwort(ergebnis: dict) -> dict: + if not ergebnis.get("ok"): + raise HTTPException(status_code=int(ergebnis.get("status") or 409), + detail=ergebnis.get("detail") or "Das ging nicht.") + return ergebnis + + +@router.get("/radar") +def radar_stand() -> dict: + return radar.uebersicht() + + +@router.post("/radar/suche") +def radar_suche() -> dict: + """Sucht sofort (Netz: Hugging Face) und liefert danach den neuen Stand.""" + ergebnis = radar.suche() + return {**radar.uebersicht(), "suche": ergebnis} + + +@router.post("/radar/{kandidat_id}/uebernehmen") +def radar_uebernehmen(kandidat_id: str) -> dict: + return _antwort(radar.uebernehmen(kandidat_id)) + + +@router.post("/radar/{kandidat_id}/verwerfen") +def radar_verwerfen(kandidat_id: str) -> dict: + return _antwort(radar.verwerfen(kandidat_id)) diff --git a/backend/services/llamaswap.py b/backend/services/llamaswap.py index 20079fe..7a28bf1 100644 --- a/backend/services/llamaswap.py +++ b/backend/services/llamaswap.py @@ -474,6 +474,21 @@ def set_role(model_id: str, role: str | None) -> bool: return True +def add_role(model_id: str, role: str) -> bool: + """Wie set_role, aber die übrigen Aliase des Ziel-Modells bleiben — für Modelle mit zwei Rollen + (Coder: coder UND heavy). set_role behielte nur die geschützten Aliase und würfe coder wieder weg.""" + cfg = read_config() + models = cfg.get("models") or {} + rolle = (role or "").strip().lower() + if model_id not in models or not rolle or not isinstance(models[model_id], dict): + return False + bisher = [a for a in (models[model_id].get("aliases") or []) if str(a).lower() != rolle] + set_role_alias(cfg, model_id, rolle) # nimmt die Rolle allen anderen Modellen weg + models[model_id]["aliases"] = bisher + [rolle] + write_config(cfg) + return True + + def set_ctx(model_id: str, ctx: int) -> bool: """Kontextlänge (-c) eines bestehenden Modells ändern.""" cfg = read_config() diff --git a/backend/services/maintenance.py b/backend/services/maintenance.py index 2f4dd23..ce9fd51 100644 --- a/backend/services/maintenance.py +++ b/backend/services/maintenance.py @@ -24,7 +24,7 @@ SYSTEM_SERVICES = {"llama-swap"} # erneut laufen lassen“ — der Wächter bietet das als Knopf an (services/waechter.py). USER_SERVICES = {"mission-control-2", "mc2-gateway", "mc2-steward", "box-console", "hermes-gateway", "hermes-builtin-ui", "voice-service", "lucy-stimme", - "projekte-sync", "mc2-backup"} + "projekte-sync", "mc2-backup", "mc2-radar"} # Engine-Update: lädt den neuesten Vulkan-Build (deploy/update-engine.sh, läuft als root). _REPO_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) diff --git a/backend/services/radar.py b/backend/services/radar.py new file mode 100644 index 0000000..60bacf9 --- /dev/null +++ b/backend/services/radar.py @@ -0,0 +1,1374 @@ +""" +Modell-Radar (Box-Wart, Umbau 09/2026): sucht, prüft und empfiehlt neue Modelle für genau zwei +Rollen — das Hirn (Lucy: Hermes-Agent, ~100 Werkzeuge, Deutsch, ~13k Systemprompt) und den Coder +(agentisches Coding in OpenCode). Beide sollen auch Bilder verstehen. + +Warum: Neue Modelle tauchten bisher nur als Radar-Meldung auf; ob eines wirklich besser ist, zeigte +erst ein Prüfstand von Hand (17.09.). Das Radar macht beides selbst, mit engen Leitplanken +(User-Entscheid 23.09.): + + • Suche Merkliste deploy/radar-watchlist.json + discover.safe_discover. Ein Kandidat braucht + ein GGUF, ein mmproj und muss neben das Warm-Set passen + (27 GB inkl. Cache + Kandidat inkl. KV-Cache ≤ ~115 GB). + • Test nur nachts 00:30–02:30 (um 03:00 braucht der NerdQuiz-Nachtlauf das Hirn), höchstens + ein neuer Kandidat pro Woche: Download → llama-server auf :5899 → Prüfstand + (deploy/bench/pruefstand.py) gegen das heutige Modell der Rolle → Server stoppen. + • Ergebnis Durchgefallene werden gelöscht. Bestandene bleiben liegen, bis der Nutzer entscheidet; + getauscht wird erst mit „Übernehmen“. Nur ein Bestandener wird gemeldet (radar_lauf.py → + notify.sh; nachts landet das im Morgen-Überblick), alles andere steht nur in MC2. + +Status eines Kandidaten: + neu → wartet (als Nächster dran oder angefangen) → getestet (gemessen, Vergleich steht aus) + → bestanden / durchgefallen → uebernommen / verworfen (vom Nutzer oder vom Radar mit Grund). + +Zustand: MODELS_DIR/mc2-radar.json. Zwei Schreiber (der Nachtlauf radar_lauf.py und MC2 für die +Knöpfe) → jede Änderung läuft unter einer Datei-Sperre und wird atomar geschrieben. +Auf Windows (Entwicklung) scheitert alles Box-Nahe harmlos: kein Download, kein Server. +""" + +import hashlib +import importlib.util +import json +import logging +import math +import os +import re +import shutil +import signal +import struct +import subprocess +import sys +import threading +import time +from contextlib import contextmanager +from datetime import date, datetime, timedelta +from datetime import time as uhrzeit +from pathlib import Path +from urllib.parse import quote +from zoneinfo import ZoneInfo + +import httpx +import psutil +from config import HF_DOWNLOAD_ENV, LLAMA_SWAP_URL, MODELS_DIR +from ruamel.yaml.scalarstring import LiteralScalarString + +from services import discover, geheimnisse, hf, llamaswap +from services.fit import extract_active_params_b, extract_params_b + +try: + import fcntl # Linux: Datei-Sperre zwischen MC2 und dem Nachtlauf +except ImportError: # Windows (Entwicklung) + fcntl = None + +log = logging.getLogger(__name__) + +# --- Grenzen (jede mit Env-Override) ---------------------------------------------------- + +LOCAL_TZ = ZoneInfo(os.environ.get("MC_LOCAL_TZ", "Europe/Berlin")) +FENSTER_START = os.environ.get("MC_RADAR_FENSTER_START", "00:30") # Tests nur nachts … +FENSTER_ENDE = os.environ.get("MC_RADAR_FENSTER_ENDE", "02:30") # … um 03:00 kommt NerdQuiz +KANDIDATEN_PRO_WOCHE = int(os.environ.get("MC_RADAR_PRO_WOCHE", "1")) +SPEICHER_GRENZE_GB = float(os.environ.get("MC_RADAR_GRENZE_GB", "115")) # Warm-Set + Kandidat +WARMSET_GB = float(os.environ.get("MC_RADAR_WARMSET_GB", "27")) # Hirn + embed + reranker inkl. Cache +CODER_HEUTE_GB = float(os.environ.get("MC_RADAR_CODER_GB", "29")) # Coder heute inkl. Cache +HIRN_HEUTE_GB = float(os.environ.get("MC_RADAR_HIRN_GB", "25")) # Hirn-Anteil am Warm-Set +ENG_ANTEIL = float(os.environ.get("MC_RADAR_ENG_ANTEIL", "0.9")) # ab 90 % des Budgets „eng“ +CTX_ROLLE = {"hirn": int(os.environ.get("MC_RADAR_CTX_HIRN", "131072")), # Kontext wie im Betrieb + "coder": int(os.environ.get("MC_RADAR_CTX_CODER", "131072"))} +CTX_MIN = 32768 # darunter trägt der 13k-Test nicht mehr sinnvoll +PLATTE_MAX_PCT = float(os.environ.get("MC_RADAR_PLATTE_MAX_PCT", "80")) # = gelbe Grenze des Wächters +TESTZEIT_MIN = int(os.environ.get("MC_RADAR_TESTZEIT_MIN", "40")) # so viel Fenster muss nach dem Download bleiben +MIN_RESTZEIT_MIN = int(os.environ.get("MC_RADAR_MIN_RESTZEIT_MIN", "20")) # kurz vor Fensterende fängt nichts mehr an +VERSUCHE_MAX = int(os.environ.get("MC_RADAR_VERSUCHE", "3")) +BASELINE_TAGE = int(os.environ.get("MC_RADAR_BASELINE_TAGE", "30")) # Baseline höchstens monatlich neu messen +BILD_PFLICHT = os.environ.get("MC_RADAR_BILD_PFLICHT", "1") != "0" # ohne mmproj kein Kandidat +DISCOVER_MAX_JE_ROLLE = int(os.environ.get("MC_RADAR_DISCOVER_MAX", "3")) +MIN_PARAMS_B = float(os.environ.get("MC_RADAR_MIN_PARAMS_B", "20")) +HIRN_MAX_AKTIV_B = float(os.environ.get("MC_RADAR_HIRN_MAX_AKTIV_B", "12")) # Verdikt: dichte Modelle nie als Hirn +ABGELEHNT_TAGE = 30 +TESTS_MAX = 100 + +STORE_PATH = Path(os.environ.get("MC_RADAR_STORE", str(MODELS_DIR / "mc2-radar.json"))) +BASELINE_PATH = Path(os.environ.get("MC_RADAR_BASELINE", str(MODELS_DIR / "mc2-radar-baseline.json"))) +RADAR_DIR = Path(os.environ.get("MC_RADAR_DIR", str(MODELS_DIR / "radar"))) +_REPO = Path(__file__).resolve().parents[2] +WATCHLIST_PATH = Path(os.environ.get("MC_RADAR_WATCHLIST", str(_REPO / "deploy" / "radar-watchlist.json"))) +PRUEFSTAND_PATH = _REPO / "deploy" / "bench" / "pruefstand.py" +ENGINE_LIB = Path(os.environ.get("MC_RADAR_ENGINE_LIB", "/opt/llamacpp-vulkan/libllama.so")) +STEWARD_WARMSET = Path(os.environ.get("MC_RADAR_STEWARD_WARMSET", str( + Path.home() / ".config" / "systemd" / "user" / "mc2-steward.service.d" / "warmset.conf"))) +HF_BASIS = "https://huggingface.co" + +ROLLEN = ("hirn", "coder") +ALIAS = {"hirn": "hermes", "coder": "coder"} # llama-swap-Alias der Rolle heute +DISCOVER_ROLLEN = {"coder": "coder", "fast": "hirn", "hermes": "hirn"} +PARALLEL = {"hirn": 2, "coder": 1} # Slots im Betrieb, wie heute +KANDIDAT_FELDER = ("id", "name", "rolle", "repo", "datei", "groesse_gb", "passt", "eng", "quelle", "status", + "begruendung") +TEST_FELDER = ("id", "kandidat", "rolle", "datum", "ergebnis", "werte", "vergleich", "zusammenfassung") +_REIHENFOLGE = {"wartet": 0, "neu": 1, "getestet": 2, "bestanden": 3, "uebernommen": 4, "durchgefallen": 5, + "verworfen": 6} +_SCHRITTE = {"download": "lädt herunter", "baseline": "misst das heutige Modell", "test": "testet den Kandidaten"} + + +class Abbruch(Exception): + """Ein Lauf endet ohne Urteil. zaehlt=False: nicht die Schuld des Kandidaten (zählt nicht als Versuch).""" + + def __init__(self, grund: str, zaehlt: bool = True): + super().__init__(grund) + self.grund, self.zaehlt = grund, zaehlt + + +# --- Zeit -------------------------------------------------------------------------------- + +def jetzt() -> datetime: + return datetime.now(LOCAL_TZ) + + +def _hhmm(text: str) -> uhrzeit: + stunde, minute = text.strip().split(":") + return uhrzeit(int(stunde), int(minute)) + + +def _lokal(tag: date, uhr: uhrzeit) -> datetime: + """Ortszeit als eindeutiger Zeitpunkt. Am Umstellungstag (fehlende/doppelte Stunde) gilt der + FRÜHERE Zeitpunkt — ein Fenster endet lieber zu früh als in den NerdQuiz-Lauf hinein.""" + varianten = [datetime.combine(tag, uhr, tzinfo=LOCAL_TZ).replace(fold=f) for f in (0, 1)] + return min(varianten, key=lambda d: d.timestamp()) + + +def im_fenster(dt: datetime) -> bool: + start, ende, t = _hhmm(FENSTER_START), _hhmm(FENSTER_ENDE), dt.astimezone(LOCAL_TZ).time() + return start <= t < ende if start < ende else (t >= start or t < ende) + + +def fenster_ende(dt: datetime) -> datetime: + """Ende des Test-Fensters, in dem dt liegt (bzw. des nächsten).""" + dt = dt.astimezone(LOCAL_TZ) + start, ende = _hhmm(FENSTER_START), _hhmm(FENSTER_ENDE) + tag = dt.date() + timedelta(days=1) if (start > ende and dt.time() >= start) else dt.date() + return _lokal(tag, ende) + + +def naechster_start(dt: datetime) -> datetime: + """Nächster Fensterbeginn nach dt — dann startet der Timer den nächsten Lauf. Mitten im Fenster ist + der Lauf dieser Nacht schon gestartet (oder bewusst nicht), also zählt erst die nächste Nacht.""" + dt = dt.astimezone(LOCAL_TZ) + start = _lokal(dt.date(), _hhmm(FENSTER_START)) + if start.timestamp() <= dt.timestamp(): + start = _lokal(dt.date() + timedelta(days=1), _hhmm(FENSTER_START)) + return start + + +def _tag_von(ts: float | None) -> date | None: + return datetime.fromtimestamp(ts, LOCAL_TZ).date() if ts else None + + +def _iso(ts: float | None) -> str | None: + return datetime.fromtimestamp(ts, LOCAL_TZ).isoformat(timespec="seconds") if ts else None + + +def _datum(ts: float) -> str: + return datetime.fromtimestamp(ts, LOCAL_TZ).strftime("%d.%m.") + + +def _gb(wert: float) -> str: + return f"{wert:.1f}".replace(".", ",").removesuffix(",0") + + +# --- Namen --------------------------------------------------------------------------------- + +def kandidat_id(rolle: str, repo: str, quant: str) -> str: + return re.sub(r"[^a-z0-9]+", "-", f"{rolle}-{repo}-{quant}".lower()).strip("-") + + +def anzeigename(repo: str) -> str: + """Basisname aus dem Repo: ohne Org und ohne -GGUF; bartowskis „Qwen_Qwen3.6-…“ → „Qwen3.6-…“.""" + name = re.sub(r"[-_]GGUF$", "", repo.split("/")[-1], flags=re.IGNORECASE) + if "_" in name and (name.find("-") < 0 or name.index("_") < name.find("-")): + name = name.split("_", 1)[1] + return name + + +def stamm(name: str) -> str: + """Vergleichs-Stamm eines Modells (Repo, Ordner, Datei oder llama-swap-Name).""" + s = anzeigename(name).lower() + s = re.sub(r"\.gguf$", "", s) + s = re.sub(r"-\d{5}-of-\d{5}$", "", s) + s = re.sub(r"[-_](ud-)?(i?q\d\w*|f16|bf16|fp16|f32|mxfp4)$", "", s) + return s.strip("-_ ") + + +_FAMILIEN = (("qwen", r"qwen[-_ ]?(\d+(?:\.\d+)?)"), ("gemma", r"gemma[-_ ]?(\d+(?:\.\d+)?)"), + ("llama", r"llama[-_ ]?(\d+(?:\.\d+)?)"), ("glm", r"glm[-_ ]?(\d+(?:\.\d+)?)"), + ("nemotron", r"nemotron[-_ ]?(\d+(?:\.\d+)?)"), ("mistral", r"mistral[-_ ]?(\d+(?:\.\d+)?)"), + ("phi", r"phi[-_ ]?(\d+(?:\.\d+)?)"), ("deepseek", r"deepseek[-_ ]?v?(\d+(?:\.\d+)?)")) + + +def generation(name: str) -> tuple[str, float] | None: + """(Familie, Version) aus dem Namen, z. B. „Qwen3.6-35B-A3B“ → ("qwen", 3.6).""" + klein = anzeigename(name).lower() + for familie, muster in _FAMILIEN: + if (m := re.search(muster, klein)): + return familie, float(m.group(1)) + return None + + +# --- Filter (rein, ohne Netz) ------------------------------------------------------------------- + +def entdeckung_ungeeignet(m: dict, rolle: str, bekannt: set[str], heute: dict[str, str]) -> str | None: + """Warum ein discover-Fund fürs Radar nicht taugt; None = taugt. Discover rankt nach Beliebtheit — + ohne diese Vorauswahl verbrächte das Radar Wochen mit alten oder zu kleinen Modellen.""" + repo = str(m.get("repo") or "") + if m.get("curated"): + return "steht schon im kuratierten Katalog" + if stamm(repo) in bekannt: + return "liegt schon auf der Box" + params = float(m.get("params_b") or 0) + if params < MIN_PARAMS_B: + return f"zu klein ({params:.0f}B)" + if rolle == "hirn": + aktiv = (m.get("caps") or {}).get("active_b") or extract_active_params_b(repo) + if not aktiv or float(aktiv) > HIRN_MAX_AKTIV_B: + return "kein MoE mit wenigen aktiven Parametern (dichte Modelle nie als Hirn)" + neu, alt = generation(repo), generation(heute.get(rolle, "")) + if neu and alt and neu[0] == alt[0] and neu[1] < alt[1]: + return f"ältere Generation als das heutige Modell ({heute[rolle]})" + return None + + +def _groesse(eintrag: dict) -> int: + return int(eintrag.get("size") or (eintrag.get("lfs") or {}).get("size") or 0) + + +def _ist_hilfsdatei(pfad: str) -> bool: + name = pfad.lower().rsplit("/", 1)[-1] + return name.startswith("mtp-") or "draft" in name or "dflash" in name or "/mtp/" in f"/{pfad.lower()}" + + +def waehle_dateien(baum: list[dict], quant: str) -> dict | None: + """GGUF-Auswahl eines Repos: alle Teile des gewünschten Quants (Split-Dateien als Gruppe) und das + mmproj (F16 vor BF16 vor dem Rest). None, wenn es den Quant nicht gibt.""" + ggufs = [(str(e.get("path", "")), _groesse(e)) for e in baum if str(e.get("path", "")).lower().endswith(".gguf")] + muster = re.compile(rf"(^|[-_.]){re.escape(quant.lower())}([-_.]|$)") + modell = [(p, s) for p, s in ggufs + if "mmproj" not in p.lower() and not _ist_hilfsdatei(p) and muster.search(p.lower().rsplit("/", 1)[-1])] + if not modell: + return None + teile = sorted((p, s) for p, s in modell if re.search(r"-\d{5}-of-\d{5}\.gguf$", p, re.IGNORECASE)) + if teile: + praefix = re.sub(r"-\d{5}-of-\d{5}\.gguf$", "", teile[0][0], flags=re.IGNORECASE) + dateien = [[p, s] for p, s in teile if p.startswith(praefix)] + else: + dateien = [list(min(modell, key=lambda x: x[1]))] + + def rang(pfad: str) -> int: + klein = pfad.lower() + return 1 if "bf16" in klein else (0 if "f16" in klein else 2) + + projektoren = sorted(((p, s) for p, s in ggufs if "mmproj" in p.lower()), key=lambda x: (rang(x[0]), x[0])) + return {"dateien": dateien, "mmproj": list(projektoren[0]) if projektoren else None} + + +def speicher_passung(rolle: str, dateien_gb: float, kv_je_token_gb: float, eng_markiert: bool = False) -> dict: + """Passt der Kandidat neben das Warm-Set? Kontext wie im Betrieb, sonst stufenweise kleiner. + Regel (User 23.09.): Warm-Set + Kandidat inkl. KV-Cache ≤ Grenze. Ein Coder-Kandidat ersetzt den + heutigen Coder, ein Hirn-Kandidat läuft im Test neben dem heutigen Hirn — beides zählt so.""" + budget = SPEICHER_GRENZE_GB - WARMSET_GB + ziel = CTX_ROLLE[rolle] + for ctx in dict.fromkeys(c for c in (ziel, 65536, CTX_MIN) if c <= ziel): + bedarf = dateien_gb + kv_je_token_gb * ctx + if bedarf > budget: + continue + eng = eng_markiert or ctx < ziel or bedarf > ENG_ANTEIL * budget + text = (f"Passt{' knapp' if eng else ''}: braucht ~{_gb(bedarf)} GB inkl. KV-Cache (Kontext {ctx // 1024}k), " + f"neben dem Warm-Set sind {_gb(budget)} GB frei.") + if rolle == "hirn": + # Nach dem Tausch sitzt der Kandidat im Warm-Set — dann muss auch der Coder noch daneben passen. + betrieb = WARMSET_GB - HIRN_HEUTE_GB + bedarf + CODER_HEUTE_GB + if betrieb > SPEICHER_GRENZE_GB: + eng = True + text += f" Im Betrieb mit dem Coder wären es ~{_gb(betrieb)} GB – das wird eng." + return {"passt": True, "eng": eng, "ctx": ctx, "bedarf_gb": round(bedarf, 1), "text": text} + bedarf = dateien_gb + kv_je_token_gb * CTX_MIN + return {"passt": False, "eng": True, "ctx": CTX_MIN, "bedarf_gb": round(bedarf, 1), + "text": f"Passt nicht: braucht selbst mit {CTX_MIN // 1024}k Kontext ~{_gb(bedarf)} GB, neben dem " + f"Warm-Set sind nur {_gb(budget)} GB frei."} + + +def platte_nach_download(benutzt: int, gesamt: int, zusaetzlich: int) -> float: + """Füllstand der Platte in Prozent, wenn zusaetzlich Bytes dazukommen.""" + return (benutzt + zusaetzlich) / gesamt * 100 if gesamt else 100.0 + + +# --- GGUF-Kopf ------------------------------------------------------------------------------ + +_GGUF_SKALAR = {0: " dict | None: + """Skalare Metadaten vom Anfang einer GGUF-Datei (bis zum Tokenizer). Reicht für die Speicher- + Schätzung; die ersten paar MB kommen per Range-Anfrage, ohne das Modell zu laden.""" + pos = 0 + + def lies(n: int) -> bytes: + nonlocal pos + if pos + n > len(daten): + raise EOFError + stueck = daten[pos:pos + n] + pos += n + return stueck + + def zahl(fmt: str): + return struct.unpack(fmt, lies(struct.calcsize(fmt)))[0] + + def text() -> str: + return lies(zahl(" None: + if typ == 8: + lies(zahl(" float | None: + """KV-Cache in GB pro Kontext-Token bei q8_0. Hybrid-Modelle (full_attention_interval = n, z. B. + Qwen3.5/3.8) halten nur in jeder n-ten Schicht einen KV-Cache — services.gguf_meta rechnet hier mit + allen Schichten und käme auf das Vierfache.""" + arch = kopf.get("general.architecture") + if not arch: + return None + + def wert(schluessel: str): + return kopf.get(f"{arch}.{schluessel}") + + schichten, koepfe = wert("block_count"), wert("attention.head_count") + kv_koepfe = wert("attention.head_count_kv") or koepfe + einbettung = wert("embedding_length") + k_laenge = wert("attention.key_length") or (einbettung // koepfe if einbettung and koepfe else None) + v_laenge = wert("attention.value_length") or k_laenge + if not (schichten and kv_koepfe and k_laenge and v_laenge): + return None + intervall = int(wert("full_attention_interval") or 1) + voll = math.ceil(schichten / intervall) if intervall > 1 else schichten + return voll * kv_koepfe * (k_laenge + v_laenge) * bytes_je_wert / 1e9 + + +def _kv_schaetzung(repo: str, dateien_gb: float) -> float: + """Ohne lesbaren Kopf: grobe, eher zu große Schätzung wie services.fit (f16 kalibriert, × 0,53 für q8_0).""" + params = extract_params_b(repo) + if params <= 7.0: + params = max(dateien_gb / 0.55, 7.0) + return (max(params, 7) / 7) ** 0.5 * 0.84 / 8192 * 0.53 + + +def engine_kennt(arch: str) -> bool | None: + """Kennt die installierte llama.cpp-Engine diese Architektur? Die Namen stehen als C-Strings in + libllama.so. None = nicht prüfbar (keine Engine, z. B. auf Windows).""" + try: + daten = ENGINE_LIB.read_bytes() + except OSError: + return None + return (b"\x00" + arch.encode() + b"\x00") in daten + + +# --- Hugging Face (Netz) ------------------------------------------------------------------------ + +def _hf_kopfzeilen() -> dict: + token = geheimnisse.hf_token() + return {"Authorization": f"Bearer {token}"} if token else {} + + +def _hf_baum(repo: str) -> list[dict]: + with httpx.Client(timeout=20.0, headers=_hf_kopfzeilen()) as c: + r = c.get(f"{HF_BASIS}/api/models/{repo}/tree/main", params={"recursive": "true"}) + r.raise_for_status() + daten = r.json() + return daten if isinstance(daten, list) else [] + + +def _gguf_kopf(repo: str, datei: str, max_bytes: int = 8 << 20) -> dict | None: + """Die ersten MB einer GGUF-Datei per Range-Anfrage lesen und den Kopf auswerten.""" + puffer = bytearray() + try: + with httpx.Client(timeout=30.0, follow_redirects=True, headers=_hf_kopfzeilen()) as c: + with c.stream("GET", f"{HF_BASIS}/{repo}/resolve/main/{quote(datei)}", + headers={"Range": f"bytes=0-{max_bytes - 1}"}) as r: + if r.status_code not in (200, 206): + return None + for stueck in r.iter_bytes(): + puffer += stueck + if len(puffer) >= max_bytes: + break + except Exception: + log.debug("radar: GGUF-Kopf von %s/%s nicht lesbar", repo, datei, exc_info=True) + return None + return gguf_kopf_aus_bytes(bytes(puffer)) + + +# --- Zustand ------------------------------------------------------------------------------ + +def _leer() -> dict: + return {"version": 1, "letzte_suche": 0.0, "kandidaten": {}, "tests": [], "abgelehnt": {}, "lauf": None} + + +def _lade() -> dict: + try: + daten = json.loads(STORE_PATH.read_text(encoding="utf-8")) + except (OSError, ValueError): + daten = {} + stand = _leer() + if isinstance(daten, dict): + stand.update({k: v for k, v in daten.items() if k in stand and v is not None}) + return stand + + +def lade_stand() -> dict: + return _lade() + + +def _speichere(stand: dict) -> None: + try: + tmp = STORE_PATH.with_suffix(".tmp") + tmp.write_text(json.dumps(stand, ensure_ascii=False), encoding="utf-8") + tmp.replace(STORE_PATH) + except OSError: + log.warning("radar: Zustand %s nicht schreibbar", STORE_PATH, exc_info=True) + + +_thread_sperre = threading.Lock() +_sperr_tiefe = threading.local() + + +@contextmanager +def _gesperrt(): + """Sperre für Lesen-Ändern-Schreiben: Thread-Lock plus flock (MC2 und Nachtlauf sind zwei Prozesse). + Verschachtelt im selben Thread nur einmal sperren — flock über eine zweite Datei-Öffnung hinge sonst.""" + if getattr(_sperr_tiefe, "n", 0): + _sperr_tiefe.n += 1 + try: + yield + finally: + _sperr_tiefe.n -= 1 + return + with _thread_sperre: + datei = None + if fcntl is not None: + try: + datei = open(STORE_PATH.with_suffix(".lock"), "a+") + fcntl.flock(datei, fcntl.LOCK_EX) + except OSError: + datei = None + _sperr_tiefe.n = 1 + try: + yield + finally: + _sperr_tiefe.n = 0 + if datei is not None: + try: + fcntl.flock(datei, fcntl.LOCK_UN) + finally: + datei.close() + + +def _aendere(aenderung): + with _gesperrt(): + stand = _lade() + ergebnis = aenderung(stand) + _speichere(stand) + return ergebnis + + +def _aktiver_lauf(stand: dict) -> dict | None: + """Der laufende Nachtlauf — nur, wenn sein Prozess noch lebt und die Frist nicht lange vorbei ist.""" + lauf = stand.get("lauf") + if not isinstance(lauf, dict): + return None + try: + lebt = psutil.pid_exists(int(lauf.get("pid") or 0)) + except Exception: + lebt = False + if not lebt or time.time() > float(lauf.get("frist") or 0) + 900: + return None + return lauf + + +def _hat_geschichte(k: dict) -> bool: + """Einträge mit Geschichte fasst die Suche nicht mehr an (getestet, entschieden, angefangen).""" + return (k.get("status") in ("getestet", "bestanden", "durchgefallen", "uebernommen") + or (k.get("status") == "verworfen" and k.get("verworfen_von") == "nutzer") + or bool(k.get("erster_start"))) + + +def warteschlange(stand: dict) -> list[dict]: + """Testbare Kandidaten in Reihenfolge: Angefangene zuerst, dann Merkliste, dann Entdeckung.""" + offen = [k for k in stand["kandidaten"].values() if k.get("status") in ("neu", "wartet") and k.get("passt")] + return sorted(offen, key=lambda k: (0 if k.get("erster_start") else 1, 0 if k.get("quelle") == "watchlist" else 1, + k.get("rang", 999), k.get("gefunden", 0))) + + +def _ordne(stand: dict) -> None: + """Der Kopf der Warteschlange (und jeder Angefangene) steht auf „wartet“, alle anderen offenen auf „neu“.""" + for i, k in enumerate(warteschlange(stand)): + k["status"] = "wartet" if i == 0 or k.get("erster_start") else "neu" + + +def wochen_frei_ab(stand: dict, heute: date) -> date | None: + """Frühester Tag für einen NEUEN Kandidaten; None = heute schon frei. Ein Kandidat belegt die Woche + ab seinem ersten Start; Fortsetzungen (Download, Abbruch) belegen nichts Neues.""" + if KANDIDATEN_PRO_WOCHE <= 0: # 0 = Radar testet gar nicht + return heute + timedelta(days=3650) + starts = sorted((d for k in stand["kandidaten"].values() if (d := _tag_von(k.get("erster_start")))), + reverse=True) + in_woche = [d for d in starts if 0 <= (heute - d).days < 7] + if len(in_woche) < KANDIDATEN_PRO_WOCHE: + return None + return in_woche[KANDIDATEN_PRO_WOCHE - 1] + timedelta(days=7) + + +def plane_test(stand: dict, zeit: datetime) -> dict: + """Was jetzt zu tun ist: {"kandidat": id} oder {"kandidat": None, "grund": …}.""" + if not im_fenster(zeit): + return {"kandidat": None, "grund": f"außerhalb des Test-Fensters {FENSTER_START}–{FENSTER_ENDE}"} + rest = (fenster_ende(zeit).timestamp() - zeit.timestamp()) / 60 + if rest < MIN_RESTZEIT_MIN: + return {"kandidat": None, "grund": f"nur noch {rest:.0f} Minuten bis {FENSTER_ENDE}"} + if _aktiver_lauf(stand): + return {"kandidat": None, "grund": "es läuft schon ein Test"} + schlange = warteschlange(stand) + if not schlange: + return {"kandidat": None, "grund": "kein Kandidat wartet"} + k = schlange[0] + if not k.get("erster_start") and (frei := wochen_frei_ab(stand, zeit.astimezone(LOCAL_TZ).date())): + return {"kandidat": None, "grund": f"diese Woche lief schon ein Kandidat, der nächste frühestens am " + f"{frei:%d.%m.}"} + return {"kandidat": k["id"], "grund": f"{k['name']} ({k['rolle']})"} + + +def suche_faellig(zeit: datetime) -> bool: + """Der Nachtlauf sucht höchstens einmal am Tag.""" + return _tag_von(_lade().get("letzte_suche")) != zeit.astimezone(LOCAL_TZ).date() + + +# --- Suche -------------------------------------------------------------------------------- + +def _heutige_modelle() -> dict[str, dict]: + """Rolle → llama-swap-Modell, das heute den Alias der Rolle trägt.""" + heute: dict[str, dict] = {} + try: + modelle = llamaswap.list_models() + except Exception: + log.debug("radar: llama-swap-Config nicht lesbar", exc_info=True) + return heute + for m in modelle: + aliase = {str(a).lower() for a in m.get("aliases") or []} + for rolle, alias in ALIAS.items(): + if alias in aliase: + heute[rolle] = m + return heute + + +def _bekannte_staemme() -> set[str]: + """Was schon auf der Box liegt: llama-swap-Modelle und Ordner unter MODELS_DIR.""" + staemme: set[str] = set() + try: + for m in llamaswap.list_models(): + staemme.add(stamm(m["name"])) + if m.get("gguf_path"): + staemme.update({stamm(Path(m["gguf_path"]).parent.name), stamm(Path(m["gguf_path"]).name)}) + except Exception: + pass + try: + staemme.update(stamm(d.name) for d in MODELS_DIR.iterdir() if d.is_dir() and not d.name.startswith(".")) + except OSError: + pass + return staemme + + +def _merkliste() -> tuple[list[dict], bool]: + try: + daten = json.loads(WATCHLIST_PATH.read_text(encoding="utf-8")) + except (OSError, ValueError): + log.warning("radar: Merkliste %s nicht lesbar", WATCHLIST_PATH) + return [], False + eintraege = daten.get("kandidaten") if isinstance(daten, dict) else daten + funde = [{**e, "quelle": "watchlist", "rang": i} for i, e in enumerate(eintraege or []) + if isinstance(e, dict) and e.get("rolle") in ROLLEN and e.get("repo")] + return funde, True + + +def _entdeckung(bekannt: set[str], heute: dict[str, str], ausschluss: set[str]) -> tuple[list[dict], bool]: + try: + daten = discover.safe_discover(psutil.virtual_memory().total / 1024 ** 3) + except Exception: + log.warning("radar: Entdeckung fehlgeschlagen", exc_info=True) + daten = None + if not daten: + return [], False + funde: list[dict] = [] + je_rolle = dict.fromkeys(ROLLEN, 0) + for kategorie in daten.get("categories") or []: + rolle = DISCOVER_ROLLEN.get(kategorie.get("role")) + if not rolle: + continue + for rang, m in enumerate(kategorie.get("models") or []): + if je_rolle[rolle] >= DISCOVER_MAX_JE_ROLLE: + break + if not m.get("repo") or stamm(m["repo"]) in ausschluss: + continue + if (grund := entdeckung_ungeeignet(m, rolle, bekannt, heute)): + log.debug("radar: %s übergangen (%s)", m.get("repo"), grund) + continue + funde.append({"rolle": rolle, "repo": m["repo"], "quant": "Q4_K_M", "quelle": "discover", + "rang": 100 + rang, "autor": m.get("author")}) + je_rolle[rolle] += 1 + return funde, True + + +def _bewerte(fund: dict) -> dict: + """Aus einem Fund einen Kandidaten machen: Dateien auflösen, Größe, Engine-Unterstützung, Speicher. + Braucht Netz (Hugging Face) — wird deshalb außerhalb der Sperre aufgerufen.""" + rolle = fund["rolle"] + repo = hf.normalize_repo(fund["repo"]) + quant = str(fund.get("quant") or "Q4_K_M") + k: dict = {"id": kandidat_id(rolle, repo, quant), "name": fund.get("name") or anzeigename(repo), "rolle": rolle, + "repo": repo, "quant": quant, "quelle": fund["quelle"], "rang": fund.get("rang", 999), + "datei": "", "dateien": [], "mmproj": None, "draft": None, + "flags": [str(f) for f in fund.get("flags") or []], "groesse_gb": None, "passt": False, + "eng": bool(fund.get("eng")), "ctx": None, "bedarf_gb": None, "tauglich": False, "begruendung": ""} + herkunft = "Aus der Merkliste." if fund["quelle"] == "watchlist" else \ + f"Aus der Hugging-Face-Entdeckung ({fund.get('autor') or repo.split('/')[0]})." + notiz = f" {fund['notiz']}" if fund.get("notiz") else "" + if fund.get("ueberspringen"): + k["begruendung"] = f"Übersprungen: {fund['ueberspringen']}" + return k + try: + baum = _hf_baum(repo) + except Exception as e: + k["netzfehler"] = True + k["begruendung"] = f"Hugging Face gerade nicht erreichbar ({str(e)[:80]})." + return k + wahl = waehle_dateien(baum, quant) + if not wahl: + k["begruendung"] = f"Kein GGUF mit {quant} im Repo." + return k + k.update(dateien=wahl["dateien"], mmproj=wahl["mmproj"], datei=Path(wahl["dateien"][0][0]).name) + if BILD_PFLICHT and not wahl["mmproj"]: + k["begruendung"] = "Versteht keine Bilder: kein mmproj im Repo." + return k + groesse = sum(s for _, s in wahl["dateien"]) + (wahl["mmproj"][1] if wahl["mmproj"] else 0) + if isinstance(fund.get("draft"), dict): + d = fund["draft"] + d_repo, d_datei = hf.normalize_repo(d.get("repo") or repo), d.get("datei") + d_bytes = 0 + if d_datei: + try: + treffer = [e for e in (baum if d_repo == repo else _hf_baum(d_repo)) if e.get("path") == d_datei] + except Exception: + treffer = [] + if not treffer: + k["begruendung"] = f"Draft-Datei {d_datei} fehlt im Repo {d_repo}." + return k + d_bytes = _groesse(treffer[0]) + k["draft"] = {"repo": d_repo, "datei": d_datei, "bytes": d_bytes, "typ": d.get("typ") or "draft-simple", + "n_max": d.get("n_max")} + groesse += d_bytes + kopf = _gguf_kopf(repo, wahl["dateien"][0][0]) + arch = (kopf or {}).get("general.architecture") + if arch and engine_kennt(arch) is False: + k["begruendung"] = f"Läuft noch nicht im offiziellen llama.cpp (Architektur {arch} unbekannt).{notiz}" + return k + kv = (kv_je_token_gb(kopf) if kopf else None) or _kv_schaetzung(repo, groesse / 1e9) + passung = speicher_passung(rolle, groesse / 1e9, kv, eng_markiert=bool(fund.get("eng"))) + k.update(groesse_gb=round(groesse / 1e9, 1), passt=passung["passt"], eng=passung["eng"], ctx=passung["ctx"], + bedarf_gb=passung["bedarf_gb"], tauglich=passung["passt"], arch=arch) + k["begruendung"] = f"{herkunft} {passung['text']}{notiz}" + if not kopf and not passung["passt"]: + # Ohne Kopf rechnet die Schätzung den KV-Cache grob zu groß — darauf hin nichts verwerfen, + # die nächste Suche liest den Kopf erneut. + k.update(netzfehler=True, tauglich=False, + begruendung="Speicherbedarf unklar: der GGUF-Kopf ließ sich nicht lesen. Die nächste Suche " + "versucht es wieder.") + return k + + +_UEBERNEHMEN = ("name", "rolle", "repo", "quant", "quelle", "rang", "datei", "dateien", "mmproj", "draft", "flags", + "groesse_gb", "passt", "eng", "ctx", "bedarf_gb", "arch", "begruendung") + + +def _suche_anwenden(stand: dict, bewertet: list[dict], quellen_ok: dict[str, bool], zeit: float) -> dict: + """Bewertete Funde in den Zustand übernehmen (rein, ohne Netz).""" + kandidaten = stand["kandidaten"] + geschichte = {(k["rolle"], stamm(k["repo"])): kid for kid, k in kandidaten.items() if _hat_geschichte(k)} + gesehen, neu = set(), [] + for b in bewertet: + kid = b["id"] + gesehen.add(kid) + alt = kandidaten.get(kid) + if alt and _hat_geschichte(alt): + continue + frueher = geschichte.get((b["rolle"], stamm(b["repo"]))) + if frueher and frueher != kid: + continue # dasselbe Modell lief schon (z. B. aus einem anderen Repo) + if b.get("netzfehler"): + continue # alte Bewertung behalten, nicht wegen eines Netz-Aussetzers verwerfen + if b["quelle"] == "discover" and not b.get("tauglich"): + stand["abgelehnt"][stamm(b["repo"])] = {"grund": b["begruendung"], "zeit": zeit} + kandidaten.pop(kid, None) + continue + eintrag = {**(alt or {}), **{f: b.get(f) for f in _UEBERNEHMEN}, "id": kid, + "gefunden": (alt or {}).get("gefunden", zeit), "geaendert": zeit} + if b.get("tauglich"): + eintrag.update(status=(alt or {}).get("status", "neu"), verworfen_von=None) + if eintrag["status"] not in ("neu", "wartet"): + eintrag["status"] = "neu" + if not alt or alt.get("status") == "verworfen": + neu.append(eintrag["name"]) + else: + eintrag.update(status="verworfen", verworfen_von="radar") + kandidaten[kid] = eintrag + # Offene Einträge, die ihre (erreichbare) Quelle nicht mehr nennt, fliegen raus. + for kid in [kid for kid, k in kandidaten.items() + if kid not in gesehen and not _hat_geschichte(k) and quellen_ok.get(k.get("quelle"), False)]: + del kandidaten[kid] + stand["abgelehnt"] = {s: e for s, e in stand["abgelehnt"].items() + if zeit - float(e.get("zeit") or 0) < ABGELEHNT_TAGE * 86400} + _ordne(stand) + stand["letzte_suche"] = zeit + return {"ok": True, "neu": neu, "wartend": len(warteschlange(stand)), "gesamt": len(kandidaten), + "quellen": quellen_ok} + + +def suche() -> dict: + """Merkliste und Entdeckung auswerten und in den Zustand übernehmen. Das Netz (Hugging Face) läuft + außerhalb der Sperre, damit Knöpfe und Nachtlauf nicht warten müssen.""" + stand = _lade() + heute = {rolle: m["name"] for rolle, m in _heutige_modelle().items()} + ausschluss = {s for s, e in stand["abgelehnt"].items() + if time.time() - float(e.get("zeit") or 0) < ABGELEHNT_TAGE * 86400} + ausschluss |= {stamm(k["repo"]) for k in stand["kandidaten"].values() if _hat_geschichte(k)} + merkliste, merkliste_ok = _merkliste() + entdeckung, entdeckung_ok = _entdeckung(_bekannte_staemme(), heute, ausschluss) + bewertet = [] + for fund in merkliste + entdeckung: + try: + bewertet.append(_bewerte(fund)) + except Exception: + log.warning("radar: Bewertung von %s fehlgeschlagen", fund.get("repo"), exc_info=True) + ergebnis = _aendere(lambda s: _suche_anwenden(s, bewertet, {"watchlist": merkliste_ok, + "discover": entdeckung_ok}, time.time())) + log.info("radar: Suche fertig – %s neu, %s warten, %s insgesamt", len(ergebnis["neu"]), ergebnis["wartend"], + ergebnis["gesamt"]) + return ergebnis + + +# --- Test --------------------------------------------------------------------------------- + +_PS = None +_DOWNLOAD: dict = {"prozess": None} + + +def _pruefstand(): + """deploy/bench/pruefstand.py laden — ein Skript-Ordner, kein Paket; darum per Pfad.""" + global _PS + if _PS is None: + spec = importlib.util.spec_from_file_location("pruefstand", PRUEFSTAND_PATH) + modul = importlib.util.module_from_spec(spec) + sys.modules["pruefstand"] = modul + spec.loader.exec_module(modul) + _PS = modul + return _PS + + +def _protokoll(*teile) -> None: + log.info("radar: %s", " ".join(str(t) for t in teile)) + + +def _markiere_lauf(kid: str, schritt: str, frist: float) -> None: + def aenderung(stand: dict) -> None: + k = stand["kandidaten"].get(kid) + if k: + k["erster_start"] = k.get("erster_start") or time.time() + k["status"] = "wartet" + alt = stand.get("lauf") if isinstance(stand.get("lauf"), dict) else {} + eigener = alt.get("pid") == os.getpid() and alt.get("kandidat") == kid # nicht der Rest einer Vornacht + stand["lauf"] = {"pid": os.getpid(), "kandidat": kid, "schritt": schritt, + "seit": alt.get("seit") if eigener else time.time(), "frist": frist} + _aendere(aenderung) + + +def _loesche_dateien(k: dict) -> None: + """Kandidaten-Ordner löschen — nur, wenn er wirklich direkt unter RADAR_DIR liegt.""" + ordner = k.get("ordner") + if not ordner: + return + pfad = Path(ordner) + try: + if pfad.resolve().parent != RADAR_DIR.resolve(): + log.warning("radar: %s liegt nicht im Radar-Ordner – nicht gelöscht", pfad) + return + shutil.rmtree(pfad, ignore_errors=True) + except OSError: + log.warning("radar: %s nicht löschbar", pfad, exc_info=True) + return + k["ordner"] = None + + +def _abschluss(stand: dict, kid: str, ergebnis: str | None, satz: str, *, werte: dict | None = None, + vergleich: dict | None = None, zaehlt: bool = True, zeit: float | None = None) -> dict | None: + """Ergebnis eines Laufs in den Zustand schreiben: Status, Begründung, Test-Eintrag, ggf. Dateien löschen. + ergebnis None = gemessen, aber kein Vergleich möglich → „getestet“ (Urteil folgt später).""" + k = stand["kandidaten"].get(kid) + if not k: + return None + zeit = zeit or time.time() + tag = _datum(zeit) + k["geaendert"] = zeit + if ergebnis is None: + k.update(status="getestet", messung=werte, + begruendung=f"Gemessen am {tag}; der Vergleich mit dem heutigen Modell steht noch aus.") + _ordne(stand) + return None + zusammenfassung = satz + if ergebnis == "abgebrochen": + zusammenfassung = f"Abgebrochen: {satz}" + if zaehlt: + k["versuche"] = int(k.get("versuche") or 0) + 1 + if int(k.get("versuche") or 0) >= VERSUCHE_MAX: + _loesche_dateien(k) + k.update(status="durchgefallen", + begruendung=f"{VERSUCHE_MAX}-mal abgebrochen, zuletzt am {tag}: {satz} Dateien gelöscht.") + else: + k.update(status="wartet", begruendung=f"Abgebrochen am {tag}: {satz} Nächster Versuch in der nächsten Nacht.") + elif ergebnis == "bestanden": + k.update(status="bestanden", begruendung=f"{satz} Getestet am {tag}; wartet auf deine Entscheidung.") + else: + _loesche_dateien(k) + k.update(status="durchgefallen", begruendung=f"{satz} Getestet am {tag}; Dateien gelöscht.") + k.pop("messung", None) + test = {"id": f"{kid}-{datetime.fromtimestamp(zeit, LOCAL_TZ):%Y%m%d-%H%M}", "kandidat": kid, "rolle": k["rolle"], + "datum": _iso(zeit), "ergebnis": ergebnis, "werte": werte or {}, "vergleich": vergleich or {}, + "zusammenfassung": zusammenfassung} + stand["tests"].append(test) + del stand["tests"][:-TESTS_MAX] + _ordne(stand) + return test + + +def _erwartete_dateien(k: dict) -> dict[str, int]: + """Dateiname im Kandidaten-Ordner → erwartete Größe (Modellteile, mmproj, Draft).""" + namen = {Path(p).name: int(s) for p, s in k.get("dateien") or []} + if k.get("mmproj"): + namen[Path(k["mmproj"][0]).name] = int(k["mmproj"][1]) + if (k.get("draft") or {}).get("datei"): + namen[Path(k["draft"]["datei"]).name] = int(k["draft"].get("bytes") or 0) + return namen + + +def _vollstaendig(pfad: Path, groesse: int) -> bool: + try: + return pfad.is_file() and (not groesse or pfad.stat().st_size == groesse) + except OSError: + return False + + +def _lokale_pfade(k: dict, ordner: Path) -> dict: + return {"gguf": str(ordner / Path(k["dateien"][0][0]).name), + "mmproj": str(ordner / Path(k["mmproj"][0]).name) if k.get("mmproj") else None, + "draft": str(ordner / Path(k["draft"]["datei"]).name) if (k.get("draft") or {}).get("datei") else None} + + +def _ordner_bytes(ordner: Path) -> int: + summe = 0 + for wurzel, _, dateien in os.walk(ordner): + for name in dateien: + try: + summe += os.path.getsize(os.path.join(wurzel, name)) + except OSError: + pass + return summe + + +def _flach_legen(ordner: Path) -> None: + """hf legt Dateien mit ihrem Repo-Pfad ab (UD-IQ3_XXS/…). llama-swap leitet die Modell-ID aus dem + Elternordner ab — darum alle GGUF-Dateien in den Kandidaten-Ordner selbst holen.""" + for pfad in list(ordner.rglob("*.gguf")): + teile = pfad.relative_to(ordner).parts + if len(teile) == 1 or ".cache" in teile: + continue + pfad.replace(ordner / pfad.name) + for wurzel, _, _ in sorted(os.walk(ordner), key=lambda x: -len(x[0])): + if Path(wurzel) != ordner and ".cache" not in Path(wurzel).relative_to(ordner).parts: + try: + os.rmdir(wurzel) + except OSError: + pass + + +def _beende(prozess: subprocess.Popen) -> None: + try: + if os.name == "posix": # ganze Gruppe: hf startet eigene Kindprozesse + os.killpg(prozess.pid, signal.SIGTERM) + else: + prozess.terminate() + prozess.wait(timeout=30) + except Exception: + try: + prozess.kill() + except Exception: + pass + + +def _hf_download(repo: str, dateien: list[str], ordner: Path, bis: float) -> None: + befehl = [hf.hf_bin(), "download", repo, *dateien, "--local-dir", str(ordner)] + umgebung = {**os.environ, **HF_DOWNLOAD_ENV} + if (token := geheimnisse.hf_token()): + umgebung["HF_TOKEN"] = token + vorher = _ordner_bytes(ordner) + logpfad = RADAR_DIR / "download.log" + with open(logpfad, "w", encoding="utf-8") as logdatei: + prozess = subprocess.Popen(befehl, stdout=logdatei, stderr=subprocess.STDOUT, stdin=subprocess.DEVNULL, + env=umgebung, start_new_session=True) + _DOWNLOAD["prozess"] = prozess + try: + while prozess.poll() is None: + if time.time() > bis: + _beende(prozess) + geladen = (_ordner_bytes(ordner) - vorher) / 1e9 + raise Abbruch(f"Download bis {datetime.fromtimestamp(bis, LOCAL_TZ):%H:%M} nicht fertig " + f"({_gb(geladen)} GB in dieser Nacht) – geht in der nächsten Nacht weiter.", + zaehlt=geladen < 1.0) + time.sleep(5) + finally: + _DOWNLOAD["prozess"] = None + if prozess.returncode != 0: + try: + ende = logpfad.read_text(encoding="utf-8", errors="replace").strip().splitlines()[-1:] + except OSError: + ende = [] + raise Abbruch(f"Download von {repo} scheiterte: {(ende or ['ohne Meldung'])[0][:200]}") + + +def _download(k: dict, bis: float) -> Path: + """Fehlende Dateien des Kandidaten nach RADAR_DIR/ holen; Platz vorher prüfen.""" + ordner = RADAR_DIR / k["id"] + erwartet = _erwartete_dateien(k) + fehlend = {n: b for n, b in erwartet.items() if not _vollstaendig(ordner / n, b)} + if not fehlend: + return ordner + if os.name != "posix": + raise Abbruch("Herunterladen und Testen gehen nur auf der Box.", zaehlt=False) + try: + platte = shutil.disk_usage(MODELS_DIR) + except OSError as e: + raise Abbruch(f"Plattenplatz nicht prüfbar ({e}).", zaehlt=False) from e + nachher = platte_nach_download(platte.used, platte.total, sum(fehlend.values())) + if nachher > PLATTE_MAX_PCT: + raise Abbruch(f"Zu wenig Platz: nach dem Download wäre die Platte zu {nachher:.0f} % voll " + f"(Grenze {PLATTE_MAX_PCT:.0f} %).", zaehlt=False) + ordner.mkdir(parents=True, exist_ok=True) + _aendere(lambda s: s["kandidaten"].get(k["id"], {}).update(ordner=str(ordner))) + k["ordner"] = str(ordner) + haupt = [p for p, _ in k["dateien"]] + ([k["mmproj"][0]] if k.get("mmproj") else []) + draft = k.get("draft") or {} + if draft.get("datei") and draft.get("repo") == k["repo"]: + haupt.append(draft["datei"]) + _hf_download(k["repo"], haupt, ordner, bis) + if draft.get("datei") and draft.get("repo") != k["repo"]: + _hf_download(draft["repo"], [draft["datei"]], ordner, bis) + _flach_legen(ordner) + if (noch := [n for n, b in erwartet.items() if not _vollstaendig(ordner / n, b)]): + raise Abbruch(f"Download unvollständig: {', '.join(noch)}") + return ordner + + +def _warmset() -> set[str]: + warm: set[str] = set() + for gruppe in (llamaswap.list_groups() or {}).values(): + if isinstance(gruppe, dict) and (gruppe.get("persistent") or gruppe.get("persist")): + warm.update(gruppe.get("members") or []) + return warm + + +def _fremde_modelle(warm: set[str]) -> list[str]: + return [m for m in llamaswap.get_running_models() if m and m not in warm] + + +def _nur_warmset(warte_s: float = 90) -> set[str]: + """Vor dem Kandidaten darf in llama-swap nur das Warm-Set laufen (der Coder z. B. nicht) — + sonst reicht die 115-GB-Rechnung nicht.""" + warm = _warmset() + if not warm: + raise Abbruch("Das Warm-Set ist unbekannt (llama-swap-Config ohne persistente Gruppe) – ohne sichere " + "Speicherrechnung kein Test.", zaehlt=False) + fremd = _fremde_modelle(warm) + for name in fremd: + try: + with httpx.Client(timeout=30.0) as c: + c.post(f"{LLAMA_SWAP_URL}/api/models/unload/{quote(name)}") + except Exception: + log.warning("radar: %s ließ sich nicht entladen", name, exc_info=True) + t0 = time.time() + while fremd and time.time() - t0 < warte_s: + time.sleep(3) + fremd = _fremde_modelle(warm) + if fremd: + raise Abbruch(f"{', '.join(fremd)} ließ sich nicht entladen – ohne freien Speicher kein Test.", zaehlt=False) + return warm + + +class _Nachtwaechter(threading.Thread): + """Passt während des Kandidaten-Tests auf: Lädt llama-swap nachts ein weiteres Modell (etwa den Coder + für OpenCode), reicht der Speicher nicht mehr — dann den Kandidaten sofort stoppen.""" + + def __init__(self, warm: set[str], intervall: float = 10.0): + super().__init__(daemon=True, name="radar-nachtwaechter") + self.warm, self.intervall, self.grund = warm, intervall, "" + self._halt = threading.Event() + + def run(self) -> None: + while not self._halt.wait(self.intervall): + if (fremd := _fremde_modelle(self.warm)): + self.grund = (f"Während des Tests wurde {', '.join(fremd)} geladen – abgebrochen, damit der " + f"Speicher reicht.") + _pruefstand().stoppe_alle(warte_s=10) + return + + def halt(self) -> None: + self._halt.set() + + +def _baseline(rolle: str, frist: float) -> dict | None: + """Werte des heutigen Modells der Rolle (Cache, höchstens monatlich neu gemessen).""" + heute = _heutige_modelle().get(rolle) + if not heute: + return None + befehl = str(heute.get("cmd") or "") + kennung = f"{heute['name']}|{hashlib.sha1(befehl.encode()).hexdigest()[:10]}" + return _pruefstand().baseline(rolle, str(BASELINE_PATH), kennung=kennung, bild="--mmproj" in befehl, + frist=frist, max_alter_tage=BASELINE_TAGE, modell=ALIAS[rolle], + protokoll=_protokoll) + + +def teste(kid: str, frist: float) -> dict | None: + """Einen Kandidaten prüfen: Download → Baseline → nur Warm-Set in llama-swap → Kandidat auf :5899 → + Urteil. Gibt den Test-Eintrag zurück (None, wenn nur gemessen wurde oder es den Kandidaten nicht gibt).""" + ps = _pruefstand() + k = _lade()["kandidaten"].get(kid) + if not k or k.get("status") not in ("neu", "wartet"): # inzwischen verworfen o. Ä. + return None + _markiere_lauf(kid, "download", frist) + ergebnis, satz, werte, vergleich, zaehlt = "abgebrochen", "", None, None, True + waechter, von_aussen = None, None + try: + ordner = _download(k, frist - TESTZEIT_MIN * 60) + pfade = _lokale_pfade(k, ordner) + _markiere_lauf(kid, "baseline", frist) + basis = _baseline(k["rolle"], frist) + _markiere_lauf(kid, "test", frist) + waechter = _Nachtwaechter(_nur_warmset()) + waechter.start() + draft = k.get("draft") or {} + flags = ps.draft_flags(pfade["draft"], draft.get("typ"), draft.get("n_max")) + list(k.get("flags") or []) + lauf = ps.pruefe_kandidat(k["rolle"], pfade["gguf"], mmproj=pfade["mmproj"], flags=flags, + ctx=int(k.get("ctx") or ps.CTX_STANDARD), basis=(basis or {}).get("werte"), + frist=frist, protokoll=_protokoll) + werte, vergleich = lauf["werte"], lauf["vergleich"] + if basis: + werte["baseline"] = {"modell": (basis.get("werte") or {}).get("modell"), "gemessen": _iso(basis.get("zeit"))} + ergebnis, satz = lauf["ergebnis"], lauf["zusammenfassung"] + except ps.Zeitende: + satz = f"Das Nachtfenster endete um {FENSTER_ENDE}, bevor der Test fertig war." + except ps.ServerFehler as e: + if "unknown model architecture" in str(e).lower(): + ergebnis, satz = "durchgefallen", f"Durchgefallen: läuft nicht im offiziellen llama.cpp ({str(e)[:160]})." + else: + satz = f"Der Kandidat lief nicht: {str(e)[:240]}" + except Abbruch as e: + satz, zaehlt = e.grund, e.zaehlt + except Exception as e: + if not (waechter and waechter.grund): # Wächter-Abbruch ist erwartet, kein Fehler fürs Journal + log.exception("radar: Test von %s scheiterte", kid) + satz = f"Unerwarteter Fehler: {str(e)[:200]}" + except BaseException as e: # SIGTERM von systemd (SystemExit) oder Strg+C: festhalten, dann weiter + von_aussen = e + satz, zaehlt = "Der Lauf wurde von außen beendet.", False + finally: + if waechter: + waechter.halt() + ps.stoppe_alle() + if waechter and waechter.grund: # der Wächter hat abgebrochen — dann zählt kein Messwert als Urteil + ergebnis, satz, zaehlt, vergleich = "abgebrochen", waechter.grund, False, None + + def abschluss(stand: dict): + stand["lauf"] = None + return _abschluss(stand, kid, ergebnis, satz, werte=werte, vergleich=vergleich, zaehlt=zaehlt) + test = _aendere(abschluss) + log.info("radar: %s → %s (%s)", kid, ergebnis, satz) + if von_aussen is not None: + raise von_aussen + return test + + +def nachurteilen(frist: float) -> int: + """„getestet“-Kandidaten (damals fehlte die Vergleichsmessung) jetzt beurteilen, falls es sie gibt.""" + offen = [k for k in _lade()["kandidaten"].values() if k.get("status") == "getestet" and k.get("messung")] + if not offen: + return 0 + ps, n = _pruefstand(), 0 + for k in offen: + try: + basis = _baseline(k["rolle"], frist) + except Exception: + log.warning("radar: Baseline für %s nicht messbar", k["rolle"], exc_info=True) + break + if not basis: + continue + u = ps.urteil(k["rolle"], k["messung"], basis["werte"]) + + def abschluss(stand: dict, kid=k["id"], u=u, werte=k["messung"]): + return _abschluss(stand, kid, u["ergebnis"], u["zusammenfassung"], werte=werte, vergleich=u["vergleich"]) + _aendere(abschluss) + n += 1 + return n + + +def notstopp() -> None: + """Notbremse des Nachtlaufs: Kandidaten-Server und Download sofort beenden (ohne Zustand anzufassen).""" + try: + if _PS is not None: + _PS.stoppe_alle(warte_s=10) + finally: + if (prozess := _DOWNLOAD.get("prozess")) is not None: + _beende(prozess) + + +# --- Übernehmen und Verwerfen ---------------------------------------------------------------- + +def betriebs_befehl(rolle: str, pfade: dict, k: dict) -> str: + """llama-swap-Befehl für den übernommenen Kandidaten: die getesteten Flags plus die Betriebs-Flags + der Rolle wie heute (Hirn 2 Slots, Coder 1 Slot, KV q8_0, Prompt-Cache 16 GB).""" + teile = ["llama-server", "-m", pfade["gguf"], "--host", "127.0.0.1", "--port", "${PORT}", + "-c", str(int(k.get("ctx") or CTX_ROLLE[rolle])), "-ngl", "999", "-fa", "on", "--load-mode", "none"] + if pfade.get("mmproj"): + teile += ["--mmproj", pfade["mmproj"]] + teile += ["--jinja", "--parallel", str(PARALLEL[rolle]), "-cram", "16384", "-ctk", "q8_0", "-ctv", "q8_0"] + draft = k.get("draft") or {} + if draft.get("typ"): + teile += ["--spec-type", draft["typ"]] + if pfade.get("draft"): + teile += ["--spec-draft-model", pfade["draft"]] + if draft.get("n_max"): + teile += ["--spec-draft-n-max", str(draft["n_max"])] + return " ".join(teile + [str(f) for f in k.get("flags") or []]) + + +def _steward_neu_starten() -> str | None: + """Drop-in neu einlesen und den Steward neu starten (User-Dienst, ohne sudo). Fehlertext oder None.""" + if os.name != "posix": + return None + for befehl in (["systemctl", "--user", "daemon-reload"], ["systemctl", "--user", "restart", "mc2-steward"]): + try: + subprocess.run(befehl, capture_output=True, timeout=60, check=True) + except (OSError, subprocess.SubprocessError) as e: + return str(e) + return None + + +def _warmset_umstellen(alt: str | None, neu: str) -> str | None: + """Der Re-Warm-Wächter (mc2-steward) nennt sein Warm-Set per MC_WARMSET beim Namen (systemd-Drop-in). + Bliebe dort das alte Hirn stehen, lüde er es nach dem Tausch immer wieder neben das neue. Darum den + Namen hier tauschen und den Steward neu starten. Gibt nur dann einen Hinweis zurück, wenn das nicht ging.""" + try: + text = STEWARD_WARMSET.read_text(encoding="utf-8") + except OSError: + return None # kein Drop-in: der Steward leitet das Warm-Set aus der brains-Gruppe ab + treffer = re.search(r"MC_WARMSET=([^\"\n]*)", text) + namen = treffer.group(1).split() if treffer else [] + if not treffer or not alt or alt not in namen or neu in namen: + return None + neu_text = text[:treffer.start(1)] + " ".join(neu if n == alt else n for n in namen) + text[treffer.end(1):] + try: + tmp = STEWARD_WARMSET.with_name(STEWARD_WARMSET.name + ".tmp") # systemd liest nur *.conf + tmp.write_text(neu_text, encoding="utf-8") + os.replace(tmp, STEWARD_WARMSET) + except OSError as e: + return f"Das Warm-Set des Stewards ließ sich nicht umstellen ({e}); er hält noch {alt} warm." + if (fehler := _steward_neu_starten()): + return f"Warm-Set umgestellt, aber der Steward-Neustart scheiterte ({fehler}); es greift beim nächsten Neustart." + return None + + +def _zielordner(k: dict) -> Path: + name = k["repo"].split("/")[-1] + ziel = MODELS_DIR / name + if ziel.exists(): + ziel = MODELS_DIR / f"{re.sub(r'[-_]GGUF$', '', name, flags=re.IGNORECASE)}-Radar-GGUF" + return ziel + + +def _tausche_ein(k: dict) -> dict: + """Bestandenen Kandidaten in Betrieb nehmen: Ordner nach MODELS_DIR, in llama-swap registrieren, Rolle setzen.""" + rolle = k["rolle"] + quelle = Path(k.get("ordner") or "") + if not k.get("ordner") or not Path(_lokale_pfade(k, quelle)["gguf"]).is_file(): + raise RuntimeError("Die Modelldateien fehlen – der Kandidat müsste neu getestet werden.") + alt = _heutige_modelle().get(rolle) + if quelle.resolve().parent == RADAR_DIR.resolve(): + ziel = _zielordner(k) + if ziel.exists(): + raise RuntimeError(f"{ziel} gibt es schon.") + quelle.replace(ziel) # gleiche Platte → nur umbenennen + k["ordner"] = str(ziel) # scheitert es danach, findet ein zweiter Klick die Dateien hier + else: + ziel = quelle # schon verschoben (früherer, abgebrochener Versuch) + pfade = _lokale_pfade(k, ziel) + modell_id = llamaswap.register_model(pfade["gguf"], role=ALIAS[rolle], ctx=int(k.get("ctx") or CTX_ROLLE[rolle]), + mmproj_path=pfade["mmproj"], jinja=True, set_alias=False) + cfg = llamaswap.read_config() + try: # die getesteten Flags statt der Vorlage aus register_model (sonst liefe ein ungetesteter Draft mit) + cfg["models"][modell_id]["cmd"] = LiteralScalarString(betriebs_befehl(rolle, pfade, k) + "\n") + except (KeyError, TypeError) as e: + raise RuntimeError(f"{modell_id} fehlt nach dem Eintragen in der llama-swap-Config.") from e + llamaswap.write_config(cfg) + hinweis = None + if rolle == "hirn": + from services.agent import set_agent_brain + antwort = set_agent_brain(modell_id) # hermes-Alias, brains-Gruppe, ttl 0, Hermes-Config + if not antwort.get("ok"): + raise RuntimeError(antwort.get("reason") or "Hirn-Wechsel fehlgeschlagen") + # Das Hirn ist heute hermes UND fast (Chat-Spur, warmup.sh, Oberfläche). Bliebe fast am alten + # Modell, lüde warmup.sh es nachts neben das neue Hirn. + if alt and "fast" in {str(a).lower() for a in alt.get("aliases") or []}: + llamaswap.add_role(modell_id, "fast") + hinweis = " ".join(h for h in (antwort.get("warning"), _warmset_umstellen((alt or {}).get("name"), modell_id)) + if h) or None + else: + if not llamaswap.set_role(modell_id, "coder"): + raise RuntimeError(f"Die Rolle coder ließ sich nicht auf {modell_id} setzen.") + # heavy ist heute derselbe Coder (OpenCode plant damit). Bliebe es am alten Modell, lägen zwei Coder + # bereit und der alte ließe sich nie löschen. + if alt and "heavy" in {str(a).lower() for a in alt.get("aliases") or []}: + llamaswap.add_role(modell_id, "heavy") + if alt and alt.get("ttl") is not None: + llamaswap.set_ttl(modell_id, int(alt["ttl"])) + return {"modell_id": modell_id, "pfad": str(ziel), "alt": (alt or {}).get("name"), "hinweis": hinweis} + + +def _oeffentlich(k: dict) -> dict: + return {f: k.get(f) for f in KANDIDAT_FELDER} + + +def uebernehmen(kid: str) -> dict: + """Knopf „Übernehmen“: nur bei Status „bestanden“ und nicht während eines Nachtlaufs.""" + with _gesperrt(): + stand = _lade() + k = stand["kandidaten"].get(kid) + if not k: + return {"ok": False, "status": 404, "detail": "Diesen Kandidaten gibt es nicht."} + if k.get("status") != "bestanden": + return {"ok": False, "status": 409, + "detail": f"Übernehmen geht nur bei bestandenen Kandidaten (Status: {k.get('status')})."} + if _aktiver_lauf(stand): + return {"ok": False, "status": 409, "detail": "Das Radar testet gerade – bitte nach dem Nachtlauf übernehmen."} + try: + tausch = _tausche_ein(k) + except Exception as e: + _speichere(stand) # k["ordner"] kann sich schon geändert haben + log.warning("radar: Übernehmen von %s scheiterte", kid, exc_info=True) + return {"ok": False, "status": 409, "detail": f"Übernehmen ging nicht: {e}"} + rolle_text = "das Hirn" if k["rolle"] == "hirn" else "der Coder" + k.update(status="uebernommen", modell_id=tausch["modell_id"], pfad=tausch["pfad"], ordner=None, + geaendert=time.time(), + begruendung=f"Übernommen am {_datum(time.time())}: ist jetzt {rolle_text}" + + (f" (vorher {tausch['alt']})." if tausch.get("alt") else ".") + + (f" Noch zu tun: {tausch['hinweis']}" if tausch.get("hinweis") else "")) + _ordne(stand) + _speichere(stand) + return {"ok": True, "kandidat": _oeffentlich(k), "modell_id": tausch["modell_id"], "text": tausch["hinweis"]} + + +def verwerfen(kid: str) -> dict: + """Knopf „Verwerfen“: Dateien weg, nie wieder testen.""" + def aenderung(stand: dict) -> dict: + k = stand["kandidaten"].get(kid) + if not k: + return {"ok": False, "status": 404, "detail": "Diesen Kandidaten gibt es nicht."} + if k.get("status") == "uebernommen": + return {"ok": False, "status": 409, "detail": "Schon übernommen – zurück geht es über die Modell-Rollen."} + if k.get("status") == "durchgefallen": + return {"ok": False, "status": 409, "detail": "Ist schon durchgefallen, die Dateien sind gelöscht."} + if (lauf := _aktiver_lauf(stand)) and lauf.get("kandidat") == kid: + return {"ok": False, "status": 409, "detail": "Wird gerade getestet – nach dem Nachtlauf noch einmal."} + _loesche_dateien(k) + k.pop("messung", None) + k.update(status="verworfen", verworfen_von="nutzer", geaendert=time.time(), + begruendung=f"Von dir verworfen am {_datum(time.time())}.") + _ordne(stand) + return {"ok": True, "kandidat": _oeffentlich(k)} + return _aendere(aenderung) + + +# --- Übersicht (GET /api/radar) -------------------------------------------------------------- + +def naechster_test(stand: dict, zeit: datetime | None = None) -> str | None: + """Wann der nächste Test frühestens beginnt (ISO-Zeit), None ohne wartenden Kandidaten. + Läuft gerade einer, ist es dessen Beginn.""" + zeit = (zeit or jetzt()).astimezone(LOCAL_TZ) + if (lauf := _aktiver_lauf(stand)) and lauf.get("kandidat") in stand["kandidaten"]: + return _iso(lauf.get("seit")) + schlange = warteschlange(stand) + if not schlange: + return None + start = naechster_start(zeit) + if not schlange[0].get("erster_start") and (frei := wochen_frei_ab(stand, start.date())) and frei > start.date(): + start = _lokal(frei, _hhmm(FENSTER_START)) + return start.isoformat(timespec="seconds") + + +def uebersicht(zeit: datetime | None = None) -> dict: + """GET /api/radar: nächster und letzter Test (ISO-Zeit), Kandidaten, Tests (neueste zuerst).""" + stand = _lade() + kandidaten = sorted(stand["kandidaten"].values(), + key=lambda k: (_REIHENFOLGE.get(k.get("status"), 9), 0 if k.get("quelle") == "watchlist" else 1, + k.get("rang", 999))) + oeffentlich = [_oeffentlich(k) for k in kandidaten] + if (lauf := _aktiver_lauf(stand)): # den laufenden Test in seiner Begründung zeigen (nicht gespeichert) + for k in oeffentlich: + if k["id"] == lauf.get("kandidat"): + seit = datetime.fromtimestamp(float(lauf.get("seit") or time.time()), LOCAL_TZ) + k["begruendung"] = (f"Läuft gerade seit {seit:%H:%M}: " + f"{_SCHRITTE.get(lauf.get('schritt'), lauf.get('schritt'))}.") + tests = [{f: t.get(f) for f in TEST_FELDER} for t in reversed(stand["tests"])] + return {"naechster_test": naechster_test(stand, zeit), "letzter_test": tests[0]["datum"] if tests else None, + "kandidaten": oeffentlich, "tests": tests} diff --git a/backend/services/waechter.py b/backend/services/waechter.py index 284d411..8262f5c 100644 --- a/backend/services/waechter.py +++ b/backend/services/waechter.py @@ -83,6 +83,7 @@ DIENSTE: dict[str, tuple[bool, bool, str]] = { TIMER_DIENSTE: dict[str, tuple[str, bool]] = { "projekte-sync": ("Projekte-Abgleich", False), "mc2-backup": ("Sicherung", True), + "mc2-radar": ("Modell-Radar", False), } HERMES_JOBS_PATH = HERMES_HOME / "cron" / "jobs.json" diff --git a/backend/services/zeitplan.py b/backend/services/zeitplan.py index 2e60785..85af680 100644 --- a/backend/services/zeitplan.py +++ b/backend/services/zeitplan.py @@ -14,7 +14,7 @@ from zoneinfo import ZoneInfo from services import modell_nutzung, waechter -TIMER = {"mc2-backup.timer": "Sicherung"} +TIMER = {"mc2-backup.timer": "Sicherung", "mc2-radar.timer": "Modell-Radar"} LOCAL_TZ = ZoneInfo(os.environ.get("MC_LOCAL_TZ", "Europe/Berlin")) diff --git a/backend/tests/test_radar.py b/backend/tests/test_radar.py new file mode 100644 index 0000000..b11568d --- /dev/null +++ b/backend/tests/test_radar.py @@ -0,0 +1,617 @@ +"""Tests für das Modell-Radar: reine Logik (Zeitfenster, Wochengrenze, Filter, Speicher-Rechnung, +Zustandsübergänge) und die Urteile und Programmieraufgaben des Prüfstands — ohne Netz und ohne Box. +Zahlen wie auf der Box am 23.09.2026 (Ornith 21,7 GB + mmproj, Flash-Next UD-IQ3_XXS 82 GB).""" + +import json +import os +import struct +import time +import zlib +from datetime import date, datetime + +import pytest +from services import radar + +BERLIN = radar.LOCAL_TZ + + +def _zeit(text: str) -> datetime: + return datetime.fromisoformat(text).replace(tzinfo=BERLIN) + + +def _kandidat(kid: str, rolle: str = "hirn", status: str = "neu", quelle: str = "watchlist", rang: int = 0, + **extra) -> dict: + return {"id": kid, "name": kid, "rolle": rolle, "repo": f"org/{kid}-GGUF", "quant": "Q4_K_M", "quelle": quelle, + "rang": rang, "datei": f"{kid}-Q4_K_M.gguf", "dateien": [[f"{kid}-Q4_K_M.gguf", 100]], + "mmproj": ["mmproj-F16.gguf", 10], "draft": None, "flags": [], "groesse_gb": 21.7, "passt": True, + "eng": False, "ctx": 131072, "status": status, "begruendung": "", **extra} + + +@pytest.fixture +def zustand(monkeypatch, tmp_path): + """Radar-Zustand und Radar-Ordner in einem Temp-Ordner statt unter /srv/models.""" + monkeypatch.setattr(radar, "STORE_PATH", tmp_path / "mc2-radar.json") + monkeypatch.setattr(radar, "RADAR_DIR", tmp_path / "radar") + (tmp_path / "radar").mkdir() + return tmp_path + + +# --- Zeitfenster und Wochengrenze ------------------------------------------------------------ + +def test_zeitfenster_nur_von_0030_bis_0230(): + assert not radar.im_fenster(_zeit("2026-09-29T00:29:59")) + assert radar.im_fenster(_zeit("2026-09-29T00:30:00")) + assert radar.im_fenster(_zeit("2026-09-29T02:29:59")) + assert not radar.im_fenster(_zeit("2026-09-29T02:30:00")) + assert not radar.im_fenster(_zeit("2026-09-29T14:00:00")) + assert radar.fenster_ende(_zeit("2026-09-29T00:45:00")) == _zeit("2026-09-29T02:30:00") + + +def test_fensterende_am_umstellungstag_nie_nach_0300(): + # 28.03.2027: 02:00 springt auf 03:00, 02:30 gibt es nicht. Lieber früher enden als in den NerdQuiz-Lauf. + ende = radar.fenster_ende(_zeit("2027-03-28T00:45:00")) + assert ende.timestamp() <= datetime(2027, 3, 28, 3, 0, tzinfo=BERLIN).timestamp() + + +def test_naechster_start_ist_die_naechste_nacht(): + assert radar.naechster_start(_zeit("2026-09-29T00:10:00")) == _zeit("2026-09-29T00:30:00") + assert radar.naechster_start(_zeit("2026-09-29T01:00:00")) == _zeit("2026-09-30T00:30:00") + assert radar.naechster_start(_zeit("2026-09-29T14:00:00")) == _zeit("2026-09-30T00:30:00") + + +def test_wochengrenze_ein_neuer_kandidat_pro_woche(): + stand = radar._leer() + stand["kandidaten"] = {"a": _kandidat("a", status="bestanden", + erster_start=_zeit("2026-09-29T00:31:00").timestamp()), + "b": _kandidat("b")} + assert radar.wochen_frei_ab(stand, date(2026, 10, 3)) == date(2026, 10, 6) + assert radar.wochen_frei_ab(stand, date(2026, 10, 6)) is None + + +def test_plan_testet_nur_im_fenster_mit_freier_woche_und_setzt_angefangene_fort(): + stand = radar._leer() + stand["kandidaten"] = {"a": _kandidat("a", status="bestanden", + erster_start=_zeit("2026-09-29T00:31:00").timestamp()), + "b": _kandidat("b", rang=1)} + radar._ordne(stand) + assert stand["kandidaten"]["b"]["status"] == "wartet" + + plan = radar.plane_test(stand, _zeit("2026-10-03T00:31:00")) + assert plan["kandidat"] is None and "06.10." in plan["grund"] + assert radar.plane_test(stand, _zeit("2026-10-06T00:31:00"))["kandidat"] == "b" + assert "außerhalb" in radar.plane_test(stand, _zeit("2026-10-06T14:00:00"))["grund"] + assert "Minuten" in radar.plane_test(stand, _zeit("2026-10-06T02:15:00"))["grund"] + + # angefangen (z. B. Download unterbrochen): darf in der nächsten Nacht weiter, die Woche gilt ab dem 1. Start + stand["kandidaten"]["b"]["erster_start"] = _zeit("2026-10-06T00:31:00").timestamp() + assert radar.plane_test(stand, _zeit("2026-10-07T00:31:00"))["kandidat"] == "b" + + +def test_laufender_test_blockiert_zweiten_lauf_und_zeigt_sich(zustand): + stand = radar._leer() + stand["kandidaten"]["b"] = _kandidat("b", status="wartet", erster_start=time.time()) + stand["lauf"] = {"pid": os.getpid(), "kandidat": "b", "schritt": "test", "seit": time.time(), + "frist": time.time() + 3600} + assert radar.plane_test(stand, _zeit("2026-10-06T00:40:00"))["grund"] == "es läuft schon ein Test" + radar._speichere(stand) + assert radar.uebersicht()["kandidaten"][0]["begruendung"].startswith("Läuft gerade seit") + stand["lauf"]["pid"] = 999_999_999 # Prozess tot → Lauf gilt als beendet + assert radar._aktiver_lauf(stand) is None + + +# --- Namen, Filter, Dateien, Speicher ----------------------------------------------------------- + +def test_namen_und_staemme(): + assert radar.anzeigename("bartowski/Qwen_Qwen3.6-35B-A3B-GGUF") == "Qwen3.6-35B-A3B" + assert radar.anzeigename("unsloth/Qwen3.8-Flash-Next-GGUF") == "Qwen3.8-Flash-Next" + assert radar.stamm("Qwen3.8-Flash-Next-UD-IQ3_XXS-00001-of-00003.gguf") == "qwen3.8-flash-next" + assert radar.stamm("Qwen3.6-35B-A3B") == radar.stamm("unsloth/Qwen3.6-35B-A3B-GGUF") + assert radar.generation("Qwen3.8-27B") == ("qwen", 3.8) + assert radar.kandidat_id("hirn", "ornith-ai/Ornith-1.5-35B-A3B-GGUF", "Q4_K_M") == \ + "hirn-ornith-ai-ornith-1-5-35b-a3b-gguf-q4-k-m" + + +def test_entdeckung_filtert_alte_kleine_bekannte_und_dichte_hirne(): + heute = {"hirn": "Qwen3.6-35B-A3B", "coder": "Qwen3.8-27B"} + bekannt = {"qwen3.6-35b-a3b", "qwen3.8-27b"} + + def fund(repo, params, aktiv=None, kuratiert=False): + return {"repo": repo, "params_b": params, "caps": {"active_b": aktiv}, "curated": kuratiert} + + def grund(m, rolle): + return radar.entdeckung_ungeeignet(m, rolle, bekannt, heute) + + assert "Katalog" in grund(fund("unsloth/Qwen3-Coder-30B-A3B-Instruct-GGUF", 30, 3, kuratiert=True), "coder") + assert "auf der Box" in grund(fund("bartowski/Qwen_Qwen3.6-35B-A3B-GGUF", 35, 3), "hirn") + assert "zu klein" in grund(fund("lmstudio-community/Qwen2.5-Coder-14B-Instruct-GGUF", 14), "coder") + assert "dichte" in grund(fund("bartowski/Hermes-3-Llama-3.1-70B-GGUF", 70), "hirn") + assert "ältere Generation" in grund(fund("bartowski/Qwen_Qwen3.5-35B-A3B-GGUF", 35, 3), "hirn") + assert grund(fund("unsloth/Qwen-AgentWorld-35B-A3B-GGUF", 35, 3), "hirn") is None + + +BAUM_FLASH = [ + {"type": "directory", "path": "UD-IQ3_XXS"}, + {"path": "UD-IQ3_XXS/Qwen3.8-Flash-Next-UD-IQ3_XXS-00001-of-00003.gguf", "size": 10_000_000}, + {"path": "UD-IQ3_XXS/Qwen3.8-Flash-Next-UD-IQ3_XXS-00002-of-00003.gguf", "size": 49_570_000_000}, + {"path": "UD-IQ3_XXS/Qwen3.8-Flash-Next-UD-IQ3_XXS-00003-of-00003.gguf", "lfs": {"size": 32_380_000_000}}, + {"path": "UD-IQ4_XS/Qwen3.8-Flash-Next-UD-IQ4_XS-00001-of-00003.gguf", "size": 10_000_000}, + {"path": "MTP/mtp-Qwen3.8-Flash-Next-Q8_0.gguf", "size": 4_140_000_000}, + {"path": "mmproj-BF16.gguf", "size": 910_000_000}, + {"path": "mmproj-F16.gguf", "size": 900_000_000}, +] +KOPF_FLASH = {"general.architecture": "qwen4exp", "qwen4exp.block_count": 48, "qwen4exp.attention.head_count": 24, + "qwen4exp.attention.head_count_kv": 2, "qwen4exp.attention.key_length": 256, + "qwen4exp.attention.value_length": 256, "qwen4exp.full_attention_interval": 4} + + +def test_dateiauswahl_nimmt_alle_teile_des_quants_und_das_f16_mmproj(): + wahl = radar.waehle_dateien(BAUM_FLASH, "UD-IQ3_XXS") + assert [p.rsplit("-", 3)[-3] for p, _ in wahl["dateien"]] == ["00001", "00002", "00003"] + assert all(p.startswith("UD-IQ3_XXS/") for p, _ in wahl["dateien"]) + assert wahl["mmproj"] == ["mmproj-F16.gguf", 900_000_000] + assert radar.waehle_dateien(BAUM_FLASH, "Q4_K_M") is None + assert radar.waehle_dateien(BAUM_FLASH, "Q8_0") is None # der MTP-Kopf ist kein Modell + ornith = [{"path": "Ornith-1.5-35B-Q4_K_M.gguf", "size": 21_710_000_000}, + {"path": "Ornith-1.5-35B-Q8_0.gguf", "size": 37_800_000_000}, + {"path": "mmproj-Ornith-1.5-35B-BF16.gguf", "size": 900_000_000}] + wahl = radar.waehle_dateien(ornith, "Q4_K_M") + assert wahl["dateien"] == [["Ornith-1.5-35B-Q4_K_M.gguf", 21_710_000_000]] + assert wahl["mmproj"][0] == "mmproj-Ornith-1.5-35B-BF16.gguf" + + +def _gguf_kopf_bytes(werte: dict) -> bytes: + """Minimaler GGUF-Kopf wie von llama.cpp: Architektur-Schlüssel, danach der Tokenizer (abgeschnitten).""" + def s(text: str) -> bytes: + return struct.pack(" tuple[list, dict]: + """Bestandenen Kandidaten „o“ anlegen und llama-swap/Hirn-Wechsel durch Protokoll-Attrappen ersetzen.""" + modelle = zustand / "models" + modelle.mkdir() + monkeypatch.setattr(radar, "MODELS_DIR", modelle) + ordner = radar.RADAR_DIR / "o" + ordner.mkdir() + (ordner / "o-Q4_K_M.gguf").write_bytes(b"x") + (ordner / "mmproj-F16.gguf").write_bytes(b"x") + stand = radar._leer() + stand["kandidaten"]["o"] = _kandidat("o", rolle=rolle, status="bestanden", ordner=str(ordner)) + radar._speichere(stand) + aufrufe, cfg = [], {"models": {}} + + def eintragen(pfad, **kw): + aufrufe.append(("eintragen", pfad, kw["role"], kw["set_alias"])) + cfg["models"]["o"] = {"cmd": "vorlage"} + return "o" + + from services import agent + monkeypatch.setattr(radar, "_heutige_modelle", lambda: {rolle: alt}) + monkeypatch.setattr(radar.llamaswap, "register_model", eintragen) + monkeypatch.setattr(radar.llamaswap, "read_config", lambda: cfg) + monkeypatch.setattr(radar.llamaswap, "write_config", lambda c: aufrufe.append(("schreiben",))) + monkeypatch.setattr(radar.llamaswap, "set_role", lambda mid, r: aufrufe.append(("rolle", mid, r)) or True) + monkeypatch.setattr(radar.llamaswap, "add_role", lambda mid, r: aufrufe.append(("dazu", mid, r)) or True) + monkeypatch.setattr(radar, "_steward_neu_starten", lambda: aufrufe.append(("steward",)) or None) + monkeypatch.setattr(radar.llamaswap, "set_ttl", lambda mid, ttl: aufrufe.append(("ttl", mid, ttl)) or True) + monkeypatch.setattr(agent, "set_agent_brain", lambda mid: aufrufe.append(("hirn", mid)) or {"ok": True}) + monkeypatch.setattr(radar, "STEWARD_WARMSET", zustand / "warmset.conf") + return aufrufe, cfg + + +def test_uebernehmen_hirn_nutzt_den_hirn_wechsel_und_nimmt_fast_mit(zustand, monkeypatch): + aufrufe, cfg = _uebernahme_vorbereiten(zustand, monkeypatch, "hirn", + {"name": "Qwen3.6-35B-A3B", "aliases": ["hermes", "fast"], "ttl": 0}) + (zustand / "warmset.conf").write_text('[Service]\nEnvironment="MC_WARMSET=Qwen3-Embedding-0.6B Qwen3.6-35B-A3B"\n', + encoding="utf-8") + antwort = radar.uebernehmen("o") + assert antwort["ok"] and antwort["modell_id"] == "o" + assert [a[0] for a in aufrufe] == ["eintragen", "schreiben", "hirn", "dazu", "steward"] + assert aufrufe[0][2:] == ("hermes", False) and aufrufe[3] == ("dazu", "o", "fast") + befehl = str(cfg["models"]["o"]["cmd"]) + assert "--parallel 2" in befehl and "-ctk q8_0" in befehl and "--mmproj" in befehl + assert (zustand / "models" / "o-GGUF" / "o-Q4_K_M.gguf").exists() and not (radar.RADAR_DIR / "o").exists() + k = radar._lade()["kandidaten"]["o"] + assert k["status"] == "uebernommen" and "vorher Qwen3.6-35B-A3B" in k["begruendung"] + # Der Steward hält danach das neue Hirn warm, nicht mehr das alte — ohne Handgriff. + assert 'MC_WARMSET=Qwen3-Embedding-0.6B o"' in (zustand / "warmset.conf").read_text(encoding="utf-8") + assert antwort["text"] is None and "Noch zu tun" not in k["begruendung"] + + +def test_uebernehmen_coder_nimmt_heavy_mit(zustand, monkeypatch): + aufrufe, cfg = _uebernahme_vorbereiten(zustand, monkeypatch, "coder", + {"name": "Qwen3.8-27B", "aliases": ["coder", "heavy"], "ttl": 5400}) + antwort = radar.uebernehmen("o") + assert antwort["ok"] and antwort["text"] is None + assert aufrufe[2:] == [("rolle", "o", "coder"), ("dazu", "o", "heavy"), ("ttl", "o", 5400)] + assert "--parallel 1" in str(cfg["models"]["o"]["cmd"]) + + +def test_betriebsbefehl_uebernimmt_die_getesteten_flags(): + k = _kandidat("f", rolle="coder", ctx=65536, draft={"typ": "draft-mtp", "n_max": 2, "datei": None}, flags=["-ub", "512"]) + befehl = radar.betriebs_befehl("coder", {"gguf": "/srv/models/F-GGUF/f.gguf", "mmproj": "/srv/models/F-GGUF/mm.gguf", + "draft": None}, k) + assert "-c 65536" in befehl and "--parallel 1" in befehl and "-ctk q8_0 -ctv q8_0" in befehl + assert "--mmproj /srv/models/F-GGUF/mm.gguf" in befehl and "--load-mode none" in befehl + assert befehl.endswith("--spec-type draft-mtp --spec-draft-n-max 2 -ub 512") + assert "--parallel 2" in radar.betriebs_befehl("hirn", {"gguf": "x.gguf", "mmproj": None, "draft": None}, + _kandidat("h")) + + +# --- Prüfstand: Urteil, Programmieraufgaben, Bild ---------------------------------------------------- + +@pytest.fixture(scope="module") +def ps(): + return radar._pruefstand() + + +BILD_GUT = {"direkt": 1.0, "gefunden": ["Wort ZEBRA", "Zahl 4711"], "agentisch": True} + + +def _werte(rolle: str, decode: float = 100.0, prefill: float = 13.0, werkzeuge: int = 6, code: int = 8, + bild: dict | None = None, deutsch: bool = True) -> dict: + werte = {"rolle": rolle, "tiefe": {"tg_tps": decode, "pp_s": prefill}, "werkzeuge": {"ok": werkzeuge, "von": 6}, + "bild": bild} + if rolle == "hirn": + werte.update(deutsch={"ok": deutsch}, json={"ok": True}) + else: + werte["code"] = {"ok": code, "von": 10} + return werte + + +def test_urteil_hirn_mit_bildern_besteht_ohne_verschlechterung(ps): + u = ps.urteil("hirn", _werte("hirn", decode=95.0, bild=BILD_GUT), _werte("hirn", decode=100.8)) + assert u["ergebnis"] == "bestanden" + assert u["zusammenfassung"] == "Bestanden: versteht Bilder (heute nicht)." + assert u["vergleich"]["Decode bei 13k"]["urteil"] == "gleich" # −6 % liegt in der Toleranz + assert list(u["vergleich"]) == ["Decode bei 13k", "Prefill bei 13k", "Werkzeug-Aufrufe", "Deutsch", "JSON", + "Bilder"] + + +def test_urteil_hirn_faellt_bei_schwaeche_oder_ohne_vorteil_durch(ps): + basis = _werte("hirn", decode=100.8) + u = ps.urteil("hirn", _werte("hirn", werkzeuge=5, bild=BILD_GUT), basis) + assert u["ergebnis"] == "durchgefallen" and "Werkzeuge 5/6 (heute 6/6)" in u["zusammenfassung"] + u = ps.urteil("hirn", _werte("hirn", decode=70.0, bild=BILD_GUT), basis) + assert u["ergebnis"] == "durchgefallen" and "Decode bei 13k 70 statt 100,8 t/s" in u["zusammenfassung"] + u = ps.urteil("hirn", _werte("hirn", bild=BILD_GUT), _werte("hirn", bild=BILD_GUT)) + assert u["zusammenfassung"] == "Durchgefallen: kein Vorteil gegenüber dem heutigen Modell." + u = ps.urteil("hirn", _werte("hirn", decode=130.0), basis) # schneller, aber blind + assert u["ergebnis"] == "durchgefallen" and "versteht keine Bilder" in u["zusammenfassung"] + + +def test_urteil_coder_zaehlt_programmieraufgaben_und_bilder(ps): + basis = _werte("coder", decode=30.4, prefill=41.2, code=8, bild=BILD_GUT) + u = ps.urteil("coder", _werte("coder", decode=45.0, prefill=12.0, code=9, bild=BILD_GUT), basis) + assert u["ergebnis"] == "bestanden" and "Programmieraufgaben 9/10 statt 8/10" in u["zusammenfassung"] + u = ps.urteil("coder", _werte("coder", decode=45.0, prefill=12.0, code=7, bild=BILD_GUT), basis) + assert u["ergebnis"] == "durchgefallen" and "Programmieraufgaben 7/10 (heute 8/10)" in u["zusammenfassung"] + u = ps.urteil("coder", _werte("coder", code=9), basis) # der heutige Coder kann Bilder + assert u["ergebnis"] == "durchgefallen" and "versteht keine Bilder" in u["zusammenfassung"] + + +REFERENZ = { + "palindrom": "def ist_palindrom(text):\n z = [c.lower() for c in text if c.isalnum()]\n return z == z[::-1]\n", + "roemisch": ( + "def roemisch(zahl):\n" + " if not isinstance(zahl, int) or not 1 <= zahl <= 3999:\n" + " raise ValueError(zahl)\n" + " out = ''\n" + " for wert, zeichen in ((1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'), (100, 'C'), (90, 'XC'),\n" + " (50, 'L'), (40, 'XL'), (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')):\n" + " while zahl >= wert:\n" + " out += zeichen\n" + " zahl -= wert\n" + " return out\n"), + "intervalle": ( + "def zusammenfassen(intervalle):\n" + " out = []\n" + " for a, b in sorted(intervalle):\n" + " if out and a <= out[-1][1]:\n" + " out[-1][1] = max(out[-1][1], b)\n" + " else:\n" + " out.append([a, b])\n" + " return out\n"), + "flach": ( + "def flach(liste):\n" + " out = []\n" + " for x in liste:\n" + " out.extend(flach(x) if isinstance(x, list) else [x])\n" + " return out\n"), + "iban": ( + "def iban_gueltig(iban):\n" + " s = iban.replace(' ', '').upper()\n" + " if not 15 <= len(s) <= 34 or not s.isalnum() or not s.isascii():\n" + " return False\n" + " return int(''.join(str(int(c, 36)) for c in s[4:] + s[:4])) % 97 == 1\n"), + "lru": ( + "from collections import OrderedDict\n" + "class LRUCache:\n" + " def __init__(self, kapazitaet):\n" + " self.k, self.d = kapazitaet, OrderedDict()\n" + " def get(self, schluessel):\n" + " if schluessel not in self.d:\n" + " return None\n" + " self.d.move_to_end(schluessel)\n" + " return self.d[schluessel]\n" + " def put(self, schluessel, wert):\n" + " self.d[schluessel] = wert\n" + " self.d.move_to_end(schluessel)\n" + " if len(self.d) > self.k:\n" + " self.d.popitem(last=False)\n"), + "klammern": ( + "def klammern_ok(text):\n" + " paare, stapel = {')': '(', ']': '[', '}': '{'}, []\n" + " for c in text:\n" + " if c in '([{':\n" + " stapel.append(c)\n" + " elif c in paare and (not stapel or stapel.pop() != paare[c]):\n" + " return False\n" + " return not stapel\n"), + "wege": ( + "import heapq\n" + "def kuerzeste_wege(graph, start):\n" + " dist, heap = {start: 0}, [(0, start)]\n" + " while heap:\n" + " d, u = heapq.heappop(heap)\n" + " if d > dist[u]:\n" + " continue\n" + " for v, w in graph.get(u, {}).items():\n" + " if v not in dist or d + w < dist[v]:\n" + " dist[v] = d + w\n" + " heapq.heappush(heap, (d + w, v))\n" + " return dist\n"), + "median": ( + "def median(zahlen):\n" + " if not zahlen:\n" + " raise ValueError('leer')\n" + " s, n = sorted(zahlen), len(zahlen)\n" + " return s[n // 2] if n % 2 else (s[n // 2 - 1] + s[n // 2]) / 2\n"), + "csv": ( + "def spaltensumme(csv_text, spalte):\n" + " zeilen = [z for z in csv_text.splitlines() if z.strip()]\n" + " kopf = zeilen[0].split(';')\n" + " if spalte not in kopf:\n" + " raise KeyError(spalte)\n" + " i, summe = kopf.index(spalte), 0.0\n" + " for z in zeilen[1:]:\n" + " zellen = z.split(';')\n" + " wert = zellen[i].strip() if i < len(zellen) else ''\n" + " if wert:\n" + " summe += float(wert.replace('.', '').replace(',', '.'))\n" + " return summe\n"), +} + + +def test_referenzloesungen_bestehen_alle_programmieraufgaben(ps): + assert {a["id"] for a in ps.AUFGABEN_CODE} == set(REFERENZ) + for aufgabe in ps.AUFGABEN_CODE: + ok, grund = ps.fuehre_aufgabe_aus(REFERENZ[aufgabe["id"]], aufgabe["tests"]) + assert ok, f"{aufgabe['id']}: {grund}" + + +def test_falsche_verbotene_und_endlose_loesungen_fallen_durch(ps): + tests = next(a["tests"] for a in ps.AUFGABEN_CODE if a["id"] == "median") + ok, _ = ps.fuehre_aufgabe_aus("def median(z):\n z.sort()\n return z[len(z) // 2]\n", tests) + assert not ok + ok, grund = ps.fuehre_aufgabe_aus("import os\ndef median(z):\n return os.getpid()\n", tests) + assert not ok and grund.startswith("unerlaubter Aufruf") + ok, grund = ps.fuehre_aufgabe_aus("def median(z):\n while True:\n pass\n", tests, zeitlimit=2) + assert not ok and "Zeitlimit" in grund + + +def test_code_aus_antwort_nimmt_den_loesungsblock(ps): + antwort = "kurz nachdenkenHier:\n```python\ndef f():\n return 1\n```\nAufruf:\n```python\nf()\n```" + assert ps.code_aus_antwort(antwort) == "def f():\n return 1\n" + assert ps.code_aus_antwort("def g(): return 2") == "def g(): return 2" + + +def test_bild_ist_ein_gueltiges_png_mit_rotem_kreis(ps): + png = ps.bild_png() + assert png.startswith(b"\x89PNG\r\n\x1a\n") + breite, hoehe = struct.unpack(">II", png[16:24]) + assert (breite, hoehe) == (448, 300) + laenge = struct.unpack(">I", png[33:37])[0] + roh = zlib.decompress(png[41:41 + laenge]) + zeile = 1 + breite * 3 + assert roh[95 * zeile + 1 + 80 * 3:95 * zeile + 1 + 81 * 3] == b"\xdc\x14\x14" # Mitte des Kreises + beschreibung = "Ein roter Kreis, ein blaues Quadrat, ein grünes Dreieck und darunter der Text ZEBRA 4711." + assert ps.bild_merkmale(beschreibung) == list(ps.BILD_MERKMALE) + assert ps.bild_data_url().startswith("data:image/png;base64,") + + +def test_werkzeug_treffer_liest_json_argumente(ps): + aufruf = [{"function": {"name": "send_telegram", "arguments": json.dumps({"text": "Prüfstand läuft."})}}] + assert ps.trifft(aufruf, [("send_telegram", r"pr(ü|ue)fstand")]) + assert not ps.trifft(aufruf, [("terminal", r".*")]) + assert len(ps.WERKZEUGE_HIRN) >= 90 # Lucy hat ~100 Werkzeuge + assert ps.tiefen_prompt("ab12").startswith("Messlauf ab12.") + + +def test_add_role_behaelt_die_uebrigen_aliase(monkeypatch): + """add_role ohne Attrappe: coder bleibt, heavy wandert vom alten Coder herüber.""" + from services import llamaswap + cfg = {"models": {"alt": {"cmd": "x", "aliases": ["coder", "heavy"]}, "neu": {"cmd": "y", "aliases": ["coder"]}}} + monkeypatch.setattr(llamaswap, "read_config", lambda: cfg) + monkeypatch.setattr(llamaswap, "write_config", lambda c: None) + assert llamaswap.add_role("neu", "heavy") is True + assert cfg["models"]["neu"]["aliases"] == ["coder", "heavy"] + assert cfg["models"]["alt"]["aliases"] == ["coder"] + assert llamaswap.add_role("gibt-es-nicht", "heavy") is False diff --git a/deploy/bench/pruefstand-hirn.py b/deploy/bench/pruefstand-hirn.py index 71f8812..78e335d 100644 --- a/deploy/bench/pruefstand-hirn.py +++ b/deploy/bench/pruefstand-hirn.py @@ -1,22 +1,23 @@ #!/usr/bin/env python3 -"""Prüfstand für Hirn-Kandidaten (17.09.2026). Kandidat läuft standalone auf :5899 — der Live-Stack bleibt unberührt —, -Baselines laufen über llama-swap :8080. Je Betriebsart: Kurz- und 13k-Tiefenmessung (Prefill/Decode/Draft-Akzeptanz), -Tool-Calling direkt (3 Aufgaben, Denken an), Deutsch- und JSON-Probe (Denken aus) und der Tool-Smoke durch den ECHTEN -Hermes-Agenten (`hermes chat --provider pruefstand -m kandidat`; Provider `pruefstand` -> http://127.0.0.1:5899/v1 muss in -`providers:` der Hermes-Config stehen). Aufruf auf der Box: python3 pruefstand-hirn.py [baseline] [nemo] [u38] [u36] -(Kandidaten-Pfade unten anpassen). Ergebnis: ~/pruefstand-.json + Log auf stdout. Lehren: Denk-Modelle brauchen -für Tool-Aufrufe >=1500 Tokens Budget, /no_think wirkt bei Qwen 3.6 nicht (chat_template_kwargs.enable_thinking=false); -der erste Lauf nach dem Laden ist ~40 % langsamer (Warmlauf verwerfen).""" +"""Prüfstand für Hirn-Kandidaten (17.09.2026), seit 09/2026 eine dünne Hülle um pruefstand.py. + +Die Messungen selbst (Tempo, 13k-Tiefe, Werkzeuge, Deutsch/JSON, Bild-Probe, Server auf :5899) liegen +im Modul — dasselbe nutzt das Modell-Radar nachts. Dieses Skript bleibt der Handbetrieb: Kandidaten +mit festen Pfaden gegen die Live-Modelle (llama-swap :8080) messen, optional mit dem Tool-Smoke durch +den ECHTEN Hermes-Agenten (`hermes chat --provider pruefstand -m kandidat`; der Provider `pruefstand` +-> http://127.0.0.1:5899/v1 muss in `providers:` der Hermes-Config stehen). + +Aufruf auf der Box: python3 pruefstand-hirn.py [baseline] [nemo] [u38] [u36] (Pfade unten anpassen). +Ergebnis: ~/pruefstand-.json + Log auf stdout. +""" + import json import os -import re -import subprocess import sys import time -import urllib.request -BIN = "/opt/llamacpp-vulkan/llama-server"; PORT = 5899 -BASE = ["-c", "65536", "-ngl", "999", "-fa", "on", "--load-mode", "none", "--jinja", "--parallel", "1", "-ctk", "q8_0", "-ctv", "q8_0"] +import pruefstand as ps # liegt daneben; beim Skriptaufruf steht dieser Ordner auf sys.path + M = "/srv/models" DFLASH_36 = f"{M}/Qwen3.6-35B-A3B-DFlash-GGUF/giocom-Qwen3.6-35B-A3B-DFlash-Q8_0.gguf" DFLASH2_38 = f"{M}/Qwen3.8-27B-DFlash2-GGUF/Qwen3.8-27B-DFlash2-Q4_K_M.gguf" @@ -24,170 +25,65 @@ NEMO = f"{M}/Nemotron-3.5-Lightning-30B-A3B-GGUF/NVIDIA-Nemotron-3.5-Lightning-3 NEMO_MTP = f"{M}/Nemotron-3.5-Lightning-30B-A3B-GGUF/mtp-NVIDIA-Nemotron-3.5-Lightning-30B-A3B-Q8_0.gguf" U38 = f"{M}/Qwen3.8-27B-Uncensored-GGUF/Qwen3.8-27B-Uncensored-Q4_K_M.gguf" U36 = f"{M}/Qwen3.6-35B-A3B-Uncensored-GGUF/Qwen3.6-35B-A3B-Uncensored-HauhauCS-Aggressive-Q4_K_M.gguf" -HERMES = os.path.expanduser("~/.local/bin/hermes") -OUT = os.path.expanduser("~/pruefstand-2026-09-17.json") -RESULTS = [] +OUT = os.path.expanduser(f"~/pruefstand-{time.strftime('%Y-%m-%d')}.json") +RESULTS: list[dict] = [] -def log(*a): - print(*a, flush=True) +def save() -> None: + with open(OUT, "w", encoding="utf-8") as f: + json.dump(RESULTS, f, indent=1, ensure_ascii=False) -def post(url, payload, timeout=900): - r = urllib.request.Request(url, data=json.dumps(payload).encode(), headers={"Content-Type": "application/json"}) - return json.loads(urllib.request.urlopen(r, timeout=timeout).read()) - - -def chat(base, model, messages, max_tokens=200, tools=None, think=True): - p = {"model": model, "temperature": 0, "max_tokens": max_tokens, "messages": messages} - if not think: - p["chat_template_kwargs"] = {"enable_thinking": False} - if tools: - p["tools"] = tools - p["tool_choice"] = "auto" - t0 = time.time() - j = post(f"{base}/v1/chat/completions", p) - j["_wall"] = time.time() - t0 - return j - - -PARA = ("Notiz {i}: Die Box läuft mit llama-swap auf Port 8080, das Hirn ist ein Mixture-of-Experts-Modell mit drei Milliarden " - "aktiven Parametern, der Coder ein dichtes 27B-Modell mit Draft-Beschleunigung. Lucy hört über Parakeet, spricht über " - "pocket-tts und meldet sich per Telegram. Der Sonntags-Job aktualisiert Router, Engine und Agent und rollt bei Rot zurück. ") -DEPTH_PROMPT = "".join(PARA.format(i=i) for i in range(130)) + \ - "\n\nFrage: Fasse in drei Sätzen zusammen, was in den Notizen steht, und nenne die Nummer der letzten Notiz." - -TOOLS = [ - {"type": "function", "function": {"name": "terminal", "description": "Führt einen Shell-Befehl auf der Box aus und gibt stdout zurück.", - "parameters": {"type": "object", "properties": {"command": {"type": "string"}}, "required": ["command"]}}}, - {"type": "function", "function": {"name": "read_file", "description": "Liest eine Datei und gibt den Inhalt zurück.", - "parameters": {"type": "object", "properties": {"path": {"type": "string"}}, "required": ["path"]}}}, - {"type": "function", "function": {"name": "send_telegram", "description": "Schickt dem Nutzer eine Telegram-Nachricht.", - "parameters": {"type": "object", "properties": {"text": {"type": "string"}}, "required": ["text"]}}}, -] -TOOL_TASKS = [ - ("Wie viel freier Speicher ist auf /srv/models? Nutze das passende Werkzeug.", "terminal", r"df"), - ("Lies die Datei /etc/hostname und sag mir, wie die Box heißt.", "read_file", r"/etc/hostname"), - ("Schick mir per Telegram die Nachricht: Prüfstand läuft.", "send_telegram", r"Pr.fstand"), -] - - -def timings(j): - t = j.get("timings") or {} - acc = (t.get("draft_n_accepted", 0) / t["draft_n"]) if t.get("draft_n") else None - return {"pp_n": t.get("prompt_n"), "pp_s": round((t.get("prompt_ms") or 0) / 1000, 1), "pp_tps": round(t.get("prompt_per_second") or 0), - "tg_n": t.get("predicted_n"), "tg_tps": round(t.get("predicted_per_second") or 0, 1), "acc": None if acc is None else round(acc, 2)} - - -def save(): - json.dump(RESULTS, open(OUT, "w"), indent=1, ensure_ascii=False) - - -def probes(base, model, label, with_hermes, hermes_args): - res = {"label": label} - chat(base, model, [{"role": "user", "content": "Sag kurz hallo."}], 32) # Warmlauf - j = chat(base, model, [{"role": "user", "content": "Erkläre in fünf Sätzen, was ein Mixture-of-Experts-Modell ist."}], 200) - res["kurz"] = timings(j); log(f" kurz : {res['kurz']}") - j = chat(base, model, [{"role": "user", "content": DEPTH_PROMPT}], 160) - res["tiefe"] = timings(j); log(f" 13k : {res['tiefe']}") - tc = [] - for q, want_fn, want_arg in TOOL_TASKS: - try: - j = chat(base, model, [{"role": "user", "content": q}], 1500, TOOLS) - msg = j["choices"][0]["message"] - calls = msg.get("tool_calls") or [] - ok = any(c["function"]["name"] == want_fn and re.search(want_arg, c["function"].get("arguments", "")) for c in calls) - raw = "" if calls else (msg.get("content") or "")[:120].replace("\n", " ") - tc.append({"task": want_fn, "ok": ok, "calls": [(c["function"]["name"], c["function"].get("arguments", "")[:80]) for c in calls], "raw": raw}) - except Exception as e: - tc.append({"task": want_fn, "ok": False, "error": str(e)[:120]}) - res["tools_direkt"] = tc - log(f" tools: {sum(1 for t in tc if t['ok'])}/3 " + "; ".join(f"{t['task']}={'✓' if t['ok'] else '✗'}" for t in tc)) - for t in tc: - if not t["ok"]: - log(f" {t['task']}: calls={t.get('calls')} raw={t.get('raw', '')!r} {t.get('error', '')}") - j = chat(base, model, [{"role": "user", "content": "Antworte auf Deutsch in genau drei Sätzen: Warum braucht ein Heimserver ein Backup?"}], 300, think=False) - m = j["choices"][0]["message"] - txt = (m.get("content") or "").strip() or ("[nur reasoning] " + (m.get("reasoning_content") or "")[:200]) - res["deutsch"] = txt[:400]; log(f" de : {txt[:160]!r}") - j = chat(base, model, [{"role": "user", "content": 'Antworte NUR mit JSON, ohne Erklärung: {"modell": "", "ok": true}'}], 120, think=False) - m = j["choices"][0]["message"] - txt = (m.get("content") or "").strip() - try: - json.loads(txt[txt.find("{"): txt.rfind("}") + 1]); js = True - except Exception: - js = False - res["json_ok"] = js; log(f" json : {'✓' if js else '✗'} {txt[:80]!r}") +def probes(basis: str, modell: str, label: str, with_hermes: bool, hermes_args: list[str], bild: bool = False) -> None: + werte = {"label": label, **ps.pruefe("hirn", basis, modell, bild=bild)} if with_hermes: - hz = [] - for q, want in [("Führe im Terminal exakt den Befehl echo pruefstand-ok aus und gib mir nur dessen Ausgabe zurück.", "pruefstand-ok"), - ("Welche Verzeichnisse liegen direkt unter /srv/models? Nenne mir drei davon.", "GGUF")]: - t0 = time.time() - try: - p = subprocess.run([HERMES, "chat", *hermes_args, "-Q", "--oneshot", "--max-turns", "6", "-q", q], - capture_output=True, text=True, timeout=900) - out = (p.stdout + p.stderr)[-600:] - except subprocess.TimeoutExpired: - out = "TIMEOUT" - ok = want.lower() in out.lower() - hz.append({"ok": ok, "s": round(time.time() - t0), "tail": out[-160:].replace("\n", " ")}) - log(f" hermes: {'✓' if ok else '✗'} {round(time.time() - t0)} s {out[-120:].replace(chr(10), ' ')!r}") - res["hermes"] = hz - RESULTS.append(res); save() + werte["hermes"] = ps.hermes_smoke(hermes_args) + RESULTS.append(werte) + save() -def start_server(model, extra): - cmd = [BIN, "-m", model, "--host", "127.0.0.1", "--port", str(PORT), *BASE, *extra] - logf = open("/tmp/pruefstand-server.log", "w") - p = subprocess.Popen(cmd, stdout=logf, stderr=subprocess.STDOUT) - t0 = time.time() - for _ in range(150): - time.sleep(2) - if p.poll() is not None: - tail = open("/tmp/pruefstand-server.log", errors="replace").read()[-500:] - return None, f"LOAD-CRASH rc={p.returncode}: {tail.strip()[-300:]}" - try: - if b"ok" in urllib.request.urlopen(f"http://127.0.0.1:{PORT}/health", timeout=2).read(): - return p, round(time.time() - t0) - except Exception: - pass - p.kill() - return None, "TIMEOUT beim Laden" - - -def candidate(label, model, extra, with_hermes): - log(f"\n=== {label}"); log(f" {os.path.basename(model)} {' '.join(extra)}") - if not os.path.exists(model): - log(" FEHLT: Datei nicht da"); RESULTS.append({"label": label, "fehler": "Datei fehlt"}); save(); return - p, info = start_server(model, extra) - if p is None: - log(f" {info}"); RESULTS.append({"label": label, "fehler": info}); save(); return - log(f" geladen in {info} s") +def candidate(label: str, model: str, extra: list[str], with_hermes: bool, mmproj: str | None = None) -> None: + ps.log(f"\n=== {label}") + ps.log(f" {os.path.basename(model)} {' '.join(extra)}") try: - probes(f"http://127.0.0.1:{PORT}", "kandidat", label, with_hermes, ["--provider", "pruefstand", "-m", "kandidat"]) + server = ps.starte_server(model, mmproj=mmproj, flags=extra, ctx=ps.CTX_STANDARD) + except ps.ServerFehler as e: + ps.log(f" {e}") + RESULTS.append({"label": label, "fehler": str(e)[:300]}) + save() + return + try: + probes(ps.KANDIDAT_URL, "kandidat", label, with_hermes, ["--provider", "pruefstand", "-m", "kandidat"], + bild=bool(mmproj)) except Exception as e: - log(f" FEHLER in Proben: {e}"); RESULTS.append({"label": label, "fehler": str(e)[:200]}); save() + ps.log(f" FEHLER in Proben: {e}") + RESULTS.append({"label": label, "fehler": str(e)[:200]}) + save() finally: - p.terminate() - try: - p.wait(timeout=60) - except Exception: - p.kill() + ps.stoppe_server(server) time.sleep(3) -which = set(sys.argv[1:]) or {"baseline", "nemo", "u38", "u36"} -if "baseline" in which: - log("\n=== BASELINE fast (live, llama-swap)"); probes("http://127.0.0.1:8080", "fast", "fast-live", True, ["-m", "fast"]) - log("\n=== BASELINE coder = Qwen3.8-27B+DFlash2 (live)"); probes("http://127.0.0.1:8080", "coder", "coder-live", True, ["-m", "coder"]) -if "nemo" in which: - candidate("Nemotron 3.5 Lightning · MTP n3", NEMO, ["--spec-type", "draft-mtp", "--spec-draft-model", NEMO_MTP, "--spec-draft-n-max", "3"], True) - candidate("Nemotron 3.5 Lightning · ohne Spec", NEMO, [], False) -if "u38" in which: - candidate("Qwen3.8-27B-Uncensored · MTP fused n2", U38, ["--spec-type", "draft-mtp", "--spec-draft-n-max", "2"], True) - candidate("Qwen3.8-27B-Uncensored · DFlash2 (z-lab) n3", U38, ["--spec-type", "draft-dflash", "--spec-draft-model", DFLASH2_38, "--spec-draft-n-max", "3"], False) - candidate("Qwen3.8-27B-Uncensored · ohne Spec", U38, [], False) -if "u36" in which: - candidate("Qwen3.6-35B-A3B-Uncensored-Aggressive · DFlash (giocom)", U36, ["--spec-type", "draft-dflash", "--spec-draft-model", DFLASH_36], True) - candidate("Qwen3.6-35B-A3B-Uncensored-Aggressive · ohne Spec", U36, [], False) -log("\nPRUEFSTAND_DONE") +def main() -> None: + which = set(sys.argv[1:]) or {"baseline", "nemo", "u38", "u36"} + if "baseline" in which: + ps.log("\n=== BASELINE fast (live, llama-swap)") + probes(ps.SWAP_URL, "fast", "fast-live", True, ["-m", "fast"]) + ps.log("\n=== BASELINE coder (live, llama-swap)") + probes(ps.SWAP_URL, "coder", "coder-live", True, ["-m", "coder"], bild=True) + if "nemo" in which: + candidate("Nemotron 3.5 Lightning · MTP n3", NEMO, + ps.draft_flags(NEMO_MTP, "draft-mtp", 3), True) + candidate("Nemotron 3.5 Lightning · ohne Spec", NEMO, [], False) + if "u38" in which: + candidate("Qwen3.8-27B · MTP fused n2", U38, ps.draft_flags(None, "draft-mtp", 2), True) + candidate("Qwen3.8-27B · DFlash2 (z-lab) n3", U38, ps.draft_flags(DFLASH2_38, "draft-dflash", 3), False) + candidate("Qwen3.8-27B · ohne Spec", U38, [], False) + if "u36" in which: + candidate("Qwen3.6-35B-A3B · DFlash (giocom)", U36, ps.draft_flags(DFLASH_36, "draft-dflash"), True) + candidate("Qwen3.6-35B-A3B · ohne Spec", U36, [], False) + ps.log("\nPRUEFSTAND_DONE") + + +if __name__ == "__main__": + main() diff --git a/deploy/bench/pruefstand.py b/deploy/bench/pruefstand.py new file mode 100644 index 0000000..9c2db0f --- /dev/null +++ b/deploy/bench/pruefstand.py @@ -0,0 +1,1106 @@ +#!/usr/bin/env python3 +""" +Prüfstand als Modul (Modell-Radar, 09/2026) — herausgelöst aus pruefstand-hirn.py (17.09.). + +Warum: Der Prüfstand vom 17.09. lief von Hand, mit festen Pfaden und nur für das Hirn. Das +Modell-Radar (backend/services/radar.py) misst Kandidaten nachts selbst — für beide Rollen, +gegen das heutige Modell der Rolle und mit einem Urteil, das ohne Menschen trägt. Deshalb +nimmt hier jede Messung einen Kandidaten-Pfad (GGUF, optional mmproj und Draft), und jede +Anfrage kennt eine Frist (das Nachtfenster endet hart um 02:30). + + • Server Kandidat standalone auf 127.0.0.1:5899 (llama-server, Flags wie am 17.09.); + der Live-Stack bleibt unberührt. + • hirn Tempo kurz + 13k-Tiefe (Prefill, Decode, Draft-Akzeptanz), Werkzeug-Aufrufe + zwischen ~100 Werkzeugen mit ~12k Kontext, Deutsch- und JSON-Probe. + • coder Tempo, Werkzeug-Aufrufe eines Coding-Agenten, 10 kleine Programmieraufgaben, + deren Lösung mit Unit-Tests in einem Temp-Ordner mit Zeitlimit läuft. + • Bild Nur mit mmproj: ein im Code gezeichnetes PNG (Formen, Farben, Text) als + image_url — einmal direkt, einmal mitten in einer Werkzeug-Aufgabe. + • Baseline Das heutige Modell der Rolle über llama-swap (:8080). Das Ergebnis wird + gecacht und höchstens monatlich neu gemessen. + • Urteil bestanden = keine Verschlechterung bei den Pflichtwerten UND mindestens ein + echter Vorteil (siehe urteil()). + +Lehren vom 17.09. (gelten weiter): Denk-Modelle brauchen für Werkzeug-Aufrufe >= 1500 Tokens +Budget; /no_think wirkt bei Qwen 3.6 nicht (chat_template_kwargs.enable_thinking=false); der +erste Lauf nach dem Laden ist ~40 % langsamer (Warmlauf verwerfen). Neu: Das warme Live-Hirn +hatte den 13k-Text im Prompt-Cache (Prefill 0,1 s statt ~13 s) — jede Tiefenmessung beginnt +deshalb mit einer Zufallsmarke. + +Nur Standardbibliothek: läuft mit dem System-Python der Box genauso wie im MC2-venv. +""" + +import atexit +import base64 +import json +import os +import re +import secrets +import signal +import socket +import struct +import subprocess +import sys +import tempfile +import textwrap +import time +import urllib.error +import urllib.request +import zlib +from pathlib import Path + +# --- Grundeinstellungen --------------------------------------------------------------- + +BIN = os.environ.get("MC_PRUEFSTAND_BIN", "/opt/llamacpp-vulkan/llama-server") +LIB_DIR = os.environ.get("MC_PRUEFSTAND_LIB", os.path.dirname(BIN)) +PORT = int(os.environ.get("MC_PRUEFSTAND_PORT", "5899")) +KANDIDAT_URL = f"http://127.0.0.1:{PORT}" +SWAP_URL = os.environ.get("MC_LLAMA_SWAP_URL", "http://127.0.0.1:8080").rstrip("/") +SERVER_LOG = os.path.join(tempfile.gettempdir(), "pruefstand-server.log") +HERMES = os.path.expanduser("~/.local/bin/hermes") + +CTX_STANDARD = 65536 +# Flags wie am 17.09. (der Kontext kommt je Kandidat dazu): voller GPU-Offload, Flash-Attention, +# kein mmap (--load-mode none, das alte --no-mmap gibt es seit b10936 nicht mehr), ein Slot, +# KV-Cache q8_0 wie im Betrieb. +BASIS_FLAGS = ["-ngl", "999", "-fa", "on", "--load-mode", "none", "--jinja", "--parallel", "1", + "-ctk", "q8_0", "-ctv", "q8_0"] +LADEZEIT_MAX_S = int(os.environ.get("MC_PRUEFSTAND_LADEZEIT", "600")) +ANFRAGE_MAX_S = 900 +WERKZEUG_TOKENS = 1500 # Denk-Modelle brauchen so viel Luft vor dem Werkzeug-Aufruf +CODE_TOKENS = 2500 +CODE_ZEITLIMIT_S = 10 + +# Baseline = das heutige Modell der Rolle, angesprochen über seinen llama-swap-Alias. +ALIAS = {"hirn": "hermes", "coder": "coder"} + +# Urteil: Faktor Kandidat/Baseline. *_min = Pflicht (darunter durchgefallen), *_plus = Vorteil. +# Beim Hirn zählt Tempo mehr (Lucy antwortet live), beim Coder die Code-Qualität. +REGELN = { + "hirn": {"decode_min": 0.85, "decode_plus": 1.10, "prefill_min": 0.80, "prefill_plus": 1.10}, + "coder": {"decode_min": 0.80, "decode_plus": 1.15, "prefill_min": 0.67, "prefill_plus": 1.25}, +} +WERKZEUG_BODEN = 0.5 # so viele Werkzeug-Aufgaben muss jeder schaffen, auch wenn heute alle scheitern +BILD_MIN = 0.75 # Anteil erkannter Bild-Merkmale +# Beide Rollen sollen Bilder verstehen (User-Entscheid 23.09.) — wer es nicht kann, fällt durch. +BILD_PFLICHT = os.environ.get("MC_RADAR_BILD_PFLICHT", "1") != "0" + + +class Zeitende(Exception): + """Die Frist (Ende des Nachtfensters) ist erreicht — Messung abbrechen.""" + + +class ServerFehler(Exception): + """Der Kandidat startet nicht oder stürzt ab (Laden, Port belegt, Absturz im Test).""" + + +def log(*teile) -> None: + """Protokollzeile. Eine Konsole ohne UTF-8 darf nie eine Messung abbrechen.""" + try: + print(*teile, flush=True) + except UnicodeEncodeError: + print(*(str(t).encode("ascii", "replace").decode() for t in teile), flush=True) + + +# --- HTTP --------------------------------------------------------------------------- + +def _restzeit(frist: float | None) -> float | None: + if frist is None: + return None + rest = frist - time.time() + if rest <= 5: + raise Zeitende("Frist erreicht.") + return rest + + +def post(url: str, nutzlast: dict, timeout: float = ANFRAGE_MAX_S, frist: float | None = None) -> dict: + """JSON-POST; der Timeout endet spätestens mit der Frist.""" + rest = _restzeit(frist) + if rest is not None: + timeout = min(timeout, rest) + anfrage = urllib.request.Request(url, data=json.dumps(nutzlast).encode(), + headers={"Content-Type": "application/json"}) + try: + with urllib.request.urlopen(anfrage, timeout=timeout) as antwort: + return json.loads(antwort.read()) + except (TimeoutError, urllib.error.URLError) as e: + if frist is not None and time.time() >= frist - 5: + raise Zeitende("Frist während einer Anfrage erreicht.") from e + raise + + +def chat(basis: str, modell: str, messages: list, max_tokens: int = 200, tools: list | None = None, + think: bool = True, frist: float | None = None) -> dict: + p: dict = {"model": modell, "temperature": 0, "max_tokens": max_tokens, "messages": messages} + if not think: + p["chat_template_kwargs"] = {"enable_thinking": False} + if tools: + p["tools"] = tools + p["tool_choice"] = "auto" + t0 = time.time() + j = post(f"{basis}/v1/chat/completions", p, frist=frist) + j["_wall"] = time.time() - t0 + return j + + +def _nachricht(j: dict) -> dict: + return ((j.get("choices") or [{}])[0].get("message")) or {} + + +def _text(j: dict) -> str: + """Antworttext ohne Denkblock (manche Templates lassen im content stehen).""" + text = _nachricht(j).get("content") or "" + return re.sub(r".*?", "", text, flags=re.DOTALL).strip() + + +def timings(j: dict) -> dict: + t = j.get("timings") or {} + acc = (t.get("draft_n_accepted", 0) / t["draft_n"]) if t.get("draft_n") else None + return {"pp_n": t.get("prompt_n"), "pp_s": round((t.get("prompt_ms") or 0) / 1000, 1), + "pp_tps": round(t.get("prompt_per_second") or 0), "tg_n": t.get("predicted_n"), + "tg_tps": round(t.get("predicted_per_second") or 0, 1), "acc": None if acc is None else round(acc, 2)} + + +# --- Tempo --------------------------------------------------------------------------- + +PARA = ("Notiz {i}: Die Box läuft mit llama-swap auf Port 8080, das Hirn ist ein Mixture-of-Experts-Modell mit drei " + "Milliarden aktiven Parametern, der Coder ein dichtes 27B-Modell mit Draft-Beschleunigung. Lucy hört über " + "Parakeet, spricht über pocket-tts und meldet sich per Telegram. Der Sonntags-Job aktualisiert Router, Engine " + "und Agent und rollt bei Rot zurück. ") + + +def tiefen_prompt(marke: str) -> str: + """~13k Tokens. Die Zufallsmarke vorn verhindert, dass ein warmes Modell den Text aus dem + Prompt-Cache holt (am 17.09. kam das Live-Hirn so auf 0,1 s Prefill).""" + return (f"Messlauf {marke}.\n" + "".join(PARA.format(i=i) for i in range(130)) + + "\n\nFrage: Fasse in drei Sätzen zusammen, was in den Notizen steht, und nenne die Nummer der letzten Notiz.") + + +def messe_tempo(basis: str, modell: str, frist: float | None = None) -> dict: + chat(basis, modell, [{"role": "user", "content": "Sag kurz hallo."}], 32, frist=frist) # Warmlauf + kurz = chat(basis, modell, [{"role": "user", "content": + "Erkläre in fünf Sätzen, was ein Mixture-of-Experts-Modell ist."}], 200, frist=frist) + tiefe = chat(basis, modell, [{"role": "user", "content": tiefen_prompt(secrets.token_hex(4))}], 160, frist=frist) + return {"kurz": timings(kurz), "tiefe": timings(tiefe)} + + +# --- Werkzeuge ----------------------------------------------------------------------- + +def _werkzeug(name: str, beschreibung: str, **parameter: str) -> dict: + return {"type": "function", "function": { + "name": name, "description": beschreibung, + "parameters": {"type": "object", "properties": {k: {"type": "string", "description": v} + for k, v in parameter.items()}, + "required": list(parameter)}}} + + +SCREENSHOT = _werkzeug("screenshot", "Nimmt ein Bildschirmfoto vom PC des Nutzers auf und zeigt es dir.") +WERKZEUGE_HIRN_ECHT = [ + _werkzeug("terminal", "Führt einen Shell-Befehl auf der Box aus und gibt stdout zurück.", command="Der Befehl"), + _werkzeug("read_file", "Liest eine Datei und gibt den Inhalt zurück.", path="Absoluter Pfad"), + _werkzeug("send_telegram", "Schickt dem Nutzer eine Telegram-Nachricht.", text="Nachrichtentext"), + _werkzeug("web_fetch", "Ruft eine Webseite ab und liefert ihren Text.", url="Adresse der Seite"), + _werkzeug("erinnerung_anlegen", "Legt eine Erinnerung für den Nutzer an.", text="Worum es geht", + zeit="Wann (ISO-Zeit oder natürlich)"), + SCREENSHOT, +] +# Lucy hat ~100 Werkzeuge. Die Ablenker machen die Auswahl so schwer wie im Alltag. +_ABLENKER = { + "kalender": ("Kalender", ("lesen", "eintragen", "verschieben", "loeschen")), + "notiz": ("Notizen", ("lesen", "anlegen", "suchen", "loeschen")), + "mail": ("E-Mails", ("lesen", "suchen", "entwerfen", "archivieren")), + "kontakt": ("Kontakte", ("suchen", "anlegen", "aendern")), + "einkauf": ("Einkaufsliste", ("lesen", "ergaenzen", "leeren")), + "licht": ("Licht", ("einschalten", "ausschalten", "dimmen")), + "heizung": ("Heizung", ("lesen", "stellen")), + "rollladen": ("Rollläden", ("oeffnen", "schliessen")), + "musik": ("Musik", ("abspielen", "pausieren", "suchen")), + "jellyfin": ("Jellyfin-Mediathek", ("suchen", "abspielen")), + "docker": ("Docker-Container", ("auflisten", "neustarten", "logs")), + "gitea": ("Gitea-Repos", ("auflisten", "issue_anlegen", "pr_lesen")), + "backup": ("Sicherungen", ("auflisten", "starten", "pruefen")), + "wetter": ("Wetter", ("heute", "vorhersage")), + "bahn": ("Bahnverbindungen", ("suchen", "verspaetung")), + "paket": ("Paketsendungen", ("verfolgen",)), + "rezept": ("Rezepte", ("suchen", "speichern")), + "wissen": ("Wissensartikel", ("suchen", "zusammenfassen")), + "uebersetzung": ("Übersetzungen", ("deutsch_englisch", "englisch_deutsch")), + "rechner": ("Taschenrechner", ("rechnen",)), + "timer": ("Küchentimer", ("stellen", "stoppen")), + "wecker": ("Wecker", ("stellen", "loeschen")), + "drucker": ("Drucker", ("drucken", "status")), + "sauger": ("Saugroboter", ("starten", "stoppen", "status")), + "tuer": ("Haustür", ("status",)), + "kamera": ("Kamera an der Haustür", ("bild_holen",)), + "strom": ("Stromverbrauch", ("heute", "monat")), + "nerdquiz": ("NerdQuiz", ("frage_holen", "punkte")), + "projekt": ("Projekte", ("status", "anlegen")), + "modell": ("KI-Modelle", ("auflisten", "laden")), + "system": ("Box-System", ("temperatur", "speicher", "prozesse")), + "datei": ("Dateien", ("suchen", "kopieren", "verschieben")), + "aufgabe": ("Aufgaben", ("anlegen", "erledigen", "auflisten")), + "browser": ("Browser-Tabs", ("auflisten", "schliessen")), + "ablage": ("Zwischenablage", ("lesen", "setzen")), + "sprache": ("Sprachausgabe", ("sprechen",)), + "tagebuch": ("Tagebuch", ("eintragen", "lesen")), + "nachrichten": ("Nachrichten", ("schlagzeilen", "suchen")), +} +WERKZEUGE_HIRN = WERKZEUGE_HIRN_ECHT + [ + _werkzeug(f"{objekt}_{verb}", f"{anzeige}: {verb.replace('_', ' ')}.", eingabe="Freitext") + for objekt, (anzeige, verben) in _ABLENKER.items() for verb in verben] +SYSTEM_HIRN = ("Du bist Lucy, die persönliche Assistentin auf der Box. Du antwortest auf Deutsch, knapp und freundlich. " + "Wenn eine Aufgabe ein Werkzeug braucht, rufst du genau das passende auf, statt zu raten.\n\n" + "Hintergrundwissen aus deinem Gedächtnis:\n" + "".join(PARA.format(i=i) for i in range(80))) +# (Frage, [(Werkzeug, Muster in den Argumenten), …]) — eine Alternative reicht. +AUFGABEN_HIRN = [ + ("Wie viel Platz ist auf /srv/models noch frei? Nutze das passende Werkzeug.", [("terminal", r"\bd[fu]\b")]), + ("Lies die Datei /etc/hostname und sag mir, wie die Box heißt.", [("read_file", r"/etc/hostname")]), + ("Schick mir per Telegram die Nachricht: Prüfstand läuft.", [("send_telegram", r"pr(ü|ue)fstand")]), + ("Was steht gerade auf https://example.org? Ruf die Seite ab.", [("web_fetch", r"example\.org")]), + ("Erinnere mich morgen um 8 Uhr an den Zahnarzttermin.", [("erinnerung_anlegen", r"zahnarzt")]), + ("Schau auf meinen Bildschirm: Was ist da gerade offen?", [("screenshot", r"")]), +] + +WERKZEUGE_CODER = [ + _werkzeug("bash", "Führt einen Shell-Befehl im Projektordner aus.", command="Befehl", description="Wozu, kurz"), + _werkzeug("read", "Liest eine Datei.", filePath="Pfad"), + _werkzeug("write", "Schreibt eine Datei (legt sie an oder überschreibt sie).", filePath="Pfad", content="Inhalt"), + _werkzeug("edit", "Ersetzt in einer Datei einen Textabschnitt.", filePath="Pfad", oldString="Alter Text", + newString="Neuer Text"), + _werkzeug("glob", "Findet Dateien per Muster.", pattern="z. B. src/**/*.py"), + _werkzeug("grep", "Durchsucht Dateien nach einem regulären Ausdruck.", pattern="Suchmuster", include="Dateimuster"), + _werkzeug("list", "Listet einen Ordner auf.", path="Ordner"), + _werkzeug("webfetch", "Lädt eine Webseite.", url="Adresse"), + _werkzeug("todowrite", "Schreibt die Aufgabenliste des Agenten.", todos="Aufgaben als Text"), + _werkzeug("task", "Startet einen Unter-Agenten für eine Teilaufgabe.", description="Kurzbeschreibung", + prompt="Auftrag"), +] +SYSTEM_CODER = ("Du bist ein Coding-Agent in OpenCode. Das Projekt liegt in /home/nutzer/projekt (Python, Tests mit " + "pytest, Quellcode unter src/). Erledige Aufträge mit den Werkzeugen, ohne nachzufragen. " + "In src/config.py steht die Zeile `PORT = 8080`.") +AUFGABEN_CODER = [ + ("Führe die Tests des Projekts mit pytest aus.", [("bash", r"pytest")]), + ("Zeig mir den Inhalt von src/app.py.", [("read", r"src/app\.py")]), + ("Ersetze in src/config.py den Port 8080 durch 9090.", + [("edit", r"8080[\s\S]*9090"), ("write", r"9090"), ("bash", r"sed[\s\S]*9090")]), + ("Finde alle Stellen im Code, an denen TODO steht.", [("grep", r"TODO"), ("bash", r"grep[\s\S]*TODO")]), + ("Lege die Datei hallo.py an, mit einer Funktion hallo(), die 'Hallo' zurückgibt.", + [("write", r"hallo\.py[\s\S]*def hallo")]), +] + + +def _werkzeug_satz(rolle: str) -> tuple[str, list, list]: + if rolle == "hirn": + return SYSTEM_HIRN, WERKZEUGE_HIRN, AUFGABEN_HIRN + return SYSTEM_CODER, WERKZEUGE_CODER, AUFGABEN_CODER + + +def argumente_text(roh) -> str: + """Argumente eines Werkzeug-Aufrufs als durchsuchbarer Text (JSON-Escapes wie \\u00fc aufgelöst).""" + werte = roh + if not isinstance(roh, dict): + try: + werte = json.loads(roh or "{}") + except (TypeError, ValueError): + return str(roh or "") + if isinstance(werte, dict): + return " ".join(str(v) for v in werte.values()) + return str(werte) + + +def trifft(aufrufe: list, erwartet: list) -> bool: + for aufruf in aufrufe or []: + fn = (aufruf or {}).get("function") or {} + text = argumente_text(fn.get("arguments")) + if any(fn.get("name") == name and re.search(muster, text, re.IGNORECASE) for name, muster in erwartet): + return True + return False + + +def _aufrufe_kurz(aufrufe: list) -> list: + return [[(a.get("function") or {}).get("name"), argumente_text((a.get("function") or {}).get("arguments"))[:80]] + for a in aufrufe or []] + + +def messe_werkzeuge(basis: str, modell: str, rolle: str, frist: float | None = None) -> dict: + system, werkzeuge, aufgaben = _werkzeug_satz(rolle) + details, ok, kontext = [], 0, None + for frage, erwartet in aufgaben: + eintrag: dict = {"aufgabe": frage[:60], "ok": False} + try: + j = chat(basis, modell, [{"role": "system", "content": system}, {"role": "user", "content": frage}], + WERKZEUG_TOKENS, werkzeuge, frist=frist) + t = j.get("timings") or {} + kontext = kontext or ((t.get("prompt_n") or 0) + (t.get("cache_n") or 0)) or None + aufrufe = _nachricht(j).get("tool_calls") or [] + eintrag["ok"] = trifft(aufrufe, erwartet) + eintrag["aufrufe"] = _aufrufe_kurz(aufrufe) + if not aufrufe: + eintrag["antwort"] = _text(j)[:120] + except Zeitende: + raise + except Exception as e: + eintrag["fehler"] = str(e)[:120] + ok += eintrag["ok"] + details.append(eintrag) + return {"ok": ok, "von": len(aufgaben), "kontext_tokens": kontext, "details": details} + + +# --- Deutsch und JSON (Hirn) -------------------------------------------------------------- + +_DEUTSCHE_WOERTER = re.compile(r"\b(und|die|der|das|ist|nicht|ein|eine|für|mit|wird|sind|auch|oder)\b", re.IGNORECASE) + + +def ist_deutsch(text: str) -> bool: + return len(text) >= 60 and len({w.lower() for w in _DEUTSCHE_WOERTER.findall(text)}) >= 3 + + +def ist_json(text: str) -> bool: + try: + json.loads(text[text.find("{"): text.rfind("}") + 1]) + return True + except ValueError: + return False + + +def messe_sprache(basis: str, modell: str, frist: float | None = None) -> dict: + j = chat(basis, modell, [{"role": "user", "content": + "Antworte auf Deutsch in genau drei Sätzen: Warum braucht ein Heimserver ein Backup?"}], + 300, think=False, frist=frist) + deutsch = _text(j) + j = chat(basis, modell, [{"role": "user", "content": + 'Antworte NUR mit JSON, ohne Erklärung: {"modell": "", "ok": true}'}], + 120, think=False, frist=frist) + roh = _text(j) + return {"deutsch": {"ok": ist_deutsch(deutsch), "text": deutsch[:300]}, + "json": {"ok": ist_json(roh), "text": roh[:120]}} + + +# --- Programmieraufgaben (Coder) ------------------------------------------------------------- + +def _aufgabe(kennung: str, auftrag: str, tests: str) -> dict: + return {"id": kennung, "auftrag": auftrag, "tests": textwrap.dedent(tests).strip() + "\n"} + + +AUFGABEN_CODE = [ + _aufgabe("palindrom", + "Schreibe eine Python-Funktion `ist_palindrom(text: str) -> bool`. Sie gibt True zurück, wenn der Text " + "vorwärts wie rückwärts gleich lautet. Groß- und Kleinschreibung, Leerzeichen und Satzzeichen zählen " + "nicht; verglichen werden nur Buchstaben (auch Umlaute) und Ziffern. Ein leerer Text ist ein Palindrom.", + """ + assert ist_palindrom("Ein Esel lese nie") is True + assert ist_palindrom("Reliefpfeiler") is True + assert ist_palindrom("Otto!") is True + assert ist_palindrom("Ölö") is True + assert ist_palindrom("12a21") is True + assert ist_palindrom("") is True + assert ist_palindrom("Hallo Welt") is False + """), + _aufgabe("roemisch", + "Schreibe `roemisch(zahl: int) -> str`, die eine ganze Zahl von 1 bis 3999 als römische Zahl schreibt " + "(mit Subtraktion: 4 = IV, 9 = IX, 40 = XL, 90 = XC, 400 = CD, 900 = CM). Zahlen außerhalb des Bereichs " + "lösen ValueError aus.", + """ + assert roemisch(1) == "I" + assert roemisch(4) == "IV" + assert roemisch(9) == "IX" + assert roemisch(58) == "LVIII" + assert roemisch(1994) == "MCMXCIV" + assert roemisch(3999) == "MMMCMXCIX" + for falsch in (0, 4000, -3): + try: + roemisch(falsch) + except ValueError: + pass + else: + raise AssertionError(f"kein ValueError für {falsch}") + """), + _aufgabe("intervalle", + "Schreibe `zusammenfassen(intervalle: list[list[int]]) -> list[list[int]]`. Sie fasst sich überlappende " + "oder berührende Intervalle [start, ende] zusammen und gibt sie nach Start sortiert zurück. Die Eingabe " + "ist unsortiert und darf nicht verändert werden.", + """ + assert zusammenfassen([[1, 3], [2, 6], [8, 10], [15, 18]]) == [[1, 6], [8, 10], [15, 18]] + assert zusammenfassen([[1, 4], [4, 5]]) == [[1, 5]] + assert zusammenfassen([]) == [] + assert zusammenfassen([[5, 7], [1, 2]]) == [[1, 2], [5, 7]] + assert zusammenfassen([[1, 10], [2, 3], [4, 8]]) == [[1, 10]] + eingabe = [[3, 4], [1, 2]] + zusammenfassen(eingabe) + assert eingabe == [[3, 4], [1, 2]] + """), + _aufgabe("flach", + "Schreibe `flach(liste: list) -> list`, die beliebig tief verschachtelte Listen zu einer flachen Liste " + "macht. Die Reihenfolge bleibt erhalten. Nur Listen werden aufgelöst; Tupel und Strings bleiben einzelne " + "Elemente.", + """ + assert flach([1, [2, [3, [4]], 5]]) == [1, 2, 3, 4, 5] + assert flach([]) == [] + assert flach([[[]]]) == [] + assert flach(["ab", ("c", "d"), ["e"]]) == ["ab", ("c", "d"), "e"] + tief = [1] + for _ in range(50): + tief = [tief] + assert flach(tief) == [1] + """), + _aufgabe("iban", + "Schreibe `iban_gueltig(iban: str) -> bool`. Leerzeichen werden ignoriert, Groß-/Kleinschreibung ist " + "egal. Prüfe die Länge (15 bis 34 Zeichen), dass nur Buchstaben und Ziffern vorkommen, und die Prüfsumme " + "nach ISO 13616: die ersten vier Zeichen ans Ende stellen, Buchstaben durch Zahlen ersetzen (A=10 … Z=35), " + "die entstehende Zahl modulo 97 muss 1 ergeben.", + """ + assert iban_gueltig("DE89 3704 0044 0532 0130 00") is True + assert iban_gueltig("de89370400440532013000") is True + assert iban_gueltig("GB82 WEST 1234 5698 7654 32") is True + assert iban_gueltig("DE89 3704 0044 0532 0130 01") is False + assert iban_gueltig("DE89-3704-0044") is False + assert iban_gueltig("") is False + """), + _aufgabe("lru", + "Schreibe eine Klasse `LRUCache` mit `__init__(self, kapazitaet: int)`, `get(self, schluessel)` (liefert " + "den Wert oder None und markiert den Eintrag als zuletzt benutzt) und `put(self, schluessel, wert)` (legt " + "an oder überschreibt, ebenfalls als zuletzt benutzt; ist die Kapazität überschritten, fliegt der am " + "längsten nicht benutzte Eintrag raus).", + """ + c = LRUCache(2) + c.put("a", 1) + c.put("b", 2) + assert c.get("a") == 1 + c.put("c", 3) + assert c.get("b") is None + assert c.get("a") == 1 + assert c.get("c") == 3 + c.put("a", 10) + c.put("d", 4) + assert c.get("c") is None + assert c.get("a") == 10 + assert c.get("d") == 4 + """), + _aufgabe("klammern", + "Schreibe `klammern_ok(text: str) -> bool`. Sie prüft, ob die Klammern (), [] und {} im Text korrekt " + "geschachtelt und geschlossen sind. Alle anderen Zeichen werden ignoriert.", + """ + assert klammern_ok("") is True + assert klammern_ok("f(a[1], {b: 2})") is True + assert klammern_ok("x = {'a': [1, (2, 3)]}") is True + assert klammern_ok("([)]") is False + assert klammern_ok("((") is False + assert klammern_ok("())") is False + """), + _aufgabe("wege", + "Schreibe `kuerzeste_wege(graph: dict[str, dict[str, int]], start: str) -> dict[str, int]`. graph ordnet " + "jedem Knoten seine Nachbarn mit nicht negativen Kantengewichten zu. Liefere die kürzeste Entfernung vom " + "Start zu jedem erreichbaren Knoten (der Start selbst mit 0). Nicht erreichbare Knoten fehlen im " + "Ergebnis. Nachbarn, die nicht als Schlüssel in graph stehen, sind trotzdem gültige Knoten.", + """ + g = {"A": {"B": 1, "C": 4}, "B": {"C": 2, "D": 5}, "C": {"D": 1}, "D": {}, "X": {"A": 1}} + assert kuerzeste_wege(g, "A") == {"A": 0, "B": 1, "C": 3, "D": 4} + assert kuerzeste_wege(g, "D") == {"D": 0} + assert kuerzeste_wege(g, "X") == {"X": 0, "A": 1, "B": 2, "C": 4, "D": 5} + assert kuerzeste_wege({"A": {"Z": 7}}, "A") == {"A": 0, "Z": 7} + """), + _aufgabe("median", + "Diese Funktion soll den Median einer Liste von Zahlen liefern, ist aber fehlerhaft. Korrigiere sie. Die " + "Eingabeliste darf nicht verändert werden; bei einer leeren Liste soll ValueError kommen.\n\n" + "```python\ndef median(zahlen):\n zahlen.sort()\n mitte = len(zahlen) // 2\n" + " return zahlen[mitte]\n```", + """ + assert median([3, 1, 2]) == 2 + assert median([4, 1, 3, 2]) == 2.5 + assert median([5]) == 5 + daten = [9, 7, 8] + median(daten) + assert daten == [9, 7, 8] + try: + median([]) + except ValueError: + pass + else: + raise AssertionError("kein ValueError bei leerer Liste") + """), + _aufgabe("csv", + "Schreibe `spaltensumme(csv_text: str, spalte: str) -> float`. Der Text ist eine CSV-Datei mit Semikolon " + "als Trenner und einer Kopfzeile. Zahlen haben ein Komma als Dezimaltrenner und können einen Punkt als " + "Tausendertrenner haben (z. B. 1.234,5). Leere Zellen zählen als 0. Gibt es die Spalte nicht, löse " + "KeyError aus.", + """ + text = "name;betrag;menge\\nA;1,5;2\\nB;1.234,5;\\nC;;3\\n" + assert abs(spaltensumme(text, "betrag") - 1236.0) < 1e-9 + assert abs(spaltensumme(text, "menge") - 5.0) < 1e-9 + try: + spaltensumme(text, "preis") + except KeyError: + pass + else: + raise AssertionError("kein KeyError") + """), +] +SYSTEM_CODE = "Du bist ein erfahrener Python-Entwickler. Antworte nur mit einem Python-Codeblock, ohne Erklärung." + +# Modell-Code läuft auf der Box — nur reine Funktionen sind erlaubt, kein Zugriff auf Dateien, +# Prozesse oder Netz. Die Sperrliste ist grob, aber für diese Aufgaben braucht es nichts davon. +_VERBOTEN = re.compile( + r"^\s*(?:import|from)\s+(?:os|subprocess|shutil|socket|pathlib|ctypes|multiprocessing|threading|urllib|http|" + r"requests|signal|importlib|builtins|pty|resource|glob|tempfile|io|codecs)\b" + r"|__import__|(? str: + """Längster Python-Codeblock der Antwort (Lösung statt Beispielaufruf); ohne Block die ganze Antwort.""" + text = re.sub(r".*?", "", text or "", flags=re.DOTALL) + bloecke = re.findall(r"```[ \t]*(?:python|py|python3)?[^\n]*\n(.*?)```", text, re.DOTALL | re.IGNORECASE) + return max(bloecke, key=len) if bloecke else text.strip() + + +def fuehre_aufgabe_aus(code: str, tests: str, zeitlimit: float = CODE_ZEITLIMIT_S) -> tuple[bool, str]: + """Lösung + Tests in einem frischen Temp-Ordner mit Zeit- und Speichergrenze ausführen.""" + if not code.strip(): + return False, "keine Lösung in der Antwort" + if (treffer := _VERBOTEN.search(code)): + return False, f"unerlaubter Aufruf: {treffer.group(0).strip()[:40]}" + with tempfile.TemporaryDirectory(prefix="pruefstand-code-") as ordner: + Path(ordner, "loesung.py").write_text(code, encoding="utf-8") + Path(ordner, "pruefung.py").write_text(_RUNNER_KOPF + tests + "print('OK')\n", encoding="utf-8") + umgebung = {"PATH": os.environ.get("PATH", ""), "HOME": ordner, "TMPDIR": ordner, "LANG": "C.UTF-8"} + umgebung.update({k: os.environ[k] for k in ("SYSTEMROOT", "WINDIR") if k in os.environ}) + try: + p = subprocess.run([sys.executable, "-I", "pruefung.py"], cwd=ordner, capture_output=True, + encoding="utf-8", errors="replace", timeout=zeitlimit, env=umgebung, + stdin=subprocess.DEVNULL) + except subprocess.TimeoutExpired: + return False, f"Zeitlimit {zeitlimit:.0f} s überschritten" + if p.returncode == 0 and "OK" in p.stdout: + return True, "" + zeilen = (p.stderr or p.stdout or "").strip().splitlines() + return False, (zeilen[-1] if zeilen else f"Exit-Code {p.returncode}")[:200] + + +def messe_code(basis: str, modell: str, frist: float | None = None) -> dict: + """Denken aus: bei so kleinen Aufgaben misst das die Code-Qualität und hält die Nacht kurz.""" + details, ok, t0 = [], 0, time.time() + for aufgabe in AUFGABEN_CODE: + try: + j = chat(basis, modell, [{"role": "system", "content": SYSTEM_CODE}, + {"role": "user", "content": aufgabe["auftrag"]}], + CODE_TOKENS, think=False, frist=frist) + geschafft, grund = fuehre_aufgabe_aus(code_aus_antwort(_text(j)), aufgabe["tests"]) + except Zeitende: + raise + except Exception as e: + geschafft, grund = False, f"Anfrage scheiterte: {e}"[:160] + ok += geschafft + details.append({"aufgabe": aufgabe["id"], "ok": geschafft, "grund": grund}) + return {"ok": ok, "von": len(AUFGABEN_CODE), "sekunden": round(time.time() - t0), "details": details} + + +# --- Bild-Probe ------------------------------------------------------------------------ + +BILD_TEXT = "ZEBRA 4711" +BILD_MERKMALE = { + "Wort ZEBRA": r"zebra", + "Zahl 4711": r"4[\s.]?711", + "rot": r"\brot(e|er|es|en)?\b|\bred\b", + "blau": r"\bblau|\bblue\b", + "grün": r"\bgr(ü|ue)n|\bgreen\b", + "Kreis": r"kreis|circle", + "Quadrat": r"quadrat|rechteck|viereck|square|rectangle", + "Dreieck": r"dreieck|triangle", +} +_GLYPHEN = { + "Z": ("#####", "....#", "...#.", "..#..", ".#...", "#....", "#####"), + "E": ("#####", "#....", "#....", "####.", "#....", "#....", "#####"), + "B": ("####.", "#...#", "#...#", "####.", "#...#", "#...#", "####."), + "R": ("####.", "#...#", "#...#", "####.", "#.#..", "#..#.", "#...#"), + "A": (".###.", "#...#", "#...#", "#####", "#...#", "#...#", "#...#"), + "4": ("...#.", "..##.", ".#.#.", "#..#.", "#####", "...#.", "...#."), + "7": ("#####", "....#", "...#.", "..#..", ".#...", ".#...", ".#..."), + "1": ("..#..", ".##..", "..#..", "..#..", "..#..", "..#..", ".###."), + " ": (".....",) * 7, +} + + +def bild_png(breite: int = 448, hoehe: int = 300) -> bytes: + """Testbild ohne Pillow: roter Kreis, blaues Quadrat, grünes Dreieck, darunter „ZEBRA 4711“.""" + px = bytearray(b"\xff" * (breite * hoehe * 3)) + + def setze(x: int, y: int, farbe: bytes) -> None: + if 0 <= x < breite and 0 <= y < hoehe: + i = (y * breite + x) * 3 + px[i:i + 3] = farbe + + rot, blau, gruen, schwarz = b"\xdc\x14\x14", b"\x14\x3c\xdc", b"\x14\xa0\x28", b"\x10\x10\x10" + cx, cy, r = 80, 95, 55 + for y in range(cy - r, cy + r + 1): + for x in range(cx - r, cx + r + 1): + if (x - cx) ** 2 + (y - cy) ** 2 <= r * r: + setze(x, y, rot) + for y in range(40, 150): + for x in range(170, 280): + setze(x, y, blau) + spitze_x, oben, unten, links, rechts = 370, 40, 150, 315, 425 + for y in range(oben, unten + 1): + anteil = (y - oben) / (unten - oben) + for x in range(round(spitze_x + (links - spitze_x) * anteil), round(spitze_x + (rechts - spitze_x) * anteil) + 1): + setze(x, y, gruen) + skala, zelle = 6, 6 + x0, y0 = (breite - len(BILD_TEXT) * zelle * skala) // 2, 205 + for n, zeichen in enumerate(BILD_TEXT): + for zy, reihe in enumerate(_GLYPHEN[zeichen]): + for zx, punkt in enumerate(reihe): + if punkt == "#": + for dy in range(skala): + for dx in range(skala): + setze(x0 + (n * zelle + zx) * skala + dx, y0 + zy * skala + dy, schwarz) + roh = b"".join(b"\x00" + bytes(px[y * breite * 3:(y + 1) * breite * 3]) for y in range(hoehe)) + + def block(typ: bytes, daten: bytes) -> bytes: + return struct.pack(">I", len(daten)) + typ + daten + struct.pack(">I", zlib.crc32(typ + daten) & 0xFFFFFFFF) + + return (b"\x89PNG\r\n\x1a\n" + block(b"IHDR", struct.pack(">IIBBBBB", breite, hoehe, 8, 2, 0, 0, 0)) + + block(b"IDAT", zlib.compress(roh, 9)) + block(b"IEND", b"")) + + +def bild_data_url() -> str: + return "data:image/png;base64," + base64.b64encode(bild_png()).decode() + + +def bild_merkmale(text: str) -> list[str]: + return [name for name, muster in BILD_MERKMALE.items() if re.search(muster, text or "", re.IGNORECASE)] + + +def _bild_im_ablauf(basis: str, modell: str, rolle: str, url: str, frist: float | None) -> dict: + """Das Bild kommt mitten in einer Werkzeug-Aufgabe (als Ergebnis von „screenshot“), wie bei Lucy + am Bildschirm oder beim Coder mit einem Screenshot der App. Erwartet wird der nächste richtige Schritt.""" + if rolle == "hirn": + system, werkzeuge = SYSTEM_HIRN, WERKZEUGE_HIRN + auftrag = "Schau auf meinen Bildschirm und schick mir per Telegram, welches Wort und welche Zahl dort stehen." + erwartet = [("send_telegram", r"zebra[\s\S]*4[\s.]?711|4[\s.]?711[\s\S]*zebra")] + else: + system, werkzeuge = SYSTEM_CODER, WERKZEUGE_CODER + [SCREENSHOT] + auftrag = ("Mach einen Screenshot der laufenden App. Die Zahl, die dort angezeigt wird, soll in src/config.py " + "als PORT stehen. Pass die Datei an.") + erwartet = [("edit", r"4711"), ("write", r"4711"), ("bash", r"4711")] + verlauf = [ + {"role": "system", "content": system}, + {"role": "user", "content": auftrag}, + {"role": "assistant", "content": "", "tool_calls": [ + {"id": "call_bild_1", "type": "function", "function": {"name": "screenshot", "arguments": "{}"}}]}, + {"role": "tool", "tool_call_id": "call_bild_1", "content": "Bildschirmfoto aufgenommen, es folgt als Bild."}, + {"role": "user", "content": [{"type": "image_url", "image_url": {"url": url}}, + {"type": "text", "text": "Bildschirmfoto aus dem Werkzeug screenshot."}]}, + ] + j = chat(basis, modell, verlauf, WERKZEUG_TOKENS, werkzeuge, frist=frist) + aufrufe = _nachricht(j).get("tool_calls") or [] + return {"ok": trifft(aufrufe, erwartet), "aufrufe": _aufrufe_kurz(aufrufe), + "antwort": "" if aufrufe else _text(j)[:160]} + + +def messe_bild(basis: str, modell: str, rolle: str, frist: float | None = None) -> dict: + url = bild_data_url() + j = chat(basis, modell, [{"role": "user", "content": [ + {"type": "image_url", "image_url": {"url": url}}, + {"type": "text", "text": "Beschreibe das Bild: Welche Formen in welchen Farben siehst du, und welcher Text " + "steht darin?"}]}], 600, think=False, frist=frist) + antwort = _text(j) + gefunden = bild_merkmale(antwort) + try: + ablauf = _bild_im_ablauf(basis, modell, rolle, url, frist) + except Zeitende: + raise + except Exception as e: + ablauf = {"ok": False, "fehler": str(e)[:160]} + return {"direkt": round(len(gefunden) / len(BILD_MERKMALE), 2), "gefunden": gefunden, + "agentisch": bool(ablauf.get("ok")), "ablauf": ablauf, "antwort": antwort[:300]} + + +# --- Gesamtprüfung --------------------------------------------------------------------- + +def pruefe(rolle: str, basis: str, modell: str, *, bild: bool = False, frist: float | None = None, + protokoll=log) -> dict: + """Alle Proben der Rolle gegen ein laufendes Modell (Kandidat auf :5899 oder Baseline über llama-swap).""" + if rolle not in ALIAS: + raise ValueError(f"Unbekannte Rolle {rolle!r}") + t0 = time.time() + werte: dict = {"rolle": rolle, "modell": modell, + "zeitpunkt": time.strftime("%Y-%m-%dT%H:%M:%S%z")} + werte.update(messe_tempo(basis, modell, frist)) + protokoll(f" kurz : {werte['kurz']}") + protokoll(f" 13k : {werte['tiefe']}") + werte["werkzeuge"] = messe_werkzeuge(basis, modell, rolle, frist) + protokoll(f" werkzeuge: {werte['werkzeuge']['ok']}/{werte['werkzeuge']['von']}") + if rolle == "hirn": + werte.update(messe_sprache(basis, modell, frist)) + protokoll(f" deutsch: {'ja' if werte['deutsch']['ok'] else 'nein'} json: {'ja' if werte['json']['ok'] else 'nein'}") + else: + werte["code"] = messe_code(basis, modell, frist) + protokoll(f" code : {werte['code']['ok']}/{werte['code']['von']} in {werte['code']['sekunden']} s") + werte["bild"] = None + if bild: + try: + werte["bild"] = messe_bild(basis, modell, rolle, frist) + except Zeitende: + raise + except Exception as e: + werte["bild"] = {"direkt": 0.0, "gefunden": [], "agentisch": False, "fehler": str(e)[:160]} + protokoll(f" bild : {werte['bild'].get('direkt')} direkt, im Ablauf " + f"{'ja' if werte['bild'].get('agentisch') else 'nein'}") + werte["dauer_s"] = round(time.time() - t0) + return werte + + +# --- Kandidaten-Server ------------------------------------------------------------------- + +class Server: + """Ein laufender Kandidaten-Server (llama-server auf PORT).""" + + def __init__(self, prozess: subprocess.Popen, befehl: list[str], log_pfad: str): + self.prozess, self.befehl, self.log_pfad = prozess, befehl, log_pfad + self.ladezeit = 0 + + +_LAUFENDE: list[Server] = [] + + +def draft_flags(pfad: str | None = None, typ: str | None = None, n_max: int | None = None) -> list[str]: + """Spekulatives Dekodieren: Typ (draft-dflash, draft-mtp, draft-simple …) plus Entwurfsmodell. + Ein MTP-Kopf im Modell selbst braucht nur den Typ.""" + if not typ: + return [] + flags = ["--spec-type", typ] + if pfad: + flags += ["--spec-draft-model", pfad] + if n_max: + flags += ["--spec-draft-n-max", str(n_max)] + return flags + + +def server_befehl(gguf: str, *, mmproj: str | None = None, ctx: int = CTX_STANDARD, flags=(), + binary: str | None = None) -> list[str]: + befehl = [binary or BIN, "-m", gguf, "--host", "127.0.0.1", "--port", str(PORT), "-c", str(ctx), *BASIS_FLAGS] + if mmproj: + befehl += ["--mmproj", mmproj] + return befehl + [str(f) for f in flags] + + +def port_belegt(port: int = PORT) -> bool: + try: + with socket.create_connection(("127.0.0.1", port), timeout=1): + return True + except OSError: + return False + + +def _gesund() -> bool: + try: + with urllib.request.urlopen(f"{KANDIDAT_URL}/health", timeout=3) as antwort: + return antwort.status == 200 and b"ok" in antwort.read() + except Exception: + return False + + +def log_ende(pfad: str, zeichen: int = 400) -> str: + try: + return Path(pfad).read_text(encoding="utf-8", errors="replace")[-zeichen:].strip() + except OSError: + return "" + + +def _signal(prozess: subprocess.Popen, hart: bool) -> None: + try: + if os.name == "posix": # ganze Prozessgruppe (start_new_session), falls llama-server Kinder hat + os.killpg(prozess.pid, signal.SIGKILL if hart else signal.SIGTERM) + elif hart: + prozess.kill() + else: + prozess.terminate() + except OSError: + pass + + +def stoppe_server(server: Server, warte_s: float = 60) -> None: + p = server.prozess + if p.poll() is None: + _signal(p, hart=False) + try: + p.wait(timeout=warte_s) + except subprocess.TimeoutExpired: + _signal(p, hart=True) + try: + p.wait(timeout=15) + except subprocess.TimeoutExpired: + pass + if server in _LAUFENDE: + _LAUFENDE.remove(server) + + +def stoppe_alle(warte_s: float = 20) -> None: + """Alle Kandidaten-Server dieses Prozesses stoppen (Notbremse, Programmende).""" + for server in _LAUFENDE.copy(): # Kopie: stoppe_server nimmt den Server aus der Liste + stoppe_server(server, warte_s) + + +atexit.register(stoppe_alle) + + +def starte_server(gguf: str, *, mmproj: str | None = None, ctx: int = CTX_STANDARD, flags=(), + frist: float | None = None, ladezeit_max: float = LADEZEIT_MAX_S, protokoll=log) -> Server: + """Kandidat standalone starten und warten, bis /health „ok“ meldet.""" + if not os.path.exists(gguf): + raise ServerFehler(f"Modelldatei fehlt: {gguf}") + if mmproj and not os.path.exists(mmproj): + raise ServerFehler(f"mmproj fehlt: {mmproj}") + if port_belegt(): + raise ServerFehler(f"Port {PORT} ist belegt – läuft noch ein anderer Prüfstand?") + befehl = server_befehl(gguf, mmproj=mmproj, ctx=ctx, flags=flags) + umgebung = dict(os.environ) + umgebung["LD_LIBRARY_PATH"] = os.pathsep.join(p for p in (LIB_DIR, umgebung.get("LD_LIBRARY_PATH")) if p) + protokoll(" starte: " + " ".join(befehl)) + with open(SERVER_LOG, "w", encoding="utf-8") as logdatei: + prozess = subprocess.Popen(befehl, stdout=logdatei, stderr=subprocess.STDOUT, stdin=subprocess.DEVNULL, + env=umgebung, start_new_session=(os.name == "posix")) + server = Server(prozess, befehl, SERVER_LOG) + _LAUFENDE.append(server) + t0 = time.time() + try: + while True: + if prozess.poll() is not None: + raise ServerFehler(f"Absturz beim Laden (Code {prozess.returncode}): {log_ende(SERVER_LOG, 300)}") + if _gesund(): + server.ladezeit = round(time.time() - t0) + protokoll(f" geladen in {server.ladezeit} s") + return server + if time.time() - t0 > ladezeit_max: + raise ServerFehler(f"Nach {ladezeit_max:.0f} s noch nicht geladen: {log_ende(SERVER_LOG, 200)}") + if frist is not None and time.time() > frist - 5: + raise Zeitende("Frist erreicht, während der Kandidat noch lud.") + time.sleep(2) + except BaseException: + stoppe_server(server) + raise + + +def pruefe_kandidat(rolle: str, gguf: str, *, mmproj: str | None = None, flags=(), ctx: int = CTX_STANDARD, + basis: dict | None = None, frist: float | None = None, protokoll=log) -> dict: + """Ganzer Durchlauf eines Kandidaten: Server starten → messen → stoppen → urteilen. + basis = Werte der Baseline (ohne sie gibt es kein Urteil, ergebnis None). + Rückgabe: {"werte", "ergebnis", "vergleich", "zusammenfassung"}.""" + server = starte_server(gguf, mmproj=mmproj, ctx=ctx, flags=flags, frist=frist, protokoll=protokoll) + + def absturz() -> str: + return f"Während des Tests abgestürzt (Code {server.prozess.returncode}): {log_ende(SERVER_LOG, 300)}" + + try: + werte = pruefe(rolle, KANDIDAT_URL, "kandidat", bild=bool(mmproj), frist=frist, protokoll=protokoll) + except Exception as e: + if not isinstance(e, Zeitende) and server.prozess.poll() is not None: + raise ServerFehler(absturz()) from e + raise + else: + # Einzelproben fangen Fehler ab — ein toter Server darf nicht wie ein schlechtes Modell aussehen. + if server.prozess.poll() is not None: + raise ServerFehler(absturz()) + finally: + stoppe_server(server) + time.sleep(3) # Speicher freigeben lassen, bevor jemand anderes lädt + werte.update(ladezeit_s=server.ladezeit, ctx=ctx, befehl=" ".join(server.befehl)) + if not basis: + return {"werte": werte, "ergebnis": None, "vergleich": {}, + "zusammenfassung": "Gemessen, aber ohne Vergleichswerte des heutigen Modells."} + return {"werte": werte, **urteil(rolle, werte, basis)} + + +# --- Baseline ------------------------------------------------------------------------ + +def _lies_json(pfad: str) -> dict: + try: + daten = json.loads(Path(pfad).read_text(encoding="utf-8")) + return daten if isinstance(daten, dict) else {} + except (OSError, ValueError): + return {} + + +def _schreibe_json(pfad: str, daten: dict) -> None: + try: + tmp = Path(pfad).with_suffix(".tmp") + tmp.write_text(json.dumps(daten, ensure_ascii=False, indent=1), encoding="utf-8") + tmp.replace(pfad) + except OSError as e: + log(f" Baseline-Cache nicht schreibbar ({pfad}): {e}") + + +def baseline(rolle: str, cache_pfad: str, *, kennung: str, bild: bool = False, frist: float | None = None, + max_alter_tage: int = 30, basis_url: str = SWAP_URL, modell: str | None = None, + protokoll=log) -> dict | None: + """Werte des heutigen Modells der Rolle, höchstens alle max_alter_tage neu gemessen. + kennung = welches Modell mit welchen Flags (ändert sie sich, wird neu gemessen). + Rückgabe {"kennung", "zeit", "werte"} oder None, wenn es weder Cache noch Messung gibt.""" + cache = _lies_json(cache_pfad) + eintrag = cache.get(rolle) if isinstance(cache.get(rolle), dict) else None + passend = eintrag if eintrag and eintrag.get("kennung") == kennung else None + if passend and time.time() - float(passend.get("zeit") or 0) < max_alter_tage * 86400: + return passend + protokoll(f" Baseline {rolle} wird neu gemessen ({modell or ALIAS[rolle]} über llama-swap)") + try: + werte = pruefe(rolle, basis_url, modell or ALIAS[rolle], bild=bild, frist=frist, protokoll=protokoll) + except Zeitende: + raise + except Exception as e: + protokoll(f" Baseline {rolle} nicht messbar: {e}") + return passend # lieber einen Monat alt als gar nicht vergleichen + neu = {"kennung": kennung, "zeit": time.time(), "werte": werte} + cache[rolle] = neu + _schreibe_json(cache_pfad, cache) + return neu + + +# --- Urteil -------------------------------------------------------------------------- + +def _zahl(wert) -> str: + if wert is None: + return "–" + if isinstance(wert, float) and wert % 1: + return f"{wert:.1f}".replace(".", ",") + return f"{wert:.0f}" + + +def _prozent(faktor: float) -> str: + return f"{(faktor - 1) * 100:+.0f} %".replace("-", "−") + + +def _anteil(wert: dict | None) -> float: + return (wert.get("ok", 0) / wert["von"]) if wert and wert.get("von") else 0.0 + + +def bild_kann(bild: dict | None) -> bool: + return bool(bild) and float(bild.get("direkt") or 0) >= BILD_MIN and bool(bild.get("agentisch")) + + +def _bild_text(bild: dict | None) -> str: + if not bild: + return "kein mmproj" + return (f"{len(bild.get('gefunden') or [])}/{len(BILD_MERKMALE)} Merkmale, im Ablauf " + f"{'ja' if bild.get('agentisch') else 'nein'}") + + +def urteil(rolle: str, k: dict, b: dict) -> dict: + """Kandidat k gegen Baseline b (jeweils die Werte aus pruefe()). + bestanden = keine Pflicht verfehlt UND mindestens ein Vorteil. Pflicht: Tempo nicht deutlich + schlechter, Werkzeuge (und beim Coder der Code) nicht schlechter, Deutsch/JSON (Hirn), Bilder.""" + b = b.get("werte", b) # auch ein ganzer Baseline-Eintrag ist recht + r = REGELN[rolle] + zeilen: dict[str, dict] = {} # Messwert → Kandidat/Baseline/Einheit/Urteil, in Anzeige-Reihenfolge + maengel, vorteile = [], [] + + def zeile(name: str, kw, bw, einheit: str, bewertung: str) -> None: + zeilen[name] = {"kandidat": kw, "baseline": bw, "einheit": einheit, "urteil": bewertung} + + kt, bt = k.get("tiefe") or {}, b.get("tiefe") or {} + # Decode in t/s (mehr ist besser), Prefill als Zeit in s (weniger ist besser, Faktor = Tempo). + kd, bd = kt.get("tg_tps"), bt.get("tg_tps") + kp, bp = kt.get("pp_s"), bt.get("pp_s") + for name, kw, bw, einheit, faktor, pmin, pplus in ( + ("Decode bei 13k", kd, bd, "t/s", (kd / bd) if kd and bd else None, r["decode_min"], r["decode_plus"]), + ("Prefill bei 13k", kp, bp, "s", (bp / kp) if kp and bp else None, r["prefill_min"], r["prefill_plus"])): + if not kw: + maengel.append(f"{name} nicht messbar") + zeile(name, kw, bw, einheit, "schlechter") + elif faktor is None: + zeile(name, kw, bw, einheit, "unbekannt") + elif faktor < pmin: + maengel.append(f"{name} {_zahl(kw)} statt {_zahl(bw)} {einheit} (Tempo {_prozent(faktor)})") + zeile(name, kw, bw, einheit, "schlechter") + elif faktor >= pplus: + vorteile.append(f"{name} {_prozent(faktor)} schneller".replace("+", "")) + zeile(name, kw, bw, einheit, "besser") + else: + zeile(name, kw, bw, einheit, "gleich") + + kw_, bw_ = k.get("werkzeuge") or {}, b.get("werkzeuge") or {} + ka, ba = _anteil(kw_), _anteil(bw_) + ktext, btext = f"{kw_.get('ok', 0)}/{kw_.get('von', 0)}", f"{bw_.get('ok', 0)}/{bw_.get('von', 0)}" + if ka + 1e-9 < ba or ka < WERKZEUG_BODEN: + maengel.append(f"Werkzeuge {ktext} (heute {btext})") + zeile("Werkzeug-Aufrufe", ktext, btext, "", "schlechter") + elif ka > ba + 1e-9: + vorteile.append(f"Werkzeuge {ktext} statt {btext}") + zeile("Werkzeug-Aufrufe", ktext, btext, "", "besser") + else: + zeile("Werkzeug-Aufrufe", ktext, btext, "", "gleich") + + if rolle == "hirn": + for schluessel, name in (("deutsch", "Deutsch"), ("json", "JSON")): + ko, bo = bool((k.get(schluessel) or {}).get("ok")), bool((b.get(schluessel) or {}).get("ok")) + if not ko: + maengel.append(f"{name}-Probe nicht bestanden") + zeile(name, "ja" if ko else "nein", "ja" if bo else "nein", "", + "gleich" if ko == bo else ("besser" if ko else "schlechter")) + else: + kc, bc = k.get("code") or {}, b.get("code") or {} + ktext, btext = f"{kc.get('ok', 0)}/{kc.get('von', 0)}", f"{bc.get('ok', 0)}/{bc.get('von', 0)}" + if kc.get("ok", 0) < bc.get("ok", 0): + maengel.append(f"Programmieraufgaben {ktext} (heute {btext})") + zeile("Programmieraufgaben", ktext, btext, "", "schlechter") + elif kc.get("ok", 0) > bc.get("ok", 0): + vorteile.append(f"Programmieraufgaben {ktext} statt {btext}") + zeile("Programmieraufgaben", ktext, btext, "", "besser") + else: + zeile("Programmieraufgaben", ktext, btext, "", "gleich") + + kb, bb = k.get("bild"), b.get("bild") + kann_k, kann_b = bild_kann(kb), bild_kann(bb) + if not kann_k and (BILD_PFLICHT or kann_b): + maengel.append("versteht keine Bilder" if not kb else f"Bild-Probe nicht bestanden ({_bild_text(kb)})") + zeile("Bilder", _bild_text(kb), _bild_text(bb), "", "schlechter") + elif kann_k and not kann_b: + vorteile.append("versteht Bilder (heute nicht)") + zeile("Bilder", _bild_text(kb), _bild_text(bb), "", "besser") + else: + zeile("Bilder", _bild_text(kb), _bild_text(bb), "", "gleich") + + if maengel: + ergebnis, satz = "durchgefallen", "Durchgefallen: " + "; ".join(maengel) + "." + elif not vorteile: + ergebnis, satz = "durchgefallen", "Durchgefallen: kein Vorteil gegenüber dem heutigen Modell." + else: + ergebnis, satz = "bestanden", "Bestanden: " + "; ".join(vorteile) + "." + return {"ergebnis": ergebnis, "vergleich": zeilen, "zusammenfassung": satz, + "maengel": maengel, "vorteile": vorteile} + + +# --- Hermes-Smoke (nur für den Handbetrieb, pruefstand-hirn.py) --------------------------------- + +def hermes_smoke(hermes_args: list[str], protokoll=log) -> list[dict]: + """Zwei Aufgaben durch den ECHTEN Hermes-Agenten (Provider `pruefstand` -> :5899 muss in + `providers:` der Hermes-Config stehen).""" + ergebnisse = [] + for frage, erwartet in ((("Führe im Terminal exakt den Befehl echo pruefstand-ok aus und gib mir nur dessen " + "Ausgabe zurück."), "pruefstand-ok"), + ("Welche Verzeichnisse liegen direkt unter /srv/models? Nenne mir drei davon.", "GGUF")): + t0 = time.time() + try: + p = subprocess.run([HERMES, "chat", *hermes_args, "-Q", "--oneshot", "--max-turns", "6", "-q", frage], + capture_output=True, text=True, timeout=900) + ausgabe = (p.stdout + p.stderr)[-600:] + except subprocess.TimeoutExpired: + ausgabe = "TIMEOUT" + except OSError as e: + ausgabe = f"FEHLER {e}" + ok = erwartet.lower() in ausgabe.lower() + ergebnisse.append({"ok": ok, "s": round(time.time() - t0), "tail": ausgabe[-160:].replace("\n", " ")}) + protokoll(f" hermes: {'ok' if ok else 'FEHLT'} {round(time.time() - t0)} s {ausgabe[-120:].replace(chr(10), ' ')!r}") + return ergebnisse diff --git a/deploy/deploy.sh b/deploy/deploy.sh index ab2073b..f6fe0be 100644 --- a/deploy/deploy.sh +++ b/deploy/deploy.sh @@ -48,7 +48,11 @@ main() { fi # 4. Systemd Units neu laden (falls sich .service Dateien geändert haben) + # Das Modell-Radar (09/2026) ist die erste Unit, die deploy.sh selbst einspielt: Sie gehört ganz dem + # Repo, auf der Box wird an ihr nichts von Hand gedreht. Die übrigen Units bleiben wie bisher Handarbeit. + install -m 644 deploy/mc2-radar.service deploy/mc2-radar.timer "$HOME/.config/systemd/user/" systemctl --user daemon-reload + systemctl --user enable --now mc2-radar.timer # 4.5 Hermes Skills synchronisieren echo "Synchronisiere Hermes Skills..." diff --git a/deploy/mc2-radar.service b/deploy/mc2-radar.service new file mode 100644 index 0000000..c5d8318 --- /dev/null +++ b/deploy/mc2-radar.service @@ -0,0 +1,28 @@ +# systemd-USER-Unit für das Modell-Radar (Box-Wart, 09/2026) — gestartet von mc2-radar.timer um 00:30. +# Sucht höchstens einmal am Tag nach neuen Modellen für Hirn und Coder und testet nachts im Fenster +# 00:30–02:30 höchstens einen neuen Kandidaten pro Woche (backend/radar_lauf.py, services/radar.py). +# Um 03:00 braucht der NerdQuiz-Nachtlauf das Hirn: Der Lauf hört um 02:30 selbst auf, um 02:35 zieht +# seine Notbremse, und RuntimeMaxSec beendet ihn spätestens 02:40 samt llama-server (control-group). +# Type=simple statt oneshot: Bei oneshot greift RuntimeMaxSec nicht. +# Sudo-frei wie alle MC2-Units: ~/.config/systemd/user/ + systemctl --user. +# Ablage: ~/.config/systemd/user/mc2-radar.service (+ mc2-radar.timer) ; dann: +# systemctl --user daemon-reload && systemctl --user enable --now mc2-radar.timer + +[Unit] +Description=MC2 Modell-Radar (Suche + nächtlicher Prüfstand 00:30–02:30) +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +WorkingDirectory=%h/mission-control-v2/backend +ExecStart=%h/mission-control-v2/backend/.venv/bin/python radar_lauf.py +Environment=PYTHONPATH=%h/mission-control-v2 +Environment=MC_LLAMA_SWAP_URL=http://127.0.0.1:8080 +Environment=MC_CONFIG_PATH=/etc/llama-swap/config.yaml +Environment=MC_MODELS_DIR=/srv/models +Environment=MC_LOCAL_TZ=Europe/Berlin +# Kein Nice=: der Kandidaten-Server erbt die Priorität — gemessen wird gegen das Live-Modell. +RuntimeMaxSec=2h10min +KillMode=control-group +TimeoutStopSec=60 diff --git a/deploy/mc2-radar.timer b/deploy/mc2-radar.timer new file mode 100644 index 0000000..4b2eaa5 --- /dev/null +++ b/deploy/mc2-radar.timer @@ -0,0 +1,10 @@ +[Unit] +Description=Nächtliches Modell-Radar (00:30, Test-Fenster bis 02:30) + +[Timer] +OnCalendar=*-*-* 00:30:00 +Persistent=true +AccuracySec=1min + +[Install] +WantedBy=timers.target diff --git a/deploy/radar-watchlist.json b/deploy/radar-watchlist.json new file mode 100644 index 0000000..110ca0d --- /dev/null +++ b/deploy/radar-watchlist.json @@ -0,0 +1,27 @@ +{ + "_hinweis": "Merkliste des Modell-Radars (backend/services/radar.py). Einträge hier werden vor den Funden der Hugging-Face-Entdeckung getestet, in dieser Reihenfolge. Felder: name, rolle (hirn|coder), repo, quant (Standard Q4_K_M), eng (true = passt nur knapp neben das Warm-Set), notiz (erscheint in der Begründung), ueberspringen (Grund; Eintrag wird nicht getestet), optional draft {repo, datei, typ, n_max} und flags (zusätzliche llama-server-Flags). Getestet wird nur, was ein mmproj hat und neben das Warm-Set passt (27 GB + Kandidat inkl. KV-Cache <= 115 GB).", + "kandidaten": [ + { + "name": "Ornith-1.5-35B-A3B", + "rolle": "hirn", + "repo": "ornith-ai/Ornith-1.5-35B-A3B-GGUF", + "quant": "Q4_K_M", + "notiz": "MoE mit 3B aktiven Parametern (Architektur qwen35moe), mmproj im Repo." + }, + { + "name": "Qwen3.8-Flash-Next", + "rolle": "coder", + "repo": "unsloth/Qwen3.8-Flash-Next-GGUF", + "quant": "UD-IQ3_XXS", + "eng": true, + "notiz": "UD-IQ3_XXS ist ca. 82 GB groß und passt nur knapp neben das Warm-Set (UD-IQ4_XS mit 94 GB passt nicht)." + }, + { + "name": "K2-Horizon-MoVA-36B-A4B", + "rolle": "hirn", + "repo": "IFM/K2-Horizon-MoVA-36B-A4B-GGUF", + "quant": "Q4_K_M", + "ueberspringen": "läuft noch nicht im offiziellen llama.cpp." + } + ] +} diff --git a/frontend/dist/assets/Bestaetigen-VrcNpcBb.js b/frontend/dist/assets/Bestaetigen-VrcNpcBb.js new file mode 100644 index 0000000..a07f376 --- /dev/null +++ b/frontend/dist/assets/Bestaetigen-VrcNpcBb.js @@ -0,0 +1 @@ +import{a as e,c as t,i as n,s as r,t as i,u as a}from"./button-Dd8hfusv.js";import{a as o,i as s,n as c,o as l,r as u,s as d,t as f}from"./dist-CgRgLCFz.js";var p=r();a();var m=t();function h(e){let t=(0,p.c)(4),n;t[0]===e?n=t[1]:({...n}=e,t[0]=e,t[1]=n);let r;return t[2]===n?r=t[3]:(r=(0,m.jsx)(f,{"data-slot":`dialog`,...n}),t[2]=n,t[3]=r),r}function g(e){let t=(0,p.c)(4),n;t[0]===e?n=t[1]:({...n}=e,t[0]=e,t[1]=n);let r;return t[2]===n?r=t[3]:(r=(0,m.jsx)(l,{"data-slot":`dialog-portal`,...n}),t[2]=n,t[3]=r),r}function _(e){let t=(0,p.c)(8),r,i;t[0]===e?(r=t[1],i=t[2]):({className:r,...i}=e,t[0]=e,t[1]=r,t[2]=i);let a;t[3]===r?a=t[4]:(a=n(`fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0`,r),t[3]=r,t[4]=a);let s;return t[5]!==i||t[6]!==a?(s=(0,m.jsx)(o,{"data-slot":`dialog-overlay`,className:a,...i}),t[5]=i,t[6]=a,t[7]=s):s=t[7],s}function v(t){let r=(0,p.c)(15),a,o,s,l;r[0]===t?(a=r[1],o=r[2],s=r[3],l=r[4]):({className:o,children:a,showCloseButton:l,...s}=t,r[0]=t,r[1]=a,r[2]=o,r[3]=s,r[4]=l);let d=l===void 0||l,f;r[5]===Symbol.for(`react.memo_cache_sentinel`)?(f=(0,m.jsx)(_,{}),r[5]=f):f=r[5];let h;r[6]===o?h=r[7]:(h=n(`fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-sm text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95`,o),r[6]=o,r[7]=h);let v;r[8]===d?v=r[9]:(v=d&&(0,m.jsx)(c,{"data-slot":`dialog-close`,asChild:!0,children:(0,m.jsxs)(i,{variant:`ghost`,className:`absolute top-2 right-2`,size:`icon-sm`,children:[(0,m.jsx)(e,{}),(0,m.jsx)(`span`,{className:`sr-only`,children:`Schließen`})]})}),r[8]=d,r[9]=v);let y;return r[10]!==a||r[11]!==s||r[12]!==h||r[13]!==v?(y=(0,m.jsxs)(g,{children:[f,(0,m.jsxs)(u,{"data-slot":`dialog-content`,className:h,...s,children:[a,v]})]}),r[10]=a,r[11]=s,r[12]=h,r[13]=v,r[14]=y):y=r[14],y}function y(e){let t=(0,p.c)(8),r,i;t[0]===e?(r=t[1],i=t[2]):({className:r,...i}=e,t[0]=e,t[1]=r,t[2]=i);let a;t[3]===r?a=t[4]:(a=n(`flex flex-col gap-2`,r),t[3]=r,t[4]=a);let o;return t[5]!==i||t[6]!==a?(o=(0,m.jsx)(`div`,{"data-slot":`dialog-header`,className:a,...i}),t[5]=i,t[6]=a,t[7]=o):o=t[7],o}function b(e){let t=(0,p.c)(14),r,a,o,s;t[0]===e?(r=t[1],a=t[2],o=t[3],s=t[4]):({className:a,showCloseButton:s,children:r,...o}=e,t[0]=e,t[1]=r,t[2]=a,t[3]=o,t[4]=s);let l=s!==void 0&&s,u;t[5]===a?u=t[6]:(u=n(`-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 sm:flex-row sm:justify-end`,a),t[5]=a,t[6]=u);let d;t[7]===l?d=t[8]:(d=l&&(0,m.jsx)(c,{asChild:!0,children:(0,m.jsx)(i,{variant:`outline`,children:`Schließen`})}),t[7]=l,t[8]=d);let f;return t[9]!==r||t[10]!==o||t[11]!==u||t[12]!==d?(f=(0,m.jsxs)(`div`,{"data-slot":`dialog-footer`,className:u,...o,children:[r,d]}),t[9]=r,t[10]=o,t[11]=u,t[12]=d,t[13]=f):f=t[13],f}function x(e){let t=(0,p.c)(8),r,i;t[0]===e?(r=t[1],i=t[2]):({className:r,...i}=e,t[0]=e,t[1]=r,t[2]=i);let a;t[3]===r?a=t[4]:(a=n(`font-heading text-base leading-none font-medium`,r),t[3]=r,t[4]=a);let o;return t[5]!==i||t[6]!==a?(o=(0,m.jsx)(d,{"data-slot":`dialog-title`,className:a,...i}),t[5]=i,t[6]=a,t[7]=o):o=t[7],o}function S(e){let t=(0,p.c)(8),r,i;t[0]===e?(r=t[1],i=t[2]):({className:r,...i}=e,t[0]=e,t[1]=r,t[2]=i);let a;t[3]===r?a=t[4]:(a=n(`text-sm text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground`,r),t[3]=r,t[4]=a);let o;return t[5]!==i||t[6]!==a?(o=(0,m.jsx)(s,{"data-slot":`dialog-description`,className:a,...i}),t[5]=i,t[6]=a,t[7]=o):o=t[7],o}function C(e){let t=(0,p.c)(26),{offen:n,titel:r,text:a,knopf:o,gefahr:s,onJa:c,onNein:l,children:u}=e,d;t[0]===l?d=t[1]:(d=e=>!e&&l(),t[0]=l,t[1]=d);let f;t[2]===r?f=t[3]:(f=(0,m.jsx)(x,{className:`schild text-xl`,children:r}),t[2]=r,t[3]=f);let g;t[4]===a?g=t[5]:(g=(0,m.jsx)(S,{className:`text-[15px] leading-relaxed text-text-2`,children:a}),t[4]=a,t[5]=g);let _;t[6]!==f||t[7]!==g?(_=(0,m.jsxs)(y,{children:[f,g]}),t[6]=f,t[7]=g,t[8]=_):_=t[8];let C;t[9]===l?C=t[10]:(C=(0,m.jsx)(i,{variant:`outline`,onClick:l,children:`Abbrechen`}),t[9]=l,t[10]=C);let w=s?`gefahr`:`default`,T;t[11]!==o||t[12]!==c||t[13]!==w?(T=(0,m.jsx)(i,{variant:w,onClick:c,children:o}),t[11]=o,t[12]=c,t[13]=w,t[14]=T):T=t[14];let E;t[15]!==C||t[16]!==T?(E=(0,m.jsxs)(b,{className:`gap-2 sm:gap-2`,children:[C,T]}),t[15]=C,t[16]=T,t[17]=E):E=t[17];let D;t[18]!==u||t[19]!==_||t[20]!==E?(D=(0,m.jsxs)(v,{className:`border-linie bg-panel sm:max-w-lg`,children:[_,u,E]}),t[18]=u,t[19]=_,t[20]=E,t[21]=D):D=t[21];let O;return t[22]!==n||t[23]!==d||t[24]!==D?(O=(0,m.jsx)(h,{open:n,onOpenChange:d,children:D}),t[22]=n,t[23]=d,t[24]=D,t[25]=O):O=t[25],O}export{C as t}; \ No newline at end of file diff --git a/frontend/dist/assets/Dienste-QEbMZv2T.js b/frontend/dist/assets/Dienste-DEn0Zjkq.js similarity index 85% rename from frontend/dist/assets/Dienste-QEbMZv2T.js rename to frontend/dist/assets/Dienste-DEn0Zjkq.js index 8a6b175..0704260 100644 --- a/frontend/dist/assets/Dienste-QEbMZv2T.js +++ b/frontend/dist/assets/Dienste-DEn0Zjkq.js @@ -1 +1 @@ -import{c as e,f as t,i as n,t as r,u as i}from"./button-Dd8hfusv.js";import{F as a,O as o,_ as s,k as c,u as l}from"./index-B6MevgIX.js";import{a as u,i as d,n as f,r as p,t as m}from"./sheet-DWG2Q04V.js";var h=t(i(),1),g=e();function _({offen:e,onSchliessen:t}){let i=a(),_=l(),[v,y]=(0,h.useState)(null),[b,x]=(0,h.useState)(null),S=s(v);async function C(e){x(null);try{let t=await o(`/api/maintenance/restart`,{service:e});t.ok?c(`erfolg`,`${e} startet neu.`):c(`fehler`,t.err||`${e} ließ sich nicht neu starten.`),i.invalidateQueries({queryKey:[`dienste`]})}catch(e){c(`fehler`,e.message)}}return(0,g.jsx)(m,{open:e,onOpenChange:e=>!e&&t(),children:(0,g.jsxs)(f,{side:`right`,className:`w-full gap-3 overflow-y-auto border-linie bg-panel sm:max-w-2xl`,children:[(0,g.jsxs)(d,{children:[(0,g.jsx)(u,{className:`schild text-lg`,children:`Dienste und Protokolle`}),(0,g.jsx)(p,{className:`text-text-2`,children:`Welcher Dienst läuft, was er zuletzt geschrieben hat.`})]}),(0,g.jsx)(`ul`,{className:`m-0 flex list-none flex-col px-4 pb-2`,children:(_.data?.services??[]).map(e=>(0,g.jsxs)(`li`,{className:`flex flex-wrap items-center justify-between gap-2 border-t border-linie py-2.5`,children:[(0,g.jsxs)(`span`,{className:`flex min-w-0 items-center gap-2.5`,children:[(0,g.jsx)(`span`,{className:n(`size-2.5 shrink-0 rounded-full`,e.ok?`bg-gruen`:`bg-rot`),"aria-hidden":!0}),(0,g.jsxs)(`span`,{className:`min-w-0`,children:[(0,g.jsx)(`span`,{className:`block text-[15px]`,children:e.name}),(0,g.jsxs)(`span`,{className:`ziffern text-xs text-text-3`,children:[e.unit,` · `,e.ok?`läuft`:`antwortet nicht`]})]})]}),(0,g.jsxs)(`span`,{className:`flex gap-2`,children:[(0,g.jsx)(r,{variant:v===e.unit?`info`:`ghost`,size:`sm`,onClick:()=>y(e.unit),children:`Protokoll`}),b===e.unit?(0,g.jsx)(r,{variant:`gefahr`,size:`sm`,onClick:()=>C(e.unit),children:`Wirklich neu starten?`}):(0,g.jsx)(r,{variant:`outline`,size:`sm`,onClick:()=>x(e.unit),children:`Neu starten`})]})]},e.unit))}),v&&(0,g.jsx)(`pre`,{className:`ziffern mx-4 mb-4 max-h-[50vh] overflow-auto rounded-lg border border-linie bg-[#0b0d0f] p-3 text-xs leading-relaxed whitespace-pre-wrap text-text-2`,children:S.isFetching?`Wird gelesen …`:S.data?.text||S.data?.err||`Kein Protokoll.`})]})})}export{_ as Dienste}; \ No newline at end of file +import{c as e,f as t,i as n,t as r,u as i}from"./button-Dd8hfusv.js";import{A as a,L as o,f as s,j as c,y as l}from"./index-ZVRs0IGR.js";import{a as u,i as d,n as f,r as p,t as m}from"./sheet-DWG2Q04V.js";var h=t(i(),1),g=e();function _({offen:e,onSchliessen:t}){let i=o(),_=s(),[v,y]=(0,h.useState)(null),[b,x]=(0,h.useState)(null),S=l(v);async function C(e){x(null);try{let t=await a(`/api/maintenance/restart`,{service:e});t.ok?c(`erfolg`,`${e} startet neu.`):c(`fehler`,t.err||`${e} ließ sich nicht neu starten.`),i.invalidateQueries({queryKey:[`dienste`]})}catch(e){c(`fehler`,e.message)}}return(0,g.jsx)(m,{open:e,onOpenChange:e=>!e&&t(),children:(0,g.jsxs)(f,{side:`right`,className:`w-full gap-3 overflow-y-auto border-linie bg-panel sm:max-w-2xl`,children:[(0,g.jsxs)(d,{children:[(0,g.jsx)(u,{className:`schild text-lg`,children:`Dienste und Protokolle`}),(0,g.jsx)(p,{className:`text-text-2`,children:`Welcher Dienst läuft, was er zuletzt geschrieben hat.`})]}),(0,g.jsx)(`ul`,{className:`m-0 flex list-none flex-col px-4 pb-2`,children:(_.data?.services??[]).map(e=>(0,g.jsxs)(`li`,{className:`flex flex-wrap items-center justify-between gap-2 border-t border-linie py-2.5`,children:[(0,g.jsxs)(`span`,{className:`flex min-w-0 items-center gap-2.5`,children:[(0,g.jsx)(`span`,{className:n(`size-2.5 shrink-0 rounded-full`,e.ok?`bg-gruen`:`bg-rot`),"aria-hidden":!0}),(0,g.jsxs)(`span`,{className:`min-w-0`,children:[(0,g.jsx)(`span`,{className:`block text-[15px]`,children:e.name}),(0,g.jsxs)(`span`,{className:`ziffern text-xs text-text-3`,children:[e.unit,` · `,e.ok?`läuft`:`antwortet nicht`]})]})]}),(0,g.jsxs)(`span`,{className:`flex gap-2`,children:[(0,g.jsx)(r,{variant:v===e.unit?`info`:`ghost`,size:`sm`,onClick:()=>y(e.unit),children:`Protokoll`}),b===e.unit?(0,g.jsx)(r,{variant:`gefahr`,size:`sm`,onClick:()=>C(e.unit),children:`Wirklich neu starten?`}):(0,g.jsx)(r,{variant:`outline`,size:`sm`,onClick:()=>x(e.unit),children:`Neu starten`})]})]},e.unit))}),v&&(0,g.jsx)(`pre`,{className:`ziffern mx-4 mb-4 max-h-[50vh] overflow-auto rounded-lg border border-linie bg-[#0b0d0f] p-3 text-xs leading-relaxed whitespace-pre-wrap text-text-2`,children:S.isFetching?`Wird gelesen …`:S.data?.text||S.data?.err||`Kein Protokoll.`})]})})}export{_ as Dienste}; \ No newline at end of file diff --git a/frontend/dist/assets/Einstellungen-DMWgWLUo.js b/frontend/dist/assets/Einstellungen-BwCmWl9x.js similarity index 86% rename from frontend/dist/assets/Einstellungen-DMWgWLUo.js rename to frontend/dist/assets/Einstellungen-BwCmWl9x.js index d0b2664..9089d16 100644 --- a/frontend/dist/assets/Einstellungen-DMWgWLUo.js +++ b/frontend/dist/assets/Einstellungen-BwCmWl9x.js @@ -1 +1 @@ -import{c as e,f as t,t as n,u as r}from"./button-Dd8hfusv.js";import{D as i,F as a,N as o,O as s,P as c,k as l}from"./index-B6MevgIX.js";import{a as u,i as d,n as f,r as p,t as m}from"./sheet-DWG2Q04V.js";var h=t(r(),1),g=e();function _({offen:e,onSchliessen:t}){let r=a(),_=c({queryKey:[`geheimnisse`],queryFn:()=>i(`/api/maintenance/geheimnisse`),enabled:e}),[v,y]=(0,h.useState)(``);async function b(e){try{await s(`/api/maintenance/geheimnisse`,{schluessel:`hf_token`,wert:e}),l(`erfolg`,e?`Hugging-Face-Zugang gespeichert.`:`Hugging-Face-Zugang gelöscht.`),y(``),r.invalidateQueries({queryKey:[`geheimnisse`]})}catch(e){l(`fehler`,e.message)}}let x=_.data;return(0,g.jsx)(m,{open:e,onOpenChange:e=>!e&&t(),children:(0,g.jsxs)(f,{side:`right`,className:`w-full gap-3 overflow-y-auto border-linie bg-panel sm:max-w-lg`,children:[(0,g.jsxs)(d,{children:[(0,g.jsx)(u,{className:`schild text-lg`,children:`Einstellungen`}),(0,g.jsx)(p,{className:`text-text-2`,children:`Was die Box sich merkt.`})]}),(0,g.jsxs)(`section`,{className:`flex flex-col gap-3 border-t border-linie px-4 pt-4`,children:[(0,g.jsx)(`h3`,{className:`schild text-sm text-text-3`,children:`Hugging-Face-Zugang`}),(0,g.jsxs)(`p`,{className:`text-sm text-text-2`,children:[x?.hf_token_gesetzt?`Ist hinterlegt.`:`Fehlt.`,` Nötig für gesperrte Modelle und schnellere Downloads.`,x?.hf_token_aus_env?` Er kommt aus der Dienst-Einstellung und lässt sich hier nicht löschen.`:``]}),(0,g.jsxs)(`form`,{className:`flex gap-2`,onSubmit:e=>{e.preventDefault(),v.trim()&&b(v.trim())},children:[(0,g.jsx)(`label`,{htmlFor:`hf-token`,className:`sr-only`,children:`Hugging-Face-Zugang`}),(0,g.jsx)(`input`,{id:`hf-token`,type:`password`,autoComplete:`off`,value:v,onChange:e=>y(e.target.value),placeholder:`hf_…`,className:`h-11 min-w-0 flex-1 rounded-lg border border-linie-stark bg-erhaben px-3 text-[15px] outline-none focus:border-cyan`}),(0,g.jsx)(n,{type:`submit`,disabled:!v.trim()||x?.schreibbar===!1,children:`Speichern`})]}),x?.hf_token_gesetzt&&!x.hf_token_aus_env&&(0,g.jsx)(n,{variant:`ghost`,size:`sm`,className:`self-start`,onClick:()=>b(null),children:`Zugang löschen`})]}),(0,g.jsxs)(`section`,{className:`flex flex-col gap-2 border-t border-linie px-4 pt-4`,children:[(0,g.jsx)(`h3`,{className:`schild text-sm text-text-3`,children:`Hinweise`}),(0,g.jsx)(`p`,{className:`text-sm text-text-2`,children:`Dringende Hinweise gehen zusätzlich per Telegram raus, alles andere bleibt hier. Einfache Probleme wie einen abgestürzten Dienst behebt der Wächter selbst und schreibt es in den Verlauf.`})]}),(0,g.jsxs)(`section`,{className:`flex flex-col gap-2 border-t border-linie px-4 pt-4 pb-4`,children:[(0,g.jsx)(`h3`,{className:`schild text-sm text-text-3`,children:`Hermes`}),(0,g.jsxs)(`a`,{href:`/hermes-ui/`,target:`_blank`,rel:`noopener`,className:`flex h-11 items-center gap-2 self-start rounded-lg border border-linie-stark bg-erhaben px-4 text-[15px] hover:border-text-3`,children:[(0,g.jsx)(o,{className:`size-4`,"aria-hidden":!0}),` Hermes-Dashboard öffnen`]}),(0,g.jsx)(`p`,{className:`text-xs text-text-3`,children:`Chat, Sitzungen und Cron-Jobs verwaltet Hermes selbst. Es fragt nach seiner eigenen Anmeldung.`})]})]})})}export{_ as Einstellungen}; \ No newline at end of file +import{c as e,f as t,t as n,u as r}from"./button-Dd8hfusv.js";import{A as i,F as a,I as o,L as s,j as c,k as l}from"./index-ZVRs0IGR.js";import{a as u,i as d,n as f,r as p,t as m}from"./sheet-DWG2Q04V.js";var h=t(r(),1),g=e();function _({offen:e,onSchliessen:t}){let r=s(),_=o({queryKey:[`geheimnisse`],queryFn:()=>l(`/api/maintenance/geheimnisse`),enabled:e}),[v,y]=(0,h.useState)(``);async function b(e){try{await i(`/api/maintenance/geheimnisse`,{schluessel:`hf_token`,wert:e}),c(`erfolg`,e?`Hugging-Face-Zugang gespeichert.`:`Hugging-Face-Zugang gelöscht.`),y(``),r.invalidateQueries({queryKey:[`geheimnisse`]})}catch(e){c(`fehler`,e.message)}}let x=_.data;return(0,g.jsx)(m,{open:e,onOpenChange:e=>!e&&t(),children:(0,g.jsxs)(f,{side:`right`,className:`w-full gap-3 overflow-y-auto border-linie bg-panel sm:max-w-lg`,children:[(0,g.jsxs)(d,{children:[(0,g.jsx)(u,{className:`schild text-lg`,children:`Einstellungen`}),(0,g.jsx)(p,{className:`text-text-2`,children:`Was die Box sich merkt.`})]}),(0,g.jsxs)(`section`,{className:`flex flex-col gap-3 border-t border-linie px-4 pt-4`,children:[(0,g.jsx)(`h3`,{className:`schild text-sm text-text-3`,children:`Hugging-Face-Zugang`}),(0,g.jsxs)(`p`,{className:`text-sm text-text-2`,children:[x?.hf_token_gesetzt?`Ist hinterlegt.`:`Fehlt.`,` Nötig für gesperrte Modelle und schnellere Downloads.`,x?.hf_token_aus_env?` Er kommt aus der Dienst-Einstellung und lässt sich hier nicht löschen.`:``]}),(0,g.jsxs)(`form`,{className:`flex gap-2`,onSubmit:e=>{e.preventDefault(),v.trim()&&b(v.trim())},children:[(0,g.jsx)(`label`,{htmlFor:`hf-token`,className:`sr-only`,children:`Hugging-Face-Zugang`}),(0,g.jsx)(`input`,{id:`hf-token`,type:`password`,autoComplete:`off`,value:v,onChange:e=>y(e.target.value),placeholder:`hf_…`,className:`h-11 min-w-0 flex-1 rounded-lg border border-linie-stark bg-erhaben px-3 text-[15px] outline-none focus:border-cyan`}),(0,g.jsx)(n,{type:`submit`,disabled:!v.trim()||x?.schreibbar===!1,children:`Speichern`})]}),x?.hf_token_gesetzt&&!x.hf_token_aus_env&&(0,g.jsx)(n,{variant:`ghost`,size:`sm`,className:`self-start`,onClick:()=>b(null),children:`Zugang löschen`})]}),(0,g.jsxs)(`section`,{className:`flex flex-col gap-2 border-t border-linie px-4 pt-4`,children:[(0,g.jsx)(`h3`,{className:`schild text-sm text-text-3`,children:`Hinweise`}),(0,g.jsx)(`p`,{className:`text-sm text-text-2`,children:`Dringende Hinweise gehen zusätzlich per Telegram raus, alles andere bleibt hier. Einfache Probleme wie einen abgestürzten Dienst behebt der Wächter selbst und schreibt es in den Verlauf.`})]}),(0,g.jsxs)(`section`,{className:`flex flex-col gap-2 border-t border-linie px-4 pt-4 pb-4`,children:[(0,g.jsx)(`h3`,{className:`schild text-sm text-text-3`,children:`Hermes`}),(0,g.jsxs)(`a`,{href:`/hermes-ui/`,target:`_blank`,rel:`noopener`,className:`flex h-11 items-center gap-2 self-start rounded-lg border border-linie-stark bg-erhaben px-4 text-[15px] hover:border-text-3`,children:[(0,g.jsx)(a,{className:`size-4`,"aria-hidden":!0}),` Hermes-Dashboard öffnen`]}),(0,g.jsx)(`p`,{className:`text-xs text-text-3`,children:`Chat, Sitzungen und Cron-Jobs verwaltet Hermes selbst. Es fragt nach seiner eigenen Anmeldung.`})]})]})})}export{_ as Einstellungen}; \ No newline at end of file diff --git a/frontend/dist/assets/MehrMenue-gZV9ubEU.js b/frontend/dist/assets/MehrMenue-CXteqmy8.js similarity index 83% rename from frontend/dist/assets/MehrMenue-gZV9ubEU.js rename to frontend/dist/assets/MehrMenue-CXteqmy8.js index 7956cf3..5af0cb3 100644 --- a/frontend/dist/assets/MehrMenue-gZV9ubEU.js +++ b/frontend/dist/assets/MehrMenue-CXteqmy8.js @@ -1 +1 @@ -import{c as e,s as t}from"./button-Dd8hfusv.js";import{M as n,N as r,j as i}from"./index-B6MevgIX.js";import{a,i as o,n as s,r as c,t as l}from"./sheet-DWG2Q04V.js";var u=t(),d=e();function f(e){let t=(0,u.c)(17),{verbindung:f,onDienste:p,onEinstellungen:m,onSchliessen:h}=e,g;t[0]===h?g=t[1]:(g=e=>!e&&h(),t[0]=h,t[1]=g);let _;t[2]===Symbol.for(`react.memo_cache_sentinel`)?(_=(0,d.jsxs)(o,{children:[(0,d.jsx)(a,{className:`schild text-lg`,children:`Mehr`}),(0,d.jsx)(c,{className:`sr-only`,children:`Weitere Bereiche`})]}),t[2]=_):_=t[2];let v;t[3]===Symbol.for(`react.memo_cache_sentinel`)?(v=(0,d.jsxs)(`a`,{href:`/hermes-ui/`,target:`_blank`,rel:`noopener`,className:`flex h-12 items-center gap-3 rounded-lg border border-linie px-4 text-base`,children:[(0,d.jsx)(r,{className:`size-5`,"aria-hidden":!0}),` Hermes-Dashboard öffnen`]}),t[3]=v):v=t[3];let y;t[4]===Symbol.for(`react.memo_cache_sentinel`)?(y=(0,d.jsx)(n,{className:`size-5`,"aria-hidden":!0}),t[4]=y):y=t[4];let b;t[5]===p?b=t[6]:(b=(0,d.jsxs)(`button`,{type:`button`,onClick:p,className:`flex h-12 items-center gap-3 rounded-lg border border-linie px-4 text-left text-base`,children:[y,` Dienste und Protokolle`]}),t[5]=p,t[6]=b);let x;t[7]===Symbol.for(`react.memo_cache_sentinel`)?(x=(0,d.jsx)(i,{className:`size-5`,"aria-hidden":!0}),t[7]=x):x=t[7];let S;t[8]===m?S=t[9]:(S=(0,d.jsxs)(`button`,{type:`button`,onClick:m,className:`flex h-12 items-center gap-3 rounded-lg border border-linie px-4 text-left text-base`,children:[x,` Einstellungen`]}),t[8]=m,t[9]=S);let C;t[10]!==b||t[11]!==S||t[12]!==f?(C=(0,d.jsxs)(s,{side:`bottom`,className:`border-linie bg-panel pb-[calc(1rem+env(safe-area-inset-bottom))]`,children:[_,(0,d.jsxs)(`div`,{className:`flex flex-col gap-2 px-4`,children:[f,v,b,S]})]}),t[10]=b,t[11]=S,t[12]=f,t[13]=C):C=t[13];let w;return t[14]!==g||t[15]!==C?(w=(0,d.jsx)(l,{open:!0,onOpenChange:g,children:C}),t[14]=g,t[15]=C,t[16]=w):w=t[16],w}export{f as MehrMenue}; \ No newline at end of file +import{c as e,s as t}from"./button-Dd8hfusv.js";import{F as n,N as r,P as i}from"./index-ZVRs0IGR.js";import{a,i as o,n as s,r as c,t as l}from"./sheet-DWG2Q04V.js";var u=t(),d=e();function f(e){let t=(0,u.c)(17),{verbindung:f,onDienste:p,onEinstellungen:m,onSchliessen:h}=e,g;t[0]===h?g=t[1]:(g=e=>!e&&h(),t[0]=h,t[1]=g);let _;t[2]===Symbol.for(`react.memo_cache_sentinel`)?(_=(0,d.jsxs)(o,{children:[(0,d.jsx)(a,{className:`schild text-lg`,children:`Mehr`}),(0,d.jsx)(c,{className:`sr-only`,children:`Weitere Bereiche`})]}),t[2]=_):_=t[2];let v;t[3]===Symbol.for(`react.memo_cache_sentinel`)?(v=(0,d.jsxs)(`a`,{href:`/hermes-ui/`,target:`_blank`,rel:`noopener`,className:`flex h-12 items-center gap-3 rounded-lg border border-linie px-4 text-base`,children:[(0,d.jsx)(n,{className:`size-5`,"aria-hidden":!0}),` Hermes-Dashboard öffnen`]}),t[3]=v):v=t[3];let y;t[4]===Symbol.for(`react.memo_cache_sentinel`)?(y=(0,d.jsx)(i,{className:`size-5`,"aria-hidden":!0}),t[4]=y):y=t[4];let b;t[5]===p?b=t[6]:(b=(0,d.jsxs)(`button`,{type:`button`,onClick:p,className:`flex h-12 items-center gap-3 rounded-lg border border-linie px-4 text-left text-base`,children:[y,` Dienste und Protokolle`]}),t[5]=p,t[6]=b);let x;t[7]===Symbol.for(`react.memo_cache_sentinel`)?(x=(0,d.jsx)(r,{className:`size-5`,"aria-hidden":!0}),t[7]=x):x=t[7];let S;t[8]===m?S=t[9]:(S=(0,d.jsxs)(`button`,{type:`button`,onClick:m,className:`flex h-12 items-center gap-3 rounded-lg border border-linie px-4 text-left text-base`,children:[x,` Einstellungen`]}),t[8]=m,t[9]=S);let C;t[10]!==b||t[11]!==S||t[12]!==f?(C=(0,d.jsxs)(s,{side:`bottom`,className:`border-linie bg-panel pb-[calc(1rem+env(safe-area-inset-bottom))]`,children:[_,(0,d.jsxs)(`div`,{className:`flex flex-col gap-2 px-4`,children:[f,v,b,S]})]}),t[10]=b,t[11]=S,t[12]=f,t[13]=C):C=t[13];let w;return t[14]!==g||t[15]!==C?(w=(0,d.jsx)(l,{open:!0,onOpenChange:g,children:C}),t[14]=g,t[15]=C,t[16]=w):w=t[16],w}export{f as MehrMenue}; \ No newline at end of file diff --git a/frontend/dist/assets/Modelle-CHK2sw1N.js b/frontend/dist/assets/Modelle-CHK2sw1N.js new file mode 100644 index 0000000..d925a95 --- /dev/null +++ b/frontend/dist/assets/Modelle-CHK2sw1N.js @@ -0,0 +1 @@ +import{c as e,f as t,o as n,s as r,t as i,u as a}from"./button-Dd8hfusv.js";import{A as o,I as s,L as c,M as l,S as u,_ as d,b as f,c as p,d as m,g as h,i as g,j as _,k as v,l as y,n as b,o as x,r as S,s as C,t as w,u as T,v as E,w as D,x as O}from"./index-ZVRs0IGR.js";import{a as k,i as A,n as j,r as M,t as N}from"./sheet-DWG2Q04V.js";import{t as P}from"./Bestaetigen-VrcNpcBb.js";var F={name:`search`,size:24,node:[[`path`,{d:`m21 21-4.34-4.34`,key:`14j7rj`}],[`circle`,{cx:`11`,cy:`11`,r:`8`,key:`4ej97u`}]]};F.node;var I=n(F),L=r(),R=t(a(),1),z=e();function B({offen:e,onSchliessen:t}){let n=c(),[r,a]=(0,R.useState)(``),[l,u]=(0,R.useState)(``),[d,f]=(0,R.useState)(null),[p,h]=(0,R.useState)(``),g=s({queryKey:[`hf-suche`,l],queryFn:()=>v(`/api/hf/search?q=${encodeURIComponent(l)}`),enabled:l.length>1}),y=s({queryKey:[`hf-quants`,d],queryFn:()=>v(`/api/hf/quants?repo=${encodeURIComponent(d??``)}`),enabled:!!d});async function b(e){if(d)try{await o(`/api/models/install`,{repo:d,quant:e,role:p||null}),_(`erfolg`,`${d} (${e}) wird heruntergeladen. Den Fortschritt siehst du unter Updates.`),n.invalidateQueries({queryKey:[`jobs`]}),n.invalidateQueries({queryKey:[`models`]}),t()}catch(e){_(`fehler`,e.message)}}let x=(y.data?.quants??[]).map(e=>typeof e==`string`?{quant:e}:e);return(0,z.jsx)(N,{open:e,onOpenChange:e=>!e&&t(),children:(0,z.jsxs)(j,{side:`right`,className:`w-full gap-3 overflow-y-auto border-linie bg-panel sm:max-w-xl`,children:[(0,z.jsxs)(A,{children:[(0,z.jsx)(k,{className:`schild text-lg`,children:`Modelle selbst suchen`}),(0,z.jsx)(M,{className:`text-text-2`,children:`Auf Hugging Face suchen, Quantisierung wählen, installieren.`})]}),(0,z.jsxs)(`form`,{className:`flex gap-2 px-4`,onSubmit:e=>{e.preventDefault(),f(null),u(r.trim())},children:[(0,z.jsx)(`label`,{htmlFor:`hf-suche`,className:`sr-only`,children:`Suchbegriff`}),(0,z.jsx)(`input`,{id:`hf-suche`,value:r,onChange:e=>a(e.target.value),placeholder:`z. B. Qwen3.8 GGUF`,className:`h-11 min-w-0 flex-1 rounded-lg border border-linie-stark bg-erhaben px-3 text-[15px] outline-none focus:border-cyan`}),(0,z.jsx)(i,{type:`submit`,children:`Suchen`})]}),(0,z.jsxs)(`div`,{className:`flex flex-col px-4 pb-4`,children:[g.isFetching&&(0,z.jsx)(`p`,{className:`py-3 text-sm text-text-2`,children:`Suche läuft …`}),!d&&g.data?.results.map(e=>(0,z.jsxs)(`button`,{type:`button`,onClick:()=>f(e.repo),className:`flex min-h-11 items-center justify-between gap-3 border-t border-linie py-2 text-left hover:text-cyan`,children:[(0,z.jsx)(`span`,{className:`ziffern min-w-0 text-sm break-all`,children:e.repo}),(0,z.jsxs)(`span`,{className:`ziffern shrink-0 text-xs text-text-3`,children:[m(e.downloads),` ↓`]})]},e.repo)),d&&(0,z.jsxs)(`div`,{className:`flex flex-col gap-3 pt-2`,children:[(0,z.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,z.jsx)(`span`,{className:`ziffern text-sm break-all`,children:d}),(0,z.jsx)(i,{variant:`ghost`,size:`sm`,onClick:()=>f(null),children:`Zurück`})]}),(0,z.jsxs)(`label`,{className:`flex items-center gap-3 text-sm text-text-2`,children:[`Rolle`,(0,z.jsxs)(`select`,{value:p,onChange:e=>h(e.target.value),className:`h-11 rounded-lg border border-linie-stark bg-erhaben px-3 text-foreground`,children:[(0,z.jsx)(`option`,{value:``,children:`ohne Rolle (nur installieren)`}),(0,z.jsx)(`option`,{value:`coder`,children:`Coder`})]})]}),y.isFetching&&(0,z.jsx)(`p`,{className:`text-sm text-text-2`,children:`Quantisierungen werden gelesen …`}),x.map(e=>{let t=e.quant??e.name??`?`,n=e.total_bytes??e.size_bytes;return(0,z.jsxs)(`div`,{className:`flex items-center justify-between gap-3 border-t border-linie py-2`,children:[(0,z.jsx)(`span`,{className:`ziffern text-sm`,children:t}),(0,z.jsxs)(`span`,{className:`flex items-center gap-3`,children:[n?(0,z.jsxs)(`span`,{className:`ziffern text-xs text-text-3`,children:[(n/1024**3).toFixed(1).replace(`.`,`,`),` GB`]}):null,(0,z.jsx)(i,{variant:`outline`,size:`sm`,onClick:()=>b(t),children:`Installieren`})]})]},t)})]})]})]})})}var V=115;function H(e){let t=(0,L.c)(55),{modelle:n,laufend:r}=e,i=l(),a=D(),o,s,c,u,d,f,p,m,h,g;if(t[0]!==r||t[1]!==i?.ram_total||t[2]!==i?.ram_used||t[3]!==n||t[4]!==a){let e=y(i?.ram_total??a.data?.box.ram_total)??122.7,l=y(i?.ram_used??a.data?.box.ram_used)??0,_;t[15]===r?_=t[16]:(_=e=>r.includes(e.name),t[15]=r,t[16]=_);let v=n.filter(_).reduce(U,0);s=Math.max(0,l-v);let b=t=>`${Math.min(100,t/e*100)}%`;o=w,m=`Speicher`,h=(0,z.jsxs)(`span`,{className:`ziffern text-sm text-text-2`,children:[Math.round(l),` von `,Math.round(e),` GB belegt · Grenze ~`,V,` GB`]});let x=`Speicher: ${Math.round(l)} von ${Math.round(e)} GB belegt`,S=b(l),C;t[17]===S?C=t[18]:(C={width:S},t[17]=S,t[18]=C);let T=`${l?v/l*100:0}%`,E;t[19]===T?E=t[20]:(E=(0,z.jsx)(`div`,{className:`h-full bg-cyan`,style:{width:T}}),t[19]=T,t[20]=E);let D=`${l?s/l*100:0}%`,O;t[21]===D?O=t[22]:(O=(0,z.jsx)(`div`,{className:`h-full bg-cyan/35`,style:{width:D}}),t[21]=D,t[22]=O);let k;t[23]!==C||t[24]!==E||t[25]!==O?(k=(0,z.jsxs)(`div`,{className:`absolute inset-y-0 left-0 flex overflow-hidden rounded-lg`,style:C,children:[E,O]}),t[23]=C,t[24]=E,t[25]=O,t[26]=k):k=t[26];let A=b(V),j;t[27]===A?j=t[28]:(j=(0,z.jsx)(`div`,{className:`absolute -top-1.5 -bottom-1.5 w-0.5 bg-bernstein`,style:{left:A}}),t[27]=A,t[28]=j),t[29]!==x||t[30]!==k||t[31]!==j?(g=(0,z.jsxs)(`div`,{className:`relative h-8 rounded-lg bg-erhaben`,role:`img`,"aria-label":x,children:[k,j]}),t[29]=x,t[30]=k,t[31]=j,t[32]=g):g=t[32],p=`flex flex-wrap gap-x-6 gap-y-2 text-sm text-text-2`,c=`flex items-center gap-2`,t[33]===Symbol.for(`react.memo_cache_sentinel`)?(u=(0,z.jsx)(`span`,{className:`size-2.5 rounded-sm bg-cyan`}),t[33]=u):u=t[33],d=` Geladene Modelle: `,f=Math.round(v),t[0]=r,t[1]=i?.ram_total,t[2]=i?.ram_used,t[3]=n,t[4]=a,t[5]=o,t[6]=s,t[7]=c,t[8]=u,t[9]=d,t[10]=f,t[11]=p,t[12]=m,t[13]=h,t[14]=g}else o=t[5],s=t[6],c=t[7],u=t[8],d=t[9],f=t[10],p=t[11],m=t[12],h=t[13],g=t[14];let _;t[34]!==c||t[35]!==u||t[36]!==d||t[37]!==f?(_=(0,z.jsxs)(`span`,{className:c,children:[u,d,f,` GB Dateien`]}),t[34]=c,t[35]=u,t[36]=d,t[37]=f,t[38]=_):_=t[38];let v;t[39]===Symbol.for(`react.memo_cache_sentinel`)?(v=(0,z.jsx)(`span`,{className:`size-2.5 rounded-sm bg-cyan/35`}),t[39]=v):v=t[39];let b;t[40]===s?b=t[41]:(b=Math.round(s),t[40]=s,t[41]=b);let x;t[42]===b?x=t[43]:(x=(0,z.jsxs)(`span`,{className:`flex items-center gap-2`,children:[v,` Cache, Dienste, System: `,b,` GB`]}),t[42]=b,t[43]=x);let S;t[44]===Symbol.for(`react.memo_cache_sentinel`)?(S=(0,z.jsxs)(`span`,{className:`flex items-center gap-2`,children:[(0,z.jsx)(`span`,{className:`h-3 w-0.5 bg-bernstein`}),` Ab hier wird es eng`]}),t[44]=S):S=t[44];let C;t[45]!==x||t[46]!==p||t[47]!==_?(C=(0,z.jsxs)(`div`,{className:p,children:[_,x,S]}),t[45]=x,t[46]=p,t[47]=_,t[48]=C):C=t[48];let T;return t[49]!==o||t[50]!==C||t[51]!==m||t[52]!==h||t[53]!==g?(T=(0,z.jsxs)(o,{titel:m,rechts:h,children:[g,C]}),t[49]=o,t[50]=C,t[51]=m,t[52]=h,t[53]=g,t[54]=T):T=t[54],T}function U(e,t){return e+(y(t.size_bytes)??0)}function W(e){let t=(0,L.c)(7),{name:n,wert:r}=e,i;t[0]===n?i=t[1]:(i=(0,z.jsx)(`dt`,{className:`text-xs text-text-3`,children:n}),t[0]=n,t[1]=i);let a;t[2]===r?a=t[3]:(a=(0,z.jsx)(`dd`,{className:`ziffern m-0 text-lg`,children:r}),t[2]=r,t[3]=a);let o;return t[4]!==i||t[5]!==a?(o=(0,z.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[i,a]}),t[4]=i,t[5]=a,t[6]=o):o=t[6],o}function G(e){let t=(0,L.c)(47),{titel:n,modell:r,laeuft:a,nutzer:o}=e,s=h();if(!r){let e;t[0]===n?e=t[1]:(e=(0,z.jsx)(`span`,{className:`schild text-sm text-text-3`,children:n}),t[0]=n,t[1]=e);let r;t[2]===Symbol.for(`react.memo_cache_sentinel`)?(r=(0,z.jsx)(x,{children:`Frei`}),t[2]=r):r=t[2];let i;t[3]===e?i=t[4]:(i=(0,z.jsxs)(`div`,{className:`flex items-center justify-between`,children:[e,r]}),t[3]=e,t[4]=i);let a,o;t[5]===Symbol.for(`react.memo_cache_sentinel`)?(a=(0,z.jsx)(`h3`,{className:`font-anzeige text-xl font-semibold text-text-2`,children:`Nicht belegt`}),o=(0,z.jsx)(`p`,{className:`text-sm text-text-2`,children:`Nur belegen, wenn ein Modell hier echten Mehrwert bringt. Das Radar meldet Kandidaten.`}),t[5]=a,t[6]=o):(a=t[5],o=t[6]);let s;return t[7]===i?s=t[8]:(s=(0,z.jsxs)(`article`,{className:`flex flex-col gap-3.5 rounded-2xl border border-dashed border-linie-stark p-5`,children:[i,a,o]}),t[7]=i,t[8]=s),s}let c;t[9]!==r.ctx||t[10]!==r.parallel_slots?(c=r.ctx?Math.round(r.ctx/Math.max(1,r.parallel_slots)/1024):null,t[9]=r.ctx,t[10]=r.parallel_slots,t[11]=c):c=t[11];let l=c,u=!!r.capabilities?.vision,d;t[12]===n?d=t[13]:(d=(0,z.jsx)(`span`,{className:`schild text-sm text-text-3`,children:n}),t[12]=n,t[13]=d);let f=a?`gruen`:`grau`,p=a?`Geladen`:`Auf Abruf`,m;t[14]!==f||t[15]!==p?(m=(0,z.jsx)(x,{art:f,children:p}),t[14]=f,t[15]=p,t[16]=m):m=t[16];let g;t[17]!==d||t[18]!==m?(g=(0,z.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[d,m]}),t[17]=d,t[18]=m,t[19]=g):g=t[19];let _;t[20]===r.name?_=t[21]:(_=(0,z.jsx)(`h3`,{className:`ziffern m-0 text-lg font-medium break-all`,children:r.name}),t[20]=r.name,t[21]=_);let v;t[22]===r.size_bytes?v=t[23]:(v=T(r.size_bytes),t[22]=r.size_bytes,t[23]=v);let y;t[24]===v?y=t[25]:(y=(0,z.jsx)(W,{name:`Größe`,wert:v}),t[24]=v,t[25]=y);let b=l?`${l}k`:`–`,S;t[26]===b?S=t[27]:(S=(0,z.jsx)(W,{name:`Kontext`,wert:b}),t[26]=b,t[27]=S);let C=u?`ja`:`nein`,w;t[28]===C?w=t[29]:(w=(0,z.jsx)(W,{name:`Bilder`,wert:C}),t[28]=C,t[29]=w);let E;t[30]!==S||t[31]!==w||t[32]!==y?(E=(0,z.jsxs)(`dl`,{className:`m-0 grid grid-cols-3 gap-3`,children:[y,S,w]}),t[30]=S,t[31]=w,t[32]=y,t[33]=E):E=t[33];let D=r.spec_active?` Mit Draft-Beschleunigung.`:``,O;t[34]!==o||t[35]!==D?(O=(0,z.jsxs)(`p`,{className:`text-sm text-text-2`,children:[`Genutzt von `,o,`.`,D]}),t[34]=o,t[35]=D,t[36]=O):O=t[36];let k;t[37]!==s||t[38]!==a||t[39]!==r.name?(k=!a&&(0,z.jsx)(i,{variant:`outline`,size:`sm`,className:`mt-auto self-start`,onClick:()=>s.mutate(r.name),disabled:s.isPending,children:`Jetzt laden`}),t[37]=s,t[38]=a,t[39]=r.name,t[40]=k):k=t[40];let A;return t[41]!==E||t[42]!==O||t[43]!==k||t[44]!==g||t[45]!==_?(A=(0,z.jsxs)(`article`,{className:`flex flex-col gap-3.5 rounded-2xl border border-linie bg-panel p-5`,children:[g,_,E,O,k]}),t[41]=E,t[42]=O,t[43]=k,t[44]=g,t[45]=_,t[46]=A):A=t[46],A}function K(e){let t=(0,L.c)(51),{nutzung:n}=e;if(!n)return null;let r;t[0]===n.absender?r=t[1]:(r=Math.max(1,...n.absender.map(X)),t[0]=n.absender,t[1]=r);let i=r,a,o,s,c,l,u,d,f,p,h,g,_;if(t[2]!==i||t[3]!==n.absender||t[4]!==n.letzte_24h||t[5]!==n.tage){let e=n.letzte_24h.map(J),r=Math.max(1,...e);a=w,_=`Wer nutzt die Modelle`,t[18]===n.tage?o=t[19]:(o=(0,z.jsxs)(`span`,{className:`ziffern text-xs text-text-3`,children:[`letzte `,n.tage,` Tage`]}),t[18]=n.tage,t[19]=o),t[20]===n.absender.length?s=t[21]:(s=n.absender.length===0&&(0,z.jsx)(`p`,{className:`text-[15px] text-text-2`,children:`Keine Anfragen aufgezeichnet.`}),t[20]=n.absender.length,t[21]=s);let v;if(t[22]!==i||t[23]!==n.absender){let e;t[25]===i?e=t[26]:(e=e=>(0,z.jsxs)(`li`,{className:`flex flex-col gap-1.5`,children:[(0,z.jsxs)(`div`,{className:`flex justify-between gap-3 text-sm`,children:[(0,z.jsx)(`span`,{children:e.name}),(0,z.jsx)(`span`,{className:`ziffern`,children:m(e.anfragen)})]}),(0,z.jsx)(`div`,{className:`h-2 rounded-full bg-erhaben`,children:(0,z.jsx)(`div`,{className:`h-2 rounded-full bg-cyan`,style:{width:`${e.anfragen/i*100}%`}})})]},e.name),t[25]=i,t[26]=e),v=n.absender.map(e),t[22]=i,t[23]=n.absender,t[24]=v}else v=t[24];t[27]===v?c=t[28]:(c=(0,z.jsx)(`ul`,{className:`m-0 flex list-none flex-col gap-3.5 p-0`,children:v}),t[27]=v,t[28]=c),h=`flex flex-col gap-1.5`,t[29]===Symbol.for(`react.memo_cache_sentinel`)?(g=(0,z.jsx)(`span`,{className:`schild text-xs text-text-3`,children:`Anfragen je Stunde, letzte 24 h`}),t[29]=g):g=t[29],l=`0 0 240 64`,u=`h-16 w-full`,d=`img`,f=`Anfragen je Stunde in den letzten 24 Stunden`;let y;t[30]===r?y=t[31]:(y=(e,t)=>{let n=e?Math.max(3,e/r*50):2;return(0,z.jsx)(`rect`,{x:t*10+1.5,y:52-n,width:7,height:n,rx:1.5,fill:e?`var(--cyan)`:`var(--linie)`},t)},t[30]=r,t[31]=y),p=e.map(y),t[2]=i,t[3]=n.absender,t[4]=n.letzte_24h,t[5]=n.tage,t[6]=a,t[7]=o,t[8]=s,t[9]=c,t[10]=l,t[11]=u,t[12]=d,t[13]=f,t[14]=p,t[15]=h,t[16]=g,t[17]=_}else a=t[6],o=t[7],s=t[8],c=t[9],l=t[10],u=t[11],d=t[12],f=t[13],p=t[14],h=t[15],g=t[16],_=t[17];let v;t[32]===Symbol.for(`react.memo_cache_sentinel`)?(v=[0,6,12,18].map(q),t[32]=v):v=t[32];let y;t[33]!==l||t[34]!==u||t[35]!==d||t[36]!==f||t[37]!==p?(y=(0,z.jsxs)(`svg`,{viewBox:l,className:u,role:d,"aria-label":f,children:[p,v]}),t[33]=l,t[34]=u,t[35]=d,t[36]=f,t[37]=p,t[38]=y):y=t[38];let b;t[39]!==y||t[40]!==h||t[41]!==g?(b=(0,z.jsxs)(`div`,{className:h,children:[g,y]}),t[39]=y,t[40]=h,t[41]=g,t[42]=b):b=t[42];let x;t[43]===Symbol.for(`react.memo_cache_sentinel`)?(x=(0,z.jsx)(`p`,{className:`text-xs text-text-3`,children:`Anfragen an llama-swap. NerdQuiz geht direkt dorthin, alles andere über MC2.`}),t[43]=x):x=t[43];let S;return t[44]!==a||t[45]!==o||t[46]!==s||t[47]!==c||t[48]!==b||t[49]!==_?(S=(0,z.jsxs)(a,{titel:_,rechts:o,children:[s,c,b,x]}),t[44]=a,t[45]=o,t[46]=s,t[47]=c,t[48]=b,t[49]=_,t[50]=S):S=t[50],S}function q(e){return(0,z.jsx)(`text`,{x:e*10+5,y:63,textAnchor:`middle`,style:{fontSize:9,fill:`var(--text-3)`,fontFamily:`var(--font-mono)`},children:e},e)}function J(e){return Object.values(e.je_absender).reduce(Y,0)}function Y(e,t){return e+t}function X(e){return e.anfragen}var Z={bestanden:`gruen`,durchgefallen:`rot`,wartet:`cyan`,neu:`cyan`,getestet:`grau`,uebernommen:`gruen`,verworfen:`grau`},Q={besser:`text-gruen`,schlechter:`text-rot-text`,gleich:`text-text-2`};function $(e){let t=(0,L.c)(4),{test:n}=e,r,i;if(t[0]!==n.vergleich){i=Symbol.for(`react.early_return_sentinel`);bb0:{let e=Object.entries(n.vergleich??{});if(e.length===0){i=null;break bb0}let a;t[3]===Symbol.for(`react.memo_cache_sentinel`)?(a=(0,z.jsxs)(`div`,{role:`row`,className:`schild grid grid-cols-[minmax(0,1fr)_auto_auto] gap-x-4 pb-1 text-xs text-text-3`,children:[(0,z.jsx)(`span`,{role:`columnheader`,children:`Messwert`}),(0,z.jsx)(`span`,{role:`columnheader`,className:`text-right`,children:`Kandidat`}),(0,z.jsx)(`span`,{role:`columnheader`,className:`text-right`,children:`Heute`})]}),t[3]=a):a=t[3],r=(0,z.jsxs)(`div`,{role:`table`,"aria-label":`Messwerte gegen das heutige Modell`,className:`rounded-lg border border-linie bg-erhaben/50 px-3 py-2 text-sm`,children:[a,e.map(ee)]})}t[0]=n.vergleich,t[1]=r,t[2]=i}else r=t[1],i=t[2];return i===Symbol.for(`react.early_return_sentinel`)?r:i}function ee(e){let[t,n]=e;return(0,z.jsxs)(`div`,{role:`row`,className:`grid grid-cols-[minmax(0,1fr)_auto_auto] gap-x-4 border-t border-linie py-1`,children:[(0,z.jsx)(`span`,{role:`rowheader`,className:`text-text-2`,children:t}),(0,z.jsx)(`span`,{role:`cell`,className:`ziffern text-right ${Q[n.urteil??``]??`text-text-2`}`,children:S(n.kandidat,n.einheit)}),(0,z.jsx)(`span`,{role:`cell`,className:`ziffern text-right text-text-3`,children:S(n.baseline,n.einheit)})]},t)}function te(e){let t=(0,L.c)(54),{k:n,test:r,heute:a}=e,o=O(),[s,c]=(0,R.useState)(null),l;t[0]===Symbol.for(`react.memo_cache_sentinel`)?(l=[`bestanden`,`wartet`,`neu`,`getestet`],t[0]=l):l=t[0];let u=l.includes(n.status),d=n.rolle===`hirn`,f;t[1]===n.name?f=t[2]:(f=(0,z.jsx)(`span`,{className:`ziffern text-[15px] font-medium`,children:n.name}),t[1]=n.name,t[2]=f);let p=d?`fürs Hirn`:`fürs Coden`,m;t[3]===p?m=t[4]:(m=(0,z.jsx)(x,{art:`cyan`,children:p}),t[3]=p,t[4]=m);let h=n.eng?`bernstein`:n.passt?`gruen`:`rot`,g=n.eng?`passt knapp`:n.passt?`passt`:`passt nicht`,_;t[5]!==h||t[6]!==g?(_=(0,z.jsx)(x,{art:h,children:g}),t[5]=h,t[6]=g,t[7]=_):_=t[7];let v=Z[n.status]??`grau`,y=b[n.status]??n.status,S;t[8]!==v||t[9]!==y?(S=(0,z.jsx)(x,{art:v,children:y}),t[8]=v,t[9]=y,t[10]=S):S=t[10];let C;t[11]!==S||t[12]!==f||t[13]!==m||t[14]!==_?(C=(0,z.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[f,m,_,S]}),t[11]=S,t[12]=f,t[13]=m,t[14]=_,t[15]=C):C=t[15];let w;t[16]===n.groesse_gb?w=t[17]:(w=n.groesse_gb==null?``:`${n.groesse_gb.toLocaleString(`de-DE`)} GB. `,t[16]=n.groesse_gb,t[17]=w);let T;t[18]!==n.begruendung||t[19]!==w?(T=(0,z.jsxs)(`p`,{className:`text-sm text-text-2`,children:[w,n.begruendung]}),t[18]=n.begruendung,t[19]=w,t[20]=T):T=t[20];let E;t[21]!==n.status||t[22]!==r?(E=r&&[`bestanden`,`durchgefallen`].includes(n.status)&&(0,z.jsx)($,{test:r}),t[21]=n.status,t[22]=r,t[23]=E):E=t[23];let D;t[24]!==o.isPending||t[25]!==n.status||t[26]!==u?(D=u&&(0,z.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[n.status===`bestanden`&&(0,z.jsx)(i,{size:`sm`,disabled:o.isPending,onClick:()=>c(`uebernehmen`),children:`Übernehmen`}),(0,z.jsx)(i,{variant:`outline`,size:`sm`,disabled:o.isPending,onClick:()=>c(`verwerfen`),children:`Verwerfen`})]}),t[24]=o.isPending,t[25]=n.status,t[26]=u,t[27]=D):D=t[27];let k=s===`uebernehmen`,A=`${n.name} übernehmen?`,j=d?`${n.name} wird Lucys Hirn${a?` und löst ${a} ab`:``}. NerdQuiz und OpenChamber nutzen ab dann ebenfalls das neue Modell. Hermes startet dafür kurz neu, Lucy ist etwa eine Minute nicht erreichbar. Das alte Modell bleibt auf der Platte.`:`${n.name} wird der Coder${a?` und löst ${a} ab`:``}. OpenChamber plant und baut ab dann damit. Das alte Modell bleibt auf der Platte.`,M;t[28]===Symbol.for(`react.memo_cache_sentinel`)?(M=()=>c(null),t[28]=M):M=t[28];let N;t[29]!==o||t[30]!==n.id||t[31]!==n.name?(N=()=>{o.mutate({id:n.id,aktion:`uebernehmen`,name:n.name}),c(null)},t[29]=o,t[30]=n.id,t[31]=n.name,t[32]=N):N=t[32];let F;t[33]!==k||t[34]!==A||t[35]!==j||t[36]!==N?(F=(0,z.jsx)(P,{offen:k,titel:A,text:j,knopf:`Übernehmen`,onNein:M,onJa:N}),t[33]=k,t[34]=A,t[35]=j,t[36]=N,t[37]=F):F=t[37];let I=s===`verwerfen`,B=`${n.name} verwerfen?`,V;t[38]===Symbol.for(`react.memo_cache_sentinel`)?(V=()=>c(null),t[38]=V):V=t[38];let H;t[39]!==o||t[40]!==n.id||t[41]!==n.name?(H=()=>{o.mutate({id:n.id,aktion:`verwerfen`,name:n.name}),c(null)},t[39]=o,t[40]=n.id,t[41]=n.name,t[42]=H):H=t[42];let U;t[43]!==I||t[44]!==B||t[45]!==H?(U=(0,z.jsx)(P,{offen:I,gefahr:!0,titel:B,text:`Die heruntergeladenen Dateien werden gelöscht, und das Radar testet dieses Modell nicht noch einmal.`,knopf:`Verwerfen`,onNein:V,onJa:H}),t[43]=I,t[44]=B,t[45]=H,t[46]=U):U=t[46];let W;return t[47]!==C||t[48]!==T||t[49]!==E||t[50]!==D||t[51]!==F||t[52]!==U?(W=(0,z.jsxs)(`li`,{className:`flex flex-col gap-2 border-t border-linie py-3.5`,children:[C,T,E,D,F,U]}),t[47]=C,t[48]=T,t[49]=E,t[50]=D,t[51]=F,t[52]=U,t[53]=W):W=t[53],W}function ne(e){let t=(0,L.c)(21),{hirn:n,coder:r}=e,a=f(),o=u();if(a.isError){let e;return t[0]===Symbol.for(`react.memo_cache_sentinel`)?(e=(0,z.jsx)(w,{titel:`Modell-Radar`,id:`radar`,children:(0,z.jsx)(`p`,{className:`text-[15px] text-text-2`,children:`Das Radar ist auf dieser Box noch nicht eingerichtet.`})}),t[0]=e):e=t[0],e}let s=a.data,c;t[1]===o?c=t[2]:(c=()=>o.mutate(void 0),t[1]=o,t[2]=c);let l;t[3]!==o.isPending||t[4]!==c?(l=(0,z.jsx)(i,{variant:`info`,size:`sm`,onClick:c,disabled:o.isPending,children:`Jetzt suchen`}),t[3]=o.isPending,t[4]=c,t[5]=l):l=t[5];let d;t[6]===s?d=t[7]:(d=s?.naechster_test?` Nächster Test: ${p(s.naechster_test)}.`:``,t[6]=s,t[7]=d);let m;t[8]===d?m=t[9]:(m=(0,z.jsxs)(`p`,{className:`-mt-2 text-sm text-text-2`,children:[`Testet nachts zwischen 00:30 und 02:30 selbst, höchstens einen Kandidaten pro Woche.`,d]}),t[8]=d,t[9]=m);let h;t[10]!==r||t[11]!==s||t[12]!==n?(h=s?s.kandidaten.length===0?(0,z.jsx)(`p`,{className:`text-[15px] text-text-2`,children:`Nichts Besseres in Sicht.`}):(0,z.jsx)(`ul`,{className:`m-0 flex list-none flex-col p-0`,children:s.kandidaten.map(e=>(0,z.jsx)(te,{k:e,test:s.tests.find(t=>t.kandidat===e.id),heute:e.rolle===`hirn`?n:r},e.id))}):(0,z.jsx)(`p`,{className:`text-[15px] text-text-2`,children:`Wird gelesen …`}),t[10]=r,t[11]=s,t[12]=n,t[13]=h):h=t[13];let g;t[14]===s?g=t[15]:(g=s&&s.tests.length>0&&(0,z.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,z.jsx)(`h3`,{className:`schild text-xs text-text-3`,children:`Letzte Tests`}),s.tests.slice(0,3).map(re)]}),t[14]=s,t[15]=g);let _;return t[16]!==l||t[17]!==m||t[18]!==h||t[19]!==g?(_=(0,z.jsxs)(w,{titel:`Modell-Radar`,id:`radar`,rechts:l,children:[m,h,g]}),t[16]=l,t[17]=m,t[18]=h,t[19]=g,t[20]=_):_=t[20],_}function re(e){return(0,z.jsxs)(`p`,{className:`text-sm text-text-2`,children:[(0,z.jsx)(`span`,{className:`ziffern text-text-3`,children:p(e.datum)}),` · `,e.zusammenfassung]},e.id)}function ie(){let e=(0,L.c)(55),t=d(),n=E(),[r,a]=(0,R.useState)(!1);if(t.isPending){let t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t=(0,z.jsx)(C,{text:`Modelle werden gelesen …`}),e[0]=t):t=e[0],t}if(t.error||!t.data){let n=`Die Modell-Liste fehlt: ${t.error?.message??`keine Daten`}`,r;return e[1]===n?r=e[2]:(r=(0,z.jsx)(C,{fehler:!0,text:n}),e[1]=n,e[2]=r),r}let o=t.data.models,s=t.data.running,c,l,u,f,m,h,g,_;if(e[3]!==s||e[4]!==o||e[5]!==n.data){let t=o.find(oe),r=o.find(ae),d=o.filter(e=>e!==t&&e!==r),v;e[14]===n.data?.zuletzt_geladen?v=e[15]:(v=n.data?.zuletzt_geladen??{},e[14]=n.data?.zuletzt_geladen,e[15]=v);let y=v;e[16]!==s||e[17]!==o?(h=(0,z.jsx)(H,{modelle:o,laufend:s}),e[16]=s,e[17]=o,e[18]=h):h=e[18];let b=(0,z.jsx)(G,{titel:`Hirn`,modell:t,laeuft:!!t&&s.includes(t.name),nutzer:`Lucy, NerdQuiz und OpenChamber für Kleinkram`}),x=!!r&&s.includes(r.name),S;e[19]!==r||e[20]!==x?(S=(0,z.jsx)(G,{titel:`Coder`,modell:r,laeuft:x,nutzer:`OpenChamber zum Planen und Bauen und Lucys Delegation`}),e[19]=r,e[20]=x,e[21]=S):S=e[21];let C;e[22]===Symbol.for(`react.memo_cache_sentinel`)?(C=(0,z.jsx)(G,{titel:`Dritte Rolle`,laeuft:!1,nutzer:``}),e[22]=C):C=e[22],e[23]!==S||e[24]!==b?(g=(0,z.jsxs)(`section`,{"aria-label":`Rollen`,className:`grid gap-5 md:grid-cols-3 md:gap-6`,children:[b,S,C]}),e[23]=S,e[24]=b,e[25]=g):g=e[25];let E;e[26]===n.data?E=e[27]:(E=(0,z.jsx)(K,{nutzung:n.data}),e[26]=n.data,e[27]=E);let D=t?.name,O=r?.name,k;e[28]!==D||e[29]!==O?(k=(0,z.jsx)(ne,{hirn:D,coder:O}),e[28]=D,e[29]=O,e[30]=k):k=e[30],e[31]!==E||e[32]!==k?(_=(0,z.jsxs)(`div`,{className:`grid gap-5 md:gap-6 lg:grid-cols-[minmax(0,1fr)_minmax(0,1.3fr)]`,children:[E,k]}),e[31]=E,e[32]=k,e[33]=_):_=e[33],c=w,f=`Weitere Einträge`,e[34]===Symbol.for(`react.memo_cache_sentinel`)?(m=(0,z.jsxs)(i,{variant:`outline`,size:`sm`,onClick:()=>a(!0),children:[(0,z.jsx)(I,{"aria-hidden":!0}),` Modelle selbst suchen`]}),e[34]=m):m=e[34],l=`m-0 flex list-none flex-col p-0`;let A;e[35]!==s||e[36]!==y?(A=e=>(0,z.jsxs)(`li`,{className:`grid grid-cols-[minmax(0,1fr)_auto] items-center gap-3 border-t border-linie py-2.5 sm:grid-cols-[minmax(0,1fr)_120px_160px]`,children:[(0,z.jsxs)(`span`,{className:`min-w-0`,children:[(0,z.jsx)(`span`,{className:`ziffern block text-sm break-all`,children:e.name}),(0,z.jsx)(`span`,{className:`text-xs text-text-3`,children:e.aliases.length?e.aliases.join(`, `):`ohne Rolle`})]}),(0,z.jsx)(`span`,{className:`ziffern text-sm text-text-2`,children:T(e.size_bytes)}),(0,z.jsx)(`span`,{className:`ziffern hidden text-xs text-text-3 sm:block`,children:s.includes(e.name)?`geladen`:y[e.name]?`zuletzt ${p(y[e.name])}`:`länger nicht geladen`})]},e.name),e[35]=s,e[36]=y,e[37]=A):A=e[37],u=d.map(A),e[3]=s,e[4]=o,e[5]=n.data,e[6]=c,e[7]=l,e[8]=u,e[9]=f,e[10]=m,e[11]=h,e[12]=g,e[13]=_}else c=e[6],l=e[7],u=e[8],f=e[9],m=e[10],h=e[11],g=e[12],_=e[13];let v;e[38]!==l||e[39]!==u?(v=(0,z.jsx)(`ul`,{className:l,children:u}),e[38]=l,e[39]=u,e[40]=v):v=e[40];let y;e[41]!==c||e[42]!==f||e[43]!==m||e[44]!==v?(y=(0,z.jsx)(c,{titel:f,rechts:m,children:v}),e[41]=c,e[42]=f,e[43]=m,e[44]=v,e[45]=y):y=e[45];let b;e[46]===Symbol.for(`react.memo_cache_sentinel`)?(b=()=>a(!1),e[46]=b):b=e[46];let x;e[47]===r?x=e[48]:(x=(0,z.jsx)(B,{offen:r,onSchliessen:b}),e[47]=r,e[48]=x);let S;return e[49]!==x||e[50]!==h||e[51]!==g||e[52]!==_||e[53]!==y?(S=(0,z.jsxs)(z.Fragment,{children:[h,g,_,y,x]}),e[49]=x,e[50]=h,e[51]=g,e[52]=_,e[53]=y,e[54]=S):S=e[54],S}function ae(e){return g(e)===`coder`}function oe(e){return g(e)===`hirn`}export{ie as ModelleSeite}; \ No newline at end of file diff --git a/frontend/dist/assets/Modelle-PWfbWtFC.js b/frontend/dist/assets/Modelle-PWfbWtFC.js deleted file mode 100644 index b09ef75..0000000 --- a/frontend/dist/assets/Modelle-PWfbWtFC.js +++ /dev/null @@ -1 +0,0 @@ -import{c as e,f as t,o as n,s as r,t as i,u as a}from"./button-Dd8hfusv.js";import{A as o,D as s,F as c,O as l,P as u,S as d,a as f,b as p,c as m,g as h,h as g,i as _,k as v,l as y,m as b,n as x,o as S,s as C,t as w,v as T,y as E}from"./index-B6MevgIX.js";import{a as D,i as O,n as k,r as A,t as j}from"./sheet-DWG2Q04V.js";var M={name:`search`,size:24,node:[[`path`,{d:`m21 21-4.34-4.34`,key:`14j7rj`}],[`circle`,{cx:`11`,cy:`11`,r:`8`,key:`4ej97u`}]]};M.node;var N=n(M),P=r(),F=t(a(),1),I=e();function L({offen:e,onSchliessen:t}){let n=c(),[r,a]=(0,F.useState)(``),[o,d]=(0,F.useState)(``),[f,p]=(0,F.useState)(null),[m,h]=(0,F.useState)(``),g=u({queryKey:[`hf-suche`,o],queryFn:()=>s(`/api/hf/search?q=${encodeURIComponent(o)}`),enabled:o.length>1}),_=u({queryKey:[`hf-quants`,f],queryFn:()=>s(`/api/hf/quants?repo=${encodeURIComponent(f??``)}`),enabled:!!f});async function b(e){if(f)try{await l(`/api/models/install`,{repo:f,quant:e,role:m||null}),v(`erfolg`,`${f} (${e}) wird heruntergeladen. Den Fortschritt siehst du unter Updates.`),n.invalidateQueries({queryKey:[`jobs`]}),n.invalidateQueries({queryKey:[`models`]}),t()}catch(e){v(`fehler`,e.message)}}let x=(_.data?.quants??[]).map(e=>typeof e==`string`?{quant:e}:e);return(0,I.jsx)(j,{open:e,onOpenChange:e=>!e&&t(),children:(0,I.jsxs)(k,{side:`right`,className:`w-full gap-3 overflow-y-auto border-linie bg-panel sm:max-w-xl`,children:[(0,I.jsxs)(O,{children:[(0,I.jsx)(D,{className:`schild text-lg`,children:`Modelle selbst suchen`}),(0,I.jsx)(A,{className:`text-text-2`,children:`Auf Hugging Face suchen, Quantisierung wählen, installieren.`})]}),(0,I.jsxs)(`form`,{className:`flex gap-2 px-4`,onSubmit:e=>{e.preventDefault(),p(null),d(r.trim())},children:[(0,I.jsx)(`label`,{htmlFor:`hf-suche`,className:`sr-only`,children:`Suchbegriff`}),(0,I.jsx)(`input`,{id:`hf-suche`,value:r,onChange:e=>a(e.target.value),placeholder:`z. B. Qwen3.8 GGUF`,className:`h-11 min-w-0 flex-1 rounded-lg border border-linie-stark bg-erhaben px-3 text-[15px] outline-none focus:border-cyan`}),(0,I.jsx)(i,{type:`submit`,children:`Suchen`})]}),(0,I.jsxs)(`div`,{className:`flex flex-col px-4 pb-4`,children:[g.isFetching&&(0,I.jsx)(`p`,{className:`py-3 text-sm text-text-2`,children:`Suche läuft …`}),!f&&g.data?.results.map(e=>(0,I.jsxs)(`button`,{type:`button`,onClick:()=>p(e.repo),className:`flex min-h-11 items-center justify-between gap-3 border-t border-linie py-2 text-left hover:text-cyan`,children:[(0,I.jsx)(`span`,{className:`ziffern min-w-0 text-sm break-all`,children:e.repo}),(0,I.jsxs)(`span`,{className:`ziffern shrink-0 text-xs text-text-3`,children:[y(e.downloads),` ↓`]})]},e.repo)),f&&(0,I.jsxs)(`div`,{className:`flex flex-col gap-3 pt-2`,children:[(0,I.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,I.jsx)(`span`,{className:`ziffern text-sm break-all`,children:f}),(0,I.jsx)(i,{variant:`ghost`,size:`sm`,onClick:()=>p(null),children:`Zurück`})]}),(0,I.jsxs)(`label`,{className:`flex items-center gap-3 text-sm text-text-2`,children:[`Rolle`,(0,I.jsxs)(`select`,{value:m,onChange:e=>h(e.target.value),className:`h-11 rounded-lg border border-linie-stark bg-erhaben px-3 text-foreground`,children:[(0,I.jsx)(`option`,{value:``,children:`ohne Rolle (nur installieren)`}),(0,I.jsx)(`option`,{value:`coder`,children:`Coder`})]})]}),_.isFetching&&(0,I.jsx)(`p`,{className:`text-sm text-text-2`,children:`Quantisierungen werden gelesen …`}),x.map(e=>{let t=e.quant??e.name??`?`,n=e.total_bytes??e.size_bytes;return(0,I.jsxs)(`div`,{className:`flex items-center justify-between gap-3 border-t border-linie py-2`,children:[(0,I.jsx)(`span`,{className:`ziffern text-sm`,children:t}),(0,I.jsxs)(`span`,{className:`flex items-center gap-3`,children:[n?(0,I.jsxs)(`span`,{className:`ziffern text-xs text-text-3`,children:[(n/1024**3).toFixed(1).replace(`.`,`,`),` GB`]}):null,(0,I.jsx)(i,{variant:`outline`,size:`sm`,onClick:()=>b(t),children:`Installieren`})]})]},t)})]})]})]})})}var R=115;function z(e){let t=(0,P.c)(55),{modelle:n,laufend:r}=e,i=o(),a=d(),s,c,l,u,f,p,m,h,g,_;if(t[0]!==r||t[1]!==i?.ram_total||t[2]!==i?.ram_used||t[3]!==n||t[4]!==a){let e=C(i?.ram_total??a.data?.box.ram_total)??122.7,o=C(i?.ram_used??a.data?.box.ram_used)??0,d;t[15]===r?d=t[16]:(d=e=>r.includes(e.name),t[15]=r,t[16]=d);let v=n.filter(d).reduce(B,0);c=Math.max(0,o-v);let y=t=>`${Math.min(100,t/e*100)}%`;s=w,h=`Speicher`,g=(0,I.jsxs)(`span`,{className:`ziffern text-sm text-text-2`,children:[Math.round(o),` von `,Math.round(e),` GB belegt · Grenze ~`,R,` GB`]});let b=`Speicher: ${Math.round(o)} von ${Math.round(e)} GB belegt`,x=y(o),S;t[17]===x?S=t[18]:(S={width:x},t[17]=x,t[18]=S);let T=`${o?v/o*100:0}%`,E;t[19]===T?E=t[20]:(E=(0,I.jsx)(`div`,{className:`h-full bg-cyan`,style:{width:T}}),t[19]=T,t[20]=E);let D=`${o?c/o*100:0}%`,O;t[21]===D?O=t[22]:(O=(0,I.jsx)(`div`,{className:`h-full bg-cyan/35`,style:{width:D}}),t[21]=D,t[22]=O);let k;t[23]!==S||t[24]!==E||t[25]!==O?(k=(0,I.jsxs)(`div`,{className:`absolute inset-y-0 left-0 flex overflow-hidden rounded-lg`,style:S,children:[E,O]}),t[23]=S,t[24]=E,t[25]=O,t[26]=k):k=t[26];let A=y(R),j;t[27]===A?j=t[28]:(j=(0,I.jsx)(`div`,{className:`absolute -top-1.5 -bottom-1.5 w-0.5 bg-bernstein`,style:{left:A}}),t[27]=A,t[28]=j),t[29]!==b||t[30]!==k||t[31]!==j?(_=(0,I.jsxs)(`div`,{className:`relative h-8 rounded-lg bg-erhaben`,role:`img`,"aria-label":b,children:[k,j]}),t[29]=b,t[30]=k,t[31]=j,t[32]=_):_=t[32],m=`flex flex-wrap gap-x-6 gap-y-2 text-sm text-text-2`,l=`flex items-center gap-2`,t[33]===Symbol.for(`react.memo_cache_sentinel`)?(u=(0,I.jsx)(`span`,{className:`size-2.5 rounded-sm bg-cyan`}),t[33]=u):u=t[33],f=` Geladene Modelle: `,p=Math.round(v),t[0]=r,t[1]=i?.ram_total,t[2]=i?.ram_used,t[3]=n,t[4]=a,t[5]=s,t[6]=c,t[7]=l,t[8]=u,t[9]=f,t[10]=p,t[11]=m,t[12]=h,t[13]=g,t[14]=_}else s=t[5],c=t[6],l=t[7],u=t[8],f=t[9],p=t[10],m=t[11],h=t[12],g=t[13],_=t[14];let v;t[34]!==l||t[35]!==u||t[36]!==f||t[37]!==p?(v=(0,I.jsxs)(`span`,{className:l,children:[u,f,p,` GB Dateien`]}),t[34]=l,t[35]=u,t[36]=f,t[37]=p,t[38]=v):v=t[38];let y;t[39]===Symbol.for(`react.memo_cache_sentinel`)?(y=(0,I.jsx)(`span`,{className:`size-2.5 rounded-sm bg-cyan/35`}),t[39]=y):y=t[39];let b;t[40]===c?b=t[41]:(b=Math.round(c),t[40]=c,t[41]=b);let x;t[42]===b?x=t[43]:(x=(0,I.jsxs)(`span`,{className:`flex items-center gap-2`,children:[y,` Cache, Dienste, System: `,b,` GB`]}),t[42]=b,t[43]=x);let S;t[44]===Symbol.for(`react.memo_cache_sentinel`)?(S=(0,I.jsxs)(`span`,{className:`flex items-center gap-2`,children:[(0,I.jsx)(`span`,{className:`h-3 w-0.5 bg-bernstein`}),` Ab hier wird es eng`]}),t[44]=S):S=t[44];let T;t[45]!==x||t[46]!==m||t[47]!==v?(T=(0,I.jsxs)(`div`,{className:m,children:[v,x,S]}),t[45]=x,t[46]=m,t[47]=v,t[48]=T):T=t[48];let E;return t[49]!==s||t[50]!==T||t[51]!==h||t[52]!==g||t[53]!==_?(E=(0,I.jsxs)(s,{titel:h,rechts:g,children:[_,T]}),t[49]=s,t[50]=T,t[51]=h,t[52]=g,t[53]=_,t[54]=E):E=t[54],E}function B(e,t){return e+(C(t.size_bytes)??0)}function V(e){let t=(0,P.c)(7),{name:n,wert:r}=e,i;t[0]===n?i=t[1]:(i=(0,I.jsx)(`dt`,{className:`text-xs text-text-3`,children:n}),t[0]=n,t[1]=i);let a;t[2]===r?a=t[3]:(a=(0,I.jsx)(`dd`,{className:`ziffern m-0 text-lg`,children:r}),t[2]=r,t[3]=a);let o;return t[4]!==i||t[5]!==a?(o=(0,I.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[i,a]}),t[4]=i,t[5]=a,t[6]=o):o=t[6],o}function H(e){let t=(0,P.c)(47),{titel:n,modell:r,laeuft:a,nutzer:o}=e,s=b();if(!r){let e;t[0]===n?e=t[1]:(e=(0,I.jsx)(`span`,{className:`schild text-sm text-text-3`,children:n}),t[0]=n,t[1]=e);let r;t[2]===Symbol.for(`react.memo_cache_sentinel`)?(r=(0,I.jsx)(_,{children:`Frei`}),t[2]=r):r=t[2];let i;t[3]===e?i=t[4]:(i=(0,I.jsxs)(`div`,{className:`flex items-center justify-between`,children:[e,r]}),t[3]=e,t[4]=i);let a,o;t[5]===Symbol.for(`react.memo_cache_sentinel`)?(a=(0,I.jsx)(`h3`,{className:`font-anzeige text-xl font-semibold text-text-2`,children:`Nicht belegt`}),o=(0,I.jsx)(`p`,{className:`text-sm text-text-2`,children:`Nur belegen, wenn ein Modell hier echten Mehrwert bringt. Das Radar meldet Kandidaten.`}),t[5]=a,t[6]=o):(a=t[5],o=t[6]);let s;return t[7]===i?s=t[8]:(s=(0,I.jsxs)(`article`,{className:`flex flex-col gap-3.5 rounded-2xl border border-dashed border-linie-stark p-5`,children:[i,a,o]}),t[7]=i,t[8]=s),s}let c;t[9]!==r.ctx||t[10]!==r.parallel_slots?(c=r.ctx?Math.round(r.ctx/Math.max(1,r.parallel_slots)/1024):null,t[9]=r.ctx,t[10]=r.parallel_slots,t[11]=c):c=t[11];let l=c,u=!!r.capabilities?.vision,d;t[12]===n?d=t[13]:(d=(0,I.jsx)(`span`,{className:`schild text-sm text-text-3`,children:n}),t[12]=n,t[13]=d);let f=a?`gruen`:`grau`,p=a?`Geladen`:`Auf Abruf`,h;t[14]!==f||t[15]!==p?(h=(0,I.jsx)(_,{art:f,children:p}),t[14]=f,t[15]=p,t[16]=h):h=t[16];let g;t[17]!==d||t[18]!==h?(g=(0,I.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[d,h]}),t[17]=d,t[18]=h,t[19]=g):g=t[19];let v;t[20]===r.name?v=t[21]:(v=(0,I.jsx)(`h3`,{className:`ziffern m-0 text-lg font-medium break-all`,children:r.name}),t[20]=r.name,t[21]=v);let y;t[22]===r.size_bytes?y=t[23]:(y=m(r.size_bytes),t[22]=r.size_bytes,t[23]=y);let x;t[24]===y?x=t[25]:(x=(0,I.jsx)(V,{name:`Größe`,wert:y}),t[24]=y,t[25]=x);let S=l?`${l}k`:`–`,C;t[26]===S?C=t[27]:(C=(0,I.jsx)(V,{name:`Kontext`,wert:S}),t[26]=S,t[27]=C);let w=u?`ja`:`nein`,T;t[28]===w?T=t[29]:(T=(0,I.jsx)(V,{name:`Bilder`,wert:w}),t[28]=w,t[29]=T);let E;t[30]!==C||t[31]!==T||t[32]!==x?(E=(0,I.jsxs)(`dl`,{className:`m-0 grid grid-cols-3 gap-3`,children:[x,C,T]}),t[30]=C,t[31]=T,t[32]=x,t[33]=E):E=t[33];let D=r.spec_active?` Mit Draft-Beschleunigung.`:``,O;t[34]!==o||t[35]!==D?(O=(0,I.jsxs)(`p`,{className:`text-sm text-text-2`,children:[`Genutzt von `,o,`.`,D]}),t[34]=o,t[35]=D,t[36]=O):O=t[36];let k;t[37]!==s||t[38]!==a||t[39]!==r.name?(k=!a&&(0,I.jsx)(i,{variant:`outline`,size:`sm`,className:`mt-auto self-start`,onClick:()=>s.mutate(r.name),disabled:s.isPending,children:`Jetzt laden`}),t[37]=s,t[38]=a,t[39]=r.name,t[40]=k):k=t[40];let A;return t[41]!==E||t[42]!==O||t[43]!==k||t[44]!==g||t[45]!==v?(A=(0,I.jsxs)(`article`,{className:`flex flex-col gap-3.5 rounded-2xl border border-linie bg-panel p-5`,children:[g,v,E,O,k]}),t[41]=E,t[42]=O,t[43]=k,t[44]=g,t[45]=v,t[46]=A):A=t[46],A}function U(e){let t=(0,P.c)(51),{nutzung:n}=e;if(!n)return null;let r;t[0]===n.absender?r=t[1]:(r=Math.max(1,...n.absender.map(q)),t[0]=n.absender,t[1]=r);let i=r,a,o,s,c,l,u,d,f,p,m,h,g;if(t[2]!==i||t[3]!==n.absender||t[4]!==n.letzte_24h||t[5]!==n.tage){let e=n.letzte_24h.map(G),r=Math.max(1,...e);a=w,g=`Wer nutzt die Modelle`,t[18]===n.tage?o=t[19]:(o=(0,I.jsxs)(`span`,{className:`ziffern text-xs text-text-3`,children:[`letzte `,n.tage,` Tage`]}),t[18]=n.tage,t[19]=o),t[20]===n.absender.length?s=t[21]:(s=n.absender.length===0&&(0,I.jsx)(`p`,{className:`text-[15px] text-text-2`,children:`Keine Anfragen aufgezeichnet.`}),t[20]=n.absender.length,t[21]=s);let _;if(t[22]!==i||t[23]!==n.absender){let e;t[25]===i?e=t[26]:(e=e=>(0,I.jsxs)(`li`,{className:`flex flex-col gap-1.5`,children:[(0,I.jsxs)(`div`,{className:`flex justify-between gap-3 text-sm`,children:[(0,I.jsx)(`span`,{children:e.name}),(0,I.jsx)(`span`,{className:`ziffern`,children:y(e.anfragen)})]}),(0,I.jsx)(`div`,{className:`h-2 rounded-full bg-erhaben`,children:(0,I.jsx)(`div`,{className:`h-2 rounded-full bg-cyan`,style:{width:`${e.anfragen/i*100}%`}})})]},e.name),t[25]=i,t[26]=e),_=n.absender.map(e),t[22]=i,t[23]=n.absender,t[24]=_}else _=t[24];t[27]===_?c=t[28]:(c=(0,I.jsx)(`ul`,{className:`m-0 flex list-none flex-col gap-3.5 p-0`,children:_}),t[27]=_,t[28]=c),m=`flex flex-col gap-1.5`,t[29]===Symbol.for(`react.memo_cache_sentinel`)?(h=(0,I.jsx)(`span`,{className:`schild text-xs text-text-3`,children:`Anfragen je Stunde, letzte 24 h`}),t[29]=h):h=t[29],l=`0 0 240 64`,u=`h-16 w-full`,d=`img`,f=`Anfragen je Stunde in den letzten 24 Stunden`;let v;t[30]===r?v=t[31]:(v=(e,t)=>{let n=e?Math.max(3,e/r*50):2;return(0,I.jsx)(`rect`,{x:t*10+1.5,y:52-n,width:7,height:n,rx:1.5,fill:e?`var(--cyan)`:`var(--linie)`},t)},t[30]=r,t[31]=v),p=e.map(v),t[2]=i,t[3]=n.absender,t[4]=n.letzte_24h,t[5]=n.tage,t[6]=a,t[7]=o,t[8]=s,t[9]=c,t[10]=l,t[11]=u,t[12]=d,t[13]=f,t[14]=p,t[15]=m,t[16]=h,t[17]=g}else a=t[6],o=t[7],s=t[8],c=t[9],l=t[10],u=t[11],d=t[12],f=t[13],p=t[14],m=t[15],h=t[16],g=t[17];let _;t[32]===Symbol.for(`react.memo_cache_sentinel`)?(_=[0,6,12,18].map(W),t[32]=_):_=t[32];let v;t[33]!==l||t[34]!==u||t[35]!==d||t[36]!==f||t[37]!==p?(v=(0,I.jsxs)(`svg`,{viewBox:l,className:u,role:d,"aria-label":f,children:[p,_]}),t[33]=l,t[34]=u,t[35]=d,t[36]=f,t[37]=p,t[38]=v):v=t[38];let b;t[39]!==v||t[40]!==m||t[41]!==h?(b=(0,I.jsxs)(`div`,{className:m,children:[h,v]}),t[39]=v,t[40]=m,t[41]=h,t[42]=b):b=t[42];let x;t[43]===Symbol.for(`react.memo_cache_sentinel`)?(x=(0,I.jsx)(`p`,{className:`text-xs text-text-3`,children:`Anfragen an llama-swap. NerdQuiz geht direkt dorthin, alles andere über MC2.`}),t[43]=x):x=t[43];let S;return t[44]!==a||t[45]!==o||t[46]!==s||t[47]!==c||t[48]!==b||t[49]!==g?(S=(0,I.jsxs)(a,{titel:g,rechts:o,children:[s,c,b,x]}),t[44]=a,t[45]=o,t[46]=s,t[47]=c,t[48]=b,t[49]=g,t[50]=S):S=t[50],S}function W(e){return(0,I.jsx)(`text`,{x:e*10+5,y:63,textAnchor:`middle`,style:{fontSize:9,fill:`var(--text-3)`,fontFamily:`var(--font-mono)`},children:e},e)}function G(e){return Object.values(e.je_absender).reduce(K,0)}function K(e,t){return e+t}function q(e){return e.anfragen}var J={bestanden:`gruen`,durchgefallen:`rot`,wartet:`cyan`,neu:`cyan`,getestet:`grau`,uebernommen:`gruen`,verworfen:`grau`};function Y(e){let t=(0,P.c)(31),{k:n}=e,r=E(),a;t[0]===Symbol.for(`react.memo_cache_sentinel`)?(a=[`bestanden`,`wartet`,`neu`],t[0]=a):a=t[0];let o=a.includes(n.status),s;t[1]===n.name?s=t[2]:(s=(0,I.jsx)(`span`,{className:`ziffern text-[15px] font-medium`,children:n.name}),t[1]=n.name,t[2]=s);let c=n.rolle===`hirn`?`fürs Hirn`:`fürs Coden`,l;t[3]===c?l=t[4]:(l=(0,I.jsx)(_,{art:`cyan`,children:c}),t[3]=c,t[4]=l);let u=n.eng?`bernstein`:n.passt?`gruen`:`rot`,d=n.eng?`passt knapp`:n.passt?`passt`:`passt nicht`,f;t[5]!==u||t[6]!==d?(f=(0,I.jsx)(_,{art:u,children:d}),t[5]=u,t[6]=d,t[7]=f):f=t[7];let p=J[n.status]??`grau`,m;t[8]!==n.status||t[9]!==p?(m=(0,I.jsx)(_,{art:p,children:n.status}),t[8]=n.status,t[9]=p,t[10]=m):m=t[10];let h;t[11]!==s||t[12]!==l||t[13]!==f||t[14]!==m?(h=(0,I.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[s,l,f,m]}),t[11]=s,t[12]=l,t[13]=f,t[14]=m,t[15]=h):h=t[15];let g;t[16]===n.groesse_gb?g=t[17]:(g=n.groesse_gb==null?``:`${n.groesse_gb.toLocaleString(`de-DE`)} GB. `,t[16]=n.groesse_gb,t[17]=g);let v;t[18]!==n.begruendung||t[19]!==g?(v=(0,I.jsxs)(`p`,{className:`text-sm text-text-2`,children:[g,n.begruendung]}),t[18]=n.begruendung,t[19]=g,t[20]=v):v=t[20];let y;t[21]!==r||t[22]!==n.id||t[23]!==n.name||t[24]!==n.status||t[25]!==o?(y=o&&(0,I.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[n.status===`bestanden`&&(0,I.jsx)(i,{size:`sm`,disabled:r.isPending,onClick:()=>r.mutate({id:n.id,aktion:`uebernehmen`,name:n.name}),children:`Übernehmen`}),(0,I.jsx)(i,{variant:`outline`,size:`sm`,disabled:r.isPending,onClick:()=>r.mutate({id:n.id,aktion:`verwerfen`,name:n.name}),children:`Verwerfen`})]}),t[21]=r,t[22]=n.id,t[23]=n.name,t[24]=n.status,t[25]=o,t[26]=y):y=t[26];let b;return t[27]!==h||t[28]!==v||t[29]!==y?(b=(0,I.jsxs)(`li`,{className:`flex flex-col gap-2 border-t border-linie py-3.5`,children:[h,v,y]}),t[27]=h,t[28]=v,t[29]=y,t[30]=b):b=t[30],b}function X(){let e=(0,P.c)(18),t=T(),n=p();if(t.isError){let t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t=(0,I.jsx)(w,{titel:`Modell-Radar`,id:`radar`,children:(0,I.jsx)(`p`,{className:`text-[15px] text-text-2`,children:`Das Radar ist auf dieser Box noch nicht eingerichtet.`})}),e[0]=t):t=e[0],t}let r=t.data,a;e[1]===n?a=e[2]:(a=()=>n.mutate(void 0),e[1]=n,e[2]=a);let o;e[3]!==n.isPending||e[4]!==a?(o=(0,I.jsx)(i,{variant:`info`,size:`sm`,onClick:a,disabled:n.isPending,children:`Jetzt suchen`}),e[3]=n.isPending,e[4]=a,e[5]=o):o=e[5];let s;e[6]===r?s=e[7]:(s=r?.naechster_test?` Nächster Test: ${S(r.naechster_test)}.`:``,e[6]=r,e[7]=s);let c;e[8]===s?c=e[9]:(c=(0,I.jsxs)(`p`,{className:`-mt-2 text-sm text-text-2`,children:[`Testet nachts zwischen 00:30 und 02:30 selbst, höchstens einen Kandidaten pro Woche.`,s]}),e[8]=s,e[9]=c);let l,u;e[10]===r?(l=e[11],u=e[12]):(l=r?r.kandidaten.length===0?(0,I.jsx)(`p`,{className:`text-[15px] text-text-2`,children:`Nichts Besseres in Sicht.`}):(0,I.jsx)(`ul`,{className:`m-0 flex list-none flex-col p-0`,children:r.kandidaten.map(Q)}):(0,I.jsx)(`p`,{className:`text-[15px] text-text-2`,children:`Wird gelesen …`}),u=r&&r.tests.length>0&&(0,I.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,I.jsx)(`h3`,{className:`schild text-xs text-text-3`,children:`Letzte Tests`}),r.tests.slice(0,3).map(Z)]}),e[10]=r,e[11]=l,e[12]=u);let d;return e[13]!==o||e[14]!==c||e[15]!==l||e[16]!==u?(d=(0,I.jsxs)(w,{titel:`Modell-Radar`,id:`radar`,rechts:o,children:[c,l,u]}),e[13]=o,e[14]=c,e[15]=l,e[16]=u,e[17]=d):d=e[17],d}function Z(e){return(0,I.jsxs)(`p`,{className:`text-sm text-text-2`,children:[(0,I.jsx)(`span`,{className:`ziffern text-text-3`,children:S(e.datum)}),` · `,e.zusammenfassung]},e.id)}function Q(e){return(0,I.jsx)(Y,{k:e},e.id)}function $(){let e=(0,P.c)(52),t=g(),n=h(),[r,a]=(0,F.useState)(!1);if(t.isPending){let t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t=(0,I.jsx)(f,{text:`Modelle werden gelesen …`}),e[0]=t):t=e[0],t}if(t.error||!t.data){let n=`Die Modell-Liste fehlt: ${t.error?.message??`keine Daten`}`,r;return e[1]===n?r=e[2]:(r=(0,I.jsx)(f,{fehler:!0,text:n}),e[1]=n,e[2]=r),r}let o=t.data.models,s=t.data.running,c,l,u,d,p,_,v,y;if(e[3]!==s||e[4]!==o||e[5]!==n.data){let t=o.find(te),r=o.find(ee),f=o.filter(e=>e!==t&&e!==r),h;e[14]===n.data?.zuletzt_geladen?h=e[15]:(h=n.data?.zuletzt_geladen??{},e[14]=n.data?.zuletzt_geladen,e[15]=h);let g=h;e[16]!==s||e[17]!==o?(_=(0,I.jsx)(z,{modelle:o,laufend:s}),e[16]=s,e[17]=o,e[18]=_):_=e[18];let b=(0,I.jsx)(H,{titel:`Hirn`,modell:t,laeuft:!!t&&s.includes(t.name),nutzer:`Lucy, NerdQuiz und OpenChamber für Kleinkram`}),x=!!r&&s.includes(r.name),C;e[19]!==r||e[20]!==x?(C=(0,I.jsx)(H,{titel:`Coder`,modell:r,laeuft:x,nutzer:`OpenChamber zum Planen und Bauen und Lucys Delegation`}),e[19]=r,e[20]=x,e[21]=C):C=e[21];let T;e[22]===Symbol.for(`react.memo_cache_sentinel`)?(T=(0,I.jsx)(H,{titel:`Dritte Rolle`,laeuft:!1,nutzer:``}),e[22]=T):T=e[22],e[23]!==C||e[24]!==b?(v=(0,I.jsxs)(`section`,{"aria-label":`Rollen`,className:`grid gap-5 md:grid-cols-3 md:gap-6`,children:[b,C,T]}),e[23]=C,e[24]=b,e[25]=v):v=e[25];let E;e[26]===n.data?E=e[27]:(E=(0,I.jsx)(U,{nutzung:n.data}),e[26]=n.data,e[27]=E);let D;e[28]===Symbol.for(`react.memo_cache_sentinel`)?(D=(0,I.jsx)(X,{}),e[28]=D):D=e[28],e[29]===E?y=e[30]:(y=(0,I.jsxs)(`div`,{className:`grid gap-5 md:gap-6 lg:grid-cols-[minmax(0,1fr)_minmax(0,1.3fr)]`,children:[E,D]}),e[29]=E,e[30]=y),c=w,d=`Weitere Einträge`,e[31]===Symbol.for(`react.memo_cache_sentinel`)?(p=(0,I.jsxs)(i,{variant:`outline`,size:`sm`,onClick:()=>a(!0),children:[(0,I.jsx)(N,{"aria-hidden":!0}),` Modelle selbst suchen`]}),e[31]=p):p=e[31],l=`m-0 flex list-none flex-col p-0`;let O;e[32]!==s||e[33]!==g?(O=e=>(0,I.jsxs)(`li`,{className:`grid grid-cols-[minmax(0,1fr)_auto] items-center gap-3 border-t border-linie py-2.5 sm:grid-cols-[minmax(0,1fr)_120px_160px]`,children:[(0,I.jsxs)(`span`,{className:`min-w-0`,children:[(0,I.jsx)(`span`,{className:`ziffern block text-sm break-all`,children:e.name}),(0,I.jsx)(`span`,{className:`text-xs text-text-3`,children:e.aliases.length?e.aliases.join(`, `):`ohne Rolle`})]}),(0,I.jsx)(`span`,{className:`ziffern text-sm text-text-2`,children:m(e.size_bytes)}),(0,I.jsx)(`span`,{className:`ziffern hidden text-xs text-text-3 sm:block`,children:s.includes(e.name)?`geladen`:g[e.name]?`zuletzt ${S(g[e.name])}`:`länger nicht geladen`})]},e.name),e[32]=s,e[33]=g,e[34]=O):O=e[34],u=f.map(O),e[3]=s,e[4]=o,e[5]=n.data,e[6]=c,e[7]=l,e[8]=u,e[9]=d,e[10]=p,e[11]=_,e[12]=v,e[13]=y}else c=e[6],l=e[7],u=e[8],d=e[9],p=e[10],_=e[11],v=e[12],y=e[13];let b;e[35]!==l||e[36]!==u?(b=(0,I.jsx)(`ul`,{className:l,children:u}),e[35]=l,e[36]=u,e[37]=b):b=e[37];let x;e[38]!==c||e[39]!==d||e[40]!==p||e[41]!==b?(x=(0,I.jsx)(c,{titel:d,rechts:p,children:b}),e[38]=c,e[39]=d,e[40]=p,e[41]=b,e[42]=x):x=e[42];let C;e[43]===Symbol.for(`react.memo_cache_sentinel`)?(C=()=>a(!1),e[43]=C):C=e[43];let T;e[44]===r?T=e[45]:(T=(0,I.jsx)(L,{offen:r,onSchliessen:C}),e[44]=r,e[45]=T);let E;return e[46]!==T||e[47]!==_||e[48]!==v||e[49]!==y||e[50]!==x?(E=(0,I.jsxs)(I.Fragment,{children:[_,v,y,x,T]}),e[46]=T,e[47]=_,e[48]=v,e[49]=y,e[50]=x,e[51]=E):E=e[51],E}function ee(e){return x(e)===`coder`}function te(e){return x(e)===`hirn`}export{$ as ModelleSeite}; \ No newline at end of file diff --git a/frontend/dist/assets/Updates-3PYj6oWY.js b/frontend/dist/assets/Updates-3PYj6oWY.js deleted file mode 100644 index 22f2d4a..0000000 --- a/frontend/dist/assets/Updates-3PYj6oWY.js +++ /dev/null @@ -1,2 +0,0 @@ -import{a as e,c as t,f as n,i as r,s as i,t as a,u as o}from"./button-Dd8hfusv.js";import{a as s,i as c,n as l,o as u,r as d,s as f,t as p}from"./dist-CgRgLCFz.js";import{C as m,E as h,S as g,T as _,a as v,d as y,f as b,i as x,o as S,p as C,r as w,t as T,w as E,x as D}from"./index-B6MevgIX.js";var O=i(),k=n(o(),1),A=t();function j(e){let t=(0,O.c)(4),n;t[0]===e?n=t[1]:({...n}=e,t[0]=e,t[1]=n);let r;return t[2]===n?r=t[3]:(r=(0,A.jsx)(p,{"data-slot":`dialog`,...n}),t[2]=n,t[3]=r),r}function M(e){let t=(0,O.c)(4),n;t[0]===e?n=t[1]:({...n}=e,t[0]=e,t[1]=n);let r;return t[2]===n?r=t[3]:(r=(0,A.jsx)(u,{"data-slot":`dialog-portal`,...n}),t[2]=n,t[3]=r),r}function N(e){let t=(0,O.c)(8),n,i;t[0]===e?(n=t[1],i=t[2]):({className:n,...i}=e,t[0]=e,t[1]=n,t[2]=i);let a;t[3]===n?a=t[4]:(a=r(`fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0`,n),t[3]=n,t[4]=a);let o;return t[5]!==i||t[6]!==a?(o=(0,A.jsx)(s,{"data-slot":`dialog-overlay`,className:a,...i}),t[5]=i,t[6]=a,t[7]=o):o=t[7],o}function P(t){let n=(0,O.c)(15),i,o,s,c;n[0]===t?(i=n[1],o=n[2],s=n[3],c=n[4]):({className:o,children:i,showCloseButton:c,...s}=t,n[0]=t,n[1]=i,n[2]=o,n[3]=s,n[4]=c);let u=c===void 0||c,f;n[5]===Symbol.for(`react.memo_cache_sentinel`)?(f=(0,A.jsx)(N,{}),n[5]=f):f=n[5];let p;n[6]===o?p=n[7]:(p=r(`fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-sm text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95`,o),n[6]=o,n[7]=p);let m;n[8]===u?m=n[9]:(m=u&&(0,A.jsx)(l,{"data-slot":`dialog-close`,asChild:!0,children:(0,A.jsxs)(a,{variant:`ghost`,className:`absolute top-2 right-2`,size:`icon-sm`,children:[(0,A.jsx)(e,{}),(0,A.jsx)(`span`,{className:`sr-only`,children:`Schließen`})]})}),n[8]=u,n[9]=m);let h;return n[10]!==i||n[11]!==s||n[12]!==p||n[13]!==m?(h=(0,A.jsxs)(M,{children:[f,(0,A.jsxs)(d,{"data-slot":`dialog-content`,className:p,...s,children:[i,m]})]}),n[10]=i,n[11]=s,n[12]=p,n[13]=m,n[14]=h):h=n[14],h}function F(e){let t=(0,O.c)(8),n,i;t[0]===e?(n=t[1],i=t[2]):({className:n,...i}=e,t[0]=e,t[1]=n,t[2]=i);let a;t[3]===n?a=t[4]:(a=r(`flex flex-col gap-2`,n),t[3]=n,t[4]=a);let o;return t[5]!==i||t[6]!==a?(o=(0,A.jsx)(`div`,{"data-slot":`dialog-header`,className:a,...i}),t[5]=i,t[6]=a,t[7]=o):o=t[7],o}function I(e){let t=(0,O.c)(14),n,i,o,s;t[0]===e?(n=t[1],i=t[2],o=t[3],s=t[4]):({className:i,showCloseButton:s,children:n,...o}=e,t[0]=e,t[1]=n,t[2]=i,t[3]=o,t[4]=s);let c=s!==void 0&&s,u;t[5]===i?u=t[6]:(u=r(`-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 sm:flex-row sm:justify-end`,i),t[5]=i,t[6]=u);let d;t[7]===c?d=t[8]:(d=c&&(0,A.jsx)(l,{asChild:!0,children:(0,A.jsx)(a,{variant:`outline`,children:`Schließen`})}),t[7]=c,t[8]=d);let f;return t[9]!==n||t[10]!==o||t[11]!==u||t[12]!==d?(f=(0,A.jsxs)(`div`,{"data-slot":`dialog-footer`,className:u,...o,children:[n,d]}),t[9]=n,t[10]=o,t[11]=u,t[12]=d,t[13]=f):f=t[13],f}function L(e){let t=(0,O.c)(8),n,i;t[0]===e?(n=t[1],i=t[2]):({className:n,...i}=e,t[0]=e,t[1]=n,t[2]=i);let a;t[3]===n?a=t[4]:(a=r(`font-heading text-base leading-none font-medium`,n),t[3]=n,t[4]=a);let o;return t[5]!==i||t[6]!==a?(o=(0,A.jsx)(f,{"data-slot":`dialog-title`,className:a,...i}),t[5]=i,t[6]=a,t[7]=o):o=t[7],o}function R(e){let t=(0,O.c)(8),n,i;t[0]===e?(n=t[1],i=t[2]):({className:n,...i}=e,t[0]=e,t[1]=n,t[2]=i);let a;t[3]===n?a=t[4]:(a=r(`text-sm text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground`,n),t[3]=n,t[4]=a);let o;return t[5]!==i||t[6]!==a?(o=(0,A.jsx)(c,{"data-slot":`dialog-description`,className:a,...i}),t[5]=i,t[6]=a,t[7]=o):o=t[7],o}function z(e){let t=(0,O.c)(26),{offen:n,titel:r,text:i,knopf:o,gefahr:s,onJa:c,onNein:l,children:u}=e,d;t[0]===l?d=t[1]:(d=e=>!e&&l(),t[0]=l,t[1]=d);let f;t[2]===r?f=t[3]:(f=(0,A.jsx)(L,{className:`schild text-xl`,children:r}),t[2]=r,t[3]=f);let p;t[4]===i?p=t[5]:(p=(0,A.jsx)(R,{className:`text-[15px] leading-relaxed text-text-2`,children:i}),t[4]=i,t[5]=p);let m;t[6]!==f||t[7]!==p?(m=(0,A.jsxs)(F,{children:[f,p]}),t[6]=f,t[7]=p,t[8]=m):m=t[8];let h;t[9]===l?h=t[10]:(h=(0,A.jsx)(a,{variant:`outline`,onClick:l,children:`Abbrechen`}),t[9]=l,t[10]=h);let g=s?`gefahr`:`default`,_;t[11]!==o||t[12]!==c||t[13]!==g?(_=(0,A.jsx)(a,{variant:g,onClick:c,children:o}),t[11]=o,t[12]=c,t[13]=g,t[14]=_):_=t[14];let v;t[15]!==h||t[16]!==_?(v=(0,A.jsxs)(I,{className:`gap-2 sm:gap-2`,children:[h,_]}),t[15]=h,t[16]=_,t[17]=v):v=t[17];let y;t[18]!==u||t[19]!==m||t[20]!==v?(y=(0,A.jsxs)(P,{className:`border-linie bg-panel sm:max-w-lg`,children:[m,u,v]}),t[18]=u,t[19]=m,t[20]=v,t[21]=y):y=t[21];let b;return t[22]!==n||t[23]!==d||t[24]!==y?(b=(0,A.jsx)(j,{open:n,onOpenChange:d,children:y}),t[22]=n,t[23]=d,t[24]=y,t[25]=b):b=t[25],b}var B=[{id:`os`,name:`Betriebssystem`},{id:`engine`,name:`Motor (llama.cpp)`},{id:`swap`,name:`llama-swap`},{id:`hermes`,name:`Hermes`}];function V(e){let t=(0,O.c)(45),{id:n,name:r,gelesen:i,hatUpdate:o,fest:s,onStart:c,onFreigeben:l,laeuftGerade:u}=e,{data:d,isPending:f}=m(n),p;t[0]!==d||t[1]!==n?(p=w(n,d),t[0]=d,t[1]=n,t[2]=p):p=t[2];let h=p,g=o?h.neu??`neu`:null,_;t[3]!==d?.count||t[4]!==d?.summary||t[5]!==i||t[6]!==o||t[7]!==n||t[8]!==f?(_=i?o?d?.summary?.trim()||(n===`os`&&d?.count?`Paketliste unten in den Details.`:f?`Wird gelesen …`:``):`Aktuell.`:`Wird gerade geprüft …`,t[3]=d?.count,t[4]=d?.summary,t[5]=i,t[6]=o,t[7]=n,t[8]=f,t[9]=_):_=t[9];let v=_,y;t[10]===g?y=t[11]:(y=g?(0,A.jsx)(`span`,{className:`text-cyan`,children:g}):(0,A.jsx)(`span`,{className:`text-text-3`,children:`–`}),t[10]=g,t[11]=y);let b=y,x;t[12]===r?x=t[13]:(x=(0,A.jsx)(`span`,{role:`rowheader`,className:`text-[15px] font-semibold`,children:r}),t[12]=r,t[13]=x);let S;t[14]!==g||t[15]!==b?(S=g&&(0,A.jsxs)(A.Fragment,{children:[` → `,b]}),t[14]=g,t[15]=b,t[16]=S):S=t[16];let C;t[17]!==S||t[18]!==h.laeuft?(C=(0,A.jsxs)(`span`,{role:`cell`,className:`ziffern text-right text-sm text-text-2 md:hidden`,children:[h.laeuft,S]}),t[17]=S,t[18]=h.laeuft,t[19]=C):C=t[19];let T;t[20]===h.laeuft?T=t[21]:(T=(0,A.jsx)(`span`,{role:`cell`,className:`ziffern hidden text-sm text-text-2 md:block`,children:h.laeuft}),t[20]=h.laeuft,t[21]=T);let E;t[22]===b?E=t[23]:(E=(0,A.jsx)(`span`,{role:`cell`,className:`ziffern hidden text-sm md:block`,children:b}),t[22]=b,t[23]=E);let D;t[24]!==s||t[25]!==r?(D=s&&(0,A.jsxs)(`span`,{className:`mb-1.5 block text-bernstein`,children:[`Festgehalten seit `,s.seit,` auf `,s.version,`: `,s.grund,`. Der Sonntags-Lauf überspringt `,r,`.`]}),t[24]=s,t[25]=r,t[26]=D):D=t[26];let k;t[27]===v?k=t[28]:(k=(0,A.jsx)(`span`,{className:`line-clamp-3 whitespace-pre-line`,children:v}),t[27]=v,t[28]=k);let j;t[29]!==k||t[30]!==D?(j=(0,A.jsxs)(`span`,{role:`cell`,className:`col-span-2 text-sm leading-relaxed text-text-2 md:col-span-1`,children:[D,k]}),t[29]=k,t[30]=D,t[31]=j):j=t[31];let M;t[32]!==s||t[33]!==o||t[34]!==u||t[35]!==l||t[36]!==c?(M=(s||o)&&(0,A.jsxs)(`span`,{role:`cell`,className:`col-span-2 flex flex-wrap gap-2 md:col-span-1 md:flex-col md:items-end`,children:[s&&(0,A.jsx)(a,{variant:`outline`,size:`sm`,onClick:l,children:`Freigeben`}),o&&(0,A.jsx)(a,{variant:`outline`,size:`sm`,onClick:c,disabled:u,children:`Aktualisieren`})]}),t[32]=s,t[33]=o,t[34]=u,t[35]=l,t[36]=c,t[37]=M):M=t[37];let N;return t[38]!==j||t[39]!==M||t[40]!==x||t[41]!==C||t[42]!==T||t[43]!==E?(N=(0,A.jsxs)(`div`,{role:`row`,className:`grid grid-cols-[minmax(0,1fr)_auto] items-baseline gap-x-4 gap-y-2 border-t border-linie py-3.5 md:grid-cols-[170px_100px_170px_minmax(0,1fr)_auto] md:items-start`,children:[x,C,T,E,j,M]}),t[38]=j,t[39]=M,t[40]=x,t[41]=C,t[42]=T,t[43]=E,t[44]=N):N=t[44],N}var H={rot:`rot`,gelb:`bernstein`,gruen:`gruen`,info:`cyan`,grau:`grau`},U={rot:`bg-rot`,gelb:`bg-bernstein`,gruen:`bg-gruen`,info:`bg-cyan`,grau:`bg-text-3`};function W(e){let t=(0,O.c)(19),{lauf:n}=e,r;t[0]===n.start?r=t[1]:(r=S(n.start),t[0]=n.start,t[1]=r);let i;t[2]===r?i=t[3]:(i=(0,A.jsx)(`span`,{className:`ziffern text-sm text-text-3`,children:r}),t[2]=r,t[3]=i);let a;t[4]===n.anlass?a=t[5]:(a=(0,A.jsx)(`span`,{className:`min-w-0 text-[15px]`,children:n.anlass}),t[4]=n.anlass,t[5]=a);let o=H[n.stufe],s;t[6]!==n.titel||t[7]!==o?(s=(0,A.jsx)(x,{art:o,children:n.titel}),t[6]=n.titel,t[7]=o,t[8]=s):s=t[8];let c;t[9]!==i||t[10]!==a||t[11]!==s?(c=(0,A.jsxs)(`div`,{className:`grid grid-cols-[auto_minmax(0,1fr)_auto] items-center gap-3 md:grid-cols-[112px_minmax(0,1fr)_auto]`,children:[i,a,s]}),t[9]=i,t[10]=a,t[11]=s,t[12]=c):c=t[12];let l;t[13]!==n.stufe||t[14]!==n.zeilen?(l=n.stufe!==`grau`&&n.zeilen.length>0&&(0,A.jsx)(`ul`,{className:`m-0 flex list-none flex-col gap-1 p-0 md:pl-[124px]`,children:n.zeilen.map(G)}),t[13]=n.stufe,t[14]=n.zeilen,t[15]=l):l=t[15];let u;return t[16]!==c||t[17]!==l?(u=(0,A.jsxs)(`li`,{className:`flex flex-col gap-2 border-t border-linie py-3`,children:[c,l]}),t[16]=c,t[17]=l,t[18]=u):u=t[18],u}function G(e){return(0,A.jsxs)(`li`,{className:`flex items-baseline gap-2 text-sm leading-snug text-text-2`,children:[(0,A.jsx)(`span`,{"aria-hidden":!0,className:r(`size-1.5 shrink-0 -translate-y-px rounded-full`,U[e.stufe])}),(0,A.jsxs)(`span`,{className:`min-w-0`,children:[(0,A.jsx)(`span`,{className:`text-foreground`,children:e.baustein}),` · `,e.text]})]},`${e.baustein}-${e.text}`)}function K(e){let t=(0,O.c)(13),{job:n}=e,r=n.state===`done`?`gruen`:n.state===`failed`?`rot`:`cyan`,i=n.state===`done`?`Fertig`:n.state===`failed`?`Fehler`:n.state===`queued`?`Wartet`:`Läuft`,a;t[0]===n.label?a=t[1]:(a=(0,A.jsx)(`span`,{className:`text-[15px] font-semibold`,children:n.label}),t[0]=n.label,t[1]=a);let o;t[2]!==r||t[3]!==i?(o=(0,A.jsx)(x,{art:r,children:i}),t[2]=r,t[3]=i,t[4]=o):o=t[4];let s;t[5]!==a||t[6]!==o?(s=(0,A.jsxs)(`div`,{className:`flex items-center justify-between gap-3`,children:[a,o]}),t[5]=a,t[6]=o,t[7]=s):s=t[7];let c;t[8]===n.log?c=t[9]:(c=n.log&&n.log.length>0&&(0,A.jsx)(`pre`,{className:`ziffern max-h-40 overflow-auto rounded-md bg-[#0b0d0f] p-2 text-xs whitespace-pre-wrap text-text-2`,children:n.log.slice(-8).join(` -`)}),t[8]=n.log,t[9]=c);let l;return t[10]!==s||t[11]!==c?(l=(0,A.jsxs)(`div`,{className:`flex flex-col gap-2 rounded-xl border border-linie bg-erhaben/50 p-3`,children:[s,c]}),t[10]=s,t[11]=c,t[12]=l):l=t[12],l}function q(e){return e.mtime?S(new Date(e.mtime*1e3).toISOString()):e.snapshot}function J(){let e=(0,O.c)(60),t=g(),n=C(),r=_(),i=D(),o=E(),s=y(),c=b(),l=h(),[u,d]=(0,k.useState)(null),f;e[0]===t.data?.updates.bausteine?f=e[1]:(f=new Set(t.data?.updates.bausteine.map(re)??[]),e[0]=t.data?.updates.bausteine,e[1]=f);let p=f,m;e[2]===t.data?.updates.festgehalten?m=e[3]:(m=new Map((t.data?.updates.festgehalten??[]).map(ne)),e[2]=t.data?.updates.festgehalten,e[3]=m);let x=m,S;if(e[4]!==x||e[5]!==s||e[6]!==n.data?.jobs||e[7]!==p||e[8]!==t.data?.updates||e[9]!==t.isPending||e[10]!==o){let r=(n.data?.jobs??[]).filter(te),i=r.some(ee),c;e[12]===o?c=e[13]:(c=()=>o.mutate(`pruefen`),e[12]=o,e[13]=c);let l;e[14]!==c||e[15]!==o.isPending?(l=(0,A.jsx)(a,{variant:`outline`,onClick:c,disabled:o.isPending,children:`Nach Neuem suchen`}),e[14]=c,e[15]=o.isPending,e[16]=l):l=e[16];let u;e[17]===Symbol.for(`react.memo_cache_sentinel`)?(u=()=>d({art:`alle`}),e[17]=u):u=e[17];let f;e[18]===Symbol.for(`react.memo_cache_sentinel`)?(f=(0,A.jsx)(`p`,{className:`-mt-2 text-[15px] text-text-2`,children:`Jeden Sonntag um 04:30 automatisch. Vorher wird gesichert, danach geprüft.`}),e[18]=f):f=e[18],S=(0,A.jsxs)(T,{titel:`Updates`,rechts:(0,A.jsxs)(`div`,{className:`flex flex-wrap gap-2.5`,children:[l,(0,A.jsx)(a,{onClick:u,disabled:i||p.size===0,children:`Alles jetzt aktualisieren`})]}),children:[f,t.isPending?(0,A.jsx)(v,{text:`Updates werden gelesen …`}):(0,A.jsxs)(`div`,{role:`table`,"aria-label":`Bausteine und ihre Updates`,className:`flex flex-col`,children:[(0,A.jsxs)(`div`,{role:`row`,className:`schild hidden grid-cols-[170px_100px_170px_minmax(0,1fr)_auto] gap-x-4 pb-2 text-xs font-semibold text-text-3 md:grid`,children:[(0,A.jsx)(`span`,{role:`columnheader`,children:`Baustein`}),(0,A.jsx)(`span`,{role:`columnheader`,children:`Läuft`}),(0,A.jsx)(`span`,{role:`columnheader`,children:`Neu`}),(0,A.jsx)(`span`,{role:`columnheader`,children:`Was sich ändert`}),(0,A.jsx)(`span`,{role:`columnheader`,className:`sr-only`,children:`Aktion`})]}),B.map(e=>(0,A.jsx)(V,{id:e.id,name:e.name,gelesen:t.data?.updates.gelesen??!1,hatUpdate:p.has(e.id),fest:x.get(e.id),laeuftGerade:i,onStart:()=>o.mutate(e.id),onFreigeben:()=>s.mutate(e.id)},e.id))]}),r.length>0&&(0,A.jsxs)(`div`,{className:`flex flex-col gap-2.5`,children:[(0,A.jsx)(`h3`,{className:`schild text-sm text-text-3`,children:`Laufende und letzte Aufträge`}),r.slice(-3).reverse().map(X)]})]}),e[4]=x,e[5]=s,e[6]=n.data?.jobs,e[7]=p,e[8]=t.data?.updates,e[9]=t.isPending,e[10]=o,e[11]=S}else S=e[11];let w;e[19]!==r.data||e[20]!==r.isPending?(w=(0,A.jsx)(T,{titel:`Verlauf`,children:r.data?.laeufe.length?(0,A.jsx)(`ol`,{className:`m-0 flex list-none flex-col p-0`,children:r.data.laeufe.map(Y)}):(0,A.jsx)(`p`,{className:`text-[15px] text-text-2`,children:r.isPending?`Wird gelesen …`:`Noch keine Update-Läufe aufgezeichnet.`})}),e[19]=r.data,e[20]=r.isPending,e[21]=w):w=e[21];let j;e[22]===c?j=e[23]:(j=()=>c.mutate(void 0),e[22]=c,e[23]=j);let M;e[24]!==c.isPending||e[25]!==j?(M=(0,A.jsx)(a,{variant:`outline`,size:`sm`,onClick:j,disabled:c.isPending,children:`Jetzt sichern`}),e[24]=c.isPending,e[25]=j,e[26]=M):M=e[26];let N;e[27]===Symbol.for(`react.memo_cache_sentinel`)?(N=(0,A.jsx)(`p`,{className:`-mt-2 text-[15px] text-text-2`,children:`Täglich um 03:35, mit Kopie auf einem zweiten Gerät.`}),e[27]=N):N=e[27];let P;if(e[28]!==i.data?.available||e[29]!==i.data?.backups){let t;e[31]===i.data?.available?t=e[32]:(t=e=>(0,A.jsxs)(`li`,{className:`flex items-center justify-between gap-3 border-t border-linie py-2.5`,children:[(0,A.jsx)(`span`,{className:`ziffern text-sm`,children:q(e)}),(0,A.jsxs)(`span`,{className:`flex items-center gap-3`,children:[(0,A.jsxs)(`span`,{className:`ziffern text-xs text-text-3`,children:[e.size_mb.toLocaleString(`de-DE`),` MB`]}),(0,A.jsx)(a,{variant:`ghost`,size:`sm`,disabled:!i.data?.available,onClick:()=>d({art:`zurueck`,datei:e.file,zeit:q(e)}),children:`Zurückspielen`})]})]},e.file),e[31]=i.data?.available,e[32]=t),P=(i.data?.backups??[]).slice(0,5).map(t),e[28]=i.data?.available,e[29]=i.data?.backups,e[30]=P}else P=e[30];let F;e[33]===P?F=e[34]:(F=(0,A.jsx)(`ul`,{className:`m-0 flex list-none flex-col p-0`,children:P}),e[33]=P,e[34]=F);let I;e[35]!==M||e[36]!==F?(I=(0,A.jsxs)(T,{titel:`Sicherungen`,rechts:M,children:[N,F]}),e[35]=M,e[36]=F,e[37]=I):I=e[37];let L;e[38]!==w||e[39]!==I?(L=(0,A.jsxs)(`div`,{className:`grid gap-5 md:gap-6 lg:grid-cols-[minmax(0,1.4fr)_minmax(0,1fr)]`,children:[w,I]}),e[38]=w,e[39]=I,e[40]=L):L=e[40];let R=u?.art===`alle`,H;e[41]===Symbol.for(`react.memo_cache_sentinel`)?(H=()=>d(null),e[41]=H):H=e[41];let U;e[42]===o?U=e[43]:(U=()=>{o.mutate(`alle`),d(null)},e[42]=o,e[43]=U);let W;e[44]!==R||e[45]!==U?(W=(0,A.jsx)(z,{offen:R,titel:`Alles jetzt aktualisieren?`,text:`Betriebssystem, Motor, llama-swap und Hermes werden nacheinander aktualisiert. Vorher wird gesichert, danach geprüft. Lucy ist dabei ein paar Minuten nicht erreichbar.`,knopf:`Aktualisieren`,onNein:H,onJa:U}),e[44]=R,e[45]=U,e[46]=W):W=e[46];let G=u?.art===`zurueck`,K=`Die Einstellungen von Hermes und llama-swap werden auf den Stand von ${u?.art===`zurueck`?u.zeit:``} gesetzt. Vorher wird der jetzige Stand gesichert. Die Dienste starten danach neu.`,J;e[47]===Symbol.for(`react.memo_cache_sentinel`)?(J=()=>d(null),e[47]=J):J=e[47];let Z;e[48]!==u||e[49]!==l?(Z=()=>{u?.art===`zurueck`&&l.mutate(u.datei),d(null)},e[48]=u,e[49]=l,e[50]=Z):Z=e[50];let Q;e[51]!==G||e[52]!==K||e[53]!==Z?(Q=(0,A.jsx)(z,{offen:G,gefahr:!0,titel:`Sicherung zurückspielen?`,text:K,knopf:`Zurückspielen`,onNein:J,onJa:Z}),e[51]=G,e[52]=K,e[53]=Z,e[54]=Q):Q=e[54];let $;return e[55]!==L||e[56]!==W||e[57]!==Q||e[58]!==S?($=(0,A.jsxs)(A.Fragment,{children:[S,L,W,Q]}),e[55]=L,e[56]=W,e[57]=Q,e[58]=S,e[59]=$):$=e[59],$}function Y(e){return(0,A.jsx)(W,{lauf:e},e.start)}function X(e){return(0,A.jsx)(K,{job:e},e.id)}function ee(e){return e.state===`running`||e.state===`queued`}function te(e){return e.group===`maintenance`}function ne(e){return[e.baustein,e]}function re(e){return e.id}export{J as UpdatesSeite}; \ No newline at end of file diff --git a/frontend/dist/assets/Updates-DPFIId2v.js b/frontend/dist/assets/Updates-DPFIId2v.js new file mode 100644 index 0000000..035d4c6 --- /dev/null +++ b/frontend/dist/assets/Updates-DPFIId2v.js @@ -0,0 +1,2 @@ +import{c as e,f as t,i as n,s as r,t as i,u as a}from"./button-Dd8hfusv.js";import{C as o,D as s,E as c,O as l,T as u,a as d,c as f,h as p,m,o as h,p as g,s as _,t as v,w as y}from"./index-ZVRs0IGR.js";import{t as b}from"./Bestaetigen-VrcNpcBb.js";var x=r(),S=t(a(),1),C=e(),w=[{id:`os`,name:`Betriebssystem`},{id:`engine`,name:`Motor (llama.cpp)`},{id:`swap`,name:`llama-swap`},{id:`hermes`,name:`Hermes`}];function T(e){let t=(0,x.c)(45),{id:n,name:r,gelesen:a,hatUpdate:o,fest:s,onStart:c,onFreigeben:l,laeuftGerade:f}=e,{data:p,isPending:m}=u(n),h;t[0]!==p||t[1]!==n?(h=d(n,p),t[0]=p,t[1]=n,t[2]=h):h=t[2];let g=h,_=o?g.neu??`neu`:null,v;t[3]!==p?.count||t[4]!==p?.summary||t[5]!==a||t[6]!==o||t[7]!==n||t[8]!==m?(v=a?o?p?.summary?.trim()||(n===`os`&&p?.count?`Paketliste unten in den Details.`:m?`Wird gelesen …`:``):`Aktuell.`:`Wird gerade geprüft …`,t[3]=p?.count,t[4]=p?.summary,t[5]=a,t[6]=o,t[7]=n,t[8]=m,t[9]=v):v=t[9];let y=v,b;t[10]===_?b=t[11]:(b=_?(0,C.jsx)(`span`,{className:`text-cyan`,children:_}):(0,C.jsx)(`span`,{className:`text-text-3`,children:`–`}),t[10]=_,t[11]=b);let S=b,w;t[12]===r?w=t[13]:(w=(0,C.jsx)(`span`,{role:`rowheader`,className:`text-[15px] font-semibold`,children:r}),t[12]=r,t[13]=w);let T;t[14]!==_||t[15]!==S?(T=_&&(0,C.jsxs)(C.Fragment,{children:[` → `,S]}),t[14]=_,t[15]=S,t[16]=T):T=t[16];let E;t[17]!==T||t[18]!==g.laeuft?(E=(0,C.jsxs)(`span`,{role:`cell`,className:`ziffern text-right text-sm text-text-2 md:hidden`,children:[g.laeuft,T]}),t[17]=T,t[18]=g.laeuft,t[19]=E):E=t[19];let D;t[20]===g.laeuft?D=t[21]:(D=(0,C.jsx)(`span`,{role:`cell`,className:`ziffern hidden text-sm text-text-2 md:block`,children:g.laeuft}),t[20]=g.laeuft,t[21]=D);let O;t[22]===S?O=t[23]:(O=(0,C.jsx)(`span`,{role:`cell`,className:`ziffern hidden text-sm md:block`,children:S}),t[22]=S,t[23]=O);let k;t[24]!==s||t[25]!==r?(k=s&&(0,C.jsxs)(`span`,{className:`mb-1.5 block text-bernstein`,children:[`Festgehalten seit `,s.seit,` auf `,s.version,`: `,s.grund,`. Der Sonntags-Lauf überspringt `,r,`.`]}),t[24]=s,t[25]=r,t[26]=k):k=t[26];let A;t[27]===y?A=t[28]:(A=(0,C.jsx)(`span`,{className:`line-clamp-3 whitespace-pre-line`,children:y}),t[27]=y,t[28]=A);let j;t[29]!==A||t[30]!==k?(j=(0,C.jsxs)(`span`,{role:`cell`,className:`col-span-2 text-sm leading-relaxed text-text-2 md:col-span-1`,children:[k,A]}),t[29]=A,t[30]=k,t[31]=j):j=t[31];let M;t[32]!==s||t[33]!==o||t[34]!==f||t[35]!==l||t[36]!==c?(M=(s||o)&&(0,C.jsxs)(`span`,{role:`cell`,className:`col-span-2 flex flex-wrap gap-2 md:col-span-1 md:flex-col md:items-end`,children:[s&&(0,C.jsx)(i,{variant:`outline`,size:`sm`,onClick:l,children:`Freigeben`}),o&&(0,C.jsx)(i,{variant:`outline`,size:`sm`,onClick:c,disabled:f,children:`Aktualisieren`})]}),t[32]=s,t[33]=o,t[34]=f,t[35]=l,t[36]=c,t[37]=M):M=t[37];let N;return t[38]!==j||t[39]!==M||t[40]!==w||t[41]!==E||t[42]!==D||t[43]!==O?(N=(0,C.jsxs)(`div`,{role:`row`,className:`grid grid-cols-[minmax(0,1fr)_auto] items-baseline gap-x-4 gap-y-2 border-t border-linie py-3.5 md:grid-cols-[170px_100px_170px_minmax(0,1fr)_auto] md:items-start`,children:[w,E,D,O,j,M]}),t[38]=j,t[39]=M,t[40]=w,t[41]=E,t[42]=D,t[43]=O,t[44]=N):N=t[44],N}var E={rot:`rot`,gelb:`bernstein`,gruen:`gruen`,info:`cyan`,grau:`grau`},D={rot:`bg-rot`,gelb:`bg-bernstein`,gruen:`bg-gruen`,info:`bg-cyan`,grau:`bg-text-3`};function O(e){let t=(0,x.c)(19),{lauf:n}=e,r;t[0]===n.start?r=t[1]:(r=f(n.start),t[0]=n.start,t[1]=r);let i;t[2]===r?i=t[3]:(i=(0,C.jsx)(`span`,{className:`ziffern text-sm text-text-3`,children:r}),t[2]=r,t[3]=i);let a;t[4]===n.anlass?a=t[5]:(a=(0,C.jsx)(`span`,{className:`min-w-0 text-[15px]`,children:n.anlass}),t[4]=n.anlass,t[5]=a);let o=E[n.stufe],s;t[6]!==n.titel||t[7]!==o?(s=(0,C.jsx)(h,{art:o,children:n.titel}),t[6]=n.titel,t[7]=o,t[8]=s):s=t[8];let c;t[9]!==i||t[10]!==a||t[11]!==s?(c=(0,C.jsxs)(`div`,{className:`grid grid-cols-[auto_minmax(0,1fr)_auto] items-center gap-3 md:grid-cols-[112px_minmax(0,1fr)_auto]`,children:[i,a,s]}),t[9]=i,t[10]=a,t[11]=s,t[12]=c):c=t[12];let l;t[13]!==n.stufe||t[14]!==n.zeilen?(l=n.stufe!==`grau`&&n.zeilen.length>0&&(0,C.jsx)(`ul`,{className:`m-0 flex list-none flex-col gap-1 p-0 md:pl-[124px]`,children:n.zeilen.map(k)}),t[13]=n.stufe,t[14]=n.zeilen,t[15]=l):l=t[15];let u;return t[16]!==c||t[17]!==l?(u=(0,C.jsxs)(`li`,{className:`flex flex-col gap-2 border-t border-linie py-3`,children:[c,l]}),t[16]=c,t[17]=l,t[18]=u):u=t[18],u}function k(e){return(0,C.jsxs)(`li`,{className:`flex items-baseline gap-2 text-sm leading-snug text-text-2`,children:[(0,C.jsx)(`span`,{"aria-hidden":!0,className:n(`size-1.5 shrink-0 -translate-y-px rounded-full`,D[e.stufe])}),(0,C.jsxs)(`span`,{className:`min-w-0`,children:[(0,C.jsx)(`span`,{className:`text-foreground`,children:e.baustein}),` · `,e.text]})]},`${e.baustein}-${e.text}`)}function A(e){let t=(0,x.c)(13),{job:n}=e,r=n.state===`done`?`gruen`:n.state===`failed`?`rot`:`cyan`,i=n.state===`done`?`Fertig`:n.state===`failed`?`Fehler`:n.state===`queued`?`Wartet`:`Läuft`,a;t[0]===n.label?a=t[1]:(a=(0,C.jsx)(`span`,{className:`text-[15px] font-semibold`,children:n.label}),t[0]=n.label,t[1]=a);let o;t[2]!==r||t[3]!==i?(o=(0,C.jsx)(h,{art:r,children:i}),t[2]=r,t[3]=i,t[4]=o):o=t[4];let s;t[5]!==a||t[6]!==o?(s=(0,C.jsxs)(`div`,{className:`flex items-center justify-between gap-3`,children:[a,o]}),t[5]=a,t[6]=o,t[7]=s):s=t[7];let c;t[8]===n.log?c=t[9]:(c=n.log&&n.log.length>0&&(0,C.jsx)(`pre`,{className:`ziffern max-h-40 overflow-auto rounded-md bg-[#0b0d0f] p-2 text-xs whitespace-pre-wrap text-text-2`,children:n.log.slice(-8).join(` +`)}),t[8]=n.log,t[9]=c);let l;return t[10]!==s||t[11]!==c?(l=(0,C.jsxs)(`div`,{className:`flex flex-col gap-2 rounded-xl border border-linie bg-erhaben/50 p-3`,children:[s,c]}),t[10]=s,t[11]=c,t[12]=l):l=t[12],l}function j(e){return e.mtime?f(new Date(e.mtime*1e3).toISOString()):e.snapshot}function M(){let e=(0,x.c)(60),t=y(),n=p(),r=s(),a=o(),u=c(),d=g(),f=m(),h=l(),[E,D]=(0,S.useState)(null),O;e[0]===t.data?.updates.bausteine?O=e[1]:(O=new Set(t.data?.updates.bausteine.map(re)??[]),e[0]=t.data?.updates.bausteine,e[1]=O);let k=O,A;e[2]===t.data?.updates.festgehalten?A=e[3]:(A=new Map((t.data?.updates.festgehalten??[]).map(ne)),e[2]=t.data?.updates.festgehalten,e[3]=A);let M=A,F;if(e[4]!==M||e[5]!==d||e[6]!==n.data?.jobs||e[7]!==k||e[8]!==t.data?.updates||e[9]!==t.isPending||e[10]!==u){let r=(n.data?.jobs??[]).filter(te),a=r.some(ee),o;e[12]===u?o=e[13]:(o=()=>u.mutate(`pruefen`),e[12]=u,e[13]=o);let s;e[14]!==o||e[15]!==u.isPending?(s=(0,C.jsx)(i,{variant:`outline`,onClick:o,disabled:u.isPending,children:`Nach Neuem suchen`}),e[14]=o,e[15]=u.isPending,e[16]=s):s=e[16];let c;e[17]===Symbol.for(`react.memo_cache_sentinel`)?(c=()=>D({art:`alle`}),e[17]=c):c=e[17];let l;e[18]===Symbol.for(`react.memo_cache_sentinel`)?(l=(0,C.jsx)(`p`,{className:`-mt-2 text-[15px] text-text-2`,children:`Jeden Sonntag um 04:30 automatisch. Vorher wird gesichert, danach geprüft.`}),e[18]=l):l=e[18],F=(0,C.jsxs)(v,{titel:`Updates`,rechts:(0,C.jsxs)(`div`,{className:`flex flex-wrap gap-2.5`,children:[s,(0,C.jsx)(i,{onClick:c,disabled:a||k.size===0,children:`Alles jetzt aktualisieren`})]}),children:[l,t.isPending?(0,C.jsx)(_,{text:`Updates werden gelesen …`}):(0,C.jsxs)(`div`,{role:`table`,"aria-label":`Bausteine und ihre Updates`,className:`flex flex-col`,children:[(0,C.jsxs)(`div`,{role:`row`,className:`schild hidden grid-cols-[170px_100px_170px_minmax(0,1fr)_auto] gap-x-4 pb-2 text-xs font-semibold text-text-3 md:grid`,children:[(0,C.jsx)(`span`,{role:`columnheader`,children:`Baustein`}),(0,C.jsx)(`span`,{role:`columnheader`,children:`Läuft`}),(0,C.jsx)(`span`,{role:`columnheader`,children:`Neu`}),(0,C.jsx)(`span`,{role:`columnheader`,children:`Was sich ändert`}),(0,C.jsx)(`span`,{role:`columnheader`,className:`sr-only`,children:`Aktion`})]}),w.map(e=>(0,C.jsx)(T,{id:e.id,name:e.name,gelesen:t.data?.updates.gelesen??!1,hatUpdate:k.has(e.id),fest:M.get(e.id),laeuftGerade:a,onStart:()=>u.mutate(e.id),onFreigeben:()=>d.mutate(e.id)},e.id))]}),r.length>0&&(0,C.jsxs)(`div`,{className:`flex flex-col gap-2.5`,children:[(0,C.jsx)(`h3`,{className:`schild text-sm text-text-3`,children:`Laufende und letzte Aufträge`}),r.slice(-3).reverse().map(P)]})]}),e[4]=M,e[5]=d,e[6]=n.data?.jobs,e[7]=k,e[8]=t.data?.updates,e[9]=t.isPending,e[10]=u,e[11]=F}else F=e[11];let I;e[19]!==r.data||e[20]!==r.isPending?(I=(0,C.jsx)(v,{titel:`Verlauf`,children:r.data?.laeufe.length?(0,C.jsx)(`ol`,{className:`m-0 flex list-none flex-col p-0`,children:r.data.laeufe.map(N)}):(0,C.jsx)(`p`,{className:`text-[15px] text-text-2`,children:r.isPending?`Wird gelesen …`:`Noch keine Update-Läufe aufgezeichnet.`})}),e[19]=r.data,e[20]=r.isPending,e[21]=I):I=e[21];let L;e[22]===f?L=e[23]:(L=()=>f.mutate(void 0),e[22]=f,e[23]=L);let R;e[24]!==f.isPending||e[25]!==L?(R=(0,C.jsx)(i,{variant:`outline`,size:`sm`,onClick:L,disabled:f.isPending,children:`Jetzt sichern`}),e[24]=f.isPending,e[25]=L,e[26]=R):R=e[26];let z;e[27]===Symbol.for(`react.memo_cache_sentinel`)?(z=(0,C.jsx)(`p`,{className:`-mt-2 text-[15px] text-text-2`,children:`Täglich um 03:35, mit Kopie auf einem zweiten Gerät.`}),e[27]=z):z=e[27];let B;if(e[28]!==a.data?.available||e[29]!==a.data?.backups){let t;e[31]===a.data?.available?t=e[32]:(t=e=>(0,C.jsxs)(`li`,{className:`flex items-center justify-between gap-3 border-t border-linie py-2.5`,children:[(0,C.jsx)(`span`,{className:`ziffern text-sm`,children:j(e)}),(0,C.jsxs)(`span`,{className:`flex items-center gap-3`,children:[(0,C.jsxs)(`span`,{className:`ziffern text-xs text-text-3`,children:[e.size_mb.toLocaleString(`de-DE`),` MB`]}),(0,C.jsx)(i,{variant:`ghost`,size:`sm`,disabled:!a.data?.available,onClick:()=>D({art:`zurueck`,datei:e.file,zeit:j(e)}),children:`Zurückspielen`})]})]},e.file),e[31]=a.data?.available,e[32]=t),B=(a.data?.backups??[]).slice(0,5).map(t),e[28]=a.data?.available,e[29]=a.data?.backups,e[30]=B}else B=e[30];let V;e[33]===B?V=e[34]:(V=(0,C.jsx)(`ul`,{className:`m-0 flex list-none flex-col p-0`,children:B}),e[33]=B,e[34]=V);let H;e[35]!==R||e[36]!==V?(H=(0,C.jsxs)(v,{titel:`Sicherungen`,rechts:R,children:[z,V]}),e[35]=R,e[36]=V,e[37]=H):H=e[37];let U;e[38]!==I||e[39]!==H?(U=(0,C.jsxs)(`div`,{className:`grid gap-5 md:gap-6 lg:grid-cols-[minmax(0,1.4fr)_minmax(0,1fr)]`,children:[I,H]}),e[38]=I,e[39]=H,e[40]=U):U=e[40];let W=E?.art===`alle`,G;e[41]===Symbol.for(`react.memo_cache_sentinel`)?(G=()=>D(null),e[41]=G):G=e[41];let K;e[42]===u?K=e[43]:(K=()=>{u.mutate(`alle`),D(null)},e[42]=u,e[43]=K);let q;e[44]!==W||e[45]!==K?(q=(0,C.jsx)(b,{offen:W,titel:`Alles jetzt aktualisieren?`,text:`Betriebssystem, Motor, llama-swap und Hermes werden nacheinander aktualisiert. Vorher wird gesichert, danach geprüft. Lucy ist dabei ein paar Minuten nicht erreichbar.`,knopf:`Aktualisieren`,onNein:G,onJa:K}),e[44]=W,e[45]=K,e[46]=q):q=e[46];let J=E?.art===`zurueck`,Y=`Die Einstellungen von Hermes und llama-swap werden auf den Stand von ${E?.art===`zurueck`?E.zeit:``} gesetzt. Vorher wird der jetzige Stand gesichert. Die Dienste starten danach neu.`,X;e[47]===Symbol.for(`react.memo_cache_sentinel`)?(X=()=>D(null),e[47]=X):X=e[47];let Z;e[48]!==E||e[49]!==h?(Z=()=>{E?.art===`zurueck`&&h.mutate(E.datei),D(null)},e[48]=E,e[49]=h,e[50]=Z):Z=e[50];let Q;e[51]!==J||e[52]!==Y||e[53]!==Z?(Q=(0,C.jsx)(b,{offen:J,gefahr:!0,titel:`Sicherung zurückspielen?`,text:Y,knopf:`Zurückspielen`,onNein:X,onJa:Z}),e[51]=J,e[52]=Y,e[53]=Z,e[54]=Q):Q=e[54];let $;return e[55]!==U||e[56]!==q||e[57]!==Q||e[58]!==F?($=(0,C.jsxs)(C.Fragment,{children:[F,U,q,Q]}),e[55]=U,e[56]=q,e[57]=Q,e[58]=F,e[59]=$):$=e[59],$}function N(e){return(0,C.jsx)(O,{lauf:e},e.start)}function P(e){return(0,C.jsx)(A,{job:e},e.id)}function ee(e){return e.state===`running`||e.state===`queued`}function te(e){return e.group===`maintenance`}function ne(e){return[e.baustein,e]}function re(e){return e.id}export{M as UpdatesSeite}; \ No newline at end of file diff --git a/frontend/dist/assets/index-C3amg33Y.css b/frontend/dist/assets/index-C3amg33Y.css new file mode 100644 index 0000000..67eddcc --- /dev/null +++ b/frontend/dist/assets/index-C3amg33Y.css @@ -0,0 +1,2 @@ +/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */ +@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){:root,:host{--shimmer-angle:20deg}*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-animation-delay:0s;--tw-animation-direction:normal;--tw-animation-duration:initial;--tw-animation-fill-mode:none;--tw-animation-iteration-count:1;--tw-enter-blur:0;--tw-enter-opacity:1;--tw-enter-rotate:0;--tw-enter-scale:1;--tw-enter-translate-x:0;--tw-enter-translate-y:0;--tw-exit-blur:0;--tw-exit-opacity:1;--tw-exit-rotate:0;--tw-exit-scale:1;--tw-exit-translate-x:0;--tw-exit-translate-y:0;--scroll-fade-t:0px;--scroll-fade-b:0px;--scroll-fade-s:0px;--scroll-fade-e:0px;--scroll-fade-mask:initial;--shimmer-image:initial;--shimmer-text-fill:initial}}}@layer theme{:root,:host{--font-mono:"JetBrains Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;--color-black:#000;--spacing:.25rem;--container-sm:24rem;--container-lg:32rem;--container-xl:36rem;--container-2xl:42rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-normal:0em;--leading-tight:1.25;--leading-snug:1.375;--leading-relaxed:1.625;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--blur-xs:4px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:"Barlow", "Segoe UI", system-ui, sans-serif;--default-mono-font-family:"JetBrains Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;--font-anzeige:"Barlow Condensed", "Barlow", "Segoe UI", sans-serif}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}*{border-color:var(--border);outline-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){*{outline-color:color-mix(in oklab, var(--ring) 50%, transparent)}}html{-webkit-font-smoothing:antialiased;font-family:Barlow,Segoe UI,system-ui,sans-serif}body{background-color:var(--background);color:var(--foreground);margin:0}:focus-visible{outline:2px solid var(--cyan);outline-offset:2px}}@layer components;@layer utilities{.\@container{container-type:inline-size}.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.not-sr-only{clip-path:none;white-space:normal;width:auto;height:auto;margin:0;padding:0;position:static;overflow:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:0}.inset-x-0{inset-inline:0}.inset-y-0{inset-block:0}.-top-1\.5{top:calc(var(--spacing) * -1.5)}.top-1\/2{top:50%}.top-2{top:calc(var(--spacing) * 2)}.top-3{top:calc(var(--spacing) * 3)}.right-2{right:calc(var(--spacing) * 2)}.right-3{right:calc(var(--spacing) * 3)}.right-4{right:calc(var(--spacing) * 4)}.-bottom-1\.5{bottom:calc(var(--spacing) * -1.5)}.bottom-0{bottom:0}.bottom-24{bottom:calc(var(--spacing) * 24)}.left-0{left:0}.left-1\/2{left:50%}.left-4{left:calc(var(--spacing) * 4)}.isolate{isolation:isolate}.z-40{z-index:40}.z-50{z-index:50}.col-span-2{grid-column:span 2/span 2}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.-m-2{margin:calc(var(--spacing) * -2)}.m-0{margin:0}.-mx-4{margin-inline:calc(var(--spacing) * -4)}.mx-4{margin-inline:calc(var(--spacing) * 4)}.mx-auto{margin-inline:auto}.-mt-2{margin-top:calc(var(--spacing) * -2)}.mt-auto{margin-top:auto}.mr-2{margin-right:calc(var(--spacing) * 2)}.-mb-4{margin-bottom:calc(var(--spacing) * -4)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.ml-0\.5{margin-left:calc(var(--spacing) * .5)}.line-clamp-3{-webkit-line-clamp:3;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.contents{display:contents}.flex{display:flex}.flow-root{display:flow-root}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.table-caption{display:table-caption}.table-cell{display:table-cell}.table-column{display:table-column}.table-column-group{display:table-column-group}.table-footer-group{display:table-footer-group}.table-header-group{display:table-header-group}.table-row{display:table-row}.size-1\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.size-2{width:calc(var(--spacing) * 2);height:calc(var(--spacing) * 2)}.size-2\.5{width:calc(var(--spacing) * 2.5);height:calc(var(--spacing) * 2.5)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-11{width:calc(var(--spacing) * 11);height:calc(var(--spacing) * 11)}.h-0{height:0}.h-2{height:calc(var(--spacing) * 2)}.h-3{height:calc(var(--spacing) * 3)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-10{height:calc(var(--spacing) * 10)}.h-11{height:calc(var(--spacing) * 11)}.h-12{height:calc(var(--spacing) * 12)}.h-14{height:calc(var(--spacing) * 14)}.h-16{height:calc(var(--spacing) * 16)}.h-\[150px\]{height:150px}.h-auto{height:auto}.h-full{height:100%}.max-h-40{max-height:calc(var(--spacing) * 40)}.max-h-\[50vh\]{max-height:50vh}.min-h-11{min-height:calc(var(--spacing) * 11)}.min-h-\[58px\]{min-height:58px}.min-h-\[130px\]{min-height:130px}.min-h-dvh{min-height:100dvh}.w-0\.5{width:calc(var(--spacing) * .5)}.w-\[38px\]{width:38px}.w-full{width:100%}.w-px{width:1px}.max-w-\[200px\]{max-width:200px}.max-w-\[1440px\]{max-width:1440px}.max-w-\[calc\(100\%-2rem\)\]{max-width:calc(100% - 2rem)}.max-w-full{max-width:100%}.min-w-0{min-width:0}.flex-1{flex:1}.shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-px{--tw-translate-y:-1px;translate:var(--tw-translate-x) var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.resize{resize:both}.list-none{list-style-type:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-\[112px_minmax\(0\,1fr\)_auto\]{grid-template-columns:112px minmax(0,1fr) auto}.grid-cols-\[170px_100px_170px_minmax\(0\,1fr\)_auto\]{grid-template-columns:170px 100px 170px minmax(0,1fr) auto}.grid-cols-\[auto_minmax\(0\,1fr\)_auto\]{grid-template-columns:auto minmax(0,1fr) auto}.grid-cols-\[minmax\(0\,1fr\)_auto\]{grid-template-columns:minmax(0,1fr) auto}.grid-cols-\[minmax\(0\,1fr\)_auto_auto\]{grid-template-columns:minmax(0,1fr) auto auto}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-3\.5{gap:calc(var(--spacing) * 3.5)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}.gap-x-4{column-gap:calc(var(--spacing) * 4)}.gap-x-6{column-gap:calc(var(--spacing) * 6)}.gap-y-2{row-gap:calc(var(--spacing) * 2)}.gap-y-6{row-gap:calc(var(--spacing) * 6)}.self-start{align-self:flex-start}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded-2xl{border-radius:calc(var(--radius) * 1.8)}.rounded-\[9px\]{border-radius:9px}.rounded-full{border-radius:2147483647px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) * .8)}.rounded-sm{border-radius:calc(var(--radius) * .6)}.rounded-xl{border-radius:calc(var(--radius) * 1.4)}.rounded-b-xl{border-bottom-right-radius:calc(var(--radius) * 1.4);border-bottom-left-radius:calc(var(--radius) * 1.4)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-dotted{--tw-border-style:dotted;border-style:dotted}.\!border-linie-stark{border-color:var(--linie-stark)!important}.border-\[\#2a3036\]{border-color:#2a3036}.border-aus-rand{border-color:var(--aus-rand)}.border-bernstein,.border-bernstein\/60{border-color:var(--bernstein)}@supports (color:color-mix(in lab, red, red)){.border-bernstein\/60{border-color:color-mix(in oklab, var(--bernstein) 60%, transparent)}}.border-cyan-rand{border-color:var(--cyan-rand)}.border-gruen-rand{border-color:var(--gruen-rand)}.border-linie{border-color:var(--linie)}.border-linie-stark{border-color:var(--linie-stark)}.border-rot{border-color:var(--rot)}.border-rot-rand{border-color:var(--rot-rand)}.border-transparent{border-color:#0000}.bg-\[\#0b0d0f\]{background-color:#0b0d0f}.bg-\[\#0e1119\]\/95{background-color:oklab(17.8423% -.00041081 -.0172642/.95)}.bg-\[\#121518\]{background-color:#121518}.bg-aus-grund{background-color:var(--aus-grund)}.bg-bernstein{background-color:var(--bernstein)}.bg-bernstein-grund{background-color:var(--bernstein-grund)}.bg-bernstein-lampe{background-color:var(--bernstein-lampe)}.bg-black\/10{background-color:#0000001a}@supports (color:color-mix(in lab, red, red)){.bg-black\/10{background-color:color-mix(in oklab, var(--color-black) 10%, transparent)}}.bg-cyan{background-color:var(--cyan)}.bg-cyan-grund{background-color:var(--cyan-grund)}.bg-cyan\/35{background-color:var(--cyan)}@supports (color:color-mix(in lab, red, red)){.bg-cyan\/35{background-color:color-mix(in oklab, var(--cyan) 35%, transparent)}}.bg-erhaben,.bg-erhaben\/50{background-color:var(--erhaben)}@supports (color:color-mix(in lab, red, red)){.bg-erhaben\/50{background-color:color-mix(in oklab, var(--erhaben) 50%, transparent)}}.bg-gruen{background-color:var(--gruen)}.bg-gruen-grund{background-color:var(--gruen-grund)}.bg-linie{background-color:var(--linie)}.bg-muted\/50{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\/50{background-color:color-mix(in oklab, var(--muted) 50%, transparent)}}.bg-panel{background-color:var(--panel)}.bg-popover{background-color:var(--popover)}.bg-rot{background-color:var(--rot)}.bg-rot-grund{background-color:var(--rot-grund)}.bg-text-3{background-color:var(--text-3)}.bg-transparent{background-color:#0000}.bg-clip-padding{background-clip:padding-box}.p-0{padding:0}.p-1{padding:var(--spacing)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-6{padding:calc(var(--spacing) * 6)}.px-0{padding-inline:0}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-1{padding-block:var(--spacing)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-3\.5{padding-block:calc(var(--spacing) * 3.5)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-8{padding-block:calc(var(--spacing) * 8)}.pt-1{padding-top:var(--spacing)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pb-1{padding-bottom:var(--spacing)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pb-5{padding-bottom:calc(var(--spacing) * 5)}.pb-28{padding-bottom:calc(var(--spacing) * 28)}.pb-\[calc\(0\.75rem\+env\(safe-area-inset-bottom\)\)\]{padding-bottom:calc(.75rem + env(safe-area-inset-bottom))}.pb-\[calc\(1rem\+env\(safe-area-inset-bottom\)\)\]{padding-bottom:calc(1rem + env(safe-area-inset-bottom))}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-anzeige,.font-heading{font-family:Barlow Condensed,Barlow,Segoe UI,sans-serif}.font-sans{font-family:Barlow,Segoe UI,system-ui,sans-serif}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[13px\]{font-size:13px}.text-\[15px\]{font-size:15px}.text-\[17px\]{font-size:17px}.text-\[28px\]{font-size:28px}.text-\[32px\]{font-size:32px}.text-\[40px\]{font-size:40px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-\[0\.04em\]{--tw-tracking:.04em;letter-spacing:.04em}.tracking-\[0\.06em\]{--tw-tracking:.06em;letter-spacing:.06em}.tracking-\[0\.12em\]{--tw-tracking:.12em;letter-spacing:.12em}.tracking-\[0\.18em\]{--tw-tracking:.18em;letter-spacing:.18em}.tracking-\[0\.22em\]{--tw-tracking:.22em;letter-spacing:.22em}.tracking-\[0\.26em\]{--tw-tracking:.26em;letter-spacing:.26em}.tracking-normal{--tw-tracking:var(--tracking-normal);letter-spacing:var(--tracking-normal)}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-line{white-space:pre-line}.whitespace-pre-wrap{white-space:pre-wrap}.\!text-foreground{color:var(--foreground)!important}.text-\[\#f2c46b\]{color:#f2c46b}.text-aus-text{color:var(--aus-text)}.text-bernstein{color:var(--bernstein)}.text-bernstein-hell{color:var(--bernstein-hell)}.text-cyan{color:var(--cyan)}.text-cyan-text{color:var(--cyan-text)}.text-foreground{color:var(--foreground)}.text-gruen{color:var(--gruen)}.text-gruen-text{color:var(--gruen-text)}.text-muted-foreground{color:var(--muted-foreground)}.text-popover-foreground{color:var(--popover-foreground)}.text-primary-foreground{color:var(--primary-foreground)}.text-rot{color:var(--rot)}.text-rot-text{color:var(--rot-text)}.text-text-2{color:var(--text-2)}.text-text-3{color:var(--text-3)}.capitalize{text-transform:capitalize}.lowercase{text-transform:lowercase}.normal-case{text-transform:none}.uppercase{text-transform:uppercase}.italic{font-style:italic}.diagonal-fractions{--tw-numeric-fraction:diagonal-fractions;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.lining-nums{--tw-numeric-figure:lining-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.proportional-nums{--tw-numeric-spacing:proportional-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.no-underline{text-decoration-line:none}.underline-offset-4{text-underline-offset:4px}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-70{opacity:.7}.opacity-80{opacity:.8}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_0_8px_rgba\(61\,220\,138\,0\.7\)\]{--tw-shadow:0 0 8px var(--tw-shadow-color,#3ddc8ab3);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_0_18px_rgba\(255\,90\,79\,0\.35\)\]{--tw-shadow:0 0 18px var(--tw-shadow-color,#ff5a4f59);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_0_32px_rgba\(255\,90\,79\,0\.3\)\]{--tw-shadow:0 0 32px var(--tw-shadow-color,#ff5a4f4d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-1{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-foreground\/10{--tw-ring-color:var(--foreground)}@supports (color:color-mix(in lab, red, red)){.ring-foreground\/10{--tw-ring-color:color-mix(in oklab, var(--foreground) 10%, transparent)}}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter\!{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)!important}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-100{--tw-duration:.1s;transition-duration:.1s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.paused{animation-play-state:paused}.running{animation-play-state:running}.zoom-in{--tw-enter-scale:0}@media (hover:hover){.hover\:border-text-3:hover{border-color:var(--text-3)}.hover\:bg-\[\#3a1512\]:hover{background-color:#3a1512}.hover\:bg-\[\#232931\]:hover{background-color:#232931}.hover\:bg-bernstein-hell:hover{background-color:var(--bernstein-hell)}.hover\:bg-cyan-grund:hover{background-color:var(--cyan-grund)}.hover\:bg-erhaben:hover{background-color:var(--erhaben)}.hover\:text-cyan:hover{color:var(--cyan)}.hover\:text-foreground:hover{color:var(--foreground)}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-100:hover{opacity:1}}.focus\:border-cyan:focus{border-color:var(--cyan)}.focus-visible\:ring-3:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:color-mix(in oklab, var(--ring) 50%, transparent)}}.active\:not-aria-\[haspopup\]\:translate-y-px:active:not([aria-haspopup]){--tw-translate-y:1px;translate:var(--tw-translate-x) var(--tw-translate-y)}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-45:disabled{opacity:.45}.data-\[side\=bottom\]\:inset-x-0[data-side=bottom]{inset-inline:0}.data-\[side\=bottom\]\:bottom-0[data-side=bottom]{bottom:0}.data-\[side\=bottom\]\:h-auto[data-side=bottom]{height:auto}.data-\[side\=bottom\]\:border-t[data-side=bottom]{border-top-style:var(--tw-border-style);border-top-width:1px}.data-\[side\=left\]\:inset-y-0[data-side=left]{inset-block:0}.data-\[side\=left\]\:left-0[data-side=left]{left:0}.data-\[side\=left\]\:h-full[data-side=left]{height:100%}.data-\[side\=left\]\:w-3\/4[data-side=left]{width:75%}.data-\[side\=left\]\:border-r[data-side=left]{border-right-style:var(--tw-border-style);border-right-width:1px}.data-\[side\=right\]\:inset-y-0[data-side=right]{inset-block:0}.data-\[side\=right\]\:right-0[data-side=right]{right:0}.data-\[side\=right\]\:h-full[data-side=right]{height:100%}.data-\[side\=right\]\:w-3\/4[data-side=right]{width:75%}.data-\[side\=right\]\:border-l[data-side=right]{border-left-style:var(--tw-border-style);border-left-width:1px}.data-\[side\=top\]\:inset-x-0[data-side=top]{inset-inline:0}.data-\[side\=top\]\:top-0[data-side=top]{top:0}.data-\[side\=top\]\:h-auto[data-side=top]{height:auto}.data-\[side\=top\]\:border-b[data-side=top]{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}@supports ((-webkit-backdrop-filter:var(--tw)) or (backdrop-filter:var(--tw))){.supports-backdrop-filter\:backdrop-blur-xs{--tw-backdrop-blur:blur(var(--blur-xs));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}}@media (width>=40rem){.sm\:block{display:block}.sm\:max-w-2xl{max-width:var(--container-2xl)}.sm\:max-w-lg{max-width:var(--container-lg)}.sm\:max-w-sm{max-width:var(--container-sm)}.sm\:max-w-xl{max-width:var(--container-xl)}.sm\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.sm\:grid-cols-\[minmax\(0\,1fr\)_120px_160px\]{grid-template-columns:minmax(0,1fr) 120px 160px}.sm\:flex-row{flex-direction:row}.sm\:justify-end{justify-content:flex-end}.sm\:gap-2{gap:calc(var(--spacing) * 2)}.sm\:p-6{padding:calc(var(--spacing) * 6)}.sm\:px-6{padding-inline:calc(var(--spacing) * 6)}.sm\:text-\[44px\]{font-size:44px}.data-\[side\=left\]\:sm\:max-w-sm[data-side=left],.data-\[side\=right\]\:sm\:max-w-sm[data-side=right]{max-width:var(--container-sm)}}@media (width>=48rem){.md\:bottom-6{bottom:calc(var(--spacing) * 6)}.md\:left-auto{left:auto}.md\:col-span-1{grid-column:span 1/span 1}.md\:block{display:block}.md\:flex{display:flex}.md\:grid{display:grid}.md\:hidden{display:none}.md\:w-\[420px\]{width:420px}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-\[112px_minmax\(0\,1fr\)_auto\]{grid-template-columns:112px minmax(0,1fr) auto}.md\:grid-cols-\[170px_100px_170px_minmax\(0\,1fr\)_auto\]{grid-template-columns:170px 100px 170px minmax(0,1fr) auto}.md\:grid-cols-\[260px_minmax\(0\,1fr\)\]{grid-template-columns:260px minmax(0,1fr)}.md\:flex-col{flex-direction:column}.md\:items-end{align-items:flex-end}.md\:items-start{align-items:flex-start}.md\:gap-5{gap:calc(var(--spacing) * 5)}.md\:gap-6{gap:calc(var(--spacing) * 6)}.md\:px-10{padding-inline:calc(var(--spacing) * 10)}.md\:pt-8{padding-top:calc(var(--spacing) * 8)}.md\:pb-10{padding-bottom:calc(var(--spacing) * 10)}.md\:pl-\[124px\]{padding-left:124px}}@media (width>=64rem){.lg\:block{display:block}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:grid-cols-\[minmax\(0\,1\.4fr\)_minmax\(0\,1fr\)\]{grid-template-columns:minmax(0,1.4fr) minmax(0,1fr)}.lg\:grid-cols-\[minmax\(0\,1\.35fr\)_minmax\(0\,1fr\)\]{grid-template-columns:minmax(0,1.35fr) minmax(0,1fr)}.lg\:grid-cols-\[minmax\(0\,1fr\)_minmax\(0\,1\.3fr\)\]{grid-template-columns:minmax(0,1fr) minmax(0,1.3fr)}.lg\:px-6{padding-inline:calc(var(--spacing) * 6)}}.data-open\:animate-in:where([data-state=open]),.data-open\:animate-in:where([data-open]:not([data-open=false])){animation:enter var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-open\:fade-in-0:where([data-state=open]),.data-open\:fade-in-0:where([data-open]:not([data-open=false])){--tw-enter-opacity:0}.data-open\:zoom-in-95:where([data-state=open]),.data-open\:zoom-in-95:where([data-open]:not([data-open=false])){--tw-enter-scale:.95}.data-\[side\=bottom\]\:data-open\:slide-in-from-bottom-10[data-side=bottom]:where([data-state=open]),.data-\[side\=bottom\]\:data-open\:slide-in-from-bottom-10[data-side=bottom]:where([data-open]:not([data-open=false])){--tw-enter-translate-y:calc(.1*100%)}.data-\[side\=left\]\:data-open\:slide-in-from-left-10[data-side=left]:where([data-state=open]),.data-\[side\=left\]\:data-open\:slide-in-from-left-10[data-side=left]:where([data-open]:not([data-open=false])){--tw-enter-translate-x:calc(.1*-100%)}.data-\[side\=right\]\:data-open\:slide-in-from-right-10[data-side=right]:where([data-state=open]),.data-\[side\=right\]\:data-open\:slide-in-from-right-10[data-side=right]:where([data-open]:not([data-open=false])){--tw-enter-translate-x:calc(.1*100%)}.data-\[side\=top\]\:data-open\:slide-in-from-top-10[data-side=top]:where([data-state=open]),.data-\[side\=top\]\:data-open\:slide-in-from-top-10[data-side=top]:where([data-open]:not([data-open=false])){--tw-enter-translate-y:calc(.1*-100%)}.data-closed\:animate-out:where([data-state=closed]),.data-closed\:animate-out:where([data-closed]:not([data-closed=false])){animation:exit var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-closed\:fade-out-0:where([data-state=closed]),.data-closed\:fade-out-0:where([data-closed]:not([data-closed=false])){--tw-exit-opacity:0}.data-closed\:zoom-out-95:where([data-state=closed]),.data-closed\:zoom-out-95:where([data-closed]:not([data-closed=false])){--tw-exit-scale:.95}.data-\[side\=bottom\]\:data-closed\:slide-out-to-bottom-10[data-side=bottom]:where([data-state=closed]),.data-\[side\=bottom\]\:data-closed\:slide-out-to-bottom-10[data-side=bottom]:where([data-closed]:not([data-closed=false])){--tw-exit-translate-y:calc(.1*100%)}.data-\[side\=left\]\:data-closed\:slide-out-to-left-10[data-side=left]:where([data-state=closed]),.data-\[side\=left\]\:data-closed\:slide-out-to-left-10[data-side=left]:where([data-closed]:not([data-closed=false])){--tw-exit-translate-x:calc(.1*-100%)}.data-\[side\=right\]\:data-closed\:slide-out-to-right-10[data-side=right]:where([data-state=closed]),.data-\[side\=right\]\:data-closed\:slide-out-to-right-10[data-side=right]:where([data-closed]:not([data-closed=false])){--tw-exit-translate-x:calc(.1*100%)}.data-\[side\=top\]\:data-closed\:slide-out-to-top-10[data-side=top]:where([data-state=closed]),.data-\[side\=top\]\:data-closed\:slide-out-to-top-10[data-side=top]:where([data-closed]:not([data-closed=false])){--tw-exit-translate-y:calc(.1*-100%)}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&_svg\:not\(\[class\*\=\'size-\'\]\)\]\:size-4 svg:not([class*=size-]){width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}:is(.\*\:\[a\]\:underline>*):is(a){text-decoration-line:underline}:is(.\*\:\[a\]\:underline-offset-3>*):is(a){text-underline-offset:3px}@media (hover:hover){:is(.\*\:\[a\]\:hover\:text-foreground>*):is(a):hover{color:var(--foreground)}}.schild{font-family:var(--font-anzeige);text-transform:uppercase;letter-spacing:.16em;font-weight:600}.ziffern{font-family:var(--font-mono);font-variant-numeric:tabular-nums}}@property --tw-animation-delay{syntax:"*";inherits:false;initial-value:0s}@property --tw-animation-direction{syntax:"*";inherits:false;initial-value:normal}@property --tw-animation-duration{syntax:"*";inherits:false}@property --tw-animation-fill-mode{syntax:"*";inherits:false;initial-value:none}@property --tw-animation-iteration-count{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-translate-y{syntax:"*";inherits:false;initial-value:0}@property --scroll-fade-t{syntax:"";inherits:false;initial-value:0}@property --scroll-fade-b{syntax:"";inherits:false;initial-value:0}@property --scroll-fade-s{syntax:"";inherits:false;initial-value:0}@property --scroll-fade-e{syntax:"";inherits:false;initial-value:0}@property --scroll-fade-mask{syntax:"*";inherits:false}@property --shimmer-angle{syntax:"";inherits:true;initial-value:20deg}@property --shimmer-image{syntax:"*";inherits:false}@property --shimmer-text-fill{syntax:"*";inherits:false}@media (prefers-reduced-motion:reduce){.shimmer{-webkit-text-fill-color:currentColor;background-image:none;animation:none}}@font-face{font-family:Barlow;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/barlow-vietnamese-400-normal-Dpl4UHAZ.woff2)format("woff2"),url(/assets/barlow-vietnamese-400-normal-BFeobeCK.woff)format("woff");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Barlow;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/barlow-latin-ext-400-normal-HxX4XjxC.woff2)format("woff2"),url(/assets/barlow-latin-ext-400-normal-CvBsJvxq.woff)format("woff");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Barlow;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/barlow-latin-400-normal-qiz4-Cze.woff2)format("woff2"),url(/assets/barlow-latin-400-normal-fsAxiSwU.woff)format("woff");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Barlow;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/barlow-vietnamese-500-normal-zTViEIzf.woff2)format("woff2"),url(/assets/barlow-vietnamese-500-normal-GNfB7rCE.woff)format("woff");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Barlow;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/barlow-latin-ext-500-normal-DOaysfXq.woff2)format("woff2"),url(/assets/barlow-latin-ext-500-normal-CJPcKP2Q.woff)format("woff");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Barlow;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/barlow-latin-500-normal-BPAOfeC8.woff2)format("woff2"),url(/assets/barlow-latin-500-normal-C1h8hMer.woff)format("woff");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Barlow;font-style:normal;font-display:swap;font-weight:600;src:url(/assets/barlow-vietnamese-600-normal-DcjprdFV.woff2)format("woff2"),url(/assets/barlow-vietnamese-600-normal-CA_GiK2e.woff)format("woff");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Barlow;font-style:normal;font-display:swap;font-weight:600;src:url(/assets/barlow-latin-ext-600-normal-B8NK_A3D.woff2)format("woff2"),url(/assets/barlow-latin-ext-600-normal-DMVRjfRT.woff)format("woff");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Barlow;font-style:normal;font-display:swap;font-weight:600;src:url(/assets/barlow-latin-600-normal-DILqtrty.woff2)format("woff2"),url(/assets/barlow-latin-600-normal-CNwfPWQD.woff)format("woff");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Barlow Condensed;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/barlow-condensed-vietnamese-500-normal-DjeaNLFD.woff2)format("woff2"),url(/assets/barlow-condensed-vietnamese-500-normal-CsrJDWc5.woff)format("woff");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Barlow Condensed;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/barlow-condensed-latin-ext-500-normal-yA5ONLQ9.woff2)format("woff2"),url(/assets/barlow-condensed-latin-ext-500-normal-B1RE8WP7.woff)format("woff");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Barlow Condensed;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/barlow-condensed-latin-500-normal-BgYH2mbd.woff2)format("woff2"),url(/assets/barlow-condensed-latin-500-normal-HIEiP5Ov.woff)format("woff");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Barlow Condensed;font-style:normal;font-display:swap;font-weight:600;src:url(/assets/barlow-condensed-vietnamese-600-normal-A5AYRdjN.woff2)format("woff2"),url(/assets/barlow-condensed-vietnamese-600-normal-CNlPk46_.woff)format("woff");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Barlow Condensed;font-style:normal;font-display:swap;font-weight:600;src:url(/assets/barlow-condensed-latin-ext-600-normal-18ESti3H.woff2)format("woff2"),url(/assets/barlow-condensed-latin-ext-600-normal-Clv9cIcR.woff)format("woff");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Barlow Condensed;font-style:normal;font-display:swap;font-weight:600;src:url(/assets/barlow-condensed-latin-600-normal-DepVgxBB.woff2)format("woff2"),url(/assets/barlow-condensed-latin-600-normal-BFJEwTuo.woff)format("woff");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Barlow Condensed;font-style:normal;font-display:swap;font-weight:700;src:url(/assets/barlow-condensed-vietnamese-700-normal-DYeBwlKR.woff2)format("woff2"),url(/assets/barlow-condensed-vietnamese-700-normal-DhIzd8Tb.woff)format("woff");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Barlow Condensed;font-style:normal;font-display:swap;font-weight:700;src:url(/assets/barlow-condensed-latin-ext-700-normal-CwuXbfVR.woff2)format("woff2"),url(/assets/barlow-condensed-latin-ext-700-normal-BIHFfxf0.woff)format("woff");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Barlow Condensed;font-style:normal;font-display:swap;font-weight:700;src:url(/assets/barlow-condensed-latin-700-normal-v1xN8_Wq.woff2)format("woff2"),url(/assets/barlow-condensed-latin-700-normal-Dmwat-ge.woff)format("woff");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(data:font/woff2;base64,d09GMgABAAAAAASIABAAAAAACQQAAAQuAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGhwbHhwoBmA/U1RBVF4AdBEICoRkhAALIAABNgIkAzoEIAWFAAeBFAwHG2oHKJ6DceNW4lJEFHn9tEOE37LNsvkjHr7f739rn3u+OSrSxLQytE91Dw2PYtNVq3Qaw/vJ7fUBMdOj/u2ImB98cT5WUx9F13ZKt06mU7tG1sAYcM26yCRX4f/0904bmwq8hwkUUMTRX61pa9C3xlpAGYw1vOu8C2SBZZFlld7DAW82RJWmwYMI1AJCKBNCIASqdZGFmtPSNQRhMpR0EKjWTwm6z6sJ+4jqhxjovTinVdRpZaQjaQzAYjI8NgAKDJCokgunCn9oUQE8VZd/F//+v6P4F1U9gLr58yNI/dJX9BAshEoJbTDogz7ocKoUsPvES8UK/aQIUQgpGgECBVLkOEV6iASTYgNAPKdNXayhDPL7IJuAZnEYSZ0eOLc9i5Rv5/+lEi3sW/kfnCf/+fTe0sxS7CKLx5erRJkKOixEqQaoqrvx5HN4iz4VhX0gS6DjFIWUzn/fIXJRVFY1NFRVNVeFt+SYmrK6vCU6eJsnKnJj5HTESMTQZOTI3Y/tzr3rUcOsiRy/ciP50s3Mycgxmhz9GMXhjzVH30ut796NHP0UUa31/Zoa6vCH6iPvdIM0IRANaT60FablmZlZd+UKNFy9NrvnFGxb5NC2CRxR0/rIyF/WNn+35sv9r+tHVhkseuWGKkCPPh96+GXt8Lc/Sh24ujfjf+tNw1lZWreiPuHb/PSpyjdv2rf/++ZE5TSKjFdZxYsBvr1sEHl5STuHZqYR7jGYGvGBBdjcaB5bODY1GAxMjsd0wDMIzXAXODRd74DxNMtO4YuYHclgLQRzp9KlUmxptCwv9bYgvWGD2xBW7r9413fdJu+mxzvzAUYeeONQvZP4kgfqZle4jhH/MWh+UbxgtJdrLdXLymNL53PRU0D3Q6FcXTfGqGcul6vrqhgLGAVSv+IVIfZOHpu+mlLqSlnj903j8mazXDsba/wbxhS/4Oubh1c5/uXDgt4j5KtnGEy5BIJHo0ur+jD+r2qCkuP1aRVM8EpUoRYSJyqNRA38uwDvHBNo0AejO2Z+ZYLLal1QiFyFh1EDQOgSCSCpjwwKU8yDbIjroEwne0G5Qca49cYp4AlqtQNZfWTQoFb1tRpFYAmRD+HXTkV4uQhG2bg4OKmyoypAsUGtWgQXyFxYrkpODeUxvGqIZA61erXo0sFG1UBGuPgpuon8RNUG2DhovAjZCBuZwtXrU3mQGki9+pm0eVZAXoWxLWTQoYHBPrJR4WunNxIFbCHfkTyPK+sqxjxDmGArZvf79JGJ3GwEqjwc7a7NIrl/7bJ7Nzu4+n1Ow6shEPnUrtVo7cnd5Wi5qCUbBIQbNKCP95FMCSZylEV5VCiiMqqiOmrKZ/I/C0gI1fyuulVcM2E1r4MhtcV/fbCD+HwEvVzH1dGNAzFE0FTbKzyQz3gootrNbN2a4PuG0j0JOgE=)format("woff2"),url(data:font/woff;base64,d09GRgABAAAAAAbUAA8AAAAACOgAAQABAAAAAAAAAAAAAAAAAAAAAAAAAABHREVGAAABWAAAABgAAAAcABQABEdQT1MAAAFwAAAAHgAAAB5EdEx1R1NVQgAAAZAAAAAnAAAAKLj8uOpPUy8yAAABuAAAAFEAAABgFwRca1NUQVQAAAIMAAAARgAAAF7mY9MfY21hcAAAAlQAAABRAAAAdAyHCodnYXNwAAACqAAAAAgAAAAIAAAAEGdseWYAAAKwAAAB6QAAAl7g5OpvaGVhZAAABJwAAAA2AAAANhSQ8UNoaGVhAAAE1AAAAB8AAAAkAcoBImhtdHgAAAT0AAAAHgAAADofBAM2bG9jYQAABRQAAAAgAAAAIATcBZ9tYXhwAAAFNAAAABwAAAAgAIcCb25hbWUAAAVQAAABEgAAAoA4pV3kcG9zdAAABmQAAABwAAAAlNdzMTB42mNgZGBg4GGAAEYgZAWTjCAeAAG0ABkAAQAAAAoAHAAcAAFERkxUAAgABAAAAAD//wAAAAAAAHjaY2BkYGDgYlADQiYXN58QBqGcxJI8Bj4GEGABEf//g0gAWkkFVQB42mNgYYpinMDAysDA1MUUwcDA4A2hGeMYjBgdgKIMDJwMUMDEzoAEvJyAxAEGXpaXzH/+XWFgYP7DqKPAwDj//nWgSjWmW0BZBQZWABNDDdYAAAB42kXIIQIBARQFwHl/QQIkWXInUAANXMOBJCcTd+KIGCjMNViq9/H0CM6P/S0j0bOwUqh08iEb8kPTXn3RiMoYhD90Nwc3AAB42lXIRwHCQBAF0JceehWAlTjhjikUgAVQA4mJLbdk5neUqHBVKWSv3XF2VCnt3AyevkVZv+sxBBbbq/6HfFP4hEcYQgEK82v1aHQ5RTs3FRQAAAAAAQAB//8AD3jabZA1tNRAFEDfTGDdfXHI2QQnZJJvK5ngDs13Welwt/78CtcS7xvcrcHKbXCtceh+wgtu437nXRCgC4BY9AGOXOAFYNHR0dzoKCGju8gJ6xiZaF3DWqcPBiSV5i2geaCgAlAJ77ghgjfiLC7KojvOZEmSXS63emXr5W7lsTLtXFMkRmks4ly+cYOEnvO2YLDNANv+9oJwhkpAAJAcHPG/1RC2BERc1ZGGMxYVWDyVSjc0NMaZELUf9e4JhCgNB3b2PiJRctuqZ0WPR8zilxutN/ji97vUBYMAnGjtzxjtK3wrDaMABo+R9KjWwNRUMppwuWS1QdfFZCIlMF2TxDGuJJlYW7OmVlvD+sx86b1hvC/l8yXf2hqZ66xbZ80yWzyD9/fzGaRzA58+nSOzYC+gw9AP+vyNqUAUhoD4lSnputbgUFPJ5O9Y+ReWlxkrc96naX08b3zk/KORb+E+VjYPmH1M6+UHeVlDtCzzGZ9FY8YMA8gPMsQA0jqaGkHT6cYSdVwl7Zs9Wzx+DyWUugPujd03T52ikrUvM26kF9PIcRmycuDBKcd3XRhPDgtnQACINzJ3fVl1tTB++3bc2S7kyD3cCQIQNMcSKaY2YOciE+d0zFbGjps6u0PILTFlRZHNJfAFnfeHtgAAAAABAAAAAjYEro52gl8PPPUAAwPoAAAAANvSppoAAAAA29rQ8vk5/tQEkgP8AAAABgACAAAAAAAAeNpjYGRgYP7z7woDA8uGn5Z/+1kmAUVQAR8Ar8AG6gB42mOKYIgCYiMkrAzCUHEbJJoBikHgCkMPAPDwCFUAAAAAABoAOwBGAFEAbwB3AKkAsQDmAQkBCQEJAQkBFgEveNpjYGRgYOBn3MGQx7CFgQ3MQwBmBiYALRoB+HjajJADbgVQEEXPZ20bQW3bthvXbr8Vp4to1KV0AV1Wb9JvZzJvzhvcB6CQL0wYzHnAj6E/yAYaDeVBNlJsMAfZxCy/QTbTy3eQLdTzGWQr3VwGuZhx2v/ZAIVUB9kc0TSUKJ8f5FIRHGPjnWs+2MKt+MYzt1xwr/jIk3JymR0X0wzIXKo7VbXjFvfLn3lTtCn7qPoB6+yyzb3qy8pdq/6hrj11fMj7OFbtEY+mrlU/516rVFCdVobplw/JEjVaCaqIYlUiUzOaW9aa/Q1idmlPXZHbCagW/B10XwaRi06VuVdMf+9DnIov6rlF8yzhUXxC/4c66Uz48UepqEN9N/Tzt2RwjOljsUUfj581AbaEXsIAAHjaY2BiAIP/qQxGQIqRAR3wA7EKw0lGJgYbRmZGFkZWRjZGdgZmRg5GTkYuRm42x6Si1LJU9tK8TAMTR1cI7WoB5btB+Zas6Ym5uYlgnoGjAZNzEF9icmlJanJ+bpJecmJxKg9IxtjADMwBAKDtHJg=)format("woff");unicode-range:U+460-52F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2)format("woff2"),url(/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff)format("woff");unicode-range:U+301,U+400-45F,U+490-491,U+4B0-4B1,U+2116}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2)format("woff2"),url(/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff)format("woff");unicode-range:U+370-377,U+37A-37F,U+384-38A,U+38C,U+38E-3A1,U+3A3-3FF}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(data:font/woff2;base64,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)format("woff2"),url(/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff)format("woff");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2)format("woff2"),url(/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff)format("woff");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2)format("woff2"),url(/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff)format("woff");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:500;src:url(data:font/woff2;base64,d09GMgABAAAAAASUABAAAAAACRAAAAQ3AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGhwbHhwoBmA/U1RBVEwAdBEICoRkg3oLIAABNgIkAzoEIAWFHgeBFAwHG3AHKB4HzukrRjyF5Gb4kQ/B873d17mv8TWkoqUUGaHodJCtoqntw7m8tiPWyGkfWDU/IMpzVk4zAs9Czv3c7Os5NvKFG1Ht9vBVXySRZpJc4tTrbM3sTRFcLa3zVboKWRIoAksKSKgqUQWEwlSoqjp44V5J9/kjd0+Fi5xaFjwJArgBAIJgIAgCCAI4CdNMqGuYXYUKdADLAkAAJwl6iX0+bZqEm1AH0Hu9rvrJHwxQG1Q/gFYwWYbgTRWgwEESVzbmtjQAt3DXO7Tu/+9Q/KNKWhTCgZ8fQSWoL0CUUgTBjgL8iEAcce7YHBeA8ZvogieCnxI0BCVeACCAAhBD/oDcAdUPABSgAX4kBPBTwjCAjwYSCneiqF65LUo/qXdYFrRwTujtMrKm07plTbSqLQFAiHBN7E4DG5wkiGXhCYBNETh3K/AciHN69iFfQjFOr9EXQQAAQXRNszs8PR0OH4fDV/dwGe76CHdj1MQa11DXYGcfZ6+B1X0OfwjY+i7KpQ1w9d+1z3/HydCB1f3U8A0fRFv+0bXxPWrZu3d9Nn4UcbLs/QCXLH/j3PCKblKOiZxLOR78W9brPo7eGTLz/F27ZPmePQdCB1YP4nJU91o4gU9cy64L3c3SPu8GfDn6ZXD2cGmllVqSxtD5vCXHm5xaeHlnpffx7DcPvXog5NnjA//cPz2btsz3yf+0MI8ri33tuv7upNbYmW5STbosW8bYItV/SPzxvXC0KnpWnFdC91oojit5Lyo6WcJQ1YzwBYbi52ohJVpcxfcHBqsv0nFz8U74rzS6M7r0RVlXZ3jJC4G92O//7Lm78VOtnUx+aQxAzsqPnrRr1t9zDrezKePvZ027x+fGte4s4NXu7/jEp3G9cM1bICYgACbuETUUD5wmenGXA/IBpAKVrl0AEJ5cqr6Q89tGq+SpqkDfX2DtG+pZ9teuae0AX98c301CX179InyErnSG8WCiABB4HFbVrw/lpTdBIOk82nXbpHKoQGyBpUovAAD4XQA8ZTUCeBJHIpI0v0FRrgcnckV3ANckrwYJKXEihQfdSKPER6XeExmEeEMmSe6QBwWmkZdmSOSthhibgIkBlUYreBKd/0NeVAE9WAyEaQpH6KikDWlUVg43Jy2FOmaYlsZhDEGZXO3mWEyWHI6zuaJkMlcSQ9k4F+KidIiFyZItGDc7r1pUj6wP6zrWB0/fbeeFeHl4YOvETMNiM8Ny+7OO6Qh2wur20YVxFts5dlORdl5Kwd5utR7SRcxqX8RA5Ehacha76hg7c6yzNm/Xf6vOLNrv544lIEkWg7xWo/ItBAeIJEmt0XgBwgM8gTifoiiLJroYYooNTeziEKe4zOoR/wvIKp89hSr+6jFAqw/LaonjmZHSscMNg4iPlWpFrO1RN3zkMU+/xUP+JQ99TbvTl1Vg0gtirT6lbwYAAAA=)format("woff2"),url(data:font/woff;base64,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)format("woff");unicode-range:U+460-52F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/jetbrains-mono-cyrillic-500-normal-DmUKJPL_.woff2)format("woff2"),url(/assets/jetbrains-mono-cyrillic-500-normal-DJqRU3vO.woff)format("woff");unicode-range:U+301,U+400-45F,U+490-491,U+4B0-4B1,U+2116}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/jetbrains-mono-greek-500-normal-JpySY46c.woff2)format("woff2"),url(/assets/jetbrains-mono-greek-500-normal-D7SFKleX.woff)format("woff");unicode-range:U+370-377,U+37A-37F,U+384-38A,U+38C,U+38E-3A1,U+3A3-3FF}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:500;src:url(data:font/woff2;base64,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)format("woff2"),url(/assets/jetbrains-mono-vietnamese-500-normal-DNRqzVM1.woff)format("woff");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/jetbrains-mono-latin-ext-500-normal-Cut-4mMH.woff2)format("woff2"),url(/assets/jetbrains-mono-latin-ext-500-normal-ckzbgY84.woff)format("woff");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2)format("woff2"),url(/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff)format("woff");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}:root{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--radius:.625rem;--background:#0e1012;--foreground:#e6eaee;--card:#15181b;--card-foreground:#e6eaee;--popover:#15181b;--popover-foreground:#e6eaee;--primary:#ffb020;--primary-foreground:#1a1300;--secondary:#1c2126;--secondary-foreground:#e6eaee;--muted:#1c2126;--muted-foreground:#8b949e;--accent:#1c2126;--accent-foreground:#e6eaee;--destructive:#ff5a4f;--border:#262b30;--input:#3a4148;--ring:#5cc8ff;--panel:#15181b;--erhaben:#1c2126;--linie:#262b30;--linie-stark:#3a4148;--text-2:#aeb6bf;--text-3:#8b949e;--bernstein:#ffb020;--bernstein-hell:#ffc24d;--bernstein-grund:#2a1e05;--bernstein-lampe:#3a2a08;--gruen:#3ddc8a;--gruen-text:#7cc9a0;--gruen-grund:#0f2319;--gruen-rand:#1f5a3b;--cyan:#5cc8ff;--cyan-text:#93d5f8;--cyan-grund:#0c2230;--cyan-rand:#2f7fb0;--rot:#ff5a4f;--rot-text:#ff9a92;--rot-grund:#2e0f0d;--rot-rand:#a33a33;--aus-grund:#171b1f;--aus-rand:#2e343a;--aus-text:#9aa3ad}@keyframes lampe-atmen{0%,to{box-shadow:0 0 10px color-mix(in srgb, var(--bernstein) 25%, transparent)}50%{box-shadow:0 0 22px color-mix(in srgb, var(--bernstein) 45%, transparent)}}@media (prefers-reduced-motion:no-preference){.lampe-atmet{animation:3.2s ease-in-out infinite lampe-atmen}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@keyframes enter{0%{opacity:var(--tw-enter-opacity,1);transform:translate3d(var(--tw-enter-translate-x,0),var(--tw-enter-translate-y,0),0)scale3d(var(--tw-enter-scale,1),var(--tw-enter-scale,1),var(--tw-enter-scale,1))rotate(var(--tw-enter-rotate,0));filter:blur(var(--tw-enter-blur,0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity,1);transform:translate3d(var(--tw-exit-translate-x,0),var(--tw-exit-translate-y,0),0)scale3d(var(--tw-exit-scale,1),var(--tw-exit-scale,1),var(--tw-exit-scale,1))rotate(var(--tw-exit-rotate,0));filter:blur(var(--tw-exit-blur,0))}} diff --git a/frontend/dist/assets/index-D4C10235.css b/frontend/dist/assets/index-D4C10235.css deleted file mode 100644 index bfa949c..0000000 --- a/frontend/dist/assets/index-D4C10235.css +++ /dev/null @@ -1,2 +0,0 @@ -/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */ -@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){:root,:host{--shimmer-angle:20deg}*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-animation-delay:0s;--tw-animation-direction:normal;--tw-animation-duration:initial;--tw-animation-fill-mode:none;--tw-animation-iteration-count:1;--tw-enter-blur:0;--tw-enter-opacity:1;--tw-enter-rotate:0;--tw-enter-scale:1;--tw-enter-translate-x:0;--tw-enter-translate-y:0;--tw-exit-blur:0;--tw-exit-opacity:1;--tw-exit-rotate:0;--tw-exit-scale:1;--tw-exit-translate-x:0;--tw-exit-translate-y:0;--scroll-fade-t:0px;--scroll-fade-b:0px;--scroll-fade-s:0px;--scroll-fade-e:0px;--scroll-fade-mask:initial;--shimmer-image:initial;--shimmer-text-fill:initial}}}@layer theme{:root,:host{--font-mono:"JetBrains Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;--color-black:#000;--spacing:.25rem;--container-sm:24rem;--container-lg:32rem;--container-xl:36rem;--container-2xl:42rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-normal:0em;--leading-tight:1.25;--leading-snug:1.375;--leading-relaxed:1.625;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--blur-xs:4px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:"Barlow", "Segoe UI", system-ui, sans-serif;--default-mono-font-family:"JetBrains Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;--font-anzeige:"Barlow Condensed", "Barlow", "Segoe UI", sans-serif}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}*{border-color:var(--border);outline-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){*{outline-color:color-mix(in oklab, var(--ring) 50%, transparent)}}html{-webkit-font-smoothing:antialiased;font-family:Barlow,Segoe UI,system-ui,sans-serif}body{background-color:var(--background);color:var(--foreground);margin:0}:focus-visible{outline:2px solid var(--cyan);outline-offset:2px}}@layer components;@layer utilities{.\@container{container-type:inline-size}.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.not-sr-only{clip-path:none;white-space:normal;width:auto;height:auto;margin:0;padding:0;position:static;overflow:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:0}.inset-x-0{inset-inline:0}.inset-y-0{inset-block:0}.-top-1\.5{top:calc(var(--spacing) * -1.5)}.top-1\/2{top:50%}.top-2{top:calc(var(--spacing) * 2)}.top-3{top:calc(var(--spacing) * 3)}.right-2{right:calc(var(--spacing) * 2)}.right-3{right:calc(var(--spacing) * 3)}.right-4{right:calc(var(--spacing) * 4)}.-bottom-1\.5{bottom:calc(var(--spacing) * -1.5)}.bottom-0{bottom:0}.bottom-24{bottom:calc(var(--spacing) * 24)}.left-0{left:0}.left-1\/2{left:50%}.left-4{left:calc(var(--spacing) * 4)}.isolate{isolation:isolate}.z-40{z-index:40}.z-50{z-index:50}.col-span-2{grid-column:span 2/span 2}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.-m-2{margin:calc(var(--spacing) * -2)}.m-0{margin:0}.-mx-4{margin-inline:calc(var(--spacing) * -4)}.mx-4{margin-inline:calc(var(--spacing) * 4)}.mx-auto{margin-inline:auto}.-mt-2{margin-top:calc(var(--spacing) * -2)}.mt-auto{margin-top:auto}.mr-2{margin-right:calc(var(--spacing) * 2)}.-mb-4{margin-bottom:calc(var(--spacing) * -4)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.ml-0\.5{margin-left:calc(var(--spacing) * .5)}.line-clamp-3{-webkit-line-clamp:3;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.contents{display:contents}.flex{display:flex}.flow-root{display:flow-root}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.table-caption{display:table-caption}.table-cell{display:table-cell}.table-column{display:table-column}.table-column-group{display:table-column-group}.table-footer-group{display:table-footer-group}.table-header-group{display:table-header-group}.table-row{display:table-row}.size-1\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.size-2{width:calc(var(--spacing) * 2);height:calc(var(--spacing) * 2)}.size-2\.5{width:calc(var(--spacing) * 2.5);height:calc(var(--spacing) * 2.5)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-11{width:calc(var(--spacing) * 11);height:calc(var(--spacing) * 11)}.h-0{height:0}.h-2{height:calc(var(--spacing) * 2)}.h-3{height:calc(var(--spacing) * 3)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-10{height:calc(var(--spacing) * 10)}.h-11{height:calc(var(--spacing) * 11)}.h-12{height:calc(var(--spacing) * 12)}.h-14{height:calc(var(--spacing) * 14)}.h-16{height:calc(var(--spacing) * 16)}.h-\[150px\]{height:150px}.h-auto{height:auto}.h-full{height:100%}.max-h-40{max-height:calc(var(--spacing) * 40)}.max-h-\[50vh\]{max-height:50vh}.min-h-11{min-height:calc(var(--spacing) * 11)}.min-h-\[58px\]{min-height:58px}.min-h-\[130px\]{min-height:130px}.min-h-dvh{min-height:100dvh}.w-0\.5{width:calc(var(--spacing) * .5)}.w-\[38px\]{width:38px}.w-full{width:100%}.w-px{width:1px}.max-w-\[200px\]{max-width:200px}.max-w-\[1440px\]{max-width:1440px}.max-w-\[calc\(100\%-2rem\)\]{max-width:calc(100% - 2rem)}.max-w-full{max-width:100%}.min-w-0{min-width:0}.flex-1{flex:1}.shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-px{--tw-translate-y:-1px;translate:var(--tw-translate-x) var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.resize{resize:both}.list-none{list-style-type:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-\[112px_minmax\(0\,1fr\)_auto\]{grid-template-columns:112px minmax(0,1fr) auto}.grid-cols-\[170px_100px_170px_minmax\(0\,1fr\)_auto\]{grid-template-columns:170px 100px 170px minmax(0,1fr) auto}.grid-cols-\[auto_minmax\(0\,1fr\)_auto\]{grid-template-columns:auto minmax(0,1fr) auto}.grid-cols-\[minmax\(0\,1fr\)_auto\]{grid-template-columns:minmax(0,1fr) auto}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-3\.5{gap:calc(var(--spacing) * 3.5)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}.gap-x-4{column-gap:calc(var(--spacing) * 4)}.gap-x-6{column-gap:calc(var(--spacing) * 6)}.gap-y-2{row-gap:calc(var(--spacing) * 2)}.gap-y-6{row-gap:calc(var(--spacing) * 6)}.self-start{align-self:flex-start}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded-2xl{border-radius:calc(var(--radius) * 1.8)}.rounded-\[9px\]{border-radius:9px}.rounded-full{border-radius:2147483647px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) * .8)}.rounded-sm{border-radius:calc(var(--radius) * .6)}.rounded-xl{border-radius:calc(var(--radius) * 1.4)}.rounded-b-xl{border-bottom-right-radius:calc(var(--radius) * 1.4);border-bottom-left-radius:calc(var(--radius) * 1.4)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-dotted{--tw-border-style:dotted;border-style:dotted}.\!border-linie-stark{border-color:var(--linie-stark)!important}.border-\[\#2a3036\]{border-color:#2a3036}.border-aus-rand{border-color:var(--aus-rand)}.border-bernstein,.border-bernstein\/60{border-color:var(--bernstein)}@supports (color:color-mix(in lab, red, red)){.border-bernstein\/60{border-color:color-mix(in oklab, var(--bernstein) 60%, transparent)}}.border-cyan-rand{border-color:var(--cyan-rand)}.border-gruen-rand{border-color:var(--gruen-rand)}.border-linie{border-color:var(--linie)}.border-linie-stark{border-color:var(--linie-stark)}.border-rot{border-color:var(--rot)}.border-rot-rand{border-color:var(--rot-rand)}.border-transparent{border-color:#0000}.bg-\[\#0b0d0f\]{background-color:#0b0d0f}.bg-\[\#0e1119\]\/95{background-color:oklab(17.8423% -.00041081 -.0172642/.95)}.bg-\[\#121518\]{background-color:#121518}.bg-aus-grund{background-color:var(--aus-grund)}.bg-bernstein{background-color:var(--bernstein)}.bg-bernstein-grund{background-color:var(--bernstein-grund)}.bg-bernstein-lampe{background-color:var(--bernstein-lampe)}.bg-black\/10{background-color:#0000001a}@supports (color:color-mix(in lab, red, red)){.bg-black\/10{background-color:color-mix(in oklab, var(--color-black) 10%, transparent)}}.bg-cyan{background-color:var(--cyan)}.bg-cyan-grund{background-color:var(--cyan-grund)}.bg-cyan\/35{background-color:var(--cyan)}@supports (color:color-mix(in lab, red, red)){.bg-cyan\/35{background-color:color-mix(in oklab, var(--cyan) 35%, transparent)}}.bg-erhaben,.bg-erhaben\/50{background-color:var(--erhaben)}@supports (color:color-mix(in lab, red, red)){.bg-erhaben\/50{background-color:color-mix(in oklab, var(--erhaben) 50%, transparent)}}.bg-gruen{background-color:var(--gruen)}.bg-gruen-grund{background-color:var(--gruen-grund)}.bg-linie{background-color:var(--linie)}.bg-muted\/50{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\/50{background-color:color-mix(in oklab, var(--muted) 50%, transparent)}}.bg-panel{background-color:var(--panel)}.bg-popover{background-color:var(--popover)}.bg-rot{background-color:var(--rot)}.bg-rot-grund{background-color:var(--rot-grund)}.bg-text-3{background-color:var(--text-3)}.bg-transparent{background-color:#0000}.bg-clip-padding{background-clip:padding-box}.p-0{padding:0}.p-1{padding:var(--spacing)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-6{padding:calc(var(--spacing) * 6)}.px-0{padding-inline:0}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-3\.5{padding-block:calc(var(--spacing) * 3.5)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-8{padding-block:calc(var(--spacing) * 8)}.pt-1{padding-top:var(--spacing)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pb-5{padding-bottom:calc(var(--spacing) * 5)}.pb-28{padding-bottom:calc(var(--spacing) * 28)}.pb-\[calc\(0\.75rem\+env\(safe-area-inset-bottom\)\)\]{padding-bottom:calc(.75rem + env(safe-area-inset-bottom))}.pb-\[calc\(1rem\+env\(safe-area-inset-bottom\)\)\]{padding-bottom:calc(1rem + env(safe-area-inset-bottom))}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-anzeige,.font-heading{font-family:Barlow Condensed,Barlow,Segoe UI,sans-serif}.font-sans{font-family:Barlow,Segoe UI,system-ui,sans-serif}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[13px\]{font-size:13px}.text-\[15px\]{font-size:15px}.text-\[17px\]{font-size:17px}.text-\[28px\]{font-size:28px}.text-\[32px\]{font-size:32px}.text-\[40px\]{font-size:40px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-\[0\.04em\]{--tw-tracking:.04em;letter-spacing:.04em}.tracking-\[0\.06em\]{--tw-tracking:.06em;letter-spacing:.06em}.tracking-\[0\.12em\]{--tw-tracking:.12em;letter-spacing:.12em}.tracking-\[0\.18em\]{--tw-tracking:.18em;letter-spacing:.18em}.tracking-\[0\.22em\]{--tw-tracking:.22em;letter-spacing:.22em}.tracking-\[0\.26em\]{--tw-tracking:.26em;letter-spacing:.26em}.tracking-normal{--tw-tracking:var(--tracking-normal);letter-spacing:var(--tracking-normal)}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-line{white-space:pre-line}.whitespace-pre-wrap{white-space:pre-wrap}.\!text-foreground{color:var(--foreground)!important}.text-\[\#f2c46b\]{color:#f2c46b}.text-aus-text{color:var(--aus-text)}.text-bernstein{color:var(--bernstein)}.text-bernstein-hell{color:var(--bernstein-hell)}.text-cyan{color:var(--cyan)}.text-cyan-text{color:var(--cyan-text)}.text-foreground{color:var(--foreground)}.text-gruen{color:var(--gruen)}.text-gruen-text{color:var(--gruen-text)}.text-muted-foreground{color:var(--muted-foreground)}.text-popover-foreground{color:var(--popover-foreground)}.text-primary-foreground{color:var(--primary-foreground)}.text-rot{color:var(--rot)}.text-rot-text{color:var(--rot-text)}.text-text-2{color:var(--text-2)}.text-text-3{color:var(--text-3)}.capitalize{text-transform:capitalize}.lowercase{text-transform:lowercase}.normal-case{text-transform:none}.uppercase{text-transform:uppercase}.italic{font-style:italic}.diagonal-fractions{--tw-numeric-fraction:diagonal-fractions;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.lining-nums{--tw-numeric-figure:lining-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.proportional-nums{--tw-numeric-spacing:proportional-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.no-underline{text-decoration-line:none}.underline-offset-4{text-underline-offset:4px}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-70{opacity:.7}.opacity-80{opacity:.8}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_0_8px_rgba\(61\,220\,138\,0\.7\)\]{--tw-shadow:0 0 8px var(--tw-shadow-color,#3ddc8ab3);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_0_18px_rgba\(255\,90\,79\,0\.35\)\]{--tw-shadow:0 0 18px var(--tw-shadow-color,#ff5a4f59);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_0_32px_rgba\(255\,90\,79\,0\.3\)\]{--tw-shadow:0 0 32px var(--tw-shadow-color,#ff5a4f4d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-1{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-foreground\/10{--tw-ring-color:var(--foreground)}@supports (color:color-mix(in lab, red, red)){.ring-foreground\/10{--tw-ring-color:color-mix(in oklab, var(--foreground) 10%, transparent)}}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter\!{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)!important}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-100{--tw-duration:.1s;transition-duration:.1s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.paused{animation-play-state:paused}.running{animation-play-state:running}.zoom-in{--tw-enter-scale:0}@media (hover:hover){.hover\:border-text-3:hover{border-color:var(--text-3)}.hover\:bg-\[\#3a1512\]:hover{background-color:#3a1512}.hover\:bg-\[\#232931\]:hover{background-color:#232931}.hover\:bg-bernstein-hell:hover{background-color:var(--bernstein-hell)}.hover\:bg-cyan-grund:hover{background-color:var(--cyan-grund)}.hover\:bg-erhaben:hover{background-color:var(--erhaben)}.hover\:text-cyan:hover{color:var(--cyan)}.hover\:text-foreground:hover{color:var(--foreground)}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-100:hover{opacity:1}}.focus\:border-cyan:focus{border-color:var(--cyan)}.focus-visible\:ring-3:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:color-mix(in oklab, var(--ring) 50%, transparent)}}.active\:not-aria-\[haspopup\]\:translate-y-px:active:not([aria-haspopup]){--tw-translate-y:1px;translate:var(--tw-translate-x) var(--tw-translate-y)}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-45:disabled{opacity:.45}.data-\[side\=bottom\]\:inset-x-0[data-side=bottom]{inset-inline:0}.data-\[side\=bottom\]\:bottom-0[data-side=bottom]{bottom:0}.data-\[side\=bottom\]\:h-auto[data-side=bottom]{height:auto}.data-\[side\=bottom\]\:border-t[data-side=bottom]{border-top-style:var(--tw-border-style);border-top-width:1px}.data-\[side\=left\]\:inset-y-0[data-side=left]{inset-block:0}.data-\[side\=left\]\:left-0[data-side=left]{left:0}.data-\[side\=left\]\:h-full[data-side=left]{height:100%}.data-\[side\=left\]\:w-3\/4[data-side=left]{width:75%}.data-\[side\=left\]\:border-r[data-side=left]{border-right-style:var(--tw-border-style);border-right-width:1px}.data-\[side\=right\]\:inset-y-0[data-side=right]{inset-block:0}.data-\[side\=right\]\:right-0[data-side=right]{right:0}.data-\[side\=right\]\:h-full[data-side=right]{height:100%}.data-\[side\=right\]\:w-3\/4[data-side=right]{width:75%}.data-\[side\=right\]\:border-l[data-side=right]{border-left-style:var(--tw-border-style);border-left-width:1px}.data-\[side\=top\]\:inset-x-0[data-side=top]{inset-inline:0}.data-\[side\=top\]\:top-0[data-side=top]{top:0}.data-\[side\=top\]\:h-auto[data-side=top]{height:auto}.data-\[side\=top\]\:border-b[data-side=top]{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}@supports ((-webkit-backdrop-filter:var(--tw)) or (backdrop-filter:var(--tw))){.supports-backdrop-filter\:backdrop-blur-xs{--tw-backdrop-blur:blur(var(--blur-xs));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}}@media (width>=40rem){.sm\:block{display:block}.sm\:max-w-2xl{max-width:var(--container-2xl)}.sm\:max-w-lg{max-width:var(--container-lg)}.sm\:max-w-sm{max-width:var(--container-sm)}.sm\:max-w-xl{max-width:var(--container-xl)}.sm\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.sm\:grid-cols-\[minmax\(0\,1fr\)_120px_160px\]{grid-template-columns:minmax(0,1fr) 120px 160px}.sm\:flex-row{flex-direction:row}.sm\:justify-end{justify-content:flex-end}.sm\:gap-2{gap:calc(var(--spacing) * 2)}.sm\:p-6{padding:calc(var(--spacing) * 6)}.sm\:px-6{padding-inline:calc(var(--spacing) * 6)}.sm\:pl-\[124px\]{padding-left:124px}.sm\:text-\[44px\]{font-size:44px}.data-\[side\=left\]\:sm\:max-w-sm[data-side=left],.data-\[side\=right\]\:sm\:max-w-sm[data-side=right]{max-width:var(--container-sm)}}@media (width>=48rem){.md\:bottom-6{bottom:calc(var(--spacing) * 6)}.md\:left-auto{left:auto}.md\:col-span-1{grid-column:span 1/span 1}.md\:block{display:block}.md\:flex{display:flex}.md\:grid{display:grid}.md\:hidden{display:none}.md\:w-\[420px\]{width:420px}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-\[112px_minmax\(0\,1fr\)_auto\]{grid-template-columns:112px minmax(0,1fr) auto}.md\:grid-cols-\[170px_100px_170px_minmax\(0\,1fr\)_auto\]{grid-template-columns:170px 100px 170px minmax(0,1fr) auto}.md\:grid-cols-\[260px_minmax\(0\,1fr\)\]{grid-template-columns:260px minmax(0,1fr)}.md\:flex-col{flex-direction:column}.md\:items-end{align-items:flex-end}.md\:items-start{align-items:flex-start}.md\:gap-5{gap:calc(var(--spacing) * 5)}.md\:gap-6{gap:calc(var(--spacing) * 6)}.md\:px-10{padding-inline:calc(var(--spacing) * 10)}.md\:pt-8{padding-top:calc(var(--spacing) * 8)}.md\:pb-10{padding-bottom:calc(var(--spacing) * 10)}.md\:pl-\[124px\]{padding-left:124px}}@media (width>=64rem){.lg\:block{display:block}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:grid-cols-\[minmax\(0\,1\.4fr\)_minmax\(0\,1fr\)\]{grid-template-columns:minmax(0,1.4fr) minmax(0,1fr)}.lg\:grid-cols-\[minmax\(0\,1\.35fr\)_minmax\(0\,1fr\)\]{grid-template-columns:minmax(0,1.35fr) minmax(0,1fr)}.lg\:grid-cols-\[minmax\(0\,1fr\)_minmax\(0\,1\.3fr\)\]{grid-template-columns:minmax(0,1fr) minmax(0,1.3fr)}.lg\:px-6{padding-inline:calc(var(--spacing) * 6)}}.data-open\:animate-in:where([data-state=open]),.data-open\:animate-in:where([data-open]:not([data-open=false])){animation:enter var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-open\:fade-in-0:where([data-state=open]),.data-open\:fade-in-0:where([data-open]:not([data-open=false])){--tw-enter-opacity:0}.data-open\:zoom-in-95:where([data-state=open]),.data-open\:zoom-in-95:where([data-open]:not([data-open=false])){--tw-enter-scale:.95}.data-\[side\=bottom\]\:data-open\:slide-in-from-bottom-10[data-side=bottom]:where([data-state=open]),.data-\[side\=bottom\]\:data-open\:slide-in-from-bottom-10[data-side=bottom]:where([data-open]:not([data-open=false])){--tw-enter-translate-y:calc(.1*100%)}.data-\[side\=left\]\:data-open\:slide-in-from-left-10[data-side=left]:where([data-state=open]),.data-\[side\=left\]\:data-open\:slide-in-from-left-10[data-side=left]:where([data-open]:not([data-open=false])){--tw-enter-translate-x:calc(.1*-100%)}.data-\[side\=right\]\:data-open\:slide-in-from-right-10[data-side=right]:where([data-state=open]),.data-\[side\=right\]\:data-open\:slide-in-from-right-10[data-side=right]:where([data-open]:not([data-open=false])){--tw-enter-translate-x:calc(.1*100%)}.data-\[side\=top\]\:data-open\:slide-in-from-top-10[data-side=top]:where([data-state=open]),.data-\[side\=top\]\:data-open\:slide-in-from-top-10[data-side=top]:where([data-open]:not([data-open=false])){--tw-enter-translate-y:calc(.1*-100%)}.data-closed\:animate-out:where([data-state=closed]),.data-closed\:animate-out:where([data-closed]:not([data-closed=false])){animation:exit var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-closed\:fade-out-0:where([data-state=closed]),.data-closed\:fade-out-0:where([data-closed]:not([data-closed=false])){--tw-exit-opacity:0}.data-closed\:zoom-out-95:where([data-state=closed]),.data-closed\:zoom-out-95:where([data-closed]:not([data-closed=false])){--tw-exit-scale:.95}.data-\[side\=bottom\]\:data-closed\:slide-out-to-bottom-10[data-side=bottom]:where([data-state=closed]),.data-\[side\=bottom\]\:data-closed\:slide-out-to-bottom-10[data-side=bottom]:where([data-closed]:not([data-closed=false])){--tw-exit-translate-y:calc(.1*100%)}.data-\[side\=left\]\:data-closed\:slide-out-to-left-10[data-side=left]:where([data-state=closed]),.data-\[side\=left\]\:data-closed\:slide-out-to-left-10[data-side=left]:where([data-closed]:not([data-closed=false])){--tw-exit-translate-x:calc(.1*-100%)}.data-\[side\=right\]\:data-closed\:slide-out-to-right-10[data-side=right]:where([data-state=closed]),.data-\[side\=right\]\:data-closed\:slide-out-to-right-10[data-side=right]:where([data-closed]:not([data-closed=false])){--tw-exit-translate-x:calc(.1*100%)}.data-\[side\=top\]\:data-closed\:slide-out-to-top-10[data-side=top]:where([data-state=closed]),.data-\[side\=top\]\:data-closed\:slide-out-to-top-10[data-side=top]:where([data-closed]:not([data-closed=false])){--tw-exit-translate-y:calc(.1*-100%)}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&_svg\:not\(\[class\*\=\'size-\'\]\)\]\:size-4 svg:not([class*=size-]){width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}:is(.\*\:\[a\]\:underline>*):is(a){text-decoration-line:underline}:is(.\*\:\[a\]\:underline-offset-3>*):is(a){text-underline-offset:3px}@media (hover:hover){:is(.\*\:\[a\]\:hover\:text-foreground>*):is(a):hover{color:var(--foreground)}}.schild{font-family:var(--font-anzeige);text-transform:uppercase;letter-spacing:.16em;font-weight:600}.ziffern{font-family:var(--font-mono);font-variant-numeric:tabular-nums}}@property --tw-animation-delay{syntax:"*";inherits:false;initial-value:0s}@property --tw-animation-direction{syntax:"*";inherits:false;initial-value:normal}@property --tw-animation-duration{syntax:"*";inherits:false}@property --tw-animation-fill-mode{syntax:"*";inherits:false;initial-value:none}@property --tw-animation-iteration-count{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-translate-y{syntax:"*";inherits:false;initial-value:0}@property --scroll-fade-t{syntax:"";inherits:false;initial-value:0}@property --scroll-fade-b{syntax:"";inherits:false;initial-value:0}@property --scroll-fade-s{syntax:"";inherits:false;initial-value:0}@property --scroll-fade-e{syntax:"";inherits:false;initial-value:0}@property --scroll-fade-mask{syntax:"*";inherits:false}@property --shimmer-angle{syntax:"";inherits:true;initial-value:20deg}@property --shimmer-image{syntax:"*";inherits:false}@property --shimmer-text-fill{syntax:"*";inherits:false}@media (prefers-reduced-motion:reduce){.shimmer{-webkit-text-fill-color:currentColor;background-image:none;animation:none}}@font-face{font-family:Barlow;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/barlow-vietnamese-400-normal-Dpl4UHAZ.woff2)format("woff2"),url(/assets/barlow-vietnamese-400-normal-BFeobeCK.woff)format("woff");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Barlow;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/barlow-latin-ext-400-normal-HxX4XjxC.woff2)format("woff2"),url(/assets/barlow-latin-ext-400-normal-CvBsJvxq.woff)format("woff");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Barlow;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/barlow-latin-400-normal-qiz4-Cze.woff2)format("woff2"),url(/assets/barlow-latin-400-normal-fsAxiSwU.woff)format("woff");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Barlow;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/barlow-vietnamese-500-normal-zTViEIzf.woff2)format("woff2"),url(/assets/barlow-vietnamese-500-normal-GNfB7rCE.woff)format("woff");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Barlow;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/barlow-latin-ext-500-normal-DOaysfXq.woff2)format("woff2"),url(/assets/barlow-latin-ext-500-normal-CJPcKP2Q.woff)format("woff");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Barlow;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/barlow-latin-500-normal-BPAOfeC8.woff2)format("woff2"),url(/assets/barlow-latin-500-normal-C1h8hMer.woff)format("woff");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Barlow;font-style:normal;font-display:swap;font-weight:600;src:url(/assets/barlow-vietnamese-600-normal-DcjprdFV.woff2)format("woff2"),url(/assets/barlow-vietnamese-600-normal-CA_GiK2e.woff)format("woff");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Barlow;font-style:normal;font-display:swap;font-weight:600;src:url(/assets/barlow-latin-ext-600-normal-B8NK_A3D.woff2)format("woff2"),url(/assets/barlow-latin-ext-600-normal-DMVRjfRT.woff)format("woff");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Barlow;font-style:normal;font-display:swap;font-weight:600;src:url(/assets/barlow-latin-600-normal-DILqtrty.woff2)format("woff2"),url(/assets/barlow-latin-600-normal-CNwfPWQD.woff)format("woff");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Barlow Condensed;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/barlow-condensed-vietnamese-500-normal-DjeaNLFD.woff2)format("woff2"),url(/assets/barlow-condensed-vietnamese-500-normal-CsrJDWc5.woff)format("woff");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Barlow Condensed;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/barlow-condensed-latin-ext-500-normal-yA5ONLQ9.woff2)format("woff2"),url(/assets/barlow-condensed-latin-ext-500-normal-B1RE8WP7.woff)format("woff");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Barlow Condensed;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/barlow-condensed-latin-500-normal-BgYH2mbd.woff2)format("woff2"),url(/assets/barlow-condensed-latin-500-normal-HIEiP5Ov.woff)format("woff");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Barlow Condensed;font-style:normal;font-display:swap;font-weight:600;src:url(/assets/barlow-condensed-vietnamese-600-normal-A5AYRdjN.woff2)format("woff2"),url(/assets/barlow-condensed-vietnamese-600-normal-CNlPk46_.woff)format("woff");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Barlow Condensed;font-style:normal;font-display:swap;font-weight:600;src:url(/assets/barlow-condensed-latin-ext-600-normal-18ESti3H.woff2)format("woff2"),url(/assets/barlow-condensed-latin-ext-600-normal-Clv9cIcR.woff)format("woff");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Barlow Condensed;font-style:normal;font-display:swap;font-weight:600;src:url(/assets/barlow-condensed-latin-600-normal-DepVgxBB.woff2)format("woff2"),url(/assets/barlow-condensed-latin-600-normal-BFJEwTuo.woff)format("woff");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Barlow Condensed;font-style:normal;font-display:swap;font-weight:700;src:url(/assets/barlow-condensed-vietnamese-700-normal-DYeBwlKR.woff2)format("woff2"),url(/assets/barlow-condensed-vietnamese-700-normal-DhIzd8Tb.woff)format("woff");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Barlow Condensed;font-style:normal;font-display:swap;font-weight:700;src:url(/assets/barlow-condensed-latin-ext-700-normal-CwuXbfVR.woff2)format("woff2"),url(/assets/barlow-condensed-latin-ext-700-normal-BIHFfxf0.woff)format("woff");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Barlow Condensed;font-style:normal;font-display:swap;font-weight:700;src:url(/assets/barlow-condensed-latin-700-normal-v1xN8_Wq.woff2)format("woff2"),url(/assets/barlow-condensed-latin-700-normal-Dmwat-ge.woff)format("woff");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(data:font/woff2;base64,d09GMgABAAAAAASIABAAAAAACQQAAAQuAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGhwbHhwoBmA/U1RBVF4AdBEICoRkhAALIAABNgIkAzoEIAWFAAeBFAwHG2oHKJ6DceNW4lJEFHn9tEOE37LNsvkjHr7f739rn3u+OSrSxLQytE91Dw2PYtNVq3Qaw/vJ7fUBMdOj/u2ImB98cT5WUx9F13ZKt06mU7tG1sAYcM26yCRX4f/0904bmwq8hwkUUMTRX61pa9C3xlpAGYw1vOu8C2SBZZFlld7DAW82RJWmwYMI1AJCKBNCIASqdZGFmtPSNQRhMpR0EKjWTwm6z6sJ+4jqhxjovTinVdRpZaQjaQzAYjI8NgAKDJCokgunCn9oUQE8VZd/F//+v6P4F1U9gLr58yNI/dJX9BAshEoJbTDogz7ocKoUsPvES8UK/aQIUQgpGgECBVLkOEV6iASTYgNAPKdNXayhDPL7IJuAZnEYSZ0eOLc9i5Rv5/+lEi3sW/kfnCf/+fTe0sxS7CKLx5erRJkKOixEqQaoqrvx5HN4iz4VhX0gS6DjFIWUzn/fIXJRVFY1NFRVNVeFt+SYmrK6vCU6eJsnKnJj5HTESMTQZOTI3Y/tzr3rUcOsiRy/ciP50s3Mycgxmhz9GMXhjzVH30ut796NHP0UUa31/Zoa6vCH6iPvdIM0IRANaT60FablmZlZd+UKNFy9NrvnFGxb5NC2CRxR0/rIyF/WNn+35sv9r+tHVhkseuWGKkCPPh96+GXt8Lc/Sh24ujfjf+tNw1lZWreiPuHb/PSpyjdv2rf/++ZE5TSKjFdZxYsBvr1sEHl5STuHZqYR7jGYGvGBBdjcaB5bODY1GAxMjsd0wDMIzXAXODRd74DxNMtO4YuYHclgLQRzp9KlUmxptCwv9bYgvWGD2xBW7r9413fdJu+mxzvzAUYeeONQvZP4kgfqZle4jhH/MWh+UbxgtJdrLdXLymNL53PRU0D3Q6FcXTfGqGcul6vrqhgLGAVSv+IVIfZOHpu+mlLqSlnj903j8mazXDsba/wbxhS/4Oubh1c5/uXDgt4j5KtnGEy5BIJHo0ur+jD+r2qCkuP1aRVM8EpUoRYSJyqNRA38uwDvHBNo0AejO2Z+ZYLLal1QiFyFh1EDQOgSCSCpjwwKU8yDbIjroEwne0G5Qca49cYp4AlqtQNZfWTQoFb1tRpFYAmRD+HXTkV4uQhG2bg4OKmyoypAsUGtWgQXyFxYrkpODeUxvGqIZA61erXo0sFG1UBGuPgpuon8RNUG2DhovAjZCBuZwtXrU3mQGki9+pm0eVZAXoWxLWTQoYHBPrJR4WunNxIFbCHfkTyPK+sqxjxDmGArZvf79JGJ3GwEqjwc7a7NIrl/7bJ7Nzu4+n1Ow6shEPnUrtVo7cnd5Wi5qCUbBIQbNKCP95FMCSZylEV5VCiiMqqiOmrKZ/I/C0gI1fyuulVcM2E1r4MhtcV/fbCD+HwEvVzH1dGNAzFE0FTbKzyQz3gootrNbN2a4PuG0j0JOgE=)format("woff2"),url(data:font/woff;base64,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)format("woff");unicode-range:U+460-52F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2)format("woff2"),url(/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff)format("woff");unicode-range:U+301,U+400-45F,U+490-491,U+4B0-4B1,U+2116}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2)format("woff2"),url(/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff)format("woff");unicode-range:U+370-377,U+37A-37F,U+384-38A,U+38C,U+38E-3A1,U+3A3-3FF}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(data:font/woff2;base64,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)format("woff2"),url(/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff)format("woff");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2)format("woff2"),url(/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff)format("woff");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2)format("woff2"),url(/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff)format("woff");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:500;src:url(data:font/woff2;base64,d09GMgABAAAAAASUABAAAAAACRAAAAQ3AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGhwbHhwoBmA/U1RBVEwAdBEICoRkg3oLIAABNgIkAzoEIAWFHgeBFAwHG3AHKB4HzukrRjyF5Gb4kQ/B873d17mv8TWkoqUUGaHodJCtoqntw7m8tiPWyGkfWDU/IMpzVk4zAs9Czv3c7Os5NvKFG1Ht9vBVXySRZpJc4tTrbM3sTRFcLa3zVboKWRIoAksKSKgqUQWEwlSoqjp44V5J9/kjd0+Fi5xaFjwJArgBAIJgIAgCCAI4CdNMqGuYXYUKdADLAkAAJwl6iX0+bZqEm1AH0Hu9rvrJHwxQG1Q/gFYwWYbgTRWgwEESVzbmtjQAt3DXO7Tu/+9Q/KNKWhTCgZ8fQSWoL0CUUgTBjgL8iEAcce7YHBeA8ZvogieCnxI0BCVeACCAAhBD/oDcAdUPABSgAX4kBPBTwjCAjwYSCneiqF65LUo/qXdYFrRwTujtMrKm07plTbSqLQFAiHBN7E4DG5wkiGXhCYBNETh3K/AciHN69iFfQjFOr9EXQQAAQXRNszs8PR0OH4fDV/dwGe76CHdj1MQa11DXYGcfZ6+B1X0OfwjY+i7KpQ1w9d+1z3/HydCB1f3U8A0fRFv+0bXxPWrZu3d9Nn4UcbLs/QCXLH/j3PCKblKOiZxLOR78W9brPo7eGTLz/F27ZPmePQdCB1YP4nJU91o4gU9cy64L3c3SPu8GfDn6ZXD2cGmllVqSxtD5vCXHm5xaeHlnpffx7DcPvXog5NnjA//cPz2btsz3yf+0MI8ri33tuv7upNbYmW5STbosW8bYItV/SPzxvXC0KnpWnFdC91oojit5Lyo6WcJQ1YzwBYbi52ohJVpcxfcHBqsv0nFz8U74rzS6M7r0RVlXZ3jJC4G92O//7Lm78VOtnUx+aQxAzsqPnrRr1t9zDrezKePvZ027x+fGte4s4NXu7/jEp3G9cM1bICYgACbuETUUD5wmenGXA/IBpAKVrl0AEJ5cqr6Q89tGq+SpqkDfX2DtG+pZ9teuae0AX98c301CX179InyErnSG8WCiABB4HFbVrw/lpTdBIOk82nXbpHKoQGyBpUovAAD4XQA8ZTUCeBJHIpI0v0FRrgcnckV3ANckrwYJKXEihQfdSKPER6XeExmEeEMmSe6QBwWmkZdmSOSthhibgIkBlUYreBKd/0NeVAE9WAyEaQpH6KikDWlUVg43Jy2FOmaYlsZhDEGZXO3mWEyWHI6zuaJkMlcSQ9k4F+KidIiFyZItGDc7r1pUj6wP6zrWB0/fbeeFeHl4YOvETMNiM8Ny+7OO6Qh2wur20YVxFts5dlORdl5Kwd5utR7SRcxqX8RA5Ehacha76hg7c6yzNm/Xf6vOLNrv544lIEkWg7xWo/ItBAeIJEmt0XgBwgM8gTifoiiLJroYYooNTeziEKe4zOoR/wvIKp89hSr+6jFAqw/LaonjmZHSscMNg4iPlWpFrO1RN3zkMU+/xUP+JQ99TbvTl1Vg0gtirT6lbwYAAAA=)format("woff2"),url(data:font/woff;base64,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)format("woff");unicode-range:U+460-52F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/jetbrains-mono-cyrillic-500-normal-DmUKJPL_.woff2)format("woff2"),url(/assets/jetbrains-mono-cyrillic-500-normal-DJqRU3vO.woff)format("woff");unicode-range:U+301,U+400-45F,U+490-491,U+4B0-4B1,U+2116}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/jetbrains-mono-greek-500-normal-JpySY46c.woff2)format("woff2"),url(/assets/jetbrains-mono-greek-500-normal-D7SFKleX.woff)format("woff");unicode-range:U+370-377,U+37A-37F,U+384-38A,U+38C,U+38E-3A1,U+3A3-3FF}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:500;src:url(data:font/woff2;base64,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)format("woff2"),url(/assets/jetbrains-mono-vietnamese-500-normal-DNRqzVM1.woff)format("woff");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/jetbrains-mono-latin-ext-500-normal-Cut-4mMH.woff2)format("woff2"),url(/assets/jetbrains-mono-latin-ext-500-normal-ckzbgY84.woff)format("woff");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2)format("woff2"),url(/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff)format("woff");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}:root{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--radius:.625rem;--background:#0e1012;--foreground:#e6eaee;--card:#15181b;--card-foreground:#e6eaee;--popover:#15181b;--popover-foreground:#e6eaee;--primary:#ffb020;--primary-foreground:#1a1300;--secondary:#1c2126;--secondary-foreground:#e6eaee;--muted:#1c2126;--muted-foreground:#8b949e;--accent:#1c2126;--accent-foreground:#e6eaee;--destructive:#ff5a4f;--border:#262b30;--input:#3a4148;--ring:#5cc8ff;--panel:#15181b;--erhaben:#1c2126;--linie:#262b30;--linie-stark:#3a4148;--text-2:#aeb6bf;--text-3:#8b949e;--bernstein:#ffb020;--bernstein-hell:#ffc24d;--bernstein-grund:#2a1e05;--bernstein-lampe:#3a2a08;--gruen:#3ddc8a;--gruen-text:#7cc9a0;--gruen-grund:#0f2319;--gruen-rand:#1f5a3b;--cyan:#5cc8ff;--cyan-text:#93d5f8;--cyan-grund:#0c2230;--cyan-rand:#2f7fb0;--rot:#ff5a4f;--rot-text:#ff9a92;--rot-grund:#2e0f0d;--rot-rand:#a33a33;--aus-grund:#171b1f;--aus-rand:#2e343a;--aus-text:#9aa3ad}@keyframes lampe-atmen{0%,to{box-shadow:0 0 10px color-mix(in srgb, var(--bernstein) 25%, transparent)}50%{box-shadow:0 0 22px color-mix(in srgb, var(--bernstein) 45%, transparent)}}@media (prefers-reduced-motion:no-preference){.lampe-atmet{animation:3.2s ease-in-out infinite lampe-atmen}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@keyframes enter{0%{opacity:var(--tw-enter-opacity,1);transform:translate3d(var(--tw-enter-translate-x,0),var(--tw-enter-translate-y,0),0)scale3d(var(--tw-enter-scale,1),var(--tw-enter-scale,1),var(--tw-enter-scale,1))rotate(var(--tw-enter-rotate,0));filter:blur(var(--tw-enter-blur,0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity,1);transform:translate3d(var(--tw-exit-translate-x,0),var(--tw-exit-translate-y,0),0)scale3d(var(--tw-exit-scale,1),var(--tw-exit-scale,1),var(--tw-exit-scale,1))rotate(var(--tw-exit-rotate,0));filter:blur(var(--tw-exit-blur,0))}} diff --git a/frontend/dist/assets/index-B6MevgIX.js b/frontend/dist/assets/index-ZVRs0IGR.js similarity index 95% rename from frontend/dist/assets/index-B6MevgIX.js rename to frontend/dist/assets/index-ZVRs0IGR.js index 9c51f76..582985c 100644 --- a/frontend/dist/assets/index-B6MevgIX.js +++ b/frontend/dist/assets/index-ZVRs0IGR.js @@ -1,4 +1,4 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/Dienste-QEbMZv2T.js","assets/button-Dd8hfusv.js","assets/sheet-DWG2Q04V.js","assets/dist-CgRgLCFz.js","assets/Einstellungen-DMWgWLUo.js","assets/MehrMenue-gZV9ubEU.js","assets/Protokollfenster-CDb28asU.js","assets/Updates-3PYj6oWY.js","assets/Modelle-PWfbWtFC.js"])))=>i.map(i=>d[i]); +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/Dienste-DEn0Zjkq.js","assets/button-Dd8hfusv.js","assets/sheet-DWG2Q04V.js","assets/dist-CgRgLCFz.js","assets/Einstellungen-BwCmWl9x.js","assets/MehrMenue-CXteqmy8.js","assets/Protokollfenster-CDb28asU.js","assets/Updates-DPFIId2v.js","assets/Bestaetigen-VrcNpcBb.js","assets/Modelle-CHK2sw1N.js"])))=>i.map(i=>d[i]); import{a as e,c as t,d as n,f as r,i,l as a,o,s,t as c,u as l}from"./button-Dd8hfusv.js";(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var u=n((e=>{function t(e,t){var n=e.length;e.push(t);a:for(;0>>1,a=e[r];if(0>>1;ri(c,n))li(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else if(li(u,n))e[r]=u,e[l]=n,r=l;else break a}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return n===0?e.id-t.id:n}if(e.unstable_now=void 0,typeof performance==`object`&&typeof performance.now==`function`){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var c=[],l=[],u=1,d=null,f=3,p=!1,m=!1,h=!1,g=!1,_=typeof setTimeout==`function`?setTimeout:null,v=typeof clearTimeout==`function`?clearTimeout:null,y=typeof setImmediate<`u`?setImmediate:null;function b(e){for(var i=n(l);i!==null;){if(i.callback===null)r(l);else if(i.startTime<=e)r(l),i.sortIndex=i.expirationTime,t(c,i);else break;i=n(l)}}function x(e){if(h=!1,b(e),!m){if(n(c)!==null)m=!0,S||(S=!0,te());else{var t=n(l);t!==null&&re(x,t.startTime-e)}}}var S=!1,C=-1,w=5,T=-1;function ee(){return g?!0:!(e.unstable_now()-Tt&&ee());){var o=d.callback;if(typeof o==`function`){d.callback=null,f=d.priorityLevel;var s=o(d.expirationTime<=t);if(t=e.unstable_now(),typeof s==`function`){d.callback=s,b(t),i=!0;break b}d===n(c)&&r(c),b(t)}else r(c);d=n(c)}if(d!==null)i=!0;else{var u=n(l);u!==null&&re(x,u.startTime-t),i=!1}}break a}finally{d=null,f=a,p=!1}i=void 0}}finally{i?te():S=!1}}}var te;if(typeof y==`function`)te=function(){y(E)};else if(typeof MessageChannel<`u`){var D=new MessageChannel,ne=D.port2;D.port1.onmessage=E,te=function(){ne.postMessage(null)}}else te=function(){_(E,0)};function re(t,n){C=_(function(){t(e.unstable_now())},n)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(e){e.callback=null},e.unstable_forceFrameRate=function(e){0>e||125o?(r.sortIndex=a,t(l,r),n(c)===null&&r===n(l)&&(h?(v(C),C=-1):h=!0,re(x,a-o))):(r.sortIndex=s,t(c,r),m||p||(m=!0,S||(S=!0,te()))),r},e.unstable_shouldYield=ee,e.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}})),d=n(((e,t)=>{t.exports=u()})),f=n((e=>{var t=d(),n=l(),r=a();function i(e){var t=`https://react.dev/errors/`+e;if(1we||(e.current=Ce[we],Ce[we]=null,we--)}function j(e,t){we++,Ce[we]=e.current,e.current=t}var De=Te(null),Oe=Te(null),ke=Te(null),Ae=Te(null);function je(e,t){switch(j(ke,t),j(Oe,e),j(De,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?up(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=up(t),e=dp(t,e);else switch(e){case`svg`:e=1;break;case`math`:e=2;break;default:e=0}}Ee(De),j(De,e)}function Me(){Ee(De),Ee(Oe),Ee(ke)}function Ne(e){var t=e.memoizedState;t!==null&&(sh._currentValue=t.memoizedState,j(Ae,e)),t=De.current;var n=dp(t,e.type);t!==n&&(j(Oe,e),j(De,n))}function Pe(e){Oe.current===e&&(Ee(De),Ee(Oe)),Ae.current===e&&(Ee(Ae),sh._currentValue=A)}var Fe,Ie;function Le(e){if(Fe===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);Fe=t&&t[1]||``,Ie=-1)`:-1>>=0,e===0?32:31-(ot(e)/st|0)|0}var lt=256,ut=262144,dt=4194304;function ft(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&-e;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function pt(e,t,n){var r=e.pendingLanes;if(r===0)return 0;var i=0,a=e.suspendedLanes,o=e.pingedLanes;e=e.warmLanes;var s=r&134217727;return s===0?(s=r&~a,s===0?o===0?n||(n=r&~e,n!==0&&(i=ft(n))):i=ft(o):i=ft(s)):(r=s&~a,r===0?(o&=s,o===0?n||(n=s&~e,n!==0&&(i=ft(n))):i=ft(o)):i=ft(r)),i===0?0:t!==0&&t!==i&&(t&a)===0&&(a=i&-i,n=t&-t,a>=n||a===32&&n&4194048)?t:i}function mt(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function ht(e,t){t&8&&(t|=t&32);var n=e.entangledLanes;if(n!==0)for(e=e.entanglements,n&=t;0n;n++)t.push(e);return t}function yt(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function bt(e,t,n,r,i,a){var o=e.pendingLanes;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=n,e.entangledLanes&=n,e.errorRecoveryDisabledLanes&=n,e.shellSuspendCounter=0;var s=e.entanglements,c=e.expirationTimes,l=e.hiddenUpdates;for(n=o&~n;0=yr),Sr=` `,Cr=!1;function wr(e,t){switch(e){case`keyup`:return _r.indexOf(t.keyCode)!==-1;case`keydown`:return t.keyCode!==229;case`keypress`:case`mousedown`:case`focusout`:return!0;default:return!1}}function Tr(e){return e=e.detail,typeof e==`object`&&`data`in e?e.data:null}var Er=!1;function Dr(e,t){switch(e){case`compositionend`:return Tr(t);case`keypress`:return t.which===32?(Cr=!0,Sr):null;case`textInput`:return e=t.data,e===Sr&&Cr?null:e;default:return null}}function Or(e,t){if(Er)return e===`compositionend`||!vr&&wr(e,t)?(e=Bn(),zn=Rn=Ln=null,Er=!1,e):null;switch(e){case`paste`:return null;case`keypress`:if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}a:{for(;n;){if(n.nextSibling){n=n.nextSibling;break a}n=n.parentNode}n=void 0}n=Zr(n)}}function $r(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?$r(e,t.parentNode):`contains`in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function ei(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=Xr(e.document);t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href==`string`}catch{n=!1}if(n)e=t.contentWindow;else break;t=Xr(e.document)}return t}function ti(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t===`input`&&(e.type===`text`||e.type===`search`||e.type===`tel`||e.type===`url`||e.type===`password`)||t===`textarea`||e.contentEditable===`true`)}var ni=Pn&&`documentMode`in document&&11>=document.documentMode,ri=null,ii=null,ai=null,oi=!1;function si(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;oi||ri==null||ri!==Xr(r)||(r=ri,`selectionStart`in r&&ti(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),ai&&Yr(ai,r)||(ai=r,r=Jf(ii,`onSelect`),0>=o,i-=o,ra=1<<32-at(t)+i|n<h?(g=d,d=null):g=d.sibling;var _=p(i,d,s[h],c);if(_===null){d===null&&(d=g);break}e&&d&&_.alternate===null&&t(i,d),a=o(_,a,h),u===null?l=_:u.sibling=_,u=_,d=g}if(h===s.length)return n(i,d),P&&aa(i,h),l;if(d===null){for(;hg?(_=h,h=null):_=h.sibling;var y=p(a,h,v.value,l);if(y===null){h===null&&(h=_);break}e&&h&&y.alternate===null&&t(a,h),s=o(y,s,g),d===null?u=y:d.sibling=y,d=y,h=_}if(v.done)return n(a,h),P&&aa(a,g),u;if(h===null){for(;!v.done;g++,v=c.next())v=f(a,v.value,l),v!==null&&(s=o(v,s,g),d===null?u=v:d.sibling=v,d=v);return P&&aa(a,g),u}for(h=r(h);!v.done;g++,v=c.next())v=m(h,a,g,v.value,l),v!==null&&(e&&(_=v.alternate,_!==null&&h.delete(_.key===null?g:_.key)),s=o(v,s,g),d===null?u=v:d.sibling=v,d=v);return e&&h.forEach(function(e){return t(a,e)}),P&&aa(a,g),u}function _(e,r,o,c){if(typeof o==`object`&&o&&o.type===re&&o.key===null&&o.props.ref===void 0&&(o=o.props.children),typeof o==`object`&&o){switch(o.$$typeof){case D:a:{for(var l=o.key;r!==null;){if(r.key===l){if(l=o.type,l===re){if(r.tag===7){n(e,r.sibling),c=a(r,o.props.children),mo(c,o),c.return=e,e=c;break a}}else if(r.elementType===l||typeof l==`object`&&l&&l.$$typeof===fe&&oo(l)===r.type){n(e,r.sibling),c=a(r,o.props),mo(c,o),c.return=e,e=c;break a}n(e,r);break}t(e,r),r=r.sibling}o.type===re?(c=Wi(o.props.children,e.mode,c,o.key),mo(c,o),c.return=e,e=c):(c=Ui(o.type,o.key,o.props,null,e.mode,c),mo(c,o),c.return=e,e=c)}return s(e);case ne:a:{for(l=o.key;r!==null;){if(r.key===l){if(r.tag===4&&r.stateNode.containerInfo===o.containerInfo&&r.stateNode.implementation===o.implementation){n(e,r.sibling),c=a(r,o.children||[]),c.return=e,e=c;break a}n(e,r);break}t(e,r),r=r.sibling}c=qi(o,e.mode,c),c.return=e,e=c}return s(e);case fe:return o=oo(o),_(e,r,o,c)}if(Se(o))return h(e,r,o,c);if(ye(o)){if(l=ye(o),typeof l!=`function`)throw Error(i(150));return o=l.call(o),g(e,r,o,c)}if(typeof o.then==`function`)return _(e,r,po(o),c);if(o.$$typeof===se)return _(e,r,Ma(e,o),c);ho(e,o)}return typeof o==`string`&&o!==``||typeof o==`number`||typeof o==`bigint`?(o=``+o,r!==null&&r.tag===6?(n(e,r.sibling),c=a(r,o),c.return=e,e=c):(n(e,r),c=Gi(o,e.mode,c),c.return=e,e=c),s(e)):n(e,r)}return function(e,t,n,r){try{fo=0;var i=_(e,t,n,r);return uo=null,i}catch(t){if(t===eo||t===no)throw t;var a=zi(29,t,null,e.mode);return a.lanes=r,a.return=e,a}}}var _o=go(!0),vo=go(!1),yo=!1;function bo(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function xo(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function So(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function Co(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,W&2){var i=r.pending;return i===null?t.next=t:(t.next=i.next,i.next=t),r.pending=t,t=Ii(e),Fi(e,null,n),t}return Mi(e,r,t,n),Ii(e)}function wo(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,n&4194048)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,St(e,n)}}function To(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var i=null,a=null;if(n=n.firstBaseUpdate,n!==null){do{var o={lane:n.lane,tag:n.tag,payload:n.payload,callback:null,next:null};a===null?i=a=o:a=a.next=o,n=n.next}while(n!==null);a===null?i=a=t:a=a.next=t}else i=a=t;n={baseState:r.baseState,firstBaseUpdate:i,lastBaseUpdate:a,shared:r.shared,callbacks:r.callbacks},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}var Eo=!1;function Do(){if(Eo){var e=Ga;if(e!==null)throw e}}function Oo(e,t,n,r){Eo=!1;var i=e.updateQueue;yo=!1;var a=i.firstBaseUpdate,o=i.lastBaseUpdate,s=i.shared.pending;if(s!==null){i.shared.pending=null;var c=s,l=c.next;c.next=null,o===null?a=l:o.next=l,o=c;var u=e.alternate;u!==null&&(u=u.updateQueue,s=u.lastBaseUpdate,s!==o&&(s===null?u.firstBaseUpdate=l:s.next=l,u.lastBaseUpdate=c))}if(a!==null){var d=i.baseState;o=0,u=l=c=null,s=a;do{var f=s.lane&-536870913,p=f!==s.lane;if(p?(q&f)===f:(r&f)===f){f!==0&&f===Wa&&(Eo=!0),u!==null&&(u=u.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});a:{var m=e,h=s;f=t;var g=n;switch(h.tag){case 1:if(m=h.payload,typeof m==`function`){d=m.call(g,d,f);break a}d=m;break a;case 3:m.flags=m.flags&-65537|128;case 0:if(m=h.payload,f=typeof m==`function`?m.call(g,d,f):m,f==null)break a;d=E({},d,f);break a;case 2:yo=!0}}f=s.callback,f!==null&&(e.flags|=64,p&&(e.flags|=8192),p=i.callbacks,p===null?i.callbacks=[f]:p.push(f))}else p={lane:f,tag:s.tag,payload:s.payload,callback:s.callback,next:null},u===null?(l=u=p,c=d):u=u.next=p,o|=f;if(s=s.next,s===null){if(s=i.shared.pending,s===null)break;p=s,s=p.next,p.next=null,i.lastBaseUpdate=p,i.shared.pending=null}}while(1);u===null&&(c=d),i.baseState=c,i.firstBaseUpdate=l,i.lastBaseUpdate=u,a===null&&(i.shared.lanes=0),sd|=o,e.lanes=o,e.memoizedState=d}}function ko(e,t){if(typeof e!=`function`)throw Error(i(191,e));e.call(t)}function Ao(e,t){var n=e.callbacks;if(n!==null)for(e.callbacks=null,e=0;ea?a:8;var o=O.T,s={};s.types=o===null?null:o.types,O.T=s,pc(e,!1,t,n);try{var c=i(),l=O.S;l!==null&&l(s,c),typeof c==`object`&&c&&typeof c.then==`function`?fc(e,t,Ja(c,r),jd(e)):fc(e,t,r,jd(e))}catch(n){fc(e,t,{then:function(){},status:`rejected`,reason:n},jd())}finally{k.p=a,o!==null&&s.types!==null&&(o.types=s.types),O.T=o}}function nc(){}function rc(e,t,n,r){if(e.tag!==5)throw Error(i(476));var a=ic(e).queue;tc(e,a,t,A,n===null?nc:function(){return ac(e),n(r)})}function ic(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:A,baseState:A,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ms,lastRenderedState:A},next:null};var n={};return t.next={memoizedState:n,baseState:n,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ms,lastRenderedState:n},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function ac(e){var t=ic(e);t.next===null&&(t=e.alternate.memoizedState),fc(e,t.next.queue,{},jd())}function oc(){return ja(sh)}function sc(){return B().memoizedState}function cc(){return B().memoizedState}function lc(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var n=jd();e=So(n);var r=Co(t,e,n);r!==null&&(Pd(r,t,n),wo(r,t,n)),t={cache:Ra()},e.payload=t;return}t=t.return}}function uc(e,t,n){var r=jd();n={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null},mc(e)?hc(t,n):(n=Ni(e,t,n,r),n!==null&&(Pd(n,e,r),gc(n,t,r)))}function dc(e,t,n){fc(e,t,n,jd())}function fc(e,t,n,r){var i={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null};if(mc(e))hc(t,i);else{var a=e.alternate;if(e.lanes===0&&(a===null||a.lanes===0)&&(a=t.lastRenderedReducer,a!==null))try{var o=t.lastRenderedState,s=a(o,n);if(i.hasEagerState=!0,i.eagerState=s,Jr(s,o))return Mi(e,t,i,0),G===null&&ji(),!1}catch{}if(n=Ni(e,t,i,r),n!==null)return Pd(n,e,r),gc(n,t,r),!0}return!1}function pc(e,t,n,r){if(r={lane:2,revertLane:Pf(),gesture:null,action:r,hasEagerState:!1,eagerState:null,next:null},mc(e)){if(t)throw Error(i(479))}else t=Ni(e,n,r,2),t!==null&&Pd(t,e,2)}function mc(e){var t=e.alternate;return e===I||t!==null&&t===I}function hc(e,t){Yo=Jo=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function gc(e,t,n){if(n&4194048){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,St(e,n)}}var _c={readContext:ja,use:fs,useCallback:z,useContext:z,useEffect:z,useImperativeHandle:z,useLayoutEffect:z,useInsertionEffect:z,useMemo:z,useReducer:z,useRef:z,useState:z,useDebugValue:z,useDeferredValue:z,useTransition:z,useSyncExternalStore:z,useId:z,useHostTransitionStatus:z,useFormState:z,useActionState:z,useOptimistic:z,useMemoCache:z,useCacheRefresh:z,useEffectEvent:z},vc={readContext:ja,use:fs,useCallback:function(e,t){return ls().memoizedState=[e,t===void 0?null:t],e},useContext:ja,useEffect:Hs,useImperativeHandle:function(e,t,n){n=n==null?null:n.concat([e]),Bs(4194308,4,Js.bind(null,t,e),n)},useLayoutEffect:function(e,t){return Bs(4194308,4,e,t)},useInsertionEffect:function(e,t){Bs(4,2,e,t)},useMemo:function(e,t){var n=ls();t=t===void 0?null:t;var r=e();if(Xo){it(!0);try{e()}finally{it(!1)}}return n.memoizedState=[r,t],r},useReducer:function(e,t,n){var r=ls();if(n!==void 0){var i=n(t);if(Xo){it(!0);try{n(t)}finally{it(!1)}}}else i=t;return r.memoizedState=r.baseState=i,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:i},r.queue=e,e=e.dispatch=uc.bind(null,I,e),[r.memoizedState,e]},useRef:function(e){var t=ls();return e={current:e},t.memoizedState=e},useState:function(e){e=ws(e);var t=e.queue,n=dc.bind(null,I,t);return t.dispatch=n,[e.memoizedState,n]},useDebugValue:Xs,useDeferredValue:function(e,t){return $s(ls(),e,t)},useTransition:function(){var e=ws(!1);return e=tc.bind(null,I,e.queue,!0,!1),ls().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,n){var r=I,a=ls();if(P){if(n===void 0)throw Error(i(407));n=n()}else{if(n=t(),G===null)throw Error(i(349));q&127||ys(r,t,n)}a.memoizedState=n;var o={value:n,getSnapshot:t};return a.queue=o,Hs(xs.bind(null,r,o,e),[e]),r.flags|=2048,Rs(9,{destroy:void 0},bs.bind(null,r,o,n,t),null),n},useId:function(){var e=ls(),t=G.identifierPrefix;if(P){var n=ia,r=ra;n=(r&~(1<<32-at(r)-1)).toString(32)+n,t=`_`+t+`R_`+n,n=Zo++,0<\/script>`,o=o.removeChild(o.firstChild);break;case`select`:o=typeof r.is==`string`?s.createElement(`select`,{is:r.is}):s.createElement(`select`),r.multiple?o.multiple=!0:r.size&&(o.size=r.size);break;default:o=typeof r.is==`string`?s.createElement(a,{is:r.is}):s.createElement(a)}}o[kt]=t,o[At]=r;a:for(s=t.child;s!==null;){if(s.tag===5||s.tag===6)o.appendChild(s.stateNode);else if(s.tag!==4&&s.tag!==27&&s.child!==null){s.child.return=s,s=s.child;continue}if(s===t)break a;for(;s.sibling===null;){if(s.return===null||s.return===t)break a;s=s.return}s.sibling.return=s.return,s=s.sibling}t.stateNode=o;a:switch(np(o,a,r),a){case`button`:case`input`:case`select`:case`textarea`:r=!!r.autoFocus;break a;case`img`:r=!0;break a;default:r=!1}r&&gl(t)}}return V(t),t.subtreeFlags&=-33554433,_l(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,n),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==r&&gl(t);else{if(typeof r!=`string`&&t.stateNode===null)throw Error(i(166));if(e=ke.current,_a(t)){if(e=t.stateNode,n=t.memoizedProps,r=null,a=ua,a!==null)switch(a.tag){case 27:case 5:r=a.memoizedProps}e[kt]=t,e=!!(e.nodeValue===n||r!==null&&!0===r.suppressHydrationWarning||ep(e.nodeValue,n)),e||ma(t,!0)}else e=lp(e).createTextNode(r),e[kt]=t,t.stateNode=e}return V(t),null;case 31:if(n=t.memoizedState,e===null||e.memoizedState!==null){if(r=_a(t),n!==null){if(e===null){if(!r)throw Error(i(318));if(e=t.memoizedState,e=e===null?null:e.dehydrated,!e)throw Error(i(557));e[kt]=t}else va(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;V(t),e=!1}else n=ya(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),e=!0;if(!e)return t.flags&256?(Ho(t),t):(Ho(t),null);if(t.flags&128)throw Error(i(558))}return V(t),null;case 13:if(r=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(a=_a(t),r!==null&&r.dehydrated!==null){if(e===null){if(!a)throw Error(i(318));if(a=t.memoizedState,a=a===null?null:a.dehydrated,!a)throw Error(i(317));a[kt]=t}else va(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;V(t),a=!1}else a=ya(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=a),a=!0;if(!a)return t.flags&256?(Ho(t),t):(Ho(t),null)}return Ho(t),t.flags&128?(t.lanes=n,t):(n=r!==null,e=e!==null&&e.memoizedState!==null,n&&(r=t.child,a=null,r.alternate!==null&&r.alternate.memoizedState!==null&&r.alternate.memoizedState.cachePool!==null&&(a=r.alternate.memoizedState.cachePool.pool),o=null,r.memoizedState!==null&&r.memoizedState.cachePool!==null&&(o=r.memoizedState.cachePool.pool),o!==a&&(r.flags|=2048)),n!==e&&n&&(t.child.flags|=8192),yl(t,t.updateQueue),V(t),null);case 4:return Me(),e===null&&Wf(t.stateNode.containerInfo),t.flags|=67108864,V(t),null;case 10:return Ta(t.type),V(t),null;case 19:if(Go(t),r=t.memoizedState,r===null)return V(t),null;if(a=!!(t.flags&128),o=r.rendering,o===null){if(a)bl(r,!1);else{if(Y!==0||e!==null&&e.flags&128)for(e=t.child;e!==null;){if(o=Ko(e),o!==null){for(t.flags|=128,bl(r,!1),e=o.updateQueue,t.updateQueue=e,yl(t,e),t.subtreeFlags=0,e=n,n=t.child;n!==null;)Hi(n,e),n=n.sibling;return Wo(t,Uo.current&1|2),P&&aa(t,r.treeForkCount),t.child}e=e.sibling}r.tail!==null&&qe()>_d&&(t.flags|=128,a=!0,bl(r,!1),t.lanes=4194304)}}else{if(!a){if(e=Ko(o),e!==null){if(t.flags|=128,a=!0,e=e.updateQueue,t.updateQueue=e,yl(t,e),bl(r,!0),r.tail===null&&r.tailMode!==`collapsed`&&r.tailMode!==`visible`&&!o.alternate&&!P)return V(t),null}else 2*qe()-r.renderingStartTime>_d&&n!==536870912&&(t.flags|=128,a=!0,bl(r,!1),t.lanes=4194304)}r.isBackwards?(o.sibling=t.child,t.child=o):(e=r.last,e===null?t.child=o:e.sibling=o,r.last=o)}if(r.tail!==null){e=r.tail;a:{for(n=e;n!==null;){if(n.alternate!==null){n=!1;break a}n=n.sibling}n=!0}return r.rendering=e,r.tail=e.sibling,r.renderingStartTime=qe(),e.sibling=null,o=Uo.current,o=a?o&1|2:o&1,r.tailMode===`visible`||r.tailMode===`collapsed`||!n||P?Wo(t,o):(n=o,j(Io,t),j(Uo,n),Lo===null&&(Lo=t)),P&&aa(t,r.treeForkCount),e}return V(t),null;case 22:case 23:return Ho(t),Fo(),r=t.memoizedState!==null,e===null?r&&(t.flags|=8192):e.memoizedState!==null!==r&&(t.flags|=8192),r?n&536870912&&!(t.flags&128)&&(V(t),t.subtreeFlags&6&&(t.flags|=8192)):V(t),n=t.updateQueue,n!==null&&yl(t,n.retryQueue),n=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(n=e.memoizedState.cachePool.pool),r=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(r=t.memoizedState.cachePool.pool),r!==n&&(t.flags|=2048),e!==null&&Ee(Xa),null;case 24:return n=null,e!==null&&(n=e.memoizedState.cache),t.memoizedState.cache!==n&&(t.flags|=2048),Ta(La),V(t),null;case 25:return null;case 30:return t.flags|=33554432,V(t),null}throw Error(i(156,t.tag))}function Sl(e,t){switch(ca(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Ta(La),Me(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return Pe(t),null;case 31:if(t.memoizedState!==null){if(Ho(t),t.alternate===null)throw Error(i(340));va()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(Ho(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(i(340));va()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return Go(t),e=t.flags,e&65536?(t.flags=e&-65537|128,e=t.memoizedState,e!==null&&(e.rendering=null,e.tail=null),t.flags|=4,t):null;case 4:return Me(),null;case 10:return Ta(t.type),null;case 22:case 23:return Ho(t),Fo(),e!==null&&Ee(Xa),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return Ta(La),null;case 25:return null;default:return null}}function Cl(e,t){switch(ca(t),t.tag){case 3:Ta(La),Me();break;case 26:case 27:case 5:Pe(t);break;case 4:Me();break;case 31:t.memoizedState!==null&&Ho(t);break;case 13:Ho(t);break;case 19:Go(t);break;case 10:Ta(t.type);break;case 22:case 23:Ho(t),Fo(),e!==null&&Ee(Xa);break;case 24:Ta(La)}}function wl(e,t){try{var n=t.updateQueue,r=n===null?null:n.lastEffect;if(r!==null){var i=r.next;n=i;do{if((n.tag&e)===e){r=void 0;var a=n.create,o=n.inst;r=a(),o.destroy=r}n=n.next}while(n!==i)}}catch(e){Z(t,t.return,e)}}function Tl(e,t,n){try{var r=t.updateQueue,i=r===null?null:r.lastEffect;if(i!==null){var a=i.next;r=a;do{if((r.tag&e)===e){var o=r.inst,s=o.destroy;if(s!==void 0){o.destroy=void 0,i=t;var c=n,l=s;try{l()}catch(e){Z(i,c,e)}}}r=r.next}while(r!==a)}}catch(e){Z(t,t.return,e)}}function El(e){var t=e.updateQueue;if(t!==null){var n=e.stateNode;try{Ao(t,n)}catch(t){Z(e,e.return,t)}}}function Dl(e,t,n){n.props=Tc(e.type,e.memoizedProps),n.state=e.memoizedState;try{n.componentWillUnmount()}catch(n){Z(e,t,n)}}function Ol(e,t){try{var n=e.ref;if(n!==null){switch(e.tag){case 26:case 27:case 5:var r=e.stateNode;break;case 30:var i=e.stateNode,a=wi(e.memoizedProps,i);(i.ref===null||i.ref.name!==a)&&(i.ref=Pp(a)),r=i.ref;break;case 7:if(e.stateNode===null){var o=new Fp(e);h(e.child,!1,Qp,o,void 0,void 0),e.stateNode=o}r=e.stateNode;break;default:r=e.stateNode}typeof n==`function`?e.refCleanup=n(r):n.current=r}}catch(n){Z(e,t,n)}}function kl(e,t){var n=e.ref,r=e.refCleanup;if(n!==null){if(typeof r==`function`)try{r()}catch(n){Z(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof n==`function`)try{n(null)}catch(n){Z(e,t,n)}else n.current=null}}function Al(e,t){if((e.tag===5||e.tag===27||e.tag===6)&&e.alternate===null&&t!==null)for(var n=0;n title`))),np(r,t,n),r[kt]=e,Ut(r),t=r;break a;case`link`:if(o=Gm(`link`,`href`,a).get(t+(n.href||``))){for(s=0;sg&&(o=g,g=h,h=o);var _=Qr(s,h),v=Qr(s,g);if(_&&v&&(p.rangeCount!==1||p.anchorNode!==_.node||p.anchorOffset!==_.offset||p.focusNode!==v.node||p.focusOffset!==v.offset)){var y=d.createRange();y.setStart(_.node,_.offset),p.removeAllRanges(),h>g?(p.addRange(y),p.extend(v.node,v.offset)):(y.setEnd(v.node,v.offset),p.addRange(y))}}}}for(d=[],p=s;p=p.parentNode;)p.nodeType===1&&d.push({element:p,left:p.scrollLeft,top:p.scrollTop});for(typeof s.focus==`function`&&s.focus(),s=0;sn?32:n,O.T=null,n=wd,wd=null;var o=bd,s=Sd;if(X=0,xd=bd=null,Sd=0,W&6)throw Error(i(331));var c=W;if(W|=4,Zu(o.current),Uu(o,o.current,s,n),W=c,Df(0,!1),rt&&typeof rt.onPostCommitFiberRoot==`function`)try{rt.onPostCommitFiberRoot(nt,o)}catch{}return!0}finally{k.p=a,O.T=r,uf(e,t)}}function pf(e,t,n){t=Yi(n,t),t=jc(e.stateNode,t,2),e=Co(e,t,2),e!==null&&(yt(e,2),Ef(e))}function Z(e,t,n){if(e.tag===3)pf(e,e,n);else for(;t!==null;){if(t.tag===3){pf(t,e,n);break}if(t.tag===1){var r=t.stateNode;if(typeof t.type.getDerivedStateFromError==`function`||typeof r.componentDidCatch==`function`&&(yd===null||!yd.has(r))){e=Yi(n,e),n=Mc(2),r=Co(t,n,2),r!==null&&(Nc(n,r,t,e),yt(r,2),Ef(r));break}}t=t.return}}function mf(e,t,n){var r=e.pingCache;if(r===null){r=e.pingCache=new td;var i=new Set;r.set(t,i)}else i=r.get(t),i===void 0&&(i=new Set,r.set(t,i));i.has(n)||(ad=!0,i.add(n),e=hf.bind(null,e,t,n),t.then(e,e))}function hf(e,t,n){var r=e.pingCache;r!==null&&r.delete(t),e.pingedLanes|=e.suspendedLanes&n,e.warmLanes&=~n,G===e&&(q&n)===n&&(Y===4||Y===3&&(q&62914560)===q&&300>qe()-hd?W&2?ld|=n:Vd(e,0):ld|=n,dd===q&&(dd=0)),Ef(e)}function gf(e,t){t===0&&(t=_t()),e=Pi(e,t),e!==null&&(yt(e,t),Ef(e))}function _f(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),gf(e,n)}function vf(e,t){var n=0;switch(e.tag){case 31:case 13:var r=e.stateNode,a=e.memoizedState;a!==null&&(n=a.retryLane);break;case 19:r=e.stateNode;break;case 22:r=e.stateNode._retryCache;break;default:throw Error(i(314))}r!==null&&r.delete(t),gf(e,n)}function yf(e,t){return Ue(e,t)}var bf=null,xf=null,Sf=!1,Cf=!1,wf=!1,Tf=0;function Ef(e){e!==xf&&e.next===null&&(xf===null?bf=xf=e:xf=xf.next=e),Cf=!0,Sf||(Sf=!0,Nf())}function Df(e,t){if(!wf&&Cf){wf=!0;do for(var n=!1,r=bf;r!==null;){if(!t){if(e!==0){var i=r.pendingLanes;if(i===0)var a=0;else{var o=r.suspendedLanes,s=r.pingedLanes;a=(1<<31-at(42|e)+1)-1,a&=i&~(o&~s),a=a&201326741?a&201326741|1:a?a|2:0}a!==0&&(n=!0,Mf(r,a))}else a=q,a=pt(r,r===G?a:0,r.cancelPendingCommit!==null||r.timeoutHandle!==-1),!(a&3)||mt(r,a)||(n=!0,Mf(r,a))}r=r.next}while(n);wf=!1}}function Of(){kf()}function kf(){Cf=Sf=!1;var e=0;Tf!==0&&hp()&&(e=Tf);for(var t=qe(),n=null,r=bf;r!==null;){var i=r.next,a=Af(r,t);a===0?(r.next=null,n===null?bf=i:n.next=i,i===null&&(xf=n)):(n=r,(e!==0||a&3)&&(Cf=!0)),r=i}X!==0&&X!==5||Df(e,!1),Tf!==0&&(Tf=0)}function Af(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,i=e.expirationTimes,a=e.pendingLanes&-62914561;0s)break;var u=c.transferSize,d=c.initiatorType;u&&ap(d)&&(c=c.responseEnd,o+=u*(c$m){s.length=o;break}f=new Promise(jp.bind(f)),s.push(f)}}}if(0`u`?null:document;function Tm(e,t,n){var r=wm;if(r&&typeof t==`string`&&t){var i=un(t);i=`link[rel="`+e+`"][href="`+i+`"]`,typeof n==`string`&&(i+=`[crossorigin="`+n+`"]`),ym.has(i)||(ym.add(i),e={rel:e,crossOrigin:n,href:t},r.querySelector(i)===null&&(t=r.createElement(`link`),np(t,`link`,e),Ut(t),r.head.appendChild(t)))}}function Em(e){xm.D(e),Tm(`dns-prefetch`,e,null)}function Dm(e,t){xm.C(e,t),Tm(`preconnect`,e,t)}function Om(e,t,n){xm.L(e,t,n);var r=wm;if(r&&e&&t){var i=`link[rel="preload"][as="`+un(t)+`"]`;t===`image`&&n&&n.imageSrcSet?(i+=`[imagesrcset="`+un(n.imageSrcSet)+`"]`,typeof n.imageSizes==`string`&&(i+=`[imagesizes="`+un(n.imageSizes)+`"]`)):i+=`[href="`+un(e)+`"]`;var a=i;switch(t){case`style`:a=Pm(e);break;case`script`:a=Rm(e)}if(!(vm.has(a)||(e=E({rel:`preload`,href:t===`image`&&n&&n.imageSrcSet?void 0:e,as:t},n),vm.set(a,e),r.querySelector(i)!==null||t===`style`&&r.querySelector(Fm(a))||t===`script`&&r.querySelector(zm(a))))){var o=r.createElement(`link`);np(o,`link`,e),t===`style`&&(o[Lt]=!0,o.onload=o.onerror=function(){Wt(o)}),Ut(o),r.head.appendChild(o)}}}function km(e,t){xm.m(e,t);var n=wm;if(n&&e){var r=t&&typeof t.as==`string`?t.as:`script`,i=`link[rel="modulepreload"][as="`+un(r)+`"][href="`+un(e)+`"]`,a=i;switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:a=Rm(e)}if(!vm.has(a)&&(e=E({rel:`modulepreload`,href:e},t),vm.set(a,e),n.querySelector(i)===null)){switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:if(n.querySelector(zm(a)))return}r=n.createElement(`link`),np(r,`link`,e),Ut(r),n.head.appendChild(r)}}}function Am(e,t,n){xm.S(e,t,n);var r=wm;if(r&&e){var i=Ht(r).hoistableStyles,a=Pm(e);t||=`default`;var o=i.get(a);if(!o){var s={loading:0,preload:null};if(o=r.querySelector(Fm(a)))s.loading=5;else{e=E({rel:`stylesheet`,href:e,"data-precedence":t},n),(n=vm.get(a))&&Hm(e,n);var c=o=r.createElement(`link`);Ut(c),np(c,`link`,e),c._p=new Promise(function(e,t){c.onload=e,c.onerror=t}),c.addEventListener(`load`,function(){s.loading|=1}),c.addEventListener(`error`,function(){s.loading|=2}),s.loading|=4,Vm(o,t,r)}o={type:`stylesheet`,instance:o,count:1,state:s},i.set(a,o)}}}function jm(e,t){xm.X(e,t);var n=wm;if(n&&e){var r=Ht(n).hoistableScripts,i=Rm(e),a=r.get(i);a||(a=n.querySelector(zm(i)),a||(e=E({src:e,async:!0},t),(t=vm.get(i))&&Um(e,t),a=n.createElement(`script`),Ut(a),np(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Mm(e,t){xm.M(e,t);var n=wm;if(n&&e){var r=Ht(n).hoistableScripts,i=Rm(e),a=r.get(i);a||(a=n.querySelector(zm(i)),a||(e=E({src:e,async:!0,type:`module`},t),(t=vm.get(i))&&Um(e,t),a=n.createElement(`script`),Ut(a),np(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Nm(e,t,n,r){var a=(a=ke.current)?bm(a):null;if(!a)throw Error(i(446));switch(e){case`meta`:case`title`:return null;case`style`:return typeof n.precedence==`string`&&typeof n.href==`string`?(n=Pm(n.href),t=Ht(a).hoistableStyles,r=t.get(n),r||(r={type:`style`,instance:null,count:0,state:null},t.set(n,r)),r):{type:`void`,instance:null,count:0,state:null};case`link`:if(n.rel===`stylesheet`&&typeof n.href==`string`&&typeof n.precedence==`string`){e=Pm(n.href);var o=Ht(a).hoistableStyles,s=o.get(e);if(s||(a=a.ownerDocument||a,s={type:`stylesheet`,instance:null,count:0,state:{loading:0,preload:null}},o.set(e,s),(o=a.querySelector(Fm(e)))?o._p||(s.instance=o,s.state.loading=5):(o=vm.get(e),o||(o={rel:`preload`,as:`style`,href:n.href,crossOrigin:n.crossOrigin,integrity:n.integrity,media:n.media,hrefLang:n.hrefLang,referrerPolicy:n.referrerPolicy},vm.set(e,o)),Lm(a,e,o,s.state))),t&&r===null)throw Error(i(528,``));return s}if(t&&r!==null)throw Error(i(529,``));return null;case`script`:return t=n.async,n=n.src,typeof n==`string`&&t&&typeof t!=`function`&&typeof t!=`symbol`?(n=Rm(n),t=Ht(a).hoistableScripts,r=t.get(n),r||(r={type:`script`,instance:null,count:0,state:null},t.set(n,r)),r):{type:`void`,instance:null,count:0,state:null};default:throw Error(i(444,e))}}function Pm(e){return`href="`+un(e)+`"`}function Fm(e){return`link[rel="stylesheet"][`+e+`]`}function Im(e){return E({},e,{"data-precedence":e.precedence,precedence:null})}function Lm(e,t,n,r){if(t=e.querySelector(`link[rel="preload"][as="style"][`+t+`]`)){if(!0!==t[Lt]){r.loading=1;return}}else t=e.createElement(`link`),t[Lt]=!0,t.onload=t.onerror=Wt.bind(null,t),np(t,`link`,n),Ut(t),e.head.appendChild(t);r.preload=t,t.addEventListener(`load`,function(){return r.loading|=1}),t.addEventListener(`error`,function(){return r.loading|=2})}function Rm(e){return`[src="`+un(e)+`"]`}function zm(e){return`script[async]`+e}function Bm(e,t,n){if(t.count++,t.instance===null)switch(t.type){case`style`:var r=e.querySelector(`style[data-href~="`+un(n.href)+`"]`);if(r)return t.instance=r,Ut(r),r;var a=E({},n,{"data-href":n.href,"data-precedence":n.precedence,href:null,precedence:null});return r=(e.ownerDocument||e).createElement(`style`),Ut(r),np(r,`style`,a),Vm(r,n.precedence,e),t.instance=r;case`stylesheet`:a=Pm(n.href);var o=e.querySelector(Fm(a));if(o)return t.state.loading|=4,t.instance=o,Ut(o),o;r=Im(n),(a=vm.get(a))&&Hm(r,a),o=(e.ownerDocument||e).createElement(`link`),Ut(o);var s=o;return s._p=new Promise(function(e,t){s.onload=e,s.onerror=t}),np(o,`link`,r),t.state.loading|=4,Vm(o,n.precedence,e),t.instance=o;case`script`:return o=Rm(n.src),(a=e.querySelector(zm(o)))?(t.instance=a,Ut(a),a):(r=n,(a=vm.get(o))&&(r=E({},n),Um(r,a)),e=e.ownerDocument||e,a=e.createElement(`script`),Ut(a),np(a,`link`,r),e.head.appendChild(a),t.instance=a);case`void`:return null;default:throw Error(i(443,t.type))}else t.type===`stylesheet`&&!(t.state.loading&4)&&(r=t.instance,t.state.loading|=4,Vm(r,n.precedence,e));return t.instance}function Vm(e,t,n){for(var r=n.querySelectorAll(`link[rel="stylesheet"][data-precedence],style[data-precedence]`),i=r.length?r[r.length-1]:null,a=i,o=0;o title`):null)}function qm(e,t,n){if(n===1||t.itemProp!=null)return!1;switch(e){case`meta`:case`title`:return!0;case`style`:if(typeof t.precedence!=`string`||typeof t.href!=`string`||t.href===``)break;return!0;case`link`:if(typeof t.rel!=`string`||typeof t.href!=`string`||t.href===``||t.onLoad||t.onError)break;switch(t.rel){case`stylesheet`:return e=t.disabled,typeof t.precedence==`string`&&e==null;default:return!0}case`script`:if(t.async&&typeof t.async!=`function`&&typeof t.async!=`symbol`&&!t.onLoad&&!t.onError&&t.src&&typeof t.src==`string`)return!0}return!1}function Jm(e,t){return e===`img`&&t.src!=null&&t.src!==``&&t.onLoad==null&&t.loading!==`lazy`}function Ym(e){return!(e.type===`stylesheet`&&!(e.state.loading&3))}function Xm(e){return(e.width||100)*(e.height||100)*(typeof devicePixelRatio==`number`?devicePixelRatio:1)*.25}function Zm(e,t){typeof t.decode==`function`&&(e.imgCount++,t.complete||(e.imgBytes+=Xm(t),e.suspenseyImages.push(t)),e=rh.bind(e),t.decode().then(e,e))}function Qm(e,t,n,r){if(n.type===`stylesheet`&&(typeof r.media!=`string`||!1!==matchMedia(r.media).matches)&&!(n.state.loading&4)){if(n.instance===null){var i=Pm(r.href),a=t.querySelector(Fm(i));if(a){t=a._p,typeof t==`object`&&t&&typeof t.then==`function`&&(e.count++,e=nh.bind(e),t.then(e,e)),n.state.loading|=4,n.instance=a,Ut(a);return}a=t.ownerDocument||t,r=Im(r),(i=vm.get(i))&&Hm(r,i),a=a.createElement(`link`),Ut(a);var o=a;o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),np(a,`link`,r),n.instance=a}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(n,t),(t=n.state.preload)&&!(n.state.loading&3)&&(e.count++,n=nh.bind(e),t.addEventListener(`load`,n),t.addEventListener(`error`,n))}}var $m=0;function eh(e,t){return e.stylesheets&&e.count===0&&ah(e,e.stylesheets),0$m?50:800)+t);return e.unsuspend=n,function(){e.unsuspend=null,clearTimeout(r),clearTimeout(i)}}:null}function th(e){if(e.count===0&&(e.imgCount===0||!e.waitingForImages)){if(e.stylesheets)ah(e,e.stylesheets);else if(e.unsuspend){var t=e.unsuspend;e.unsuspend=null,t()}}}function nh(){this.count--,th(this)}function rh(){this.imgCount--,th(this)}var ih=null;function ah(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,ih=new Map,t.forEach(oh,e),ih=null,nh.call(e))}function oh(e,t){if(!(t.state.loading&4)){var n=ih.get(e);if(n)var r=n.get(null);else{n=new Map,ih.set(e,n);for(var i=e.querySelectorAll(`link[data-precedence],style[data-precedence]`),a=0;a{function n(){if(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<`u`&&typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE==`function`)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=f()})),m=r(l(),1),h=t(),g=m.createContext(void 0),_=e=>{let t=m.useContext(g);if(e)return e;if(!t)throw Error(`No QueryClient set, use QueryClientProvider to set one`);return t},v=({client:e,children:t})=>(m.useEffect(()=>(e.mount(),()=>{e.unmount()}),[e]),(0,h.jsx)(g.Provider,{value:e,children:t})),y={setTimeout:(e,t)=>setTimeout(e,t),clearTimeout:e=>clearTimeout(e),setInterval:(e,t)=>setInterval(e,t),clearInterval:e=>clearInterval(e)},b=new class{#e=y;setTimeoutProvider(e){this.#e=e}setTimeout(e,t){return this.#e.setTimeout(e,t)}clearTimeout(e){this.#e.clearTimeout(e)}setInterval(e,t){return this.#e.setInterval(e,t)}clearInterval(e){this.#e.clearInterval(e)}};function x(e){setTimeout(e,0)}var S=typeof window>`u`||`Deno`in globalThis;function C(){}function w(e,t){return typeof e==`function`?e(t):e}function T(e){return typeof e==`number`&&e>=0&&e!==1/0}function ee(e,t){return Math.max(e+(t||0)-Date.now(),0)}function E(e,t){return typeof e==`function`?e(t):e}function te(e,t){let{type:n=`all`,exact:r,fetchStatus:i,predicate:a,queryKey:o,stale:s}=e;if(o){if(r){if(t.queryHash!==ne(o,t.options))return!1}else if(!ie(t.queryKey,o))return!1}if(n!==`all`){let e=t.isActive();if(n===`active`&&!e||n===`inactive`&&e)return!1}return!(typeof s==`boolean`&&t.isStale()!==s||i&&i!==t.state.fetchStatus||a&&!a(t))}function D(e,t){let{exact:n,status:r,predicate:i,mutationKey:a}=e;if(a){if(!t.options.mutationKey)return!1;if(n){if(re(t.options.mutationKey)!==re(a))return!1}else if(!ie(t.options.mutationKey,a))return!1}return!(r&&t.state.status!==r||i&&!i(t))}function ne(e,t){return(t?.queryKeyHashFn||re)(e)}function re(e){return JSON.stringify(e,(e,t)=>le(t)?Object.keys(t).sort().reduce((e,n)=>(e[n]=t[n],e),{}):t)}function ie(e,t){if(e===t)return!0;if(typeof e!=typeof t)return!1;if(e&&t&&typeof e==`object`&&typeof t==`object`){if(Array.isArray(e)&&Array.isArray(t)){if(t.length>e.length)return!1;for(let n=0;n500)return t;let r=ce(e)&&ce(t);if(!r&&!(le(e)&&le(t)))return t;let i=(r?e:Object.keys(e)).length,a=r?t:Object.keys(t),o=a.length,s=r?Array(o):{},c=0;for(let l=0;l{b.setTimeout(t,e)})}function fe(e,t,n){return typeof n.structuralSharing==`function`?n.structuralSharing(e,t):n.structuralSharing===!1?t:oe(e,t)}function pe(e,t,n=0){let r=[...e,t];return n&&r.length>n?r.slice(1):r}function me(e,t,n=0){let r=[t,...e];return n&&r.length>n?r.slice(0,-1):r}var he=Symbol();function ge(e,t){return!e.queryFn&&t?.initialPromise?()=>t.initialPromise:!e.queryFn||e.queryFn===he?()=>Promise.reject(Error(`Missing queryFn: '${e.queryHash}'`)):e.queryFn}function _e(e,t){return typeof e==`function`?e(...t):!!e}function ve(e,t,n){let r=!1,i;return Object.defineProperty(e,"signal",{enumerable:!0,get:()=>(i??=t(),r?i:(r=!0,i.aborted?n():i.addEventListener(`abort`,n,{once:!0}),i))}),e}var ye=()=>S,be=()=>ye(),xe=class{constructor(){this.listeners=new Set,this.subscribe=this.subscribe.bind(this)}subscribe(e){return this.listeners.add(e),this.onSubscribe(),()=>{this.listeners.delete(e),this.onUnsubscribe()}}hasListeners(){return this.listeners.size>0}onSubscribe(){}onUnsubscribe(){}},Se=new class extends xe{#e;#t;#n;constructor(){super(),this.#n=e=>{if(typeof window<`u`&&window.addEventListener){let t=()=>e();return window.addEventListener(`visibilitychange`,t,!1),()=>{window.removeEventListener(`visibilitychange`,t)}}}}onSubscribe(){this.#t||this.setEventListener(this.#n)}onUnsubscribe(){this.hasListeners()||(this.#t?.(),this.#t=void 0)}setEventListener(e){this.#n=e,this.#t?.(),this.#t=e(e=>{typeof e==`boolean`?this.setFocused(e):this.onFocus()})}setFocused(e){this.#e!==e&&(this.#e=e,this.onFocus())}onFocus(){let e=this.isFocused();this.listeners.forEach(t=>{t(e)})}isFocused(){return typeof this.#e==`boolean`?this.#e:globalThis.document?.visibilityState!==`hidden`}},O=x;function k(){let e=[],t=0,n=e=>{e()},r=e=>{e()},i=O,a=r=>{t?e.push(r):i(()=>{n(r)})},o=()=>{let t=e;e=[],t.length&&i(()=>{r(()=>{t.forEach(e=>{n(e)})})})};return{batch:e=>{let n;t++;try{n=e()}finally{t--,t||o()}return n},batchCalls:e=>(...t)=>{a(()=>{e(...t)})},schedule:a,setNotifyFunction:e=>{n=e},setBatchNotifyFunction:e=>{r=e},setScheduler:e=>{i=e}}}var A=k(),Ce=new class extends xe{#e=!0;#t;#n;constructor(){super(),this.#n=e=>{if(typeof window<`u`&&window.addEventListener){let t=()=>e(!0),n=()=>e(!1);return window.addEventListener(`online`,t,!1),window.addEventListener(`offline`,n,!1),()=>{window.removeEventListener(`online`,t),window.removeEventListener(`offline`,n)}}}}onSubscribe(){this.#t||this.setEventListener(this.#n)}onUnsubscribe(){this.hasListeners()||(this.#t?.(),this.#t=void 0)}setEventListener(e){this.#n=e,this.#t?.(),this.#t=e(this.setOnline.bind(this))}setOnline(e){this.#e!==e&&(this.#e=e,this.listeners.forEach(t=>{t(e)}))}isOnline(){return this.#e}};function we(e){return Math.min(1e3*2**e,3e4)}function Te(e){return(e??`online`)!==`online`||Ce.isOnline()}var Ee=class extends Error{constructor(e){super(`CancelledError`),this.revert=e?.revert,this.silent=e?.silent}};function j(e){let t=!1,n=0,r,i=`pending`,a,o,s=new Promise((e,t)=>{a=e,o=t});s.catch(C);let c=()=>i!==`pending`,l=t=>{if(!c()){let n=new Ee(t);h(n),e.onCancel?.(n)}},u=()=>{t=!0},d=()=>{t=!1},f=()=>Se.isFocused()&&(e.networkMode===`always`||Ce.isOnline())&&e.canRun(),p=()=>Te(e.networkMode)&&e.canRun(),m=e=>{c()||(r?.(),i=`resolved`,a(e))},h=e=>{c()||(r?.(),i=`rejected`,o(e))},g=()=>new Promise(t=>{r=e=>{(c()||f())&&t(e)},e.onPause?.()}).then(()=>{r=void 0,c()||e.onContinue?.()}),_=()=>{if(c())return;let r,i=n===0?e.initialPromise:void 0;try{r=i??e.fn()}catch(e){r=Promise.reject(e)}Promise.resolve(r).then(m).catch(r=>{if(c())return;let i=e.retry??(be()?0:3),a=e.retryDelay??we,o=typeof a==`function`?a(n,r):a,s=i===!0||typeof i==`number`&&nf()?void 0:g()).then(()=>{t?h(r):_()})})};return{promise:s,status:()=>i,cancel:l,continue:()=>(r?.(),s),cancelRetry:u,continueRetry:d,canStart:p,start:()=>(p()?_():g().then(_),s)}}var De=class{#e;destroy(){this.clearGcTimeout()}scheduleGc(){this.clearGcTimeout(),T(this.gcTime)&&(this.#e=b.setTimeout(()=>{this.optionalRemove()},this.gcTime))}updateGcTime(e){this.gcTime=Math.max(this.gcTime||0,e??(be()?1/0:3e5))}clearGcTimeout(){this.#e!==void 0&&(b.clearTimeout(this.#e),this.#e=void 0)}};function Oe(e){return{onFetch:(t,n)=>{let r=t.options,i=t.fetchOptions?.meta?.fetchMore?.direction,a=t.state.data?.pages||[],o=t.state.data?.pageParams||[],s={pages:[],pageParams:[]},c=0,l=async()=>{let n=!1,l=e=>{ve(e,()=>t.signal,()=>n=!0)},u=ge(t.options,t.fetchOptions),d=async(e,r,i)=>{if(n)return Promise.reject(t.signal.reason);if(r==null&&e.pages.length)return Promise.resolve(e);let a=(()=>{let e={client:t.client,queryKey:t.queryKey,pageParam:r,direction:i?`backward`:`forward`,meta:t.options.meta};return l(e),e})(),o=await u(a),{maxPages:s}=t.options,c=i?me:pe;return{pages:c(e.pages,o,s),pageParams:c(e.pageParams,r,s)}};if(i&&a.length){let e=i===`backward`,t=e?Ae:ke,n={pages:a,pageParams:o};s=await d(n,t(r,n),e)}else{let t=e??a.length;do{let e=c===0?o[0]??r.initialPageParam:ke(r,s);if(c>0&&e==null)break;s=await d(s,e),c++}while(ct.options.persister?.(l,{client:t.client,queryKey:t.queryKey,meta:t.options.meta,signal:t.signal},n):l}}}function ke(e,{pages:t,pageParams:n}){let r=t.length-1;return t.length>0?e.getNextPageParam(t[r],t,n[r],n):void 0}function Ae(e,{pages:t,pageParams:n}){return t.length>0?e.getPreviousPageParam?.(t[0],t,n[0],n):void 0}var je=class extends De{#e;#t;#n;#r;#i;#a;#o;#s;constructor(e){super(),this.#s=!1,this.#o=e.defaultOptions,this.setOptions(e.options),this.observers=[],this.#i=e.client,this.#r=this.#i.getQueryCache(),this.queryKey=e.queryKey,this.queryHash=e.queryHash,this.#t=Pe(this.options),this.state=e.state??this.#t,this.scheduleGc()}get meta(){return this.options.meta}get queryType(){return this.#e}get promise(){return this.#a?.promise}setOptions(e){if(this.options={...this.#o,...e},e?._type&&(this.#e=e._type),this.updateGcTime(this.options.gcTime),this.state&&this.state.data===void 0){let e=Pe(this.options);e.data!==void 0&&(this.setState(Ne(e.data,e.dataUpdatedAt)),this.#t=e)}}optionalRemove(){!this.observers.length&&this.state.fetchStatus===`idle`&&this.#r.remove(this)}setData(e,t){let n=fe(this.state.data,e,this.options);return this.#c({data:n,type:`success`,dataUpdatedAt:t?.updatedAt,manual:t?.manual}),n}setState(e){this.#c({type:`setState`,state:e})}cancel(e){let t=this.#a?.promise;return this.#a?.cancel(e),t?t.then(C).catch(C):Promise.resolve()}destroy(){super.destroy(),this.cancel({silent:!0})}get resetState(){return this.#t}reset(){this.destroy(),this.setState(this.resetState)}isActive(){return this.observers.some(e=>E(e.options.enabled,this)!==!1)}isDisabled(){return this.getObserversCount()>0?!this.isActive():this.options.queryFn===he||!this.isFetched()}isFetched(){return this.state.dataUpdateCount+this.state.errorUpdateCount>0}isStatic(){return this.getObserversCount()>0&&this.observers.some(e=>E(e.options.staleTime,this)===`static`)}isStale(){return this.getObserversCount()>0?this.observers.some(e=>e.getCurrentResult().isStale):this.state.data===void 0||this.state.isInvalidated}isStaleByTime(e=0){return this.state.data===void 0?!0:e===`static`?!1:this.state.isInvalidated?!0:!ee(this.state.dataUpdatedAt,e)}onFocus(){this.observers.find(e=>e.shouldFetchOnWindowFocus())?.refetch({cancelRefetch:!1}),this.#a?.continue()}onOnline(){this.observers.find(e=>e.shouldFetchOnReconnect())?.refetch({cancelRefetch:!1}),this.#a?.continue()}addObserver(e){this.observers.includes(e)||(this.observers.push(e),this.clearGcTimeout(),this.#r.notify({type:`observerAdded`,query:this,observer:e}))}removeObserver(e){let t=this.observers.indexOf(e);t!==-1&&(this.observers.splice(t,1),this.observers.length||(this.#a&&(this.#s||this.state.fetchStatus===`paused`&&this.state.status===`pending`?this.#a.cancel({revert:!0}):this.#a.cancelRetry()),this.scheduleGc()),this.#r.notify({type:`observerRemoved`,query:this,observer:e}))}getObserversCount(){return this.observers.length}invalidate(){this.state.isInvalidated||this.#c({type:`invalidate`})}async fetch(e,t){if(this.state.fetchStatus!==`idle`&&this.#a?.status()!==`rejected`){if(this.state.data!==void 0&&t?.cancelRefetch)this.cancel({silent:!0});else if(this.#a)return this.#a.continueRetry(),this.#a.promise}if(e&&this.setOptions(e),!this.options.queryFn){let e=this.observers.find(e=>e.options.queryFn);e&&this.setOptions(e.options)}let n=new AbortController,r=e=>{Object.defineProperty(e,"signal",{enumerable:!0,get:()=>(this.#s=!0,n.signal)})},i=()=>{let e=ge(this.options,t),n=(()=>{let e={client:this.#i,queryKey:this.queryKey,meta:this.meta};return r(e),e})();return this.#s=!1,this.options.persister?this.options.persister(e,n,this):e(n)},a=(()=>{let e={fetchOptions:t,options:this.options,queryKey:this.queryKey,client:this.#i,state:this.state,fetchFn:i};return r(e),e})();(this.#e===`infinite`?Oe(this.options.pages):this.options.behavior)?.onFetch(a,this),this.#n=this.state,(this.state.fetchStatus===`idle`||this.state.fetchMeta!==a.fetchOptions?.meta)&&this.#c({type:`fetch`,meta:a.fetchOptions?.meta});let o=this.#a=j({initialPromise:t?.initialPromise,fn:a.fetchFn,onCancel:e=>{e instanceof Ee&&e.revert&&this.setState({...this.#n,fetchStatus:`idle`}),n.abort()},onFail:(e,t)=>{this.#c({type:`failed`,failureCount:e,error:t})},onPause:()=>{this.#c({type:`pause`})},onContinue:()=>{this.#c({type:`continue`})},retry:a.options.retry,retryDelay:a.options.retryDelay,networkMode:a.options.networkMode,canRun:()=>!0});try{let e=await o.start();if(e===void 0)throw Error(`${this.queryHash} data is undefined`);return this.setData(e),this.#r.config.onSuccess?.(e,this),this.#r.config.onSettled?.(e,this.state.error,this),e}catch(e){if(e instanceof Ee){if(e.silent)return this.#a.promise;if(e.revert){if(this.state.data===void 0)throw e;return this.state.data}}throw this.#c({type:`error`,error:e}),this.#r.config.onError?.(e,this),this.#r.config.onSettled?.(this.state.data,e,this),e}finally{this.#a===o&&(this.#a=void 0),this.scheduleGc()}}#c(e){let t=t=>{switch(e.type){case`failed`:return{...t,fetchFailureCount:e.failureCount,fetchFailureReason:e.error};case`pause`:return{...t,fetchStatus:`paused`};case`continue`:return{...t,fetchStatus:`fetching`};case`fetch`:return{...t,...Me(t.data,this.options),fetchMeta:e.meta??null};case`success`:let n={...t,...Ne(e.data,e.dataUpdatedAt),dataUpdateCount:t.dataUpdateCount+1,...!e.manual&&{fetchStatus:`idle`,fetchFailureCount:0,fetchFailureReason:null}};return this.#n=e.manual?n:void 0,n;case`error`:let r=e.error;return{...t,error:r,errorUpdateCount:t.errorUpdateCount+1,errorUpdatedAt:Date.now(),fetchFailureCount:t.fetchFailureCount+1,fetchFailureReason:r,fetchStatus:`idle`,status:`error`,isInvalidated:!0};case`invalidate`:return{...t,isInvalidated:!0};case`setState`:return{...t,...e.state}}};this.state=t(this.state),A.batch(()=>{this.observers.slice().forEach(e=>{e.onQueryUpdate()}),this.#r.notify({query:this,type:`updated`,action:e})})}};function Me(e,t){return{fetchFailureCount:0,fetchFailureReason:null,fetchStatus:Te(t.networkMode)?`fetching`:`paused`,...e===void 0&&{error:null,status:`pending`}}}function Ne(e,t){return{data:e,dataUpdatedAt:t??Date.now(),error:null,isInvalidated:!1,status:`success`}}function Pe(e){let t=typeof e.initialData==`function`?e.initialData():e.initialData,n=t!==void 0,r=n?typeof e.initialDataUpdatedAt==`function`?e.initialDataUpdatedAt():e.initialDataUpdatedAt:0;return{data:t,dataUpdateCount:0,dataUpdatedAt:n?r??Date.now():0,error:null,errorUpdateCount:0,errorUpdatedAt:0,fetchFailureCount:0,fetchFailureReason:null,fetchMeta:null,isInvalidated:!1,status:n?`success`:`pending`,fetchStatus:`idle`}}var Fe=class extends xe{#e;#t=void 0;#n=void 0;#r=void 0;#i;#a;#o;#s;#c;#l;#u;#d;#f;#p=new Set;constructor(e,t){super(),this.options=t,this.#e=e,this.#o=null,this.bindMethods(),this.setOptions(t)}bindMethods(){this.refetch=this.refetch.bind(this)}onSubscribe(){this.listeners.size===1&&(this.#t.addObserver(this),Le(this.#t,this.options)?this.#m():this.updateResult(),this.#y())}onUnsubscribe(){this.hasListeners()||this.destroy()}shouldFetchOnReconnect(){return Re(this.#t,this.options,this.options.refetchOnReconnect)}shouldFetchOnWindowFocus(){return Re(this.#t,this.options,this.options.refetchOnWindowFocus)}destroy(){this.listeners=new Set,this.#b(),this.#x(),this.#t.removeObserver(this)}setOptions(e){let t=this.options,n=this.#t;if(this.options=this.#e.defaultQueryOptions(e),this.options.enabled!==void 0&&typeof this.options.enabled!=`boolean`&&typeof this.options.enabled!=`function`&&typeof E(this.options.enabled,this.#t)!=`boolean`)throw Error(`Expected enabled to be a boolean or a callback that returns a boolean`);this.#S(),this.#t.setOptions(this.options),t._defaulted&&!se(this.options,t)&&this.#e.getQueryCache().notify({type:`observerOptionsUpdated`,query:this.#t,observer:this});let r=this.hasListeners();r&&ze(this.#t,n,this.options,t)&&this.#m(),this.updateResult(),r&&(this.#t!==n||E(this.options.enabled,this.#t)!==E(t.enabled,this.#t)||E(this.options.staleTime,this.#t)!==E(t.staleTime,this.#t))&&this.#g();let i=this.#_();r&&(this.#t!==n||E(this.options.enabled,this.#t)!==E(t.enabled,this.#t)||i!==this.#f)&&this.#v(i)}getOptimisticResult(e){let t=this.#e.getQueryCache().build(this.#e,e),n=this.createResult(t,e);return se(this.getCurrentResult(),n)||(this.#r=n,this.#a=this.options,this.#i=this.#t.state),n}getCurrentResult(){return this.#r}trackResult(e,t){return new Proxy(e,{get:(e,n)=>(this.trackProp(n),t?.(n),Reflect.get(e,n))})}trackProp(e){this.#p.add(e)}getCurrentQuery(){return this.#t}refetch({...e}={}){return this.fetch({...e})}fetchOptimistic(e){let t=this.#e.defaultQueryOptions(e),n=this.#e.getQueryCache().build(this.#e,t),r=()=>{},i,a=new Promise(e=>{i=e,r=this.#e.getQueryCache().subscribe(i=>{i.type===`updated`&&i.query.queryHash===n.queryHash&&n.state.data!==void 0&&(r(),e(this.createResult(n,t)))})});return Promise.race([n.fetch().then(()=>{let e=this.createResult(n,t);return i?.(e),e}).finally(()=>{r()}),a])}fetch(e){return this.#m({...e,cancelRefetch:e.cancelRefetch??!0}).then(()=>(this.updateResult(),this.#r))}#m(e){this.#S();let t=this.#t.fetch(this.options,e);return e?.throwOnError||(t=t.catch(C)),t}#h(e){return!be()&&E(this.options.enabled,this.#t)!==!1&&T(e)}#g(){this.#b();let e=E(this.options.staleTime,this.#t);if(this.#r.isStale||!this.#h(e))return;let t=ee(this.#r.dataUpdatedAt,e)+1;this.#u=b.setTimeout(()=>{this.#r.isStale||this.updateResult()},t)}#_(){return E(this.options.refetchInterval,this.#t)??!1}#v(e){this.#x(),this.#f=e,this.#f!==0&&this.#h(this.#f)&&(this.#d=b.setInterval(()=>{(this.options.refetchIntervalInBackground||Se.isFocused())&&this.#m()},this.#f))}#y(){this.#g(),this.#v(this.#_())}#b(){this.#u!==void 0&&(b.clearTimeout(this.#u),this.#u=void 0)}#x(){this.#d!==void 0&&(b.clearInterval(this.#d),this.#d=void 0)}createResult(e,t){let n=this.#t,r=this.options,i=this.#r,a=this.#i,o=this.#a,s=e===n?this.#n:e.state,{state:c}=e,l={...c},u=!1,d;if(t._optimisticResults){let i=this.hasListeners(),a=!i&&Le(e,t),o=i&&ze(e,n,t,r);(a||o)&&(l={...l,...Me(c.data,e.options)}),t._optimisticResults===`isRestoring`&&(l.fetchStatus=`idle`)}let{error:f,errorUpdatedAt:p,status:m}=l;d=l.data;let h=!1;if(t.placeholderData!==void 0&&d===void 0&&m===`pending`){let e;i?.isPlaceholderData&&t.placeholderData===o?.placeholderData?(e=i.data,h=!0):e=typeof t.placeholderData==`function`?t.placeholderData(this.#l?.state.data,this.#l):t.placeholderData,e!==void 0&&(m=`success`,d=fe(i?.data,e,t),u=!0)}if(t.select&&d!==void 0&&!h){if(i&&d===a?.data&&t.select===this.#s)d=this.#c;else try{this.#s=t.select,d=t.select(d),d=fe(i?.data,d,t),this.#c=d,this.#o=null}catch(e){this.#o=e}}else d===void 0&&(this.#o=null);this.#o&&(f=this.#o,d=this.#c,p=Date.now(),m=`error`,u=!1);let g=l.fetchStatus===`fetching`,_=m===`pending`,v=m===`error`,y=_&&g,b=d!==void 0;return{status:m,fetchStatus:l.fetchStatus,isPending:_,isSuccess:m===`success`,isError:v,isInitialLoading:y,isLoading:y,data:d,dataUpdatedAt:l.dataUpdatedAt,error:f,errorUpdatedAt:p,failureCount:l.fetchFailureCount,failureReason:l.fetchFailureReason,errorUpdateCount:l.errorUpdateCount,isFetched:e.isFetched(),isFetchedAfterMount:l.dataUpdateCount>s.dataUpdateCount||l.errorUpdateCount>s.errorUpdateCount,isFetching:g,isRefetching:g&&!_,isLoadingError:v&&!b,isPaused:l.fetchStatus===`paused`,isPlaceholderData:u,isRefetchError:v&&b,isStale:Be(e,t),refetch:this.refetch,isEnabled:E(t.enabled,e)!==!1}}updateResult(){let e=this.#r,t=this.createResult(this.#t,this.options);if(this.#i=this.#t.state,this.#a=this.options,this.#i.data!==void 0&&(this.#l=this.#t),se(t,e))return;this.#r=t;let n=(()=>{if(!e)return!0;let{notifyOnChangeProps:t}=this.options,n=typeof t==`function`?t():t;if(n===`all`||!n&&!this.#p.size)return!0;let r=new Set(n??this.#p);return this.options.throwOnError&&r.add(`error`),Object.keys(this.#r).some(t=>{let n=t;return this.#r[n]!==e[n]&&r.has(n)})})();A.batch(()=>{n&&this.listeners.forEach(e=>{e(this.#r)}),this.#e.getQueryCache().notify({query:this.#t,type:`observerResultsUpdated`})})}#S(){let e=this.#e.getQueryCache().build(this.#e,this.options);if(e===this.#t)return;let t=this.#t;this.#t=e,this.#n=e.state,this.hasListeners()&&(t?.removeObserver(this),e.addObserver(this))}onQueryUpdate(){this.updateResult(),this.hasListeners()&&this.#y()}};function Ie(e,t){return E(t.enabled,e)!==!1&&e.state.data===void 0&&(e.state.status!==`error`||E(t.retryOnMount,e)!==!1)}function Le(e,t){return Ie(e,t)||e.state.data!==void 0&&Re(e,t,t.refetchOnMount)}function Re(e,t,n){if(E(t.enabled,e)!==!1&&E(t.staleTime,e)!==`static`){let r=E(n,e);return r===`always`||r!==!1&&Be(e,t)}return!1}function ze(e,t,n,r){return(e!==t||E(r.enabled,e)===!1)&&(!n.suspense||e.state.status!==`error`)&&Be(e,n)}function Be(e,t){return E(t.enabled,e)!==!1&&e.isStaleByTime(E(t.staleTime,e))}var Ve=class extends De{#e;#t;#n;#r;constructor(e){super(),this.#e=e.client,this.mutationId=e.mutationId,this.#n=e.mutationCache,this.#t=[],this.state=e.state||He(),this.setOptions(e.options),this.scheduleGc()}setOptions(e){this.options=e,this.updateGcTime(this.options.gcTime)}get meta(){return this.options.meta}addObserver(e){this.#t.includes(e)||(this.#t.push(e),this.clearGcTimeout(),this.#n.notify({type:`observerAdded`,mutation:this,observer:e}))}removeObserver(e){this.#t=this.#t.filter(t=>t!==e),this.scheduleGc(),this.#n.notify({type:`observerRemoved`,mutation:this,observer:e})}optionalRemove(){this.#t.length||(this.state.status===`pending`?this.scheduleGc():this.#n.remove(this))}continue(){return this.#r?.continue()??(this.state.status===`pending`?this.execute(this.state.variables):Promise.resolve())}async execute(e){let t=()=>{this.#i({type:`continue`})},n={client:this.#e,meta:this.options.meta,mutationKey:this.options.mutationKey},r=this.#r=j({fn:()=>this.options.mutationFn?this.options.mutationFn(e,n):Promise.reject(Error(`No mutationFn found`)),onFail:(e,t)=>{this.#i({type:`failed`,failureCount:e,error:t})},onPause:()=>{this.#i({type:`pause`})},onContinue:t,retry:this.options.retry??0,retryDelay:this.options.retryDelay,networkMode:this.options.networkMode,canRun:()=>this.#n.canRun(this)}),i=this.state.status===`pending`,a=!r.canStart();try{if(i)t();else{this.#i({type:`pending`,variables:e,isPaused:a}),this.#n.config.onMutate&&await this.#n.config.onMutate(e,this,n);let t=await this.options.onMutate?.(e,n);t!==this.state.context&&this.#i({type:`pending`,context:t,variables:e,isPaused:a})}let o=await r.start();return await this.#n.config.onSuccess?.(o,e,this.state.context,this,n),await this.options.onSuccess?.(o,e,this.state.context,n),await this.#n.config.onSettled?.(o,null,this.state.variables,this.state.context,this,n),await this.options.onSettled?.(o,null,e,this.state.context,n),this.#i({type:`success`,data:o}),o}catch(t){try{await this.#n.config.onError?.(t,e,this.state.context,this,n)}catch(e){Promise.reject(e)}try{await this.options.onError?.(t,e,this.state.context,n)}catch(e){Promise.reject(e)}try{await this.#n.config.onSettled?.(void 0,t,this.state.variables,this.state.context,this,n)}catch(e){Promise.reject(e)}try{await this.options.onSettled?.(void 0,t,e,this.state.context,n)}catch(e){Promise.reject(e)}throw this.#i({type:`error`,error:t}),t}finally{this.#r===r&&(this.#r=void 0),this.#n.runNext(this)}}#i(e){let t=t=>{switch(e.type){case`failed`:return{...t,failureCount:e.failureCount,failureReason:e.error};case`pause`:return{...t,isPaused:!0};case`continue`:return{...t,isPaused:!1};case`pending`:return{...t,context:e.context,data:void 0,failureCount:0,failureReason:null,error:null,isPaused:e.isPaused,status:`pending`,variables:e.variables,submittedAt:Date.now()};case`success`:return{...t,data:e.data,failureCount:0,failureReason:null,error:null,status:`success`,isPaused:!1};case`error`:return{...t,data:void 0,error:e.error,failureCount:t.failureCount+1,failureReason:e.error,isPaused:!1,status:`error`}}};this.state=t(this.state),A.batch(()=>{this.#t.forEach(t=>{t.onMutationUpdate(e)}),this.#n.notify({mutation:this,type:`updated`,action:e})})}};function He(){return{context:void 0,data:void 0,error:null,failureCount:0,failureReason:null,isPaused:!1,status:`idle`,variables:void 0,submittedAt:0}}var Ue=class extends xe{#e;#t;#n;constructor(e={}){super(),this.config=e,this.#e=new Set,this.#t=new Map,this.#n=0}build(e,t,n){let r=new Ve({client:e,mutationCache:this,mutationId:++this.#n,options:e.defaultMutationOptions(t),state:n});return this.add(r),r}add(e){this.#e.add(e);let t=We(e);if(typeof t==`string`){let n=this.#t.get(t);n?n.push(e):this.#t.set(t,[e])}this.notify({type:`added`,mutation:e})}remove(e){if(this.#e.delete(e)){let t=We(e);if(typeof t==`string`){let n=this.#t.get(t);if(n){if(n.length>1){let t=n.indexOf(e);t!==-1&&n.splice(t,1)}else n[0]===e&&this.#t.delete(t)}}}this.notify({type:`removed`,mutation:e})}canRun(e){let t=We(e);if(typeof t==`string`){let n=this.#t.get(t)?.find(e=>e.state.status===`pending`);return!n||n===e}return!0}runNext(e){let t=We(e);return typeof t==`string`?(this.#t.get(t)?.find(t=>t!==e&&t.state.isPaused))?.continue()??Promise.resolve():Promise.resolve()}clear(){A.batch(()=>{this.#e.forEach(e=>{this.notify({type:`removed`,mutation:e})}),this.#e.clear(),this.#t.clear()})}getAll(){return Array.from(this.#e)}find(e){let t={exact:!0,...e};return this.getAll().find(e=>D(t,e))}findAll(e={}){return this.getAll().filter(t=>D(e,t))}notify(e){A.batch(()=>{this.listeners.forEach(t=>{t(e)})})}resumePausedMutations(){let e=this.getAll().filter(e=>e.state.isPaused);return A.batch(()=>Promise.all(e.map(e=>e.continue().catch(C))))}};function We(e){return e.options.scope?.id}var Ge=class extends xe{#e;#t=void 0;#n;#r;constructor(e,t){super(),this.#e=e,this.setOptions(t),this.bindMethods(),this.#i()}bindMethods(){this.mutate=this.mutate.bind(this),this.reset=this.reset.bind(this)}setOptions(e){let t=this.options;this.options=this.#e.defaultMutationOptions(e),se(this.options,t)||this.#e.getMutationCache().notify({type:`observerOptionsUpdated`,mutation:this.#n,observer:this}),t?.mutationKey&&this.options.mutationKey&&re(t.mutationKey)!==re(this.options.mutationKey)?this.reset():this.#n?.state.status===`pending`&&this.#n.setOptions(this.options)}onSubscribe(){this.listeners.size===1&&this.#n&&(this.#n.addObserver(this),this.#i())}onUnsubscribe(){this.hasListeners()||this.#n?.removeObserver(this)}onMutationUpdate(e){this.#i(),this.#a(e)}getCurrentResult(){return this.#t}reset(){this.#n?.removeObserver(this),this.#n=void 0,this.#i(),this.#a()}mutate(e,t){return this.#r=t,this.#n?.removeObserver(this),this.#n=this.#e.getMutationCache().build(this.#e,this.options),this.#n.addObserver(this),this.#n.execute(e)}#i(){let e=this.#n?.state??He();this.#t={...e,isPending:e.status===`pending`,isSuccess:e.status===`success`,isError:e.status===`error`,isIdle:e.status===`idle`,mutate:this.mutate,reset:this.reset}}#a(e){A.batch(()=>{if(this.#r&&this.hasListeners()){let t=this.#t.variables,n=this.#t.context,r={client:this.#e,meta:this.options.meta,mutationKey:this.options.mutationKey};if(e?.type===`success`){try{this.#r.onSuccess?.(e.data,t,n,r)}catch(e){Promise.reject(e)}try{this.#r.onSettled?.(e.data,null,t,n,r)}catch(e){Promise.reject(e)}}else if(e?.type===`error`){try{this.#r.onError?.(e.error,t,n,r)}catch(e){Promise.reject(e)}try{this.#r.onSettled?.(void 0,e.error,t,n,r)}catch(e){Promise.reject(e)}}}this.listeners.forEach(e=>{e(this.#t)})})}},Ke=class extends xe{#e;constructor(e={}){super(),this.config=e,this.#e=new Map}build(e,t,n){let r=t.queryKey,i=t.queryHash??ne(r,t),a=this.get(i);return a||(a=new je({client:e,queryKey:r,queryHash:i,options:e.defaultQueryOptions(t),state:n,defaultOptions:e.getQueryDefaults(r)}),this.add(a)),a}add(e){this.#e.has(e.queryHash)||(this.#e.set(e.queryHash,e),this.notify({type:`added`,query:e}))}remove(e){this.#e.get(e.queryHash)===e&&(e.destroy(),this.#e.delete(e.queryHash),this.notify({type:`removed`,query:e}))}clear(){A.batch(()=>{this.getAll().forEach(e=>{this.remove(e)})})}get(e){return this.#e.get(e)}getAll(){return[...this.#e.values()]}find(e){let t={exact:!0,...e};return this.getAll().find(e=>te(t,e))}findAll(e={}){let t=this.getAll();return Object.keys(e).length>0?t.filter(t=>te(e,t)):t}notify(e){A.batch(()=>{this.listeners.forEach(t=>{t(e)})})}onFocus(){A.batch(()=>{this.getAll().forEach(e=>{e.onFocus()})})}onOnline(){A.batch(()=>{this.getAll().forEach(e=>{e.onOnline()})})}},qe=class{#e;#t;#n;#r;#i;#a;#o;#s;constructor(e={}){this.#e=e.queryCache||new Ke,this.#t=e.mutationCache||new Ue,this.#n=e.defaultOptions||{},this.#r=new Map,this.#i=new Map,this.#a=0}mount(){this.#a++,this.#a===1&&(this.#o=Se.subscribe(async e=>{e&&(await this.resumePausedMutations(),this.#e.onFocus())}),this.#s=Ce.subscribe(async e=>{e&&(await this.resumePausedMutations(),this.#e.onOnline())}))}unmount(){this.#a--,this.#a===0&&(this.#o?.(),this.#o=void 0,this.#s?.(),this.#s=void 0)}isFetching(e){return this.#e.findAll({...e,fetchStatus:`fetching`}).length}isMutating(e){return this.#t.findAll({...e,status:`pending`}).length}getQueryData(e){let t=this.defaultQueryOptions({queryKey:e});return this.#e.get(t.queryHash)?.state.data}ensureQueryData(e){let t=this.defaultQueryOptions(e),n=this.#e.build(this,t),r=n.state.data;return r===void 0?this.fetchQuery(e):(e.revalidateIfStale&&n.isStaleByTime(E(t.staleTime,n))&&this.prefetchQuery(t),Promise.resolve(r))}getQueriesData(e){return this.#e.findAll(e).map(({queryKey:e,state:t})=>[e,t.data])}setQueryData(e,t,n){let r=this.defaultQueryOptions({queryKey:e}),i=this.#e.get(r.queryHash)?.state.data,a=w(t,i);if(a!==void 0)return this.#e.build(this,r).setData(a,{...n,manual:!0})}setQueriesData(e,t,n){return A.batch(()=>this.#e.findAll(e).map(({queryKey:e})=>[e,this.setQueryData(e,t,n)]))}getQueryState(e){let t=this.defaultQueryOptions({queryKey:e});return this.#e.get(t.queryHash)?.state}removeQueries(e){let t=this.#e;A.batch(()=>{t.findAll(e).forEach(e=>{t.remove(e)})})}resetQueries(e,t){let n=this.#e;return A.batch(()=>{let r=n.findAll(e),i=new Set(r);return r.forEach(e=>{e.reset()}),this.refetchQueries({type:`active`,predicate:e=>i.has(e)},t)})}cancelQueries(e,t={}){let n={revert:!0,...t},r=A.batch(()=>this.#e.findAll(e).map(e=>e.cancel(n)));return Promise.all(r).then(C).catch(C)}invalidateQueries(e,t={}){return A.batch(()=>(this.#e.findAll(e).forEach(e=>{e.invalidate()}),e?.refetchType===`none`?Promise.resolve():this.refetchQueries({...e,type:e?.refetchType??e?.type??`active`},t)))}refetchQueries(e,t={}){let n={...t,cancelRefetch:t.cancelRefetch??!0},r=A.batch(()=>this.#e.findAll(e).filter(e=>!e.isDisabled()&&!e.isStatic()).map(e=>{let t=e.fetch(void 0,n);return n.throwOnError||(t=t.catch(C)),e.state.fetchStatus===`paused`?Promise.resolve():t}));return Promise.all(r).then(C)}async query(e){let t=this.defaultQueryOptions(e);t.retry===void 0&&(t.retry=!1);let n=this.#e.build(this,t),r=n.isStaleByTime(E(t.staleTime,n))?await n.fetch(t):n.state.data,i=t.select;return i?i(r):r}fetchQuery(e){let t=this.defaultQueryOptions(e);t.retry===void 0&&(t.retry=!1);let n=this.#e.build(this,t);return n.isStaleByTime(E(t.staleTime,n))?n.fetch(t):Promise.resolve(n.state.data)}prefetchQuery(e){return this.fetchQuery(e).then(C).catch(C)}infiniteQuery(e){return e._type=`infinite`,this.query(e)}fetchInfiniteQuery(e){return e._type=`infinite`,this.fetchQuery(e)}prefetchInfiniteQuery(e){return this.fetchInfiniteQuery(e).then(C).catch(C)}ensureInfiniteQueryData(e){return e._type=`infinite`,this.ensureQueryData(e)}resumePausedMutations(){return Ce.isOnline()?this.#t.resumePausedMutations():Promise.resolve()}getQueryCache(){return this.#e}getMutationCache(){return this.#t}getDefaultOptions(){return this.#n}setDefaultOptions(e){this.#n=e}setQueryDefaults(e,t){this.#r.set(re(e),{queryKey:e,defaultOptions:t})}getQueryDefaults(e){let t=[...this.#r.values()],n={};return t.forEach(t=>{ie(e,t.queryKey)&&Object.assign(n,t.defaultOptions)}),n}setMutationDefaults(e,t){this.#i.set(re(e),{mutationKey:e,defaultOptions:t})}getMutationDefaults(e){let t=[...this.#i.values()],n={};return t.forEach(t=>{ie(e,t.mutationKey)&&Object.assign(n,t.defaultOptions)}),n}defaultQueryOptions(e){if(e._defaulted)return e;let t={...this.#n.queries,...this.getQueryDefaults(e.queryKey),...e,_defaulted:!0};return t.queryHash||=ne(t.queryKey,t),t.refetchOnReconnect===void 0&&(t.refetchOnReconnect=t.networkMode!==`always`),t.throwOnError===void 0&&(t.throwOnError=!!t.suspense),!t.networkMode&&t.persister&&(t.networkMode=`offlineFirst`),t.queryFn===he&&(t.enabled=!1),t}defaultMutationOptions(e){return e?._defaulted?e:{...this.#n.mutations,...e?.mutationKey&&this.getMutationDefaults(e.mutationKey),...e,_defaulted:!0}}clear(){this.#e.clear(),this.#t.clear()}},Je=m.createContext(!1),Ye=()=>m.useContext(Je);Je.Provider;function Xe(){let e=!1;return{clearReset:()=>{e=!1},reset:()=>{e=!0},isReset:()=>e}}var Ze=m.createContext(Xe()),Qe=()=>m.useContext(Ze),$e=(e,t,n)=>{let r=n?.state.error&&typeof e.throwOnError==`function`?_e(e.throwOnError,[n.state.error,n]):e.throwOnError;(e.suspense||r)&&(t.isReset()||(e.retryOnMount=!1))},et=e=>{m.useEffect(()=>{e.clearReset()},[e])},tt=({result:e,errorResetBoundary:t,throwOnError:n,query:r,suspense:i})=>e.isError&&!t.isReset()&&!e.isFetching&&r&&(i&&e.data===void 0||_e(n,[e.error,r])),nt=e=>{if(e.suspense){let t=1e3,n=e=>e===`static`?e:Math.max(e??t,t),r=e.staleTime;e.staleTime=typeof r==`function`?(...e)=>n(r(...e)):n(r),typeof e.gcTime==`number`&&(e.gcTime=Math.max(e.gcTime,t))}},rt=(e,t)=>e?.suspense&&t.isPending,it=(e,t,n)=>t.fetchOptimistic(e).catch(()=>{n.clearReset()});function at(e,t,n){let r=Ye(),i=Qe(),a=_(n),o=a.defaultQueryOptions(e),s=a.getQueryCache().get(o.queryHash),c=e.subscribed!==!1;o._optimisticResults=r?`isRestoring`:c?`optimistic`:void 0,nt(o),$e(o,i,s),et(i);let[l]=m.useState(()=>new t(a,o)),u=l.getOptimisticResult(o),d=!r&&c;if(m.useSyncExternalStore(m.useCallback(e=>{let t=d?l.subscribe(A.batchCalls(e)):C;return l.updateResult(),t},[l,d]),()=>l.getCurrentResult(),()=>l.getCurrentResult()),m.useEffect(()=>{l.setOptions(o)},[o,l]),rt(o,u))throw it(o,l,i);if(tt({result:u,errorResetBoundary:i,throwOnError:o.throwOnError,query:s,suspense:o.suspense}))throw u.error;return o.notifyOnChangeProps?u:l.trackResult(u)}function ot(e,t){return at(e,Fe,t)}function st(e,t){let n=_(t),[r]=m.useState(()=>new Ge(n,e));m.useEffect(()=>{r.setOptions(e)},[r,e]);let i=m.useSyncExternalStore(m.useCallback(e=>r.subscribe(A.batchCalls(e)),[r]),()=>r.getCurrentResult(),()=>r.getCurrentResult()),a=m.useCallback((...e)=>{r.mutate(e[0],e[1]).catch(C)},[r]);if(i.error&&_e(r.options.throwOnError,[i.error]))throw i.error;return{...i,mutate:a,mutateAsync:i.mutate}}var ct=m.use,lt=m.useLayoutEffect;function ut(e){return e[e.length-1]}function dt(e,t){return typeof e==`function`?e(t):e}var ft=Object.prototype.hasOwnProperty;function pt(e){for(let t in e)if(ft.call(e,t))return!0;return!1}var mt=()=>Object.create(null),ht=(e,t)=>gt(e,t,!0);function gt(e,t,n,r=0){if(e===t)return e;if(r++>500)return t;let i=Array.isArray(e)&&Array.isArray(t);if(!i&&!(_t(e)&&_t(t)))return t;let a=Object.keys(e),o=a.length,s=Object.keys(t),c=s.length;if(i?o!==e.length||c!==t.length||o&&ut(a)!==`${o-1}`||c&&ut(s)!==`${c-1}`:o!==Object.getOwnPropertyNames(e).length||c!==Object.getOwnPropertyNames(t).length||Object.getOwnPropertySymbols(t).length)return t;let l=0,u,d,f;if(i){for(;ll&&(u=t[f],u=d===u?d:typeof d==`object`?gt(d,u,n,r):u),p[f]=o`{}]/g;function xt(e){return e.replace(bt,e=>`%`+e.charCodeAt(0).toString(16).toUpperCase().padStart(2,`0`))}function St(e){let t;try{t=decodeURI(e)}catch{t=e.replaceAll(/%[0-9A-F]{2}/gi,e=>{try{return decodeURI(e)}catch{return e}})}return xt(t)}var Ct=[`http:`,`https:`,`mailto:`,`tel:`];function wt(e){if(e[0]!==`/`&&e.includes(`:`))return/^[\x00-\x20]*([a-z][a-z\d+.\t\n\r-]*:)/i.exec(e)?.[1]?.replace(/[\t\n\r]/g,``).toLowerCase()}var Tt=/^[\x00-\x20]*[\\/][\t\n\r]*[\\/]/;function Et(e,t){if(!e)return!1;if(Tt.test(e))return!0;let n=wt(e);return n?!t.has(n):!1}function Dt(e){if(!e)return e;let t=e;if(/[%\\\x00-\x1f\x7f]/.test(e)){let n=/%25|%5C/gi,r=0,i;for(t=``;(i=n.exec(e))!==null;)t+=St(e.slice(r,i.index))+i[0],r=n.lastIndex;t+=St(r?e.slice(r):e)}return t}function Ot(e){return/[\s\u0080-\uFFFF]/.test(e)?e.replace(/\s|[^\u0000-\u007F]/gu,encodeURIComponent):e}function kt(e,t){if(e===t)return!0;if(e.length!==t.length)return!1;for(let n=0;n1&&e[t-1]===`/`?e.replace(/\/+$/,``):e}function Pt(e){return Nt(Mt(e))}function Ft(e,t){return e?.endsWith(`/`)&&e!==`/`&&e!==`${t}/`?e.slice(0,-1):e}function It(e,t,n=`never`,r){if(t.includes(`//`)&&(t=jt(t)),t.startsWith(`/`))return t.length===1||n===`preserve`?t:n===`always`?t.endsWith(`/`)?t:`${t}/`:t.endsWith(`/`)?t.slice(0,-1):t;let i=t===`.`,a;if(r){a=i?e:e+`\0`+t;let n=r.get(a);if(n)return n}let o;if(i)o=e.split(`/`);else{for(e.includes(`//`)&&(e=jt(e)),o=e.split(`/`);o.length>1&&ut(o)===``;)o.pop();let n=t.split(`/`);for(let e=0,t=n.length;e1?o.pop():o=[``]:r===`.`||o.push(r)}}o.length>1&&(ut(o)===``?n===`never`&&o.pop():n===`always`&&o.push(``));let s=o.join(`/`),c=(i?jt(s):s)||`/`;return a&&r&&r.set(a,c),c}function Lt(e){let t=new Map(e.map(e=>[encodeURIComponent(e),e])),n=new RegExp([...t.keys()].join(`|`).replace(/[.*()]/g,`\\$&`),`g`);return e=>e.replace(n,e=>t.get(e)??e)}function Rt(e){return e==null||e===``}function zt(e,t,n){if(typeof t!=`string`)return``+(t??void 0);let r=e===`_splat`;if(r&&(!t||/^[a-zA-Z0-9\-._~!/]*$/.test(t)))return t;let i=encodeURIComponent(t);return r&&(i=i.replaceAll(`%2F`,`/`)),n?n(i):i}function Bt(e,t,n,r,i){let a=e.endsWith(`/`)?`/`:``,o=``;for(let e of t){if(typeof e==`string`){o+=e;continue}let[t,s,c,l]=e,u=t===2,d=u&&l!==void 0?l+a:l,f=n[s];if(t!==3||f!=null){if(i&&(i[s]=f,u&&(i[`*`]=f)),u&&Rt(f)){if(c===`/`&&!d)continue;f=``}o+=c+zt(s,f,r)+(d||``)}}return o+a||`/`}function Vt(e){return e?.isNotFound===!0}function Ht(){try{return sessionStorage}catch{return}}var Ut=`tsr-scroll-restoration-v1_3`,Wt=Ht();function Gt(){try{return JSON.parse(Wt?.getItem(`tsr-scroll-restoration-v1_3`)||`{}`)}catch{return{}}}function Kt(){try{Wt?.setItem(Ut,JSON.stringify(qt))}catch{}}var qt=Gt(),Jt=`data-scroll-restoration-id`,Yt=e=>e.state.__TSR_key||e.href;function Xt(e){let t=e.getAttribute(Jt);if(t)return`[${Jt}="${t}"]`;let n=``,r=e,i;for(;i=r.parentNode;){let e=1,t=r;for(;t=t.previousElementSibling;)e++;let a=`${r.localName}:nth-child(${e})`;n=n?`${a} > ${n}`:a,r=i}return n}var Zt=!1,Qt=`window`;function M(e){try{return typeof e==`function`?e():document.querySelector(e)}catch{}}function $t(e){let t=new Set;for(let n of e){if(n===Qt)continue;let e=M(n);e&&t.add(e)}return t}function en(e,t){let n=t??e.options.scrollRestoration,r=e._scroll;n&&(r.restoring=!0);let i=e.options.getScrollRestorationKey||Yt,a=new Set,o=e=>{let t=qt[e]||={};for(let e of a)e===document?t[Qt]={scrollX,scrollY}:e.isConnected&&(t[Xt(e)]={scrollX:e.scrollLeft,scrollY:e.scrollTop})};n&&!r.restoration&&(r.restoration=!0,Zt=!1,history.scrollRestoration=`manual`,document.addEventListener(`scroll`,e=>{Zt||a.add(e.target)},!0),e.subscribe(`onBeforeLoad`,e=>{e.fromLocation&&o(i(e.fromLocation)),a.clear()}),addEventListener(`pagehide`,()=>{o(i(e.stores.resolvedLocation.get()??e.stores.location.get())),Kt()})),!r.reset&&(r.reset=!0,e.subscribe(`onRendered`,t=>{let n=e.options.scrollRestorationBehavior,o=e.options.scrollToTopSelectors,s=r.next,c=r.hash,l;if(a.clear(),r.next=!0,r.hash=!1,typeof e.options.scrollRestoration==`function`&&!e.options.scrollRestoration({location:e.latestLocation}))return;let u=i(t.toLocation),d=t.fromLocation&&i(t.fromLocation);if(r.restoring&&d&&d!==u){let e=qt[d];if(e){let t=qt[u];for(let n in e){if(n===Qt){if(s)continue}else{let e=M(n);if(!e||s&&o&&(l??=$t(o),l.has(e)))continue}t||=qt[u]={},t[n]??=e[n]}}}Zt=!0;try{let e=t.toLocation.hash,i=t.toLocation.state.__hashScrollIntoViewOptions??!0,a=!1;if(s){!e&&o&&(l??=$t(o));let t=e&&i&&c,s=r.restoring?qt[u]:void 0;if(s)for(let e in s){let{scrollX:r,scrollY:i}=s[e];if(e===Qt){if(t)continue;scrollTo({top:i,left:r,behavior:n}),a=!0}else{let t=M(e);t&&(t.scrollLeft=r,t.scrollTop=i,l?.delete(t))}}if(!e){let e={top:0,left:0,behavior:n};if(a||scrollTo(e),l)for(let t of l)t.scrollTo(e)}}!a&&e&&i&&document.getElementById(e)?.scrollIntoView(i)}finally{Zt=!1}}))}function tn(e,t=String){let n;for(let r in e){let i=e[r];i!==void 0&&(n||=new URLSearchParams).set(r,t(i))}return n?n.toString():``}function nn(e){return e?e===`false`?!1:e===`true`?!0:e*0==0&&+e+``===e?+e:e:``}function rn(e){let t=new URLSearchParams(e),n=Object.create(null);for(let[e,r]of t.entries()){let t=n[e];t==null?n[e]=nn(r):Array.isArray(t)?t.push(nn(r)):n[e]=[t,nn(r)]}return n}var an=/^(?:\s|["[{\d-]|fa|nu|tr)/,on=cn(JSON.parse),sn=ln(JSON.stringify,JSON.parse);function cn(e){let t=e===JSON.parse;return n=>{n[0]===`?`&&(n=n.substring(1));let r=rn(n);for(let n in r){let i=r[n];if(typeof i==`string`){if(t&&!an.test(i))continue;try{r[n]=e(i)}catch{}}}return r}}function ln(e,t){let n=t===JSON.parse;function r(r){if(r&&typeof r==`object`)try{return e(r)}catch{}else if(t&&typeof r==`string`){if(n&&!an.test(r))return r;try{return t(r),e(r)}catch{}}return r}return e=>{let t=tn(e,r);return t?`?${t}`:``}}var un=`__root__`;function dn(e){e.statusCode=e.statusCode||e.code||307;let t=new Headers(e.headers);e.href&&t.get(`Location`)===null&&t.set(`Location`,e.href);let n=new Response(null,{status:e.statusCode,headers:t});if(n.options=e,e.throw)throw n;return n}function fn(e){return e instanceof Response&&!!e.options}function pn(e){let t=new Map,n,r;return{get(e){let n=t.get(e);if(n)return n.visited=!0,n.value},set(i,a){let o=t.get(i);if(o){o.value=a;return}if(t.size>=e){let e=n?.next().value;for(;!e||e.visited;)e?e.visited=!1:n=t.values(),e=n.next().value;e===r&&(n=void 0),t.delete(e.key)}let s={key:i,value:a,visited:!1};r=s,t.set(i,s)},clear(){t.clear(),n=void 0,r=void 0}}}var mn=4,hn=5;function gn(e){let t=e.names;if(t)return t;let n=[];for(let t of e)typeof t!=`string`&&n.push(t[1]);return e.names=n}function _n(e,t,n){let r=e.substring(t,n);if(r.charCodeAt(0)===36)return r.length===1?[2,`_splat`,``,void 0]:[1,r.substring(1),``,``];let i=r.indexOf(`{`);if(i>=0){let a=r.indexOf(`}`,i),o=r.charCodeAt(i+1)===45,s=i+(o?3:2);if(a>=0&&r.charCodeAt(s-1)===36&&(!o||s!e.parse&&e.caseSensitive===_&&e.prefix===h&&e.suffix===g);if(y)c=y;else{let e=bn(r,t,_,h,g);c=e,v.push(e),v.length===2&&i?.push(v)}}r=c}p&&m=0;e--){let n=i.wildcard[e],{prefix:r,suffix:a}=n;if(!r||!_&&(n.caseSensitive?v:y??=v.toLowerCase()).startsWith(r)){if(a){if(_)continue;let e=t.slice(u).join(`/`),i=e.slice(-a.length);if((n.caseSensitive?i:i.toLowerCase())!==a||e.length-a.length=0;t--){let n=i.optional[t];s.push({node:n,index:u,skipped:e,statics:f,dynamics:p,optionals:m,extract:h,rawParams:g})}if(!_)for(let e=i.optional.length-1;e>=0;e--){let t=i.optional[e],{prefix:n,suffix:r}=t;if(n||r){let e=t.caseSensitive?v:y??=v.toLowerCase();if(n&&!e.startsWith(n)||r&&e.indexOf(r,e.length-r.length)=0;e--){let t=i.dynamic[e],{prefix:n,suffix:r}=t;if(n||r){let e=t.caseSensitive?v:y??=v.toLowerCase();if(n&&!e.startsWith(n)||r&&e.indexOf(r,e.length-r.length)=0;e--){let t=i.pathless[e];s.push({node:t,index:u,skipped:d,statics:f,dynamics:p,optionals:m,extract:h,rawParams:g})}}if(l)return l;if(r&&c){let n=c.index;for(let e=0;ee.statics||t.statics===e.statics&&(t.dynamics>e.dynamics||t.dynamics===e.dynamics&&(t.optionals>e.optionals||t.optionals===e.optionals&&((t.node.kind===mn)>(e.node.kind===mn)||t.node.kind===mn==(e.node.kind===mn)&&t.node.depth>e.node.depth)))}function Fn(e,t,n){let r=Pt(e),i=`/${r}`,a=t?i:i.toLowerCase(),o=`${a}/`,s={input:({url:e})=>{let n=t?e.pathname:e.pathname.toLowerCase();return n===a?e.pathname=`/`:n.startsWith(o)&&(e.pathname=e.pathname.slice(i.length)),e},output:({url:e})=>(e.pathname=jt(`/${r}${e.pathname}`),e)};return n?{input:({url:e})=>In(n,s.input({url:e})),output:({url:e})=>s.output({url:Ln(n,e)})}:s}function In(e,t){let n=e?.input?.({url:t});if(n){if(typeof n==`string`)return new URL(n);if(n instanceof URL)return n}return t}function Ln(e,t){let n=e?.output?.({url:t});if(n){if(typeof n==`string`)return new URL(n);if(n instanceof URL)return n}return t}function Rn(e,t){let{createMutableStore:n,createReadonlyStore:r,batch:i}=t,a=new Map,o=n(`idle`),s=n(e),c=n(void 0),l=n([]),u=r(()=>l.get().map(e=>a.get(e).get())),d=r(()=>({status:o.get(),isLoading:o.get()===`pending`,matches:u.get(),location:s.get(),resolvedLocation:c.get()}));function f(e){let t=a.get(e);return t||(t=n(void 0),a.set(e,t)),t}let p={status:o,location:s,resolvedLocation:c,ids:l,matches:u,byRoute:a,__store:d,getMatchStore:f,setMatches:m};function m(e){let t=l.get(),n=e.map(e=>e.routeId);i(()=>{kt(t,n)||l.set(n);for(let e of t)n.includes(e)||a.get(e).set(()=>void 0);for(let t of e){let e=f(t.routeId);e.get()!==t&&e.set(t)}})}return p}var zn=`__TSR_index`,Bn=`popstate`,Vn=`beforeunload`,Hn=/^[\x00-\x20]*(?:[\\/][\t\n\r]*){2,}/;function Un(e){let t=Hn.exec(e);return t?`/`+e.slice(t[0].length):e}function Wn(e){return/[\x00-\x1f\x7f]/.test(e)&&(e=e.replace(/[\x00-\x1f\x7f]/g,e=>` -\r`.includes(e)?``:encodeURIComponent(e))),Un(e)}function Gn(e){let t=e.getLocation(),n=new Set,r=r=>{t=e.getLocation(),n.forEach(e=>e({location:t,action:r}))},i=n=>{e.notifyOnIndexChange??!0?r(n):t=e.getLocation()},a=async({task:n,navigateOpts:r,...i})=>{if(r?.ignoreBlocker??!1){n();return}let a=e.getBlockers?.()??[],o=i.type===`PUSH`||i.type===`REPLACE`;if(typeof document<`u`&&a.length&&o)for(let n of a){let r=Jn(i.path,i.state);if(await n.blockerFn({currentLocation:t,nextLocation:r,action:i.type})){e.onBlocked?.();return}}n()};return{get location(){return t},get length(){return e.getLength()},subscribers:n,subscribe:e=>(n.add(e),()=>{n.delete(e)}),push:(n,i,o)=>{let s=t.state[zn];i=Kn(s+1,i),a({task:()=>{e.pushState(n,i),r({type:`PUSH`})},navigateOpts:o,type:`PUSH`,path:n,state:i})},replace:(n,i,o)=>{let s=t.state[zn];i=Kn(s,i),a({task:()=>{e.replaceState(n,i),r({type:`REPLACE`})},navigateOpts:o,type:`REPLACE`,path:n,state:i})},go:(t,n)=>{a({task:()=>{e.go(t,n?.ignoreBlocker??!1),i({type:`GO`,index:t})},navigateOpts:n,type:`GO`})},back:t=>{a({task:()=>{e.back(t?.ignoreBlocker??!1),i({type:`BACK`})},navigateOpts:t,type:`BACK`})},forward:t=>{a({task:()=>{e.forward(t?.ignoreBlocker??!1),i({type:`FORWARD`})},navigateOpts:t,type:`FORWARD`})},canGoBack:()=>t.state[zn]!==0,createHref:t=>e.createHref(t),block:t=>{if(!e.setBlockers)return()=>{};let n=e.getBlockers?.()??[];return e.setBlockers([...n,t]),()=>{let n=e.getBlockers?.()??[];e.setBlockers?.(n.filter(e=>e!==t))}},flush:()=>e.flush?.(),destroy:()=>e.destroy?.(),notify:r,_getBlockers:()=>e.getBlockers?.()??[]}}function Kn(e,t){let n=Yn();return{...t,key:n,__TSR_key:n,[zn]:e}}function qn(e){let t=e?.window??(typeof document<`u`?window:void 0),n=t.history.pushState,r=t.history.replaceState,i=[],a=()=>i,o=e=>i=e,s=t=>Wn(e?.createHref?e.createHref(t):t),c=e?.parseLocation??(()=>Jn(`${t.location.pathname}${t.location.search}${t.location.hash}`,t.history.state));if(!t.history.state?.__TSR_key&&!t.history.state?.key){let e=Yn();t.history.replaceState({[zn]:0,key:e,__TSR_key:e},``)}let l=c(),u,d=!1,f=!1,p=!1,m=!1,h=()=>l,g,_=()=>{g&&(S._ignoreSubscribers=!0,(g[2]?t.history.pushState:t.history.replaceState)(g[1],``,g[0]),S._ignoreSubscribers=!1,g=void 0,u=void 0)},v=(t,n,r)=>{let i=e?.createHref?s(n):void 0,a=!!g;a||(u=l),l=Jn(n,r),g=[i??l.href,r,g?.[2]||t],a||queueMicrotask(()=>_())},y=e=>{l=c(),S.notify({type:e})},b=async()=>{if(m=!1,f){f=!1;return}let e=c(),n=e.state[zn]-l.state[zn],r=n===1,i=n===-1,o=!r&&!i||d;d=!1;let s=o?`GO`:i?`BACK`:`FORWARD`,u=o?{type:`GO`,index:n}:{type:i?`BACK`:`FORWARD`};if(p)p=!1;else{let r=a();if(typeof document<`u`&&r.length){for(let i of r)if(await i.blockerFn({currentLocation:l,nextLocation:e,action:s})){f=!0,t.history.go(-n),S.notify(u);return}}}l=c(),S.notify(u)},x=e=>{if(m){m=!1;return}let t=!1,n=a();if(typeof document<`u`&&n.length)for(let e of n){let n=e.enableBeforeUnload??!0;if(n===!0){t=!0;break}if(typeof n==`function`&&n()===!0){t=!0;break}}if(t)return e.preventDefault(),e.returnValue=``},S=Gn({getLocation:h,getLength:()=>t.history.length,pushState:(e,t)=>v(!0,e,t),replaceState:(e,t)=>v(!1,e,t),back:e=>(e&&(p=!0,m=!0),t.history.back()),forward:e=>{e&&(p=!0,m=!0),t.history.forward()},go:(e,n)=>{d=!0,n&&(p=!0,m=!0),t.history.go(e)},createHref:e=>s(e),flush:_,destroy:()=>{t.history.pushState=n,t.history.replaceState=r,t.removeEventListener(Vn,x,{capture:!0}),t.removeEventListener(Bn,b)},onBlocked:()=>{u&&l!==u&&(l=u)},getBlockers:a,setBlockers:o,notifyOnIndexChange:!1});return S._ignoreNextBeforeUnload=e=>{m=!1;try{e=new URL(e,t.document.baseURI).href,m=/^https?:/.test(e)&&(!e.includes(`#`)||e.split(`#`)[0]!==t.location.href.split(`#`)[0])}catch{}},t.addEventListener(Vn,x,{capture:!0}),t.addEventListener(Bn,b),t.history.pushState=function(...e){let r=n.apply(t.history,e);return S._ignoreSubscribers||y(`PUSH`),r},t.history.replaceState=function(...e){let n=r.apply(t.history,e);return S._ignoreSubscribers||y(`REPLACE`),n},S}function Jn(e,t){let n=Wn(e),r=n.indexOf(`#`),i=n.indexOf(`?`);if(!t){let e=Yn();t={[zn]:0,key:e,__TSR_key:e}}return{href:n,pathname:n.substring(0,r>0?i>0?Math.min(r,i):r:i>0?i:n.length),hash:r>-1?n.substring(r):``,search:i>-1?n.slice(i,r===-1?void 0:r):``,state:t}}function Yn(){return(Math.random()+1).toString(36).substring(7)}function Xn(e,t){return e.protocol!==`http:`&&e.protocol!==`https:`||e.origin!==t||!!e.username||!!e.password}function Zn(e){return e.pathname+e.search+e.hash}function Qn(e){return e.options.loader||e.options.beforeLoad||e.lazyFn||e.options.component?.preload||e.options.pendingComponent?.preload}function $n(e,t){return{fromLocation:t,toLocation:e,pathChanged:t?.pathname!==e.pathname,hrefChanged:t?.href!==e.href,hashChanged:t?.hash!==e.hash}}function er({key:e,__TSR_key:t,__TSR_index:n,__hashScrollIntoViewOptions:r,...i}){return i}function tr(e){return e.findIndex(e=>e.status===`error`||e.status===`notFound`||e._notFound)+1}function nr(e,t,n,r,i,a){r&&(t=t.slice(0,r)),i&&(n=n.slice(0,i));for(let r of t){if(a&&e._tx!==a)return;n.some(e=>e.routeId===r.routeId)||e.routesById[r.routeId].options.onLeave?.(r)}for(let r of n){if(a&&e._tx!==a)return;e.routesById[r.routeId].options[t.some(e=>e.routeId===r.routeId)?`onStay`:`onEnter`]?.(r)}}var rr=class{constructor(e,t){this.tempLocationKey=`${Math.round(Math.random()*1e7)}`,this._scroll={next:!0},this.subscribers=new Set,this._cache=new Map,this._committed=[],this.startTransition=async e=>(e(),!1),this.update=e=>{let t=this.options;this.options={...t,...e},this.isServer=this.options.isServer??!1??typeof document>`u`,this.staticLocations=new WeakMap,this.protocolAllowlist=new Set(this.options.protocolAllowlist),(!this.history||this.options.history&&this.options.history!==this.history)&&(this.history=this.options.history?this.options.history:qn()),this.origin=this.options.origin,this.origin||=window?.origin&&window.origin!==`null`?window.origin:`http://localhost`;let n=this.options.basepath??`/`,r=this.options.rewrite,i=this.basepath!==n||t?.rewrite!==r||t?.caseSensitive!==this.options.caseSensitive;if(i&&(this.basepath=n,this.rewrite=n!==`/`&&Pt(n)?Fn(n,this.options.caseSensitive,r):r),this.history&&this.updateLatestLocation(),this.options.routeTree!==this.routeTree){this.routeTree=this.options.routeTree;let e;e=this.buildRouteTree(),this.setRoutes(e)}if(this.stores)i&&this.stores.location.set(this.latestLocation);else if(this.latestLocation){let e=this.getStoreConfig(this);this.batch=e.batch,this.stores=Rn(this.latestLocation,e),en(this)}},this.updateLatestLocation=()=>{this.latestLocation=this.parseLocation(this.history.location,this.latestLocation)},this.buildRouteTree=()=>{let e=Tn(this.routeTree,this.options.caseSensitive);return this.options.routeMasks&&xn(this.options.routeMasks,e.processedTree),{...e,resolvePathCache:pn(1e3)}},this.subscribe=(e,t)=>{let n={eventType:e,fn:t};return this.subscribers.add(n),()=>{this.subscribers.delete(n)}},this.emit=e=>{for(let t of this.subscribers)if(t.eventType===e.type)try{t.fn(e)}catch(e){console.error(e)}},this.parseLocation=(e,t)=>{let n=({pathname:e,search:n,hash:r,href:i},a)=>{if(!this.rewrite&&!/[ \x00-\x1f\x7f\u0080-\uffff]/.test(e)){let i=this.options.parseSearch(n),o=this.options.stringifySearch(i);return{href:e+o+r,publicHref:e+o+r,pathname:Dt(e),external:!1,searchStr:o,search:ht(t?.search,i),hash:Dt(r.slice(1)),state:gt(t?.state,a)}}let o=In(this.rewrite,new URL(i,this.origin)),s=this.options.parseSearch(o.search),c=this.options.stringifySearch(s);return o.search=c,{href:o.href.replace(o.origin,``),publicHref:i,pathname:Dt(Un(o.pathname)),external:!!this.rewrite&&Xn(o,this.origin),searchStr:c,search:ht(t?.search,s),hash:Dt(o.hash.slice(1)),state:gt(t?.state,a)}},r=n(e,e.state),{__tempLocation:i,__tempKey:a}=r.state;if(i&&(!a||a===this.tempLocationKey)){let e=n(i,{...i.state,__tempLocation:void 0,key:r.state.key,__TSR_key:r.state.__TSR_key});return e.maskedLocation=r,e}return r},this.matchRoutes=(e,t,n)=>typeof e==`string`?this.matchRoutesInternal({pathname:e,search:t},n):this.matchRoutesInternal(e,t),this.getMatchedRoutes=e=>{let t=Object.create(null),n=wn(Nt(e),this.processedTree,!0);return n&&Object.assign(t,n.rawParams),[n?.branch||[this.routesById.__root__],t,n?.route]},this.buildLocation=e=>{{let t=this.staticLocations.get(e);if(t)return t}let t=!1,n=(n={})=>{if(n.href){let e=Jn(n.href,{});n={...n,to:In(this.rewrite,new URL(e.pathname,this.origin)).pathname,search:this.options.parseSearch(e.search),hash:e.hash.slice(1)}}let r=n._fromLocation||this._pendingLocation||this.latestLocation,i,a=()=>(t=!0,r),o=()=>(t=!0,i??=this.matchRoutesLightweight(r)),s=n.to?`${n.to}`:`.`,c=It(s[0]===`/`?``:n.unsafeRelative===`path`?a().pathname:n.from??o()[1],s,this.options.trailingSlash,this.resolvePathCache),l=this.routesByPath[Nt(c)],u=c.includes(`$`),d;if(l)d=l._branch??=On(l);else if(u)d=[];else{let[e,t,n]=this.getMatchedRoutes(c);d=e,this.options.notFoundRoute&&(!n||n.path!==`/`&&t[`**`])&&(d=[...d,this.options.notFoundRoute])}let f=u?l?._interpolation??vn(!1,{fullPath:c},0):void 0,p;for(let e of d){let t=e.options.params?.stringify??e.options.stringifyParams;if(t){let e=o()[3];if(p??=cr(n.params,e),!pt(p))break;p===e&&(p=Object.assign(mt(),p));try{Object.assign(p,t(p))}catch{}}}p??=cr(n.params,lr(n.params,f)?o()[3]:ur);let m=e.leaveParams?c:Un(Dt(f?Bt(c,f,p,this.pathParamsDecoder):c)),h=dr(d,e._includeValidateSearch),g=()=>{let t=o()[2];if(e._includeValidateSearch&&this.options.search?.strict){let e={};d.forEach(n=>{if(n.options.validateSearch)try{Object.assign(e,sr(n.options.validateSearch,{...e,...t}))}catch{}}),t=e}return t},_=h.length?fr(h,g(),n):n.search===!0?g():typeof n.search==`function`?n.search(g()):n.search||ur,v=this.options.stringifySearch(_),y=n.hash===!0?a().hash:typeof n.hash==`function`?n.hash(a().hash):n.hash||void 0,b=y?`#${y}`:``,x=n.state?n.state===!0?a().state:typeof n.state==`function`?n.state(a().state):n.state:ur,S=`${m}${v}${b}`,C,w,T=!1;if(this.rewrite){let e=new URL(S,this.origin),t=e.origin,n=Ln(this.rewrite,e);C=Zn(e),Xn(n,t)?(w=n.href,T=!0):w=Un(Zn(n))}else C=Ot(S),w=C;return{publicHref:w,href:C,pathname:m,search:_,searchStr:v,state:x,hash:y??``,external:T,unmaskOnReload:n.unmaskOnReload}},r=n(e);if(e.mask)r.maskedLocation=n({from:e.from,...e.mask});else if(this.options.routeMasks){let t=Sn(r.pathname,this.processedTree);if(t){let i=Object.assign(mt(),t.rawParams),{from:a,params:o,...s}=t.route,c=cr(o,i);r.maskedLocation=n({from:e.from,...s,params:c})}}return!t&&e._fromLocation&&!r.maskedLocation&&this.staticLocations.set(e,r),r},this.commitLocation=async({viewTransition:e,ignoreBlocker:t,...n})=>{let r=n.maskedLocation??n;if(r.external)return ir(this,r.publicHref,{replace:n.replace,ignoreBlocker:t});let i,a=Nt(this.latestLocation.href)===Nt(n.href)&&vt(er(n.state),er(this.latestLocation.state)),o=this._commitPromise,s,c=new Promise(e=>{s=e});if(c.resolve=()=>{s(),o?.resolve()},this._commitPromise=c,a)this.load();else{let{maskedLocation:r,hashScrollIntoView:a,...o}=n;r&&(o={...r,state:{...r.state,__tempKey:void 0,__tempLocation:{...o,search:o.searchStr,state:{...o.state,__tempKey:void 0,__tempLocation:void 0,__TSR_key:void 0,key:void 0}}}},(o.unmaskOnReload??this.options.unmaskOnReload??!1)&&(o.state.__tempKey=this.tempLocationKey)),o.state={...o.state,__hashScrollIntoViewOptions:a??this.options.defaultHashScrollIntoView??!0},this.shouldViewTransition=e,i=n.replace?`REPLACE`:`PUSH`,this.history[i===`REPLACE`?`replace`:`push`](o.publicHref,o.state,{ignoreBlocker:t}),this.history.subscribers.size||this.load({action:{type:i}})}return this._scroll.next=n.resetScroll??!0,this._commitPromise},this.buildAndCommitLocation=({replace:e,resetScroll:t,hashScrollIntoView:n,viewTransition:r,ignoreBlocker:i,...a}={})=>{let o=this.buildLocation({...a,_includeValidateSearch:!0});this._pendingLocation=o;let s=this.commitLocation({...o,viewTransition:r,replace:e,resetScroll:t,hashScrollIntoView:n,ignoreBlocker:i});return queueMicrotask(()=>{this._pendingLocation===o&&(this._pendingLocation=void 0)}),s},this.navigate=async({to:e,reloadDocument:t,href:n,publicHref:r,...i})=>{let a=n?wt(n):void 0;if(a||t){if(e!==void 0||!n){let t=this.buildLocation({to:e,...i}),a=t.maskedLocation??t;n??=a.publicHref,r??=a.publicHref}let t=!a&&r?r:n;return ir(this,t,i)}return this.buildAndCommitLocation({...i,href:n,to:e,_isNavigate:!0})},this.load=async e=>{this.updateLatestLocation(),e?.action&&(this._scroll.hash=e.action.type===`PUSH`||e.action.type===`REPLACE`),await ii(this,e)},this.startViewTransition=e=>{let t=this.shouldViewTransition??this.options.defaultViewTransition;if(this.shouldViewTransition=void 0,t&&typeof document.startViewTransition==`function`){let n;if(typeof t==`object`&&window.CSS?.supports?.(`selector(:active-view-transition-type(a))`)){let r=this.latestLocation,i=this.stores.resolvedLocation.get(),a=typeof t.types==`function`?t.types($n(r,i)):t.types;if(a===!1)return e();n={update:e,types:a}}else n=e;return document.startViewTransition(n).updateCallbackDone}return e()},this.invalidate=e=>{let t=this._committed,n=e?.filter,r=this._preloads,i=new Set,a=e=>{(!n||n(e))&&i.add(e.id)};t.forEach(a),this._cache.forEach(a),r?.forEach(e=>e.forEach(a)),this._tx?.[3].forEach(a);let o=[];for(let[e,t]of r??[])t.some(e=>i.has(e.id))&&(r.delete(e),o.push(e));let s=t=>{if(i.has(t.id)){let n=this.routesById[t.routeId],r={...t,invalid:!0,...(e?.forcePending||t.status===`error`||t.status===`notFound`)&&Qn(n)?{status:`pending`,error:void 0}:void 0};return t._flight=void 0,r}return t};this._committed=t.map(s);for(let[t,n]of this._cache)i.has(t)&&(n.invalid=!0,e?.forcePending&&(n.status=`pending`));for(let e of i)this._flights?.delete(e);for(let e of o)e.abort();return this.shouldViewTransition=!1,this.load({sync:e?.sync})},this.resolveRedirect=e=>{let t=e.options,n=e.headers.get(`Location`)||t.href;if(!n){let e=this.buildLocation(t);n=(e.maskedLocation??e).publicHref||`/`}let r;if(Tt.test(n)||(r=wt(n))&&!this.protocolAllowlist.has(r))throw Error(`Redirect blocked: unsafe protocol`);if(r===`http:`||r===`https:`){let e=new URL(n);e.pathname.startsWith(`//`)?n=e.href:Xn(e,this.origin)||(n=Zn(e),r=void 0)}return r&&(t.reloadDocument=!0),t.href=n,e.headers.set(`Location`,n),e},this.clearCache=e=>{let t=this._cache,n=this._preloads,r=e?.filter,i=[],a=[];for(let[e,n]of t)(!r||r(n))&&(a.push(e),i.push(n));let o=[];for(let[e,t]of n??[])(!r||t.some(r))&&(o.push(e),i.push(...t));for(let e of a)t.delete(e);for(let e of o)n.delete(e);for(let e of i){let t=e._flight;e._flight=void 0,t&&!--t[2]&&(this._flights?.get(e.id)===t&&this._flights.delete(e.id),o.push(t[1]))}for(let e of o)e.abort()},this.loadRouteChunk=_r,this.preloadRoute=e=>ai(this,e),this.matchRoute=(e,t)=>{let n={...e,to:e.to?It(e.from||``,e.to,this.options.trailingSlash,this.resolvePathCache):void 0,params:e.params||{},leaveParams:!0},r=this.buildLocation(n),i=this.stores.status.get()===`pending`;if(t?.pending&&!i)return!1;let a=t?.pending??!i?this.latestLocation:this.stores.resolvedLocation.get()||this.stores.location.get(),o=Cn(r.pathname,t?.caseSensitive??!1,t?.fuzzy??!1,a.pathname,this.processedTree);return!o||e.params&&!vt(o.rawParams,e.params,!0)?!1:t?.includeSearch??!0?vt(a.search,r.search,!0)?o.rawParams:!1:o.rawParams},this.getStoreConfig=t,e.pathParamsAllowedCharacters?.length&&(this.pathParamsDecoder=Lt(e.pathParamsAllowedCharacters)),this.update({defaultPreloadDelay:50,defaultPendingMs:1e3,defaultPendingMinMs:500,context:void 0,...e,caseSensitive:e.caseSensitive??!1,notFoundMode:e.notFoundMode??`fuzzy`,stringifySearch:e.stringifySearch??sn,parseSearch:e.parseSearch??on,protocolAllowlist:e.protocolAllowlist??Ct}),self.__TSR_ROUTER__=this}isShell(){return!!this.options.isShell}get state(){return this.stores.__store.get()}setRoutes(e){Object.assign(this,e),this.lightweightCache=new WeakMap,this.staticLocations=new WeakMap;let t=this.options.notFoundRoute;t&&(t.init(99999999999),this.routesById[t.id]!==t&&(t._interpolation=vn(!1,t,0)),this.routesById[t.id]=t)}matchRoutesInternal(e,t){let[n,r,i]=this.getMatchedRoutes(e.pathname),a=n,o=!1;(i?i.path!==`/`&&r[`**`]:Nt(e.pathname))&&(this.options.notFoundRoute?a=[...a,this.options.notFoundRoute]:o=!0);let s=o?pr(this.options.notFoundMode,a):void 0,c=Array(a.length),l=this._committed,u=(e,t)=>{let n=l[t];return n?.routeId===e.id?n:e===this.options.notFoundRoute?l.find(t=>t.routeId===e.id):void 0},d;for(let n=0;ntypeof t!=`string`&&!ft.call(e,t[1]))}var ur=Object.freeze({});function dr(e,t){let n=[];for(let r=0;r{let n=t(i.preSearchFilters?i.preSearchFilters.reduce((e,t)=>t(e),e):e);return i.postSearchFilters?i.postSearchFilters.reduce((e,t)=>t(e),n):n});let a=i.validateSearch;t&&a&&n.push(({search:e,next:t,meta:n})=>{let r=t(e);try{let e=sr(a,r);if(n&&e)for(let t in e)t in r||(n.defaulted||=new Map).set(t,e[t]);return{...r,...e}}catch{}return r})}return n}function fr(e,t,n){let r=(t,i,a)=>{if(t>=e.length){if(!n.search)return{};if(n.search===!0)return i;let e=dt(n.search,i);return a&&(a.explicit=e),e}return e[t]({search:i,next:(e,n)=>{if(n){let n=a||{};return{search:r(t+1,e,n),meta:n}}return r(t+1,e,a)},meta:a})};return r(0,t)}function pr(e,t){if(e!==`root`){let e;for(let n=t.length-1;n>=0;n--){let r=t[n];if(r.options.notFoundComponent)return r.id;e||=r.children&&r.id}if(e)return e}return un}function mr(e,t){let n=e.options.params?.parse??e.options.parseParams;n&&Object.assign(t,n(t))}function hr(e,t){return e.options[t]?.preload?.()}function gr(e,t){let n=hr(e,`component`),r=hr(e,`pendingComponent`);return t&&(r?r=r.then(t):t()),n&&r?Promise.all([n,r]).then(()=>{}):n??r}function _r(e,t,n){let r=()=>t===!1?void 0:t?hr(e,t):gr(e,n),i=e._lazy;if(i)return i===!0?r():i.then(r);if(!e.lazyFn)return r();let a=e.lazyFn().then(t=>{{let{id:n,...r}=t.options;Object.assign(e.options,r),e._lazy=!0}},t=>{throw e._lazy=void 0,t});return e._lazy=a,a.then(r)}function vr(e){let t=e.findIndex(e=>e.status!==`success`||e._notFound)+1;return t&&t{let i=()=>r(t);t.addEventListener(`abort`,i,{once:!0}),Promise.resolve(e).then(n,r).then(()=>t.removeEventListener(`abort`,i))})}function Er(e,t){return e.routesById[t.routeId]}function Dr(e,t,n){return fn(e)?[Sr,e]:Vt(e)?(e.routeId||=n,[xr,e]):t?(typeof e?.then==`function`&&(e=Error(`A Promise was thrown`,{cause:e})),[br,e]):[yr,e]}function Or(e,t){let n=Dr(t,!0,e.id);if(n[0]!==br)return n;try{e.options.onError?.(n[1])}catch(t){n=Dr(t,!0,e.id)}return n}function kr(e,t,n,r,i){return i[0].signal.aborted?Cr:Gr(e,t,n,Or(n,r),i)}async function Ar(e,t,n,r,i,a){let[o,s]=t,c=n[0].signal,l=!!n[3];for(let i=n[6]??0;ie.navigate({...t,_fromLocation:o}),buildLocation:e.buildLocation,cause:l?`preload`:r.cause,abortController:n[0],preload:l,matches:s,routeId:u.id};try{let e=r._ctx||=u.options.context?u.options.context({...f,deps:r.loaderDeps,context:d})||{}:void 0;r.context={...d,...e}}catch(a){return Mr(e,r),[i,kr(e,t,u,a,n)]}if(c.aborted)return[i,Cr];let p=r.paramsError??r.searchError;if(p!==void 0)return Mr(e,r),[i,kr(e,t,u,p,n)];let m=u.options.beforeLoad;if(!m)continue;let h=r.status;i>=a&&(r.status=`pending`,n[7]?.());try{Fr(e,r,`beforeLoad`,n[0]);let a=m({...f,search:r.search,context:r.context,...e.options.additionalContext}),o=await(typeof a?.then==`function`?Tr(a,c):a);if(c.aborted)return[i,Cr];let s=Gr(e,t,u,Dr(o,!1,u.id),n);if(s[0]!==yr)return Mr(e,r),[i,s];r.context={...r.context,...o}}catch(a){return Mr(e,r),[i,kr(e,t,u,a,n)]}finally{r.status=h,Fr(e,r,!1,n[0])}}i()}function jr(e,t,n){if(!(!n||--n[2])){if(e._flights?.get(t.id)===n){let n=e._tx;if(n&&!n[0].signal.aborted&&!n[3].includes(t)&&n[3].some(e=>e.id===t.id)&&n[3].some(e=>e.isFetching===`beforeLoad`))return;e._flights.delete(t.id)}return n[1]}}function Mr(e,t){let n=t._flight;t._flight=void 0,jr(e,t,n)?.abort()}function Nr(e,t,n,r){let i=[];for(let a of t)if(!n?.includes(a)){let t=a._flight;if(a._flight=void 0,r&&t?.[2]===1&&e._flights?.get(a.id)===t&&n?.some(e=>e.id===a.id))t[2]=0;else{let n=jr(e,a,t);n&&i.push(n)}}for(let e of i)e.abort()}function Pr(e){for(let t of e){let e=t._flight;e&&e[2]++}}function Fr(e,t,n,r){if(t.isFetching=n,r&&e._tx?.[0]!==r)return;let i=e.stores.byRoute.get(t.routeId),a=i?.get();a?.id===t.id&&i.set({...a,isFetching:n})}function Ir(e,t,n,r,i,a,o){let s=t[0];return{params:n.params,location:s,navigate:t=>e.navigate({...t,_fromLocation:s}),cause:o?`preload`:n.cause,abortController:i,preload:o,deps:n.loaderDeps,parentMatchPromise:a,context:n.context,route:r,...e.options.additionalContext}}async function Lr(e,t,n,r,i,a,o){let s=o[0],c=s.signal;if(c.aborted)return Cr;if(!i)return[yr,void 0];let l=n._flight;Fr(e,n,`loader`,s);try{if(!l){let s=new AbortController;l=[Promise.resolve().then(()=>i(Ir(e,t,n,r,s,a,!!o[3]))).then(e=>Dr(e,!1,r.id),e=>Dr(e,!0,r.id)).then(t=>(t[0]!==yr&&e._flights?.get(n.id)===l&&(e._flights.delete(n.id),l[2]||s.abort()),t[0]===br&&l[2]?Or(r,t[1]):t)),s,1],(e._flights??=new Map).set(n.id,l)}return n._flight=l,n.abortController=l[1],Gr(e,t,r,await Tr(l[0],c),o)}catch(t){if(t!==c||!c.aborted)throw t;return Mr(e,n),Cr}finally{Fr(e,n,!1,s)}}function Rr(e,t,n){t[0]!==Sr&&(e.status=`success`,e.error=void 0,t[0]===yr?(e.loaderData=t[1],e.invalid=!1,e.updatedAt=Date.now(),e.preload=n):e.invalid=!0)}function zr(e,t,n){let r=e._cache.get(t.id);if(r!==n||e._committed.some(e=>e.id===t.id&&e._flight===t._flight))return;let i={...t,_notFound:void 0,context:{}};i._flight&&i._flight[2]++,e._cache.set(t.id,i),r&&Mr(e,r)}function Br(e,t){return t[0]===br||t[0]===xr?{...e,status:t[0]===br?`error`:`notFound`,error:t[1],_flight:void 0}:e}function Vr(e,t,n,r,i,a,o){let s=t[1][n],c=Er(e,s),l=!!a[3],u=e._cache.get(s.id),d,f=!1,p;try{if(s.status===`success`&&(d=c.options.shouldReload,typeof d==`function`&&(d=d(Ir(e,t,s,c,a[0],i,l))),a[0].signal.aborted&&(p=Cr)),!p){if(s.status!==`success`)f=!0;else{let t=l||s.preload?c.options.preloadStaleTime??e.options.defaultPreloadStaleTime??3e4:c.options.staleTime??e.options.defaultStaleTime??0;f=!!(s.invalid||d||d===void 0&&Date.now()-s.updatedAt>=t&&(a[5]||s.cause===`enter`||a[2].some(e=>e.routeId===s.routeId&&e.id!==s.id)))}}}catch(n){s.invalid=!0,Mr(e,s),p=kr(e,t,c,n,a)}let m=c.options.loader,h=typeof m==`function`,g=h?m:m?.handler,_=!l||c.options.preload!==!1,v=_&&m?e._flights?.get(s.id):void 0;v===s._flight||p?v=void 0:v&&!f&&!l&&d===void 0?f=!0:f||(v=void 0);let y=!(!m||!f||s.status!==`success`||l||a[4]||((h?void 0:m.staleReloadMode)??e.options.defaultStaleReloadMode)===`blocking`),b=f&&_,x=b&&!y&&(s.status!==`success`||!!m),S=n>=o?a[7]:void 0,C=c.lazyFn&&c._lazy!==!0?S:void 0;if(b&&!m&&(s.invalid=!1,s.updatedAt=Date.now()),v&&v[2]++,x){let t=s._flight;s._flight=v,jr(e,s,t)?.abort(),n>=o&&(s.status=`pending`),S?.()}b||(s.isFetching=!1);let w=!p&&x?Lr(e,t,s,c,g,i,a).then(t=>(Rr(s,t,l),t[0]===yr&&(m&&!a[0].signal.aborted&&zr(e,s,u),n>=o&&(s.status=`pending`)),t)):Promise.resolve(p??[yr,s.loaderData]),T=(async()=>{try{let e=_r(c,void 0,C);e&&await Tr(e,a[0].signal)}catch(r){if(!t[1].some((e,t)=>t<=n&&(e.status===`error`||e.status===`notFound`||e._notFound)))return[n,kr(e,t,c,r,a)]}let r=await w;x&&r[0]===yr&&s.status===`pending`&&!a[0].signal.aborted&&(s.status=`success`,S?.())})();if(r.push([n,w,T]),!y)return w.then(e=>Br(s,e));let ee={...s,status:`pending`,preload:!1,_flight:v};s.invalid=!1,s.isFetching=`loader`;let E=Lr(e,t,ee,c,g,i,a).then(e=>(s.isFetching=!1,Rr(ee,e,!1),e));return(t[2]??=[]).push([n,E,T,ee]),E.then(e=>Br(ee,e))}async function Hr(e,t,n,r,i=0){let a=n?.[1][1],o=a?.routeId?t.findIndex(e=>e.routeId===a.routeId):n?.[0]??t.length-1;o<0&&(o=0);for(let n=o;n>=0;n--){let i=Er(e,t[n]);try{let e=_r(i,!1);e&&await Tr(e,r)}catch(e){if(e===r&&r.aborted)throw e}if(i.options.notFoundComponent)return n}return a?.routeId?o:i}function Ur(e,t){t[2]&&=(Nr(e,t[2].map(e=>e[3])),void 0)}async function Wr(e,t,n,r){let i;try{await Promise.all(e.map(e=>e[1].then(async t=>{let a=e[0];if(!(r&&a>=await r)){if(t[0]>=Sr)throw[a,t];!i&&t[0]!==yr&&(i=[a,t],await Promise.all((n??[]).map(e=>{if(!(e[0]<=a))return e[1].then(t=>{if(t[0]===Sr)throw[e[0],t]})})))}})))}catch(e){return e}return t??i}function Gr(e,t,n,r,i,a){for(;r[0]===Sr;){let o=r[1],s=o.options;try{if((s.href||o.headers.has(`Location`))&&(e.resolveRedirect(o),s.reloadDocument)||(s.reloadDocument?i[3]:i[1]>=20))return r;let n=e.buildLocation({...s,_fromLocation:t[0],_includeValidateSearch:!0}),a=n.maskedLocation??n;if(a.external){let t=o.clone();return t.options={...s},t.headers.set(`Location`,a.publicHref),e.resolveRedirect(t),i[3]?[Sr,t]:[Sr,t,a]}return[Sr,o,n]}catch(e){r=a?[br,e]:Or(n,e),a=!0}}return r}async function Kr(e,t,n,r,i,a){let o=t[1],s=await i,c=!1,l=o.findIndex(e=>e._notFound),u=t=>t[1][0]===xr?Hr(e,o,t,r.signal):t[0],d=l<0?o.length:l;if((s?.[1][0]??0)>=Sr)d=0;else if(s){d=s[2]??=await u(s);for(let e of n){if(e[0]>=d)break;let t=await e[1];if(t[0]!==yr&&t[0]=d)break;let t=await e[2];if(t){s=t;break}}if((s?.[1][0]??0)>=Sr){let n=s[1];if(n[0]!==Sr||n[1].options.reloadDocument||n[2])return Ur(e,t),n;c=!0,s=[0,[br,Error(`Too many redirects`)]]}let f=s?s[2]??await u(s):l;if(f>=0){let i=s?.[1],l=i?.[0],u=o[f],d=i?.[1],p=()=>{i&&(u._notFound=void 0,l===br?u.status=`error`:(d.routeId=u.routeId,u.routeId===e.routeTree.id?(u.status=`success`,u._notFound=!0):u.status=`notFound`),u.error=d,u.isFetching=!1)};p(),i||a?.();let m=Er(e,u);try{await Tr(i?Promise.resolve().then(()=>_r(m,l===br?`errorComponent`:`notFoundComponent`)):Promise.all([_r(m),_r(m,`notFoundComponent`)]),r.signal)}catch(n){if(n===r.signal&&r.signal.aborted)return Ur(e,t),Cr}i?c&&(r.abort(),await Promise.all([...n.map(e=>e[1]),...n.map(e=>e[2]),...(t[2]??[]).map(e=>e[1])]),Ur(e,t),Nr(e,o),p()):u.status=`success`}return t}async function qr(e,t,n,r=0,i=t[1].length){let a=t[1];for(let t=r;te._notFound);if(e.options.notFoundMode!==`root`&&s>=0){let t=await Hr(e,n,void 0,a,s);n[s]._notFound=void 0,n[t]._notFound=!0,s=t}let c=s<0?n.length:s+1,l=0;for(;l{for(let t=d;t=Sr&&(c=0);p()}if(!a.aborted&&!r[3]){let t=[];for(let[n,r]of e._flights??[])r[2]||(e._flights.delete(n),t.push(r[1]));for(let e of t)e.abort()}let h=Kr(e,i,u,r[0],Wr(u,m,i[2]),r[7]);i[2]?.length&&(i[3]=Wr(i[2],void 0,void 0,h.then(e=>wr(e)?0:vr(n).length,()=>0))),o=await h}catch(t){if(Ur(e,i),t===a&&a.aborted)return Cr;throw t}return wr(o)?o:qr(e,o,a,r[6]===n.length?r[6]:0)}function Yr(e,t){if(e._tx!==t)return;let n=t[3],r=e.stores.matches.get(),i=e._pending;for(let a=0;a0){i[3]=setTimeout(()=>Yr(e,t),n);return}i[2]=0}let m=n.map(e=>({...e,_flight:void 0}));m[a].status=`pending`;let h=i[4]=e.startTransition(()=>e.stores.setMatches(m),m).then(t=>(t&&e._pending===i&&i[4]===h&&!i[2]&&(i[2]=Date.now()+f),t));return}}function Xr(e,t){let n=e._pending;(e._tx===t||!e._tx?.[3].some(e=>e.id===n?.[1]))&&(clearTimeout(n?.[3]),e._pending=void 0)}async function Zr(e,t){let n=e._pending;if(!n)return;clearTimeout(n[3]);let r=n[2]-Date.now();if(!n[4]||r<=0||!vr(t[3]).some(e=>e.id===n[1]))return;let i;try{await Tr(new Promise(e=>{i=setTimeout(e,r)}),t[0].signal)}catch{}clearTimeout(i)}function Qr(e,t){e._committed=t,e.stores.setMatches(t)}function $r(e,t,n,r){let i=e._committed,a=e._lifecycleEnd,o=e._cache;for(let e of n)e.preload=!1,r&&(e._assetEnd=void 0);let s=vr(n).length,c=new Map;{let t=Date.now(),r=new Set;for(let e=0;e=(n.preload?i.options.preloadGcTime??e.options.defaultPreloadGcTime??3e5:i.options.gcTime??e.options.defaultGcTime??3e5)||c.set(n.id,o.get(n.id)===n?n:{...n,_flight:void 0,isFetching:!1,context:{}})}}t[3]=[],e._cache=c;let l=e._lifecycleEnd=tr(n);Qr(e,n),Nr(e,[...o.values(),...i].filter(e=>e._flight&&c.get(e.id)!==e),n),nr(e,i,n,a,l,t)}async function ei(e,t){let n=e._tx;for(;n&&n!==t;)t=n,await n[5],n=e._tx}function ti(e,t,n){let r=n[1].options,i=n[2];if(!i)return e.navigate({...r,replace:!0,ignoreBlocker:!0});if(r.reloadDocument)return e.navigate({href:(i.maskedLocation??i).publicHref,reloadDocument:!0,replace:!0,ignoreBlocker:!0});i._redirects=t[1]+1,e._pendingLocation=i;let a=e.commitLocation({...i,viewTransition:r.viewTransition,replace:!0,resetScroll:r.resetScroll,hashScrollIntoView:r.hashScrollIntoView,ignoreBlocker:!0});return queueMicrotask(()=>{e._pendingLocation===i&&(e._pendingLocation=void 0)}),a}async function ni(e,t,n,r,i){let a=n.map(e=>({...e}));Pr(a);for(let t of r)Mr(e,a[t[0]]),a[t[0]]=t[3];let o=[t[2],a],s;try{s=await Kr(e,o,r,t[0],i)}catch(t){throw Nr(e,a),t}if(wr(s)){Nr(e,a),s[0]===Sr&&e._tx===t&&e._committed===n&&await ti(e,t,s);return}if(await qr(e,s,t[0].signal),e._tx!==t||e._committed!==n){Nr(e,a);return}for(let t of a){let n=e._cache.get(t.id);n?._flight&&n._flight===t._flight&&(e._cache.delete(t.id),Mr(e,n))}Qr(e,a),Nr(e,n,a)}async function ri(e,t,n,r,i,a){let o=await Jr(e,t[2],t[3],[t[0],t[1],e._committed,void 0,i,n,a,r]);if(wr(o)){let n=o[0]===Sr&&e._tx===t;if((!n||o[1].options.reloadDocument)&&Xr(e,t),Nr(e,t[3]),t[3]=[],!n)return;if(e._tx!==t){Xr(e,t);return}await ti(e,t,o);return}let s=o[1];if(e._tx===t&&await Zr(e,t),e._tx!==t){Xr(e,t),Nr(e,s),Ur(e,o);return}let c=t[2],l=$n(c,e.stores.resolvedLocation.get()),u=o[2];await e.startViewTransition(async()=>{if(e._tx===t&&await Zr(e,t),e._tx!==t){Xr(e,t),Nr(e,s),Ur(e,o);return}let n=await e.startTransition(()=>{Xr(e,t),$r(e,t,s,a),e._tx===t&&(e.emit({type:`onLoad`,...l}),e._tx===t&&e.emit({type:`onBeforeRouteMount`,...l}))},s);if(e._tx!==t){Ur(e,o);return}u?.length&&ni(e,t,s,u,o[3]).catch(console.error),e.batch(()=>{e.stores.resolvedLocation.set(c),e.stores.status.set(`idle`),e._tx===t&&e.emit({type:`onResolved`,...l}),n&&e._tx===t&&e.emit({type:`onRendered`,...l})}),e._tx===t&&(e._commitPromise?.resolve(),e._commitPromise=void 0)})}async function ii(e,t){let n=e._tx,r=e.stores.resolvedLocation.get(),i=r??e.stores.location.get(),a=e.latestLocation,o=e._pendingLocation,s=o?.href===a.href?o._redirects??0:0,c=e._handoff,l=c?.[0](),u=new AbortController,d=e._preflight;if(e._preflight=u,l||c?.[1](),d?.abort(),!u.signal.aborted){let t=$n(a,r);e.emit({type:`onBeforeNavigate`,...t}),u.signal.aborted||e.emit({type:`onBeforeLoad`,...t})}if(u.signal.aborted){await ei(e,n);return}let f=i.href===a.href,p=u,m=e.matchRoutes(a,{_controller:u});Pr(m);let h=l?c[1](m):void 0;if(h?p=l:l?.abort(),u.signal.aborted){Nr(e,m),await ei(e,n);return}e._preflight=void 0;let g,_=()=>ri(e,y,f,()=>Yr(e,y),t?.sync,h),v=t?.sync?new Promise(e=>g=e):Promise.resolve().then(_),y=[p,s,a,m,Date.now(),v.then(()=>ei(e,y))];if(e._tx=y,n){for(let t of e.stores.matches.get()){if(e._tx!==y)break;t.isFetching&&Fr(e,t,!1)}n[0].abort(),Nr(e,n[3],y[3],!0)}if(e._tx!==y){Nr(e,y[3]),y[3]=[],g?.(),await ei(e,y);return}e.batch(()=>{e.stores.status.set(`pending`),e.stores.location.set(a)}),(h||!e._committed.length&&m[0]?.status!==`success`&&!m.some(e=>e._notFound))&&Yr(e,y),g?.(_()),await y[5]}async function ai(e,t){let n=e.buildLocation(t);for(let t=0;;t++){let r=e._committed,i=new AbortController,a,o,s;try{try{a=e.matchRoutes(n,{_controller:i}),Pr(a),o=(e._preloads??=new Map).set(i,a),s=await Jr(e,n,a,[i,t,r,!0])}finally{o&&(o=o.delete(i),Nr(e,a)),i.abort()}if(!wr(s))return s[1];if(!o||s.length<3)return;n=s[2]}catch(e){Vt(e)||console.error(e);return}}}var oi=`Error preloading route! ☝️`,si=class{get to(){return this._to}get id(){return this._id}get path(){return this._path}get fullPath(){return this._fullPath}constructor(e){if(this.init=e=>{this.originalIndex=e,this._branch=void 0;let t=this.options,n=!t?.path&&!t?.id;this.parentRoute=this.options.getParentRoute?.(),n?this._path=un:this.parentRoute||At();let r=n?un:t?.path;r&&r!==`/`&&(r=Mt(r));let i=t?.id||r,a=n?un:jt((this.parentRoute.id===`__root__`?``:this.parentRoute.id)+`/`+(i??``));r===`__root__`&&(r=`/`);let o=a===`__root__`?`/`:r===void 0?this.parentRoute.fullPath:jt(this.parentRoute.fullPath+`/`+r);this._path=r,this._id=a,this._fullPath=o,this._to=Nt(o)},this.addChildren=e=>this._addFileChildren(e),this._addFileChildren=e=>(Array.isArray(e)&&(this.children=e),typeof e==`object`&&e&&(this.children=Object.values(e)),this),this._addFileTypes=()=>this,this.updateLoader=e=>(Object.assign(this.options,e),this),this.update=e=>(Object.assign(this.options,e),this),this.lazy=e=>(this.lazyFn=e,this),this.redirect=e=>dn({from:this.fullPath,...e}),this.options=e||{},this.isRoot=!e?.getParentRoute,e?.id&&e?.path)throw Error(`Route cannot have both an 'id' and a 'path' option.`)}},ci=class extends si{constructor(e){super(e)}},li=class extends m.Component{constructor(...e){super(...e),this.state={error:0},this.reset=()=>{this.setState({error:0})}}static getDerivedStateFromProps(e,t){let n=e.getResetKey();return t.error&&t.resetKey!==n?{resetKey:n,error:0}:{resetKey:n}}static getDerivedStateFromError(e){return{error:[e]}}componentDidCatch(e,t){this.props.onCatch?.(e,t)}render(){let e=this.state.error;return e?m.createElement(this.props.errorComponent??ui,{error:e[0],reset:this.reset}):this.props.children}};function ui({error:e}){let[t,n]=m.useState(!1);return(0,h.jsxs)(`div`,{style:{padding:`.5rem`,maxWidth:`100%`},children:[(0,h.jsxs)(`div`,{style:{display:`flex`,alignItems:`center`,gap:`.5rem`},children:[(0,h.jsx)(`strong`,{style:{fontSize:`1rem`},children:`Something went wrong!`}),(0,h.jsx)(`button`,{style:{appearance:`none`,fontSize:`.6em`,border:`1px solid currentColor`,padding:`.1rem .2rem`,fontWeight:`bold`,borderRadius:`.25rem`},onClick:()=>n(e=>!e),children:t?`Hide Error`:`Show Error`})]}),(0,h.jsx)(`div`,{style:{height:`.25rem`}}),t?(0,h.jsx)(`div`,{children:(0,h.jsx)(`pre`,{style:{fontSize:`.7em`,border:`1px solid red`,borderRadius:`.25rem`,padding:`.3rem`,color:`red`,overflow:`auto`},children:e?.message?(0,h.jsx)(`code`,{children:e.message}):null})}):null]})}var di=()=>!0,fi=()=>!1;function pi({children:e,fallback:t=null}){return(0,h.jsx)(m.Fragment,{children:mi()?e:t})}function mi(e=!0){return m.useSyncExternalStore(hi,di,e?fi:di)}function hi(){return()=>{}}var gi=m.createContext(null);function _i(e){return m.useContext(gi)}var vi=m.createContext(void 0),yi=m.createContext(void 0);function bi({update:e,notify:t,unwatched:n}){return{link:r,unlink:i,propagate:a,checkDirty:o,shallowPropagate:s};function r(e,t,n){let r=t.depsTail;if(r!==void 0&&r.dep===e)return;let i=r===void 0?t.deps:r.nextDep;if(i!==void 0&&i.dep===e){i.version=n,t.depsTail=i;return}let a=e.subsTail;if(a!==void 0&&a.version===n&&a.sub===t)return;let o=t.depsTail=e.subsTail={version:n,dep:e,sub:t,prevDep:r,nextDep:i,prevSub:a,nextSub:void 0};i!==void 0&&(i.prevDep=o),r===void 0?t.deps=o:r.nextDep=o,a===void 0?e.subs=o:a.nextSub=o}function i(e,t=e.sub){let r=e.dep,i=e.prevDep,a=e.nextDep,o=e.nextSub,s=e.prevSub;return a===void 0?t.depsTail=i:a.prevDep=i,i===void 0?t.deps=a:i.nextDep=a,o===void 0?r.subsTail=s:o.prevSub=s,s===void 0?(r.subs=o)===void 0&&n(r):s.nextSub=o,a}function a(e){let n=e.nextSub,r;top:do{let i=e.sub,a=i.flags;if(a&60?a&12?a&4?!(a&48)&&c(e,i)?(i.flags=a|40,a&=1):a=0:i.flags=a&-9|32:a=0:i.flags=a|32,a&2&&t(i),a&1){let t=i.subs;if(t!==void 0){let i=(e=t).nextSub;i!==void 0&&(r={value:n,prev:r},n=i);continue}}if((e=n)!==void 0){n=e.nextSub;continue}for(;r!==void 0;)if(e=r.value,r=r.prev,e!==void 0){n=e.nextSub;continue top}break}while(1)}function o(t,n){let r,i=0,a=!1;top:do{let o=t.dep,c=o.flags;if(n.flags&16)a=!0;else if((c&17)==17){if(e(o)){let e=o.subs;e.nextSub!==void 0&&s(e),a=!0}}else if((c&33)==33){(t.nextSub!==void 0||t.prevSub!==void 0)&&(r={value:t,prev:r}),t=o.deps,n=o,++i;continue}if(!a){let e=t.nextDep;if(e!==void 0){t=e;continue}}for(;i--;){let i=n.subs,o=i.nextSub!==void 0;if(o?(t=r.value,r=r.prev):t=i,a){if(e(n)){o&&s(i),n=t.sub;continue}a=!1}else n.flags&=-33;n=t.sub;let c=t.nextDep;if(c!==void 0){t=c;continue top}}return a}while(1)}function s(e){do{let n=e.sub,r=n.flags;(r&48)==32&&(n.flags=r|16,(r&6)==2&&t(n))}while((e=e.nextSub)!==void 0)}function c(e,t){let n=t.depsTail;for(;n!==void 0;){if(n===e)return!0;n=n.prevDep}return!1}}function xi(e,t,n){let r=typeof e==`object`,i=r?e:void 0;return{next:(r?e.next:e)?.bind(i),error:(r?e.error:t)?.bind(i),complete:(r?e.complete:n)?.bind(i)}}var Si=[],Ci=0,{link:wi,unlink:Ti,propagate:Ei,checkDirty:Di,shallowPropagate:Oi}=bi({update(e){return e._update()},notify(e){Si[Ai++]=e,e.flags&=-3},unwatched(e){e.depsTail!==void 0&&(e.depsTail=void 0,e.flags=17,Pi(e))}}),ki=0,Ai=0,ji,Mi=0;function Ni(e){try{++Mi,e()}finally{--Mi||Fi()}}function Pi(e){let t=e.depsTail,n=t===void 0?e.deps:t.nextDep;for(;n!==void 0;)n=Ti(n,e)}function Fi(){if(!(Mi>0)){for(;ki{i.get(),n.current?t.next?.(i._snapshot):n.current=!0});return{unsubscribe:()=>{r.stop()}}},_update(e){let a=ji,o=t?.compare??Object.is;if(n)ji=i,++Ci,i.depsTail=void 0;else if(e===void 0)return!1;n&&(i.flags=5);try{let t=i._snapshot,a=typeof e==`function`?e(t):e===void 0&&n?r(t):e;return t===void 0||!o(t,a)?(i._snapshot=a,!0):!1}finally{ji=a,n&&(i.flags&=-5),Pi(i)}}};return n?(i.flags=17,i.get=function(){let e=i.flags;if(e&16||e&32&&Di(i.deps,i)){if(i._update()){let e=i.subs;e!==void 0&&Oi(e)}}else e&32&&(i.flags=e&-33);return ji!==void 0&&wi(i,ji,Ci),i._snapshot}):i.set=function(e){if(i._update(e)){let e=i.subs;e!==void 0&&(Ei(e),Oi(e),Fi())}},i}function Li(e){let t=()=>{let t=ji;ji=n,++Ci,n.depsTail=void 0,n.flags=6;try{return e()}finally{ji=t,n.flags&=-5,Pi(n)}},n={deps:void 0,depsTail:void 0,subs:void 0,subsTail:void 0,flags:6,notify(){let e=this.flags;e&16||e&32&&Di(this.deps,this)?t():this.flags=2},stop(){this.flags=0,this.depsTail=void 0,Pi(this)}};return t(),n}var Ri=n((e=>{var t=l();function n(e,t){return e===t&&(e!==0||1/e==1/t)||e!==e&&t!==t}var r=typeof Object.is==`function`?Object.is:n,i=t.useState,a=t.useEffect,o=t.useLayoutEffect,s=t.useDebugValue;function c(e,t){var n=t(),r=i({inst:{value:n,getSnapshot:t}}),c=r[0].inst,l=r[1];return o(function(){c.value=n,c.getSnapshot=t,u(c)&&l({inst:c})},[e,n,t]),a(function(){return u(c)&&l({inst:c}),e(function(){u(c)&&l({inst:c})})},[e]),s(n),n}function u(e){var t=e.getSnapshot;e=e.value;try{var n=t();return!r(e,n)}catch{return!0}}function d(e,t){return t()}var f=typeof window>`u`||window.document===void 0||window.document.createElement===void 0?d:c;e.useSyncExternalStore=t.useSyncExternalStore===void 0?f:t.useSyncExternalStore})),zi=n(((e,t)=>{t.exports=Ri()})),Bi=n((e=>{var t=l(),n=zi();function r(e,t){return e===t&&(e!==0||1/e==1/t)||e!==e&&t!==t}var i=typeof Object.is==`function`?Object.is:r,a=n.useSyncExternalStore,o=t.useRef,s=t.useEffect,c=t.useMemo,u=t.useDebugValue;e.useSyncExternalStoreWithSelector=function(e,t,n,r,l){var d=o(null);if(d.current===null){var f={hasValue:!1,value:null};d.current=f}else f=d.current;d=c(function(){function e(e){if(!a){if(a=!0,o=e,e=r(e),l!==void 0&&f.hasValue){var t=f.value;if(l(t,e))return s=t}return s=e}if(t=s,i(o,e))return t;var n=r(e);return l!==void 0&&l(t,n)?(o=e,t):(o=e,s=n)}var a=!1,o,s,c=n===void 0?null:n;return[function(){return e(t())},c===null?void 0:function(){return e(c())}]},[t,n,r,l]);var p=a(e,d[0],d[1]);return s(function(){f.hasValue=!0,f.value=p},[p]),u(p),p}})),Vi=n(((e,t)=>{t.exports=Bi()}))();function Hi(e,t){return e===t}function Ui(e,t=e=>e,n){let r=n?.compare??Hi,i=(0,m.useCallback)(t=>{let{unsubscribe:n}=e.subscribe(t);return n},[e]),a=(0,m.useCallback)(()=>e.get(),[e]);return(0,Vi.useSyncExternalStoreWithSelector)(i,a,a,t,r)}var Wi={};function Gi(e,t){let n=m.useRef();return r=>{let i=e?.select?e.select(r):r;return e?.structuralSharing??t.options.defaultStructuralSharing?n.current=gt(n.current,i):i}}function Ki(e){let t=_i(),n=m.useContext(e.from?yi:vi),r=e.from??n,i=t.stores.getMatchStore(r),a=Gi(e,t),o=Ui(i,e=>e?a(e):Wi);if(o!==Wi)return o;(e.shouldThrow??!0)&&At()}function qi(e){return Ki({from:e.from,strict:e.strict,structuralSharing:e.structuralSharing,select:t=>e.select?e.select(t.loaderData):t.loaderData})}function Ji(e){let{select:t,...n}=e;return Ki({...n,select:e=>t?t(e.loaderDeps):e.loaderDeps})}function Yi(e){return Ki({from:e.from,shouldThrow:e.shouldThrow,structuralSharing:e.structuralSharing,strict:e.strict,select:t=>{let n=e.strict===!1?t.params:t._strictParams;return e.select?e.select(n):n}})}function Xi(e){return Ki({from:e.from,strict:e.strict,shouldThrow:e.shouldThrow,structuralSharing:e.structuralSharing,select:t=>e.select?e.select(t.search):t.search})}function Zi(e){let t=_i();return m.useCallback(n=>t.navigate({...n,from:n.from??e?.from}),[e?.from,t])}function Qi(e){let t=_i(),n=Zi(),r=m.useRef(null);return lt(()=>{r.current!==e&&(n(e),r.current=e)},[t,e,n]),null}function $i(e){return Ki({...e,select:t=>e.select?e.select(t.context):t.context})}function ea(...e){let t=m.useRef(e),n=t.current;return e.forEach((e,t)=>{vt(n[t],e,!1,!0)||(n[t]=e)}),t.current}function ta(e,t){e.preloadRoute(t).catch(e=>{console.warn(e),console.warn(oi)})}var na={compare:(e,t)=>e[0]===t[0]&&e[1]===t[1]};function ra(e,t){let n=typeof e==`string`&&wt(e);if(n)return t.has(n)?e:null}function ia(e,t,n,r,i){let a=Ft(e.pathname,r),o=Ft(t.pathname,r);return(n?.exact?a!==o:!a.startsWith(o)||a.length!==o.length&&a[o.length]!==`/`)||(n?.includeSearch??!0)&&!vt(e.search,t.search,!n?.exact,n?.explicitUndefined)?!1:!n?.includeHash||i&&e.hash===t.hash}function aa(e,t,n){let r=_i(),i=m.useRef(null),a=m.useCallback(e=>{if(i.current=e,typeof t==`function`)return t(e);t&&(t.current=e)},[t]),{activeOptions:o,to:s,preload:c,preloadDelay:l,hashScrollIntoView:u,replace:d,startTransition:f,resetScroll:p,viewTransition:h,ignoreBlocker:g,disabled:_,target:v,onClick:y,onBlur:b,onFocus:x,onMouseEnter:S,onMouseLeave:C,onTouchStart:w}=e,T=mi(!!o?.includeHash),[ee,E,te]=ea(e.search,e.params,o),[D,ne]=m.useMemo(()=>[e,{...e}],[r,e.from,e._fromLocation,e.hash,e.to,ee,E,e.state,e.mask,e.unsafeRelative]),re=m.useCallback(e=>{let t=ra(s,r.protocolAllowlist);if(t!==void 0)return[t??void 0];D._fromLocation||(ne._fromLocation=e);let n=r.buildLocation(ne),i=fa(n,r,_);return[i,!_&&(!i||wt(i))?void 0:ia(e,n,te,r.basepath,T)]},[te,_,T,D,ne,r,s]),[ie,ae]=Ui(r.stores.location,re,na),oe=ae===void 0?ie:void 0,se=_||ie===void 0,ce=m.useRef(!1),le=e.reloadDocument||oe||se?!1:c??r.options.defaultPreload,ue=l??r.options.defaultPreloadDelay??0,de=m.useCallback(e=>{let t=e?.isIntersecting;if(!(t??le===`intent`)){t===!1&&P(i);return}if(!ue){ta(r,D);return}N.has(i)||N.set(i,setTimeout(()=>{N.delete(i),ta(r,D)},ue))},[r,D,i,le,ue]);m.useEffect(()=>{le===`render`&&!ce.current&&(ce.current=!0,ta(r,D));let e;return le===`viewport`&&i.current&&typeof IntersectionObserver==`function`&&(e=new IntersectionObserver(e=>de(e.pop()),{rootMargin:`100px`}),e.observe(i.current)),()=>{e?.disconnect(),P(i)}},[r,D,le,de,i]);let fe=la(e,n);if(fe.ref=t?a:i,oe)return fe.href=oe,fe;let pe=e=>{let t=v??e.currentTarget.getAttribute(`target`);!se&&!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&(!t||t===`_self`)&&e.button===0&&(e.preventDefault(),r.navigate({...D,replace:d,resetScroll:p,hashScrollIntoView:u,startTransition:f,viewTransition:h,ignoreBlocker:g}))},me=()=>{le===`intent`&&ta(r,D)},he=()=>{le===`intent`&&P(i)};return fe.onClick=da(y,pe),fe.onBlur=da(b,he),fe.onFocus=da(x,de),fe.onMouseEnter=da(S,de),fe.onMouseLeave=da(C,he),fe.onTouchStart=da(w,me),ua(fe,e,ae,ie,se,n)}var oa={},sa={className:`active`},ca=new Set([`to`,`params`,`search`,`hash`,`state`,`mask`,`from`,`unsafeRelative`,`_fromLocation`,`reloadDocument`,`preload`,`preloadDelay`,`preloadIntentProximity`,`hashScrollIntoView`,`replace`,`startTransition`,`resetScroll`,`viewTransition`,`ignoreBlocker`,`activeProps`,`inactiveProps`,`activeOptions`,`_asChild`]);function la(e,t){let n={};for(let r in e)ca.has(r)||r===`type`&&t!==void 0||r===`disabled`&&t===`a`||(n[r]=e[r]);return n}function ua(e,t,n,r,i,a){let{activeProps:o,inactiveProps:s,className:c,style:l,target:u}=t,d=dt(n?o:s,{})??(n?sa:oa);Object.assign(e,d),e.href=r,a!==`a`&&(e.disabled=i),e.target=u;let f=d.style;(l||f)&&(e.style=l&&f?{...l,...f}:l||f);let p=d.className;return(c||p)&&(e.className=c?p?`${c} ${p}`:c:p),i&&(e.role=`link`,e[`aria-disabled`]=!0),n&&(e[`data-status`]=`active`,e[`aria-current`]=`page`),e}var N=new WeakMap,P=e=>{clearTimeout(N.get(e)),N.delete(e)},da=(e,t)=>e?n=>n.defaultPrevented||(e(n),n.defaultPrevented||t(n)):t;function fa(e,t,n){if(n)return;let r=e.maskedLocation??e,i=r.external?r.publicHref:t.history.createHref(r.publicHref)||`/`;if(!r.external&&i===r.publicHref||!Et(i,t.protocolAllowlist))return i}var pa=m.memo(m.forwardRef((e,t)=>{let n=e._asChild||`a`,r=aa(e,t,n),i=typeof e.children==`function`?e.children({isActive:r[`data-status`]===`active`}):e.children;return m.createElement(n,r,i)}),ma);function ma(e,t){let n=0;for(let r in t)if(n++,e[r]!==t[r]&&(!ca.has(r)||!vt(e[r],t[r],!1,!0)))return!1;for(let t in e)n--;return n===0}var ha=class extends si{constructor(e){super(e),this.useMatch=e=>Ki({...e,from:this.id}),this.useRouteContext=e=>$i({...e,from:this.id}),this.useSearch=e=>Xi({...e,from:this.id}),this.useParams=e=>Yi({...e,from:this.id}),this.useLoaderDeps=e=>Ji({...e,from:this.id}),this.useLoaderData=e=>qi({...e,from:this.id}),this.useNavigate=()=>Zi({from:this.fullPath}),this.Link=m.forwardRef((e,t)=>(0,h.jsx)(pa,{ref:t,from:this.fullPath,...e}))}};function ga(e){return new ha(e)}var _a=class extends ci{constructor(e){super(e),this.useMatch=e=>Ki({...e,from:this.id}),this.useRouteContext=e=>$i({...e,from:this.id}),this.useSearch=e=>Xi({...e,from:this.id}),this.useParams=e=>Yi({...e,from:this.id}),this.useLoaderDeps=e=>Ji({...e,from:this.id}),this.useLoaderData=e=>qi({...e,from:this.id}),this.useNavigate=()=>Zi({from:this.fullPath}),this.Link=m.forwardRef((e,t)=>(0,h.jsx)(pa,{ref:t,from:this.fullPath,...e}))}};function va(e){return new _a(e)}function ya(e,t){let n,r,i,a=()=>(n||=(i=void 0,e().then(e=>{n=void 0,o.preload=void 0,r=e[t??`default`]}).catch(e=>{n=void 0,i=e})),n),o=function(e){if(i){if(yt(i)&&typeof sessionStorage<`u`){let e=`tanstack_router_reload:${i.message}`;if(!sessionStorage.getItem(e))throw sessionStorage.setItem(e,`1`),window.location.reload(),new Promise(()=>{})}throw i}if(!r){if(ct)ct(a());else throw a()}return m.createElement(r,e)};return o.preload=a,o}function ba(e){let t=_i(),n=`not-found-${Ui(t.stores.location,e=>e.pathname)}-${Ui(t.stores.status)}`;return(0,h.jsx)(li,{getResetKey:()=>n,onCatch:(t,n)=>{if(Vt(t))e.onCatch?.(t,n);else throw t},errorComponent:({error:t})=>{if(Vt(t))return e.fallback?.(t);throw t},children:e.children})}function xa(){return(0,h.jsx)(`p`,{children:`Not Found`})}function Sa(e){return(0,h.jsx)(h.Fragment,{children:e.children})}function Ca(e,t,n){return t.options.notFoundComponent?(0,h.jsx)(t.options.notFoundComponent,{...n}):e.options.defaultNotFoundComponent?(0,h.jsx)(e.options.defaultNotFoundComponent,{...n}):(0,h.jsx)(xa,{})}function wa(e,t){let n=t?.options.pendingComponent??e.options.defaultPendingComponent;return n?(0,h.jsx)(n,{}):null}var Ta=(e,t)=>e[0]===t[0]&&e[1]===t[1],Ea=(e,t,n)=>!t.isRoot||t.options.shellComponent||t.options.wrapInSuspense||n===!1||n===`data-only`||!e.ssr,Da=m.memo(function({routeId:e}){let t=_i();return(0,h.jsx)(Oa,{router:t,match:Ui(t.stores.getMatchStore(e))})});function Oa({router:e,match:t}){let n=e.routesById[t.routeId],r=wa(e,n),i=n.options.errorComponent??e.options.defaultErrorComponent,a=n.options.onCatch??e.options.defaultOnCatch,o=n.isRoot?n.options.notFoundComponent??e.options.notFoundRoute?.options.component:n.options.notFoundComponent,s=t.ssr===!1||t.ssr===`data-only`,c=Ea(e,n,t.ssr)&&(n.options.wrapInSuspense??r??(n.options.errorComponent?.preload||s))?m.Suspense:Sa,l=i?li:Sa,u=o?ba:Sa;return(0,h.jsxs)(n.isRoot?n.options.shellComponent??Sa:Sa,{children:[(0,h.jsx)(vi.Provider,{value:t.routeId,children:(0,h.jsx)(c,{fallback:r,children:(0,h.jsx)(l,{getResetKey:()=>t,errorComponent:i,onCatch:(e,n)=>{if(Vt(e))throw e.routeId??=t.routeId,e;a?.(e,n)},children:(0,h.jsx)(u,{fallback:e=>{if(e.routeId??=t.routeId,e.routeId!==t.routeId)throw e;return m.createElement(o,e)},children:s?(0,h.jsx)(pi,{fallback:r,children:(0,h.jsx)(ka,{match:t})}):(0,h.jsx)(ka,{match:t})})})})}),null]})}var ka=m.memo(function({match:e}){let t=_i(),n=e.routeId,r=t.routesById[n],i=m.useMemo(()=>{let i=(r.options.remountDeps??t.options.defaultRemountDeps)?.({routeId:n,loaderDeps:e.loaderDeps,params:e._strictParams,search:e._strictSearch});return i?JSON.stringify(i):void 0},[n,e.loaderDeps,e._strictParams,e._strictSearch,r.options.remountDeps,t.options.defaultRemountDeps]),a=m.useMemo(()=>{let e=r.options.component??t.options.defaultComponent;return e?(0,h.jsx)(e,{},i):(0,h.jsx)(Aa,{})},[i,r.options.component,t.options.defaultComponent]);if(e.status===`pending`){if(t.ssr&&!Ea(t,r,e.ssr))return a;if(t._tx)throw t._tx[5];return wa(t,r)}if(e.status===`notFound`)return Ca(t,r,e.error);if(e.status===`error`)throw e.error;return a}),Aa=m.memo(function(){let e=_i(),t=m.useContext(vi),n,r,i;{let a=e.stores.getMatchStore(t);[n,r]=Ui(a,e=>[!!e._notFound,e.error],{compare:Ta}),i=Ui(e.stores.ids,e=>e[e.indexOf(t)+1])}if(n)return Ca(e,e.routesById[t],r);if(!i)return null;let a=(0,h.jsx)(Da,{routeId:i});return t===`__root__`?(0,h.jsx)(m.Suspense,{fallback:wa(e),children:a}):a});function ja(e,t){let n=e[1];e.length=0,n?.(t)}function Ma({t:e}){let t=_i(),n=t._rendered??=[];return t.startTransition=(r,i)=>new Promise(a=>{ja(n,!1),n.push(i,a),e(t),m.startTransition(r)}),lt(()=>{let e=t.history.subscribe(t.load);t.updateLatestLocation();let r=t.latestLocation,i=t.buildLocation({to:r.pathname,search:!0,params:!0,hash:!0,state:!0,_includeValidateSearch:!0});if(Nt(r.publicHref)!==Nt(i.publicHref))return t.commitLocation({...i,replace:!0,ignoreBlocker:!0}),e;let a=t.stores.resolvedLocation.get();return a?.href===r.href&&a.state.__TSR_key===r.state.__TSR_key?n.push(t.stores.matches.get(),e=>{e&&t.emit({type:`onRendered`,...$n(a,a)})}):t._tx||t.load({sync:!0}).catch(console.error),e},[t,t.history]),null}function Na(){let e=_i(),t=e.routesById[un],n=wa(e,t),r=e.ssr?Sa:m.Suspense,i=(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(Ma,{t:m.useState()[1]}),(0,h.jsx)(r,{fallback:n,children:(0,h.jsx)(Pa,{})})]});return e.options.InnerWrap?(0,h.jsx)(e.options.InnerWrap,{children:i}):i}function Pa(){let e=_i(),t=e._rendered,n=Ui(e.stores.matches,e=>t[0]??e),r=n[0],i=r?.routeId;lt(()=>{t[0]===n&&ja(t,!0)},[t,n]);let a=i?(0,h.jsx)(Da,{routeId:i}):null;return(0,h.jsx)(vi.Provider,{value:i,children:e.options.disableGlobalCatchBoundary?a:(0,h.jsx)(li,{getResetKey:()=>r,onCatch:void 0,children:a})})}var Fa=e=>({createMutableStore:Ii,createReadonlyStore:Ii,batch:Ni}),Ia=e=>new La(e),La=class extends rr{constructor(e){super(e,Fa)}};function Ra({router:e,children:t,...n}){pt(n)&&e.update({...e.options,...n,context:{...e.options.context,...n.context}});let r=(0,h.jsx)(gi.Provider,{value:e,children:t});return e.options.Wrap?(0,h.jsx)(e.options.Wrap,{children:r}):r}function za({router:e,...t}){return(0,h.jsx)(Ra,{router:e,...t,children:(0,h.jsx)(Na,{})})}var Ba=p(),F=s();function Va(e){let t=(0,F.c)(6),{error:n}=e,r;t[0]===Symbol.for(`react.memo_cache_sentinel`)?(r=(0,h.jsx)(`p`,{className:`schild text-lg text-rot`,children:`Diese Ansicht ist abgestürzt`}),t[0]=r):r=t[0];let i=n instanceof Error?n.message:String(n),a;t[1]===i?a=t[2]:(a=(0,h.jsx)(`p`,{className:`text-[15px]`,children:i}),t[1]=i,t[2]=a);let o;t[3]===Symbol.for(`react.memo_cache_sentinel`)?(o=(0,h.jsx)(`button`,{type:`button`,onClick:Ha,className:`schild h-11 rounded-lg border border-rot-rand px-5 text-sm text-foreground hover:bg-[#3a1512]`,children:`Neu laden`}),t[3]=o):o=t[3];let s;return t[4]===a?s=t[5]:(s=(0,h.jsxs)(`div`,{role:`alert`,className:`flex flex-col items-start gap-3 rounded-2xl border border-rot-rand bg-rot-grund p-6 text-rot-text`,children:[r,a,o]}),t[4]=a,t[5]=s),s}function Ha(){return window.location.reload()}var Ua={name:`cpu`,size:24,node:[[`path`,{d:`M12 20v2`,key:`1lh1kg`}],[`path`,{d:`M12 2v2`,key:`tus03m`}],[`path`,{d:`M17 20v2`,key:`1rnc9c`}],[`path`,{d:`M17 2v2`,key:`11trls`}],[`path`,{d:`M2 12h2`,key:`1t8f8n`}],[`path`,{d:`M2 17h2`,key:`7oei6x`}],[`path`,{d:`M2 7h2`,key:`asdhe0`}],[`path`,{d:`M20 12h2`,key:`1q8mjw`}],[`path`,{d:`M20 17h2`,key:`1fpfkl`}],[`path`,{d:`M20 7h2`,key:`1o8tra`}],[`path`,{d:`M7 20v2`,key:`4gnj0m`}],[`path`,{d:`M7 2v2`,key:`1i4yhu`}],[`rect`,{x:`4`,y:`4`,width:`16`,height:`16`,rx:`2`,key:`1vbyd7`}],[`rect`,{x:`8`,y:`8`,width:`8`,height:`8`,rx:`1`,key:`z9xiuo`}]]};Ua.node;var Wa=o(Ua),Ga={name:`ellipsis`,size:24,node:[[`circle`,{cx:`12`,cy:`12`,r:`1`,key:`41hilf`}],[`circle`,{cx:`19`,cy:`12`,r:`1`,key:`1wjl8i`}],[`circle`,{cx:`5`,cy:`12`,r:`1`,key:`1pcz8c`}]],aliases:[`more-horizontal`]};Ga.node;var Ka=o(Ga),qa={name:`external-link`,size:24,node:[[`path`,{d:`M15 3h6v6`,key:`1q9fwt`}],[`path`,{d:`M10 14 21 3`,key:`gplh6r`}],[`path`,{d:`M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6`,key:`a6xqqp`}]]};qa.node;var Ja=o(qa),Ya={name:`house`,size:24,node:[[`path`,{d:`M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8`,key:`5wwlr5`}],[`path`,{d:`M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z`,key:`r6nss1`}]],aliases:[`home`]};Ya.node;var Xa=o(Ya),Za={name:`refresh-cw`,size:24,node:[[`path`,{d:`M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8`,key:`v9h5vc`}],[`path`,{d:`M21 3v5h-5`,key:`1q7to0`}],[`path`,{d:`M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16`,key:`3uifl3`}],[`path`,{d:`M8 16H3v5`,key:`1cv678`}]]};Za.node;var Qa=o(Za),$a={name:`scroll-text`,size:24,node:[[`path`,{d:`M15 12h-5`,key:`r7krc0`}],[`path`,{d:`M15 8h-5`,key:`1khuty`}],[`path`,{d:`M19 17V5a2 2 0 0 0-2-2H4`,key:`zz82l3`}],[`path`,{d:`M8 21h12a2 2 0 0 0 2-2v-1a1 1 0 0 0-1-1H11a1 1 0 0 0-1 1v1a2 2 0 1 1-4 0V5a2 2 0 1 0-4 0v2a1 1 0 0 0 1 1h3`,key:`1ph1d7`}]]};$a.node;var eo=o($a),to={name:`settings`,size:24,node:[[`path`,{d:`M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915`,key:`1i5ecw`}],[`circle`,{cx:`12`,cy:`12`,r:`3`,key:`1v7zrd`}]]};to.node;var no=o(to),ro=`verbinde`,io=null,ao=new Set,oo=()=>ao.forEach(e=>e());function so(e){return ao.add(e),()=>{ao.delete(e)}}var co=()=>ro===`live`,lo=()=>(0,m.useSyncExternalStore)(so,ho),uo=()=>(0,m.useSyncExternalStore)(so,go);function fo(e){io=e,oo()}function po(e){e!==ro&&(ro=e,oo())}function mo(){let e=_();(0,m.useEffect)(()=>{let t=new EventSource(`/api/stream`);return t.onopen=()=>{po(`live`),e.invalidateQueries()},t.onerror=()=>po(`getrennt`),t.addEventListener(`invalidate`,t=>{try{let n=JSON.parse(t.data)?.keys??[];for(let t of n)e.invalidateQueries({queryKey:[t]})}catch{}}),t.addEventListener(`metrik`,e=>{try{fo(JSON.parse(e.data))}catch{}}),()=>{t.close(),po(`getrennt`)}},[e])}function ho(){return ro}function go(){return io}var _o=[],vo=1,yo=new Set,bo=()=>yo.forEach(e=>e());function xo(e,t){let n=vo++;_o=[..._o,{id:n,art:e,text:t}].slice(-4),bo(),e!==`fehler`&&window.setTimeout(()=>So(n),6e3)}function So(e){_o=_o.filter(t=>t.id!==e),bo()}var Co=()=>(0,m.useSyncExternalStore)(wo,To);function wo(e){return yo.add(e),()=>{yo.delete(e)}}function To(){return _o}var Eo={erfolg:`border-gruen-rand bg-gruen-grund text-gruen-text`,fehler:`border-rot-rand bg-rot-grund text-rot-text`,info:`border-cyan-rand bg-cyan-grund text-cyan-text`};function Do(){let e=(0,F.c)(4),t=Co(),n;e[0]===t?n=e[1]:(n=t.map(Oo),e[0]=t,e[1]=n);let r;return e[2]===n?r=e[3]:(r=(0,h.jsx)(`div`,{"aria-live":`polite`,className:`pointer-events-none fixed right-4 bottom-24 left-4 z-50 flex flex-col items-end gap-2 md:bottom-6 md:left-auto md:w-[420px]`,children:n}),e[2]=n,e[3]=r),r}function Oo(t){return(0,h.jsxs)(`div`,{role:t.art===`fehler`?`alert`:`status`,className:i(`pointer-events-auto flex w-full items-start gap-3 rounded-xl border px-4 py-3 text-[15px] shadow-lg`,Eo[t.art]),children:[(0,h.jsx)(`span`,{className:`min-w-0 flex-1`,children:t.text}),(0,h.jsx)(`button`,{type:`button`,onClick:()=>So(t.id),"aria-label":`Meldung schließen`,className:`-m-2 p-2 opacity-70 hover:opacity-100`,children:(0,h.jsx)(e,{className:`size-4`})})]},t.id)}var ko=`modulepreload`,Ao=function(e){return`/`+e},jo={},Mo=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function s(e){return import.meta.resolve?import.meta.resolve(e):new URL(e,import.meta.url).href}r=o(t.map(t=>{if(t=Ao(t,n),t=s(t),t in jo)return;jo[t]=!0;let r=t.endsWith(`.css`);for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}let i=document.createElement(`link`);if(i.rel=r?`stylesheet`:ko,r||(i.as=`script`),i.crossOrigin=``,i.href=t,a&&i.setAttribute(`nonce`,a),document.head.appendChild(i),r)return new Promise((e,n)=>{i.addEventListener(`load`,e),i.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}).filter(e=>e!==void 0))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},No=(0,m.lazy)(()=>Mo(()=>import(`./Dienste-QEbMZv2T.js`).then(e=>({default:e.Dienste})),__vite__mapDeps([0,1,2,3]))),Po=(0,m.lazy)(()=>Mo(()=>import(`./Einstellungen-DMWgWLUo.js`).then(e=>({default:e.Einstellungen})),__vite__mapDeps([4,1,2,3]))),Fo=(0,m.lazy)(()=>Mo(()=>import(`./MehrMenue-gZV9ubEU.js`).then(e=>({default:e.MehrMenue})),__vite__mapDeps([5,1,2,3]))),Io=[{to:`/`,label:`Start`,Icon:Xa},{to:`/updates`,label:`Updates`,Icon:Qa},{to:`/modelle`,label:`Modelle`,Icon:Wa}],Lo=new Intl.DateTimeFormat(`de-DE`,{hour:`2-digit`,minute:`2-digit`,timeZone:`Europe/Berlin`}),Ro=new Intl.DateTimeFormat(`de-DE`,{weekday:`short`,day:`2-digit`,month:`2-digit`,timeZone:`Europe/Berlin`});function zo(){let e=(0,F.c)(13),[t,n]=(0,m.useState)(Bo),r,i;e[0]===Symbol.for(`react.memo_cache_sentinel`)?(r=()=>{let e=window.setInterval(()=>n(new Date),2e4);return()=>window.clearInterval(e)},i=[],e[0]=r,e[1]=i):(r=e[0],i=e[1]),(0,m.useEffect)(r,i);let a;e[2]===t?a=e[3]:(a=Lo.format(t),e[2]=t,e[3]=a);let o;e[4]===a?o=e[5]:(o=(0,h.jsx)(`span`,{className:`ziffern text-2xl font-medium`,children:a}),e[4]=a,e[5]=o);let s;e[6]===t?s=e[7]:(s=Ro.format(t).replace(`,`,``),e[6]=t,e[7]=s);let c;e[8]===s?c=e[9]:(c=(0,h.jsx)(`span`,{className:`schild text-[13px] text-text-3`,children:s}),e[8]=s,e[9]=c);let l;return e[10]!==o||e[11]!==c?(l=(0,h.jsxs)(`div`,{className:`flex flex-col items-end leading-tight`,children:[o,c]}),e[10]=o,e[11]=c,e[12]=l):l=e[12],l}function Bo(){return new Date}function Vo(){let e=(0,F.c)(9),t=lo(),n=t===`live`,r=n?`bg-gruen shadow-[0_0_8px_rgba(61,220,138,0.7)]`:`bg-bernstein`,a;e[0]===r?a=e[1]:(a=i(`size-2 rounded-full`,r),e[0]=r,e[1]=a);let o;e[2]===a?o=e[3]:(o=(0,h.jsx)(`span`,{className:a}),e[2]=a,e[3]=o);let s=n?`Box online`:t===`verbinde`?`Verbinde`:`Getrennt`,c;e[4]===s?c=e[5]:(c=(0,h.jsx)(`span`,{children:s}),e[4]=s,e[5]=c);let l;return e[6]!==o||e[7]!==c?(l=(0,h.jsxs)(`div`,{className:`schild flex items-center gap-2 text-[15px] text-text-3`,"aria-live":`polite`,children:[o,c]}),e[6]=o,e[7]=c,e[8]=l):l=e[8],l}function Ho(){let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t=(0,h.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,h.jsxs)(`svg`,{width:`34`,height:`34`,viewBox:`0 0 34 34`,fill:`none`,"aria-hidden":!0,children:[(0,h.jsx)(`rect`,{x:`1.5`,y:`1.5`,width:`31`,height:`31`,rx:`8`,stroke:`var(--linie-stark)`,strokeWidth:`2`}),(0,h.jsx)(`path`,{d:`M7 18h5l3-7 4 13 3-6h5`,stroke:`var(--bernstein)`,strokeWidth:`2.2`,strokeLinecap:`round`,strokeLinejoin:`round`})]}),(0,h.jsx)(`span`,{className:`font-anzeige text-[28px] leading-none font-bold tracking-[0.06em]`,children:`MC2`}),(0,h.jsx)(`span`,{className:`hidden h-6 w-px bg-linie sm:block`}),(0,h.jsx)(`span`,{className:`schild hidden text-base tracking-[0.22em] text-text-3 sm:block`,children:`Box-Wart`})]}),e[0]=t):t=e[0],t}function Uo(){let e=(0,F.c)(26);mo();let[t,n]=(0,m.useState)(null),r;e[0]===Symbol.for(`react.memo_cache_sentinel`)?(r=()=>n(null),e[0]=r):r=e[0];let i=r,a;e[1]===Symbol.for(`react.memo_cache_sentinel`)?(a=(0,h.jsx)(Ho,{}),e[1]=a):a=e[1];let o;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(o=(0,h.jsx)(`nav`,{"aria-label":`Hauptnavigation`,className:`hidden gap-1 rounded-xl border border-linie bg-[#121518] p-1 md:flex`,children:Io.map(Go)}),e[2]=o):o=e[2];let s;e[3]===Symbol.for(`react.memo_cache_sentinel`)?(s=(0,h.jsx)(`div`,{className:`hidden lg:block`,children:(0,h.jsx)(Vo,{})}),e[3]=s):s=e[3];let c;e[4]===Symbol.for(`react.memo_cache_sentinel`)?(c=(0,h.jsx)(`a`,{href:`/hermes-ui/`,target:`_blank`,rel:`noopener`,className:`flex size-11 items-center justify-center rounded-lg text-text-2 hover:bg-erhaben hover:text-foreground`,title:`Hermes-Dashboard öffnen`,"aria-label":`Hermes-Dashboard öffnen`,children:(0,h.jsx)(Ja,{className:`size-5`})}),e[4]=c):c=e[4];let l;e[5]===Symbol.for(`react.memo_cache_sentinel`)?(l=()=>n(`dienste`),e[5]=l):l=e[5];let u;e[6]===Symbol.for(`react.memo_cache_sentinel`)?(u=(0,h.jsx)(`button`,{type:`button`,onClick:l,className:`flex size-11 items-center justify-center rounded-lg text-text-2 hover:bg-erhaben hover:text-foreground`,title:`Dienste und Protokolle`,"aria-label":`Dienste und Protokolle`,children:(0,h.jsx)(eo,{className:`size-5`})}),e[6]=u):u=e[6];let d;e[7]===Symbol.for(`react.memo_cache_sentinel`)?(d=()=>n(`einstellungen`),e[7]=d):d=e[7];let f;e[8]===Symbol.for(`react.memo_cache_sentinel`)?(f=(0,h.jsxs)(`header`,{className:`flex items-center justify-between gap-4 md:gap-6`,children:[a,o,(0,h.jsxs)(`div`,{className:`flex items-center gap-4 md:gap-5`,children:[s,(0,h.jsxs)(`div`,{className:`hidden items-center gap-1 md:flex`,children:[c,u,(0,h.jsx)(`button`,{type:`button`,onClick:d,className:`flex size-11 items-center justify-center rounded-lg text-text-2 hover:bg-erhaben hover:text-foreground`,title:`Einstellungen`,"aria-label":`Einstellungen`,children:(0,h.jsx)(no,{className:`size-5`})})]}),(0,h.jsx)(zo,{})]})]}),e[8]=f):f=e[8];let p;e[9]===Symbol.for(`react.memo_cache_sentinel`)?(p=(0,h.jsx)(`main`,{className:`flex min-w-0 flex-col gap-5 md:gap-6`,children:(0,h.jsx)(Aa,{})}),e[9]=p):p=e[9];let g;e[10]===Symbol.for(`react.memo_cache_sentinel`)?(g=Io.map(Wo),e[10]=g):g=e[10];let _;e[11]===Symbol.for(`react.memo_cache_sentinel`)?(_=()=>n(`mehr`),e[11]=_):_=e[11];let v;e[12]===Symbol.for(`react.memo_cache_sentinel`)?(v=(0,h.jsxs)(`nav`,{"aria-label":`Hauptnavigation`,className:`fixed inset-x-0 bottom-0 z-40 grid grid-cols-4 gap-1 border-t border-linie bg-[#0e1119]/95 px-2 pt-2 pb-[calc(0.75rem+env(safe-area-inset-bottom))] backdrop-blur md:hidden`,children:[g,(0,h.jsxs)(`button`,{type:`button`,onClick:_,className:`schild flex h-14 flex-col items-center justify-center gap-1 rounded-lg text-xs text-text-3`,children:[(0,h.jsx)(Ka,{className:`size-5`,"aria-hidden":!0}),`Mehr`]})]}),e[12]=v):v=e[12];let y;e[13]===t?y=e[14]:(y=t===`mehr`&&(0,h.jsx)(Fo,{verbindung:(0,h.jsx)(Vo,{}),onDienste:()=>n(`dienste`),onEinstellungen:()=>n(`einstellungen`),onSchliessen:i}),e[13]=t,e[14]=y);let b;e[15]===t?b=e[16]:(b=t===`dienste`&&(0,h.jsx)(No,{offen:!0,onSchliessen:i}),e[15]=t,e[16]=b);let x;e[17]===t?x=e[18]:(x=t===`einstellungen`&&(0,h.jsx)(Po,{offen:!0,onSchliessen:i}),e[17]=t,e[18]=x);let S;e[19]!==y||e[20]!==b||e[21]!==x?(S=(0,h.jsxs)(m.Suspense,{fallback:null,children:[y,b,x]}),e[19]=y,e[20]=b,e[21]=x,e[22]=S):S=e[22];let C;e[23]===Symbol.for(`react.memo_cache_sentinel`)?(C=(0,h.jsx)(Do,{}),e[23]=C):C=e[23];let w;return e[24]===S?w=e[25]:(w=(0,h.jsxs)(`div`,{className:`mx-auto flex min-h-dvh w-full max-w-[1440px] flex-col gap-5 px-4 pt-4 pb-28 sm:px-6 md:gap-6 md:px-10 md:pt-8 md:pb-10`,children:[f,p,v,S,C]}),e[24]=S,e[25]=w),w}function Wo(e){let{to:t,label:n,Icon:r}=e;return(0,h.jsxs)(pa,{to:t,className:`schild flex h-14 flex-col items-center justify-center gap-1 rounded-lg text-xs text-text-3`,activeProps:{className:`bg-erhaben !text-foreground`},activeOptions:{exact:!0},children:[(0,h.jsx)(r,{className:`size-5`,"aria-hidden":!0}),n]},t)}function Go(e){let{to:t,label:n}=e;return(0,h.jsx)(pa,{to:t,className:`schild flex h-11 items-center rounded-[9px] border border-transparent px-5 text-base text-text-3 hover:text-foreground`,activeProps:{className:`!border-linie-stark bg-erhaben !text-foreground`},activeOptions:{exact:!0},children:n},t)}var Ko=class extends Error{status;detail;constructor(e,t){super(t),this.status=e,this.detail=t,this.name=`ApiFehler`}};function qo(e,t){if(e&&typeof e==`object`&&`detail`in e){let t=e.detail;if(typeof t==`string`)return t;if(Array.isArray(t))return t.map(e=>e.msg??String(e)).join(`; `)}return`Die Box antwortet mit Fehler ${t}.`}async function I(e,t={}){let n;try{n=await fetch(e,{...t,headers:{"Content-Type":`application/json`,Accept:`application/json`,...t.headers}})}catch{throw new Ko(0,`MC2 ist nicht erreichbar. Läuft die Box?`)}let r=await n.text(),i=r?L(r):null;if(!n.ok)throw new Ko(n.status,qo(i,n.status));if(typeof i==`string`)throw new Ko(n.status,`Die Box antwortet nicht mit Daten.`);return i}function L(e){try{return JSON.parse(e)}catch{return e}}var R=(e,t)=>I(e,{method:`POST`,body:t===void 0?void 0:JSON.stringify(t)}),Jo=e=>()=>co()?e*5:e,Yo=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={queryKey:[`start`],queryFn:ms,refetchInterval:hs},e[0]=t):t=e[0],ot(t)},Xo=()=>{let e=(0,F.c)(2),t;e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t=[`models`],e[0]=t):t=e[0];let n;return e[1]===Symbol.for(`react.memo_cache_sentinel`)?(n={queryKey:t,queryFn:gs,refetchInterval:Jo(3e4)},e[1]=n):n=e[1],ot(n)},Zo=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={queryKey:[`nutzung`],queryFn:_s,refetchInterval:6e5},e[0]=t):t=e[0],ot(t)},Qo=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={queryKey:[`radar`],queryFn:vs,retry:!1,refetchInterval:3e5},e[0]=t):t=e[0],ot(t)},$o=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={queryKey:[`jobs`],queryFn:ys,refetchInterval:xs},e[0]=t):t=e[0],ot(t)},es=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={queryKey:[`sicherungen`],queryFn:Ss},e[0]=t):t=e[0],ot(t)},z=e=>{let t=(0,F.c)(7),n,r;t[0]===e?(n=t[1],r=t[2]):(n=[`update-details`,e],r=()=>I(`/api/maintenance/update-details?kind=${e}`),t[0]=e,t[1]=n,t[2]=r);let i=!!e,a;return t[3]!==n||t[4]!==r||t[5]!==i?(a={queryKey:n,queryFn:r,enabled:i,staleTime:6e5},t[3]=n,t[4]=r,t[5]=i,t[6]=a):a=t[6],ot(a)},ts=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={queryKey:[`updates-verlauf`],queryFn:Cs},e[0]=t):t=e[0],ot(t)},ns=e=>{let t=(0,F.c)(7),n,r;t[0]===e?(n=t[1],r=t[2]):(n=[`protokoll`,e],r=()=>I(`/api/maintenance/logs?service=${encodeURIComponent(e??``)}&lines=200`),t[0]=e,t[1]=n,t[2]=r);let i=!!e,a;return t[3]!==n||t[4]!==r||t[5]!==i?(a={queryKey:n,queryFn:r,enabled:i},t[3]=n,t[4]=r,t[5]=i,t[6]=a):a=t[6],ot(a)},rs=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={queryKey:[`dienste`],queryFn:ws},e[0]=t):t=e[0],ot(t)};function is(e,t){let n=(0,F.c)(6),r=_(),i;n[0]!==t||n[1]!==r?(i=(e,n)=>{let i=e;i&&i.ok===!1?xo(`fehler`,i.detail||i.err||`Das hat nicht geklappt.`):xo(`erfolg`,t.erfolg(n,e));for(let e of t.neuLaden)r.invalidateQueries({queryKey:[e]})},n[0]=t,n[1]=r,n[2]=i):i=n[2];let a;return n[3]!==e||n[4]!==i?(a={mutationFn:e,onSuccess:i,onError:as},n[3]=e,n[4]=i,n[5]=a):a=n[5],st(a)}function as(e){return xo(`fehler`,e.message)}var os=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={erfolg:Es,neuLaden:[`start`]},e[0]=t):t=e[0],is(Ts,t)},ss={alle:`/api/maintenance/update-all`,pruefen:`/api/maintenance/check-updates`,os:`/api/maintenance/os-update`,engine:`/api/maintenance/engine-update`,swap:`/api/maintenance/swap-update`,hermes:`/api/maintenance/hermes-update`},cs=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={erfolg:Os,neuLaden:[`jobs`,`start`]},e[0]=t):t=e[0],is(Ds,t)},ls=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={erfolg:As,neuLaden:[`start`]},e[0]=t):t=e[0],is(ks,t)},B=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={erfolg:Ms,neuLaden:[`sicherungen`,`start`]},e[0]=t):t=e[0],is(js,t)},us=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={erfolg:Ps,neuLaden:[`sicherungen`]},e[0]=t):t=e[0],is(Ns,t)},ds=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={erfolg:Is,neuLaden:[`models`,`start`]},e[0]=t):t=e[0],is(Fs,t)},fs=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={erfolg:Rs,neuLaden:[`radar`,`models`,`start`]},e[0]=t):t=e[0],is(Ls,t)},ps=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={erfolg:Bs,neuLaden:[`radar`]},e[0]=t):t=e[0],is(zs,t)};function ms(){return I(`/api/start`)}function hs(e){return e.state.data&&!e.state.data.updates.gelesen?4e3:Jo(2e4)()}function gs(){return I(`/api/models`)}function _s(){return I(`/api/modelle/nutzung`)}function vs(){return I(`/api/radar`)}function ys(){return I(`/api/jobs`)}function bs(e){return e.state===`running`||e.state===`queued`}function xs(e){return e.state.data?.jobs.some(bs)?2e3:Jo(3e4)()}function Ss(){return I(`/api/zeitmaschine`)}function Cs(){return I(`/api/updates/verlauf`)}function ws(){return I(`/api/system/services`)}function Ts(e){let{hinweis:t,aktion:n}=e;return R(`/api/hinweise/${encodeURIComponent(t)}/aktion/${n}`)}function Es(e){return`${e.label}: erledigt. Der Wächter prüft in einer Minute nach.`}function Ds(e){return R(ss[e])}function Os(e){return e===`pruefen`?`Suche nach Neuem läuft.`:`Update läuft. Den Fortschritt siehst du unten.`}function ks(e){return R(`/api/updates/festgehalten/${encodeURIComponent(e)}/freigeben`)}function As(e,t){return t.text??`Freigegeben.`}function js(){return R(`/api/system/backup`)}function Ms(){return`Sicherung erstellt.`}function Ns(e){return R(`/api/zeitmaschine/restore`,{file:e})}function Ps(){return`Zurückspielen läuft. Die Dienste starten gleich neu.`}function Fs(e){return R(`/api/models/${encodeURIComponent(e)}/load`)}function Is(e){return`${e} wird geladen.`}function Ls(e){let{id:t,aktion:n}=e;return R(`/api/radar/${encodeURIComponent(t)}/${n}`)}function Rs(e){return e.aktion===`uebernehmen`?`${e.name} übernommen.`:`${e.name} verworfen.`}function zs(){return R(`/api/radar/suche`)}function Bs(){return`Radar sucht nach neuen Modellen.`}var Vs=`Europe/Berlin`,Hs=new Intl.DateTimeFormat(`de-DE`,{hour:`2-digit`,minute:`2-digit`,timeZone:Vs}),Us=new Intl.DateTimeFormat(`de-DE`,{weekday:`short`,timeZone:Vs}),Ws=new Intl.DateTimeFormat(`de-DE`,{day:`2-digit`,month:`2-digit`,timeZone:Vs}),Gs=new Intl.DateTimeFormat(`en-CA`,{timeZone:Vs});function Ks(e){return Gs.format(e)}function qs(e,t=new Date){let n=new Date(e);if(Number.isNaN(n.getTime()))return`–`;let r=Ks(t),i=Ks(new Date(t.getTime()-864e5)),a=Ks(new Date(t.getTime()+864e5)),o=Ks(n),s=Hs.format(n);return o===r?`HEUTE ${s}`:o===i?`GESTERN ${s}`:o===a?`MORGEN ${s}`:Math.abs(n.getTime()-t.getTime())<5616e5?`${Us.format(n).replace(`.`,``).toUpperCase()} ${s}`:`${Ws.format(n)} ${s}`}function Js(e,t=new Date){let n=new Date(e*1e3);return Ks(n)===Ks(t)?`seit heute ${Hs.format(n)}`:`seit ${Ws.format(n)}, ${Hs.format(n)}`}function Ys(e,t=Date.now()){let n=Math.max(0,Math.round(t/1e3-e));if(n<60)return`vor ${n} s`;if(n<3600)return`vor ${Math.round(n/60)} min`;if(n<86400)return`vor ${Math.round(n/3600)} h`;let r=Math.round(n/86400);return`vor ${r} ${r===1?`Tag`:`Tagen`}`}function Xs(e){return e==null||e<0?null:[Math.floor(e/86400),Math.floor(e%86400/3600)]}var Zs=e=>e==null?null:e/1024**3;function Qs(e,t=0){let n=Zs(e);return n==null?`–`:n>=1e3?`${(n/1024).toFixed(1).replace(`.`,`,`)} TB`:`${n.toFixed(t).replace(`.`,`,`)} GB`}var $s=e=>e.toLocaleString(`de-DE`),ec=(0,m.lazy)(()=>Mo(()=>import(`./Protokollfenster-CDb28asU.js`).then(e=>({default:e.Protokollfenster})),__vite__mapDeps([6,1,2,3])));function tc({h:e}){let t=os(),[n,r]=(0,m.useState)(null),a=e.stufe===`rot`;async function o(n,i){if(n===`protokoll`){try{let t=await R(`/api/hinweise/${encodeURIComponent(e.id)}/aktion/protokoll`);r({titel:e.titel,text:t.text||t.out||t.err||`Kein Protokoll vorhanden.`})}catch(e){xo(`fehler`,e.message)}return}t.mutate({hinweis:e.id,aktion:n,label:i})}return(0,h.jsxs)(`article`,{className:`flex flex-col gap-2.5 border-t border-linie pt-4`,children:[(0,h.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,h.jsx)(`h3`,{className:`min-w-0 font-sans text-[17px] leading-snug font-semibold`,children:e.titel}),(0,h.jsx)(`span`,{"aria-hidden":!0,className:`hidden h-0 flex-grow border-b-2 border-dotted border-linie-stark sm:block`}),(0,h.jsx)(`span`,{className:i(`schild shrink-0 text-base`,a?`text-rot`:`text-bernstein`),children:a?`Jetzt`:`Prüfen`})]}),(0,h.jsxs)(`p`,{className:`ziffern text-[13px] text-text-3`,children:[Js(e.seit),` · zuletzt `,Ys(e.zuletzt)]}),e.text&&(0,h.jsx)(`p`,{className:`text-[15px] leading-relaxed break-words text-text-2`,children:e.text}),e.aktionen.length>0&&(0,h.jsx)(`div`,{className:`flex flex-wrap gap-2.5 pt-1`,children:e.aktionen.map((e,n)=>(0,h.jsx)(c,{variant:n===0&&e.id!==`protokoll`?`default`:`outline`,size:`sm`,disabled:t.isPending,onClick:()=>o(e.id,e.label),children:e.label},e.id))}),n&&(0,h.jsx)(m.Suspense,{fallback:null,children:(0,h.jsx)(ec,{offen:!0,titel:n.titel,text:n.text,onSchliessen:()=>r(null)})})]})}function nc(e){let t=(0,F.c)(12),{hinweise:n,verlauf:r}=e,i;t[0]===Symbol.for(`react.memo_cache_sentinel`)?(i=new Date().toDateString(),t[0]=i):i=t[0];let a=i,o;if(t[1]!==n.length||t[2]!==r){o=Symbol.for(`react.early_return_sentinel`);bb0:{let e;t[4]===Symbol.for(`react.memo_cache_sentinel`)?(e=e=>(e.art===`erledigt`||e.art===`auto`)&&new Date(e.ts*1e3).toDateString()===a,t[4]=e):e=t[4];let i=r.filter(e);if(n.length===0){let e;t[5]===Symbol.for(`react.memo_cache_sentinel`)?(e=(0,h.jsx)(`p`,{className:`text-[15px] text-text-2`,children:`Keine offenen Punkte. Der Wächter prüft jede Minute.`}),t[5]=e):e=t[5];let n=i.length>0&&(0,h.jsx)(`ul`,{className:`flex flex-col gap-1 text-sm text-text-3`,children:i.slice(0,4).map(ic)}),r;t[6]===n?r=t[7]:(r=(0,h.jsxs)(`div`,{className:`flex flex-col gap-2 border-t border-linie pt-4`,children:[e,n]}),t[6]=n,t[7]=r),o=r;break bb0}}t[1]=n.length,t[2]=r,t[3]=o}else o=t[3];if(o!==Symbol.for(`react.early_return_sentinel`))return o;let s;t[8]===n?s=t[9]:(s=n.map(rc),t[8]=n,t[9]=s);let c;return t[10]===s?c=t[11]:(c=(0,h.jsx)(`div`,{className:`flex flex-col gap-4`,children:s}),t[10]=s,t[11]=c),c}function rc(e){return(0,h.jsx)(tc,{h:e},e.id)}function ic(e){return(0,h.jsxs)(`li`,{children:[(0,h.jsx)(`span`,{className:`ziffern`,children:Ys(e.ts)}),` · `,e.text]},`${e.id}-${e.ts}`)}var ac={gruen:`border-gruen-rand bg-gruen-grund text-gruen`,bernstein:`border-bernstein/60 bg-bernstein-grund text-bernstein`,cyan:`border-cyan-rand bg-cyan-grund text-cyan`,rot:`border-rot-rand bg-rot-grund text-rot-text`,grau:`border-linie bg-erhaben text-text-2`};function oc(e){let t=(0,F.c)(5),{art:n,children:r}=e,a=ac[n===void 0?`grau`:n],o;t[0]===a?o=t[1]:(o=i(`schild inline-flex h-7 items-center rounded-full border px-2.5 text-xs whitespace-nowrap`,a),t[0]=a,t[1]=o);let s;return t[2]!==r||t[3]!==o?(s=(0,h.jsx)(`span`,{className:o,children:r}),t[2]=r,t[3]=o,t[4]=s):s=t[4],s}function sc(e){let t=(0,F.c)(6),{fehler:n,text:r}=e,a=n?`alert`:`status`,o=n?`border-rot-rand bg-rot-grund text-rot-text`:`border-linie bg-panel text-text-2`,s;t[0]===o?s=t[1]:(s=i(`rounded-2xl border px-5 py-8 text-center text-[15px]`,o),t[0]=o,t[1]=s);let c;return t[2]!==a||t[3]!==s||t[4]!==r?(c=(0,h.jsx)(`div`,{role:a,className:s,children:r}),t[2]=a,t[3]=s,t[4]=r,t[5]=c):c=t[5],c}var cc={erledigt:{text:`Erledigt`,farbe:`text-gruen`},fehler:{text:`Fehler`,farbe:`text-rot`},geplant:{text:`Geplant`,farbe:`text-text-3`}};function lc(e){let t=(0,F.c)(18),{e:n}=e,r=cc[n.status]??cc.geplant,a=n.status===`geplant`&&/update/i.test(n.titel)?`text-cyan`:r.farbe,o;t[0]===n.zeit?o=t[1]:(o=qs(n.zeit),t[0]=n.zeit,t[1]=o);let s;t[2]===o?s=t[3]:(s=(0,h.jsx)(`span`,{className:`ziffern text-sm text-text-3`,children:o}),t[2]=o,t[3]=s);let c;t[4]===n.text?c=t[5]:(c=n.text&&(0,h.jsxs)(`span`,{className:`text-text-3`,children:[`, `,n.text]}),t[4]=n.text,t[5]=c);let l;t[6]!==n.titel||t[7]!==c?(l=(0,h.jsxs)(`span`,{className:`min-w-0 text-base`,children:[n.titel,c]}),t[6]=n.titel,t[7]=c,t[8]=l):l=t[8];let u;t[9]===a?u=t[10]:(u=i(`schild text-[13px]`,a),t[9]=a,t[10]=u);let d;t[11]!==r.text||t[12]!==u?(d=(0,h.jsx)(`span`,{className:u,children:r.text}),t[11]=r.text,t[12]=u,t[13]=d):d=t[13];let f;return t[14]!==s||t[15]!==l||t[16]!==d?(f=(0,h.jsxs)(`li`,{className:`grid grid-cols-[112px_minmax(0,1fr)_auto] items-center gap-3 border-t border-linie py-2.5`,children:[s,l,d]}),t[14]=s,t[15]=l,t[16]=d,t[17]=f):f=t[17],f}function uc(e){let t=(0,F.c)(6),{gelaufen:n,geplant:r}=e,i;t[0]!==n||t[1]!==r?(i=[...n,...r.slice(0,5)],t[0]=n,t[1]=r,t[2]=i):i=t[2];let a=i;if(a.length===0){let e;return t[3]===Symbol.for(`react.memo_cache_sentinel`)?(e=(0,h.jsx)(`p`,{className:`text-[15px] text-text-2`,children:`Heute ist noch nichts gelaufen, und nichts ist geplant.`}),t[3]=e):e=t[3],e}let o;return t[4]===a?o=t[5]:(o=(0,h.jsx)(`ol`,{className:`m-0 flex list-none flex-col p-0`,children:a.map(dc)}),t[4]=a,t[5]=o),o}function dc(e){return(0,h.jsx)(lc,{e},`${e.titel}-${e.zeit}`)}var fc=100,pc=95,mc=210,hc=240;function gc(e,t){let n=e*Math.PI/180;return[fc+t*Math.cos(n),pc-t*Math.sin(n)]}var _c=e=>Math.round(e*100)/100;function vc(e,t,n){let r=Math.max(0,Math.min(1,e)),i=Math.max(r,Math.min(1,t)),[a,o]=gc(mc-hc*r,n),[s,c]=gc(mc-hc*i,n),l=+((i-r)*hc>180);return`M ${_c(a)} ${_c(o)} A ${n} ${n} 0 ${l} 1 ${_c(s)} ${_c(c)}`}function yc(e){return e==null?`var(--text-3)`:e>=85?`var(--rot)`:e>=70?`var(--bernstein)`:`var(--gruen)`}function bc(e){if(!e.waechter_wach)return{art:`stumm`,oben:`Wächter`,mitte:`SCHWEIGT`,unten:`Seit über 5 Minuten kein Prüflauf`};if(e.update_laeuft)return{art:`info`,oben:`Wartung`,mitte:`UPDATE LÄUFT`,unten:`Hinweise ruhen bis zum Ende`};if(e.anzahl===0)return{art:`ok`,oben:`Alles`,mitte:`IN ORDNUNG`,unten:`Keine offenen Hinweise`};let t=`${e.anzahl} HINWEIS${e.anzahl===1?``:`E`}`;return e.stufe===`rot`?{art:`rot`,oben:`Störung`,mitte:t,unten:`Drücken zum Ansehen`}:{art:`gelb`,oben:`Achtung`,mitte:t,unten:`Drücken zum Ansehen`}}function xc(e,t){if(!t)return{laeuft:`…`,neu:null};if(e===`os`)return{laeuft:`Ubuntu`,neu:t.count?`${t.count} Pakete`:null};if(e===`hermes`)return{laeuft:t.installed_version?`v${t.installed_version}`:`–`,neu:t.behind?`+${t.behind.toLocaleString(`de-DE`)} Änderungen`:null};let n=e===`engine`?`b`:`v`;return{laeuft:t.installed_build==null?`–`:`${n}${t.installed_build}`,neu:t.latest_build!=null&&t.installed_build!=null&&t.latest_build>t.installed_build?`${n}${t.latest_build}`:null}}function Sc(e){let t=e.aliases.map(e=>e.toLowerCase());return t.includes(`hermes`)||t.includes(`fast`)?`hirn`:t.includes(`coder`)?`coder`:null}function Cc(e){let t=(0,F.c)(25),{anteil:n,farbe:r,zonen:i,mitte:a,unter:o,beschriftung:s,ariaText:c}=e,l=r===void 0?`var(--cyan)`:r,u;t[0]===i?u=t[1]:(u=i===void 0?[]:i,t[0]=i,t[1]=u);let d=u,f=n!=null&&n>.004,p;t[2]===Symbol.for(`react.memo_cache_sentinel`)?(p=(0,h.jsx)(`path`,{d:vc(0,1,75),fill:`none`,stroke:`var(--linie)`,strokeWidth:12,strokeLinecap:`round`}),t[2]=p):p=t[2];let m;t[3]===d?m=t[4]:(m=d.map(wc),t[3]=d,t[4]=m);let g;t[5]!==n||t[6]!==l||t[7]!==f?(g=f&&(0,h.jsx)(`path`,{d:vc(0,n,75),fill:`none`,stroke:l,strokeWidth:12,strokeLinecap:`round`}),t[5]=n,t[6]=l,t[7]=f,t[8]=g):g=t[8];let _;t[9]===Symbol.for(`react.memo_cache_sentinel`)?(_={fontSize:34,fontWeight:500,fill:`var(--foreground)`},t[9]=_):_=t[9];let v;t[10]===a?v=t[11]:(v=(0,h.jsx)(`text`,{x:`100`,y:`100`,textAnchor:`middle`,className:`ziffern`,style:_,children:a}),t[10]=a,t[11]=v);let y;t[12]===o?y=t[13]:(y=o&&(0,h.jsx)(`text`,{x:`100`,y:`122`,textAnchor:`middle`,style:{fontFamily:`var(--font-anzeige)`,fontSize:14,fontWeight:600,letterSpacing:`0.12em`,fill:`var(--text-3)`},children:o.toUpperCase()}),t[12]=o,t[13]=y);let b;t[14]!==c||t[15]!==m||t[16]!==g||t[17]!==v||t[18]!==y?(b=(0,h.jsxs)(`svg`,{viewBox:`0 0 200 150`,className:`h-auto w-full max-w-[200px]`,role:`img`,"aria-label":c,children:[p,m,g,v,y]}),t[14]=c,t[15]=m,t[16]=g,t[17]=v,t[18]=y,t[19]=b):b=t[19];let x;t[20]===s?x=t[21]:(x=(0,h.jsx)(`figcaption`,{className:`schild text-[15px] text-text-3`,children:s}),t[20]=s,t[21]=x);let S;return t[22]!==b||t[23]!==x?(S=(0,h.jsxs)(`figure`,{className:`m-0 flex min-w-0 flex-col items-center gap-1`,children:[b,x]}),t[22]=b,t[23]=x,t[24]=S):S=t[24],S}function wc(e){return(0,h.jsx)(`path`,{d:vc(e.von,e.bis,86),fill:`none`,stroke:e.farbe,strokeWidth:4,strokeLinecap:`round`},`${e.von}-${e.bis}`)}function Tc(e){let t=(0,F.c)(11),{titel:n,rechts:r,children:a,className:o,id:s}=e,c;t[0]===o?c=t[1]:(c=i(`flex min-w-0 flex-col gap-4 rounded-2xl border border-linie bg-panel p-5 sm:p-6`,o),t[0]=o,t[1]=c);let l;t[2]!==r||t[3]!==n?(l=(n||r)&&(0,h.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-3`,children:[n&&(0,h.jsx)(`h2`,{className:`schild text-lg font-bold tracking-[0.22em] text-foreground`,children:n}),r]}),t[2]=r,t[3]=n,t[4]=l):l=t[4];let u;return t[5]!==a||t[6]!==s||t[7]!==c||t[8]!==l||t[9]!==n?(u=(0,h.jsxs)(`section`,{id:s,"aria-label":n,className:c,children:[l,a]}),t[5]=a,t[6]=s,t[7]=c,t[8]=l,t[9]=n,t[10]=u):u=t[10],u}var Ec={ok:{feld:`border-gruen-rand bg-gruen-grund`,name:`text-gruen`,wert:`text-gruen-text`},aus:{feld:`border-aus-rand bg-aus-grund`,name:`text-aus-text`,wert:`text-text-3`},warn:{feld:`border-bernstein bg-bernstein-lampe lampe-atmet`,name:`text-bernstein`,wert:`text-[#f2c46b]`},info:{feld:`border-cyan-rand bg-cyan-grund`,name:`text-cyan`,wert:`text-cyan-text`},fehler:{feld:`border-rot bg-rot-grund shadow-[0_0_18px_rgba(255,90,79,0.35)]`,name:`text-rot`,wert:`text-rot-text`}},Dc={ok:`in Ordnung`,aus:`aus`,warn:`braucht Aufmerksamkeit`,info:`Info`,fehler:`Störung`};function Oc(e){let t=(0,F.c)(19),{lampe:n}=e,r=Ec[n.zustand]??Ec.aus,a;t[0]===r.feld?a=t[1]:(a=i(`flex min-h-[58px] flex-col items-center justify-center gap-0.5 rounded-lg border px-2 py-2 text-center`,r.feld),t[0]=r.feld,t[1]=a);let o;t[2]===r.name?o=t[3]:(o=i(`schild text-[17px] leading-none font-bold tracking-[0.18em]`,r.name),t[2]=r.name,t[3]=o);let s;t[4]!==n.label||t[5]!==o?(s=(0,h.jsx)(`span`,{className:o,children:n.label}),t[4]=n.label,t[5]=o,t[6]=s):s=t[6];let c;t[7]===r.wert?c=t[8]:(c=i(`ziffern text-xs uppercase`,r.wert),t[7]=r.wert,t[8]=c);let l;t[9]!==n.wert||t[10]!==c?(l=(0,h.jsx)(`span`,{className:c,children:n.wert}),t[9]=n.wert,t[10]=c,t[11]=l):l=t[11];let u=Dc[n.zustand],d;t[12]===u?d=t[13]:(d=(0,h.jsx)(`span`,{className:`sr-only`,children:u}),t[12]=u,t[13]=d);let f;return t[14]!==a||t[15]!==s||t[16]!==l||t[17]!==d?(f=(0,h.jsxs)(`li`,{className:a,children:[s,l,d]}),t[14]=a,t[15]=s,t[16]=l,t[17]=d,t[18]=f):f=t[18],f}var kc={ok:`border-gruen-rand bg-gruen-grund text-gruen`,info:`border-cyan-rand bg-cyan-grund text-cyan`,stumm:`border-aus-rand bg-aus-grund text-aus-text`,gelb:`border-2 border-bernstein bg-bernstein-grund text-bernstein-hell lampe-atmet`,rot:`border-2 border-rot bg-rot-grund text-rot shadow-[0_0_32px_rgba(255,90,79,0.3)]`};function Ac(e){let t=(0,F.c)(26),{zustand:n,lampen:r,onAnsehen:a}=e,o;t[0]===n?o=t[1]:(o=bc(n),t[0]=n,t[1]=o);let s=o,c=s.art===`gelb`||s.art===`rot`,l=!c,u=`${s.oben} ${s.mitte}`,d=kc[s.art],f=c?`cursor-pointer`:`cursor-default`,p;t[2]!==d||t[3]!==f?(p=i(`flex min-h-[130px] flex-col items-center justify-center gap-1 rounded-2xl border px-4 py-4 font-anzeige transition-colors`,d,f),t[2]=d,t[3]=f,t[4]=p):p=t[4];let m;t[5]===s.oben?m=t[6]:(m=(0,h.jsx)(`span`,{className:`schild text-sm tracking-[0.26em]`,children:s.oben}),t[5]=s.oben,t[6]=m);let g;t[7]===s.mitte?g=t[8]:(g=(0,h.jsx)(`span`,{className:`text-[40px] leading-none font-bold tracking-[0.04em] sm:text-[44px]`,children:s.mitte}),t[7]=s.mitte,t[8]=g);let _;t[9]===s.unten?_=t[10]:(_=(0,h.jsx)(`span`,{className:`font-sans text-sm opacity-80`,children:s.unten}),t[9]=s.unten,t[10]=_);let v;t[11]!==a||t[12]!==l||t[13]!==u||t[14]!==p||t[15]!==m||t[16]!==g||t[17]!==_?(v=(0,h.jsxs)(`button`,{type:`button`,onClick:a,disabled:l,"aria-label":u,className:p,children:[m,g,_]}),t[11]=a,t[12]=l,t[13]=u,t[14]=p,t[15]=m,t[16]=g,t[17]=_,t[18]=v):v=t[18];let y;t[19]===r?y=t[20]:(y=r.map(jc),t[19]=r,t[20]=y);let b;t[21]===y?b=t[22]:(b=(0,h.jsx)(`ul`,{className:`grid grid-cols-2 gap-2.5 rounded-2xl border border-linie bg-panel p-3 sm:grid-cols-4`,children:y}),t[21]=y,t[22]=b);let x;return t[23]!==v||t[24]!==b?(x=(0,h.jsxs)(`section`,{"aria-label":`Warnpanel`,className:`grid gap-4 md:grid-cols-[260px_minmax(0,1fr)] md:gap-5`,children:[v,b]}),t[23]=v,t[24]=b,t[25]=x):x=t[25],x}function jc(e){return(0,h.jsx)(Oc,{lampe:e},e.id)}function Mc(e){let t=(0,F.c)(2),{z:n}=e,r;return t[0]===n?r=t[1]:(r=(0,h.jsx)(`span`,{className:`ziffern inline-flex h-14 w-[38px] items-center justify-center rounded-md border border-[#2a3036] bg-[#0b0d0f] text-[32px] font-medium`,children:n}),t[0]=n,t[1]=r),r}function Nc(e){let t=(0,F.c)(25),{sekunden:n}=e,r;t[0]===n?r=t[1]:(r=Xs(n),t[0]=n,t[1]=r);let i=r,a=String(Math.min(i?.[0]??0,99)),o;t[2]===a?o=t[3]:(o=a.padStart(2,`0`),t[2]=a,t[3]=o);let s=o,c=String(i?.[1]??0),l;t[4]===c?l=t[5]:(l=c.padStart(2,`0`),t[4]=c,t[5]=l);let u=l,d=i?`Laufzeit ohne Neustart: ${i[0]} Tage, ${i[1]} Stunden`:`Laufzeit unbekannt`,f=i?s[0]:`–`,p;t[6]===f?p=t[7]:(p=(0,h.jsx)(Mc,{z:f}),t[6]=f,t[7]=p);let m=i?s[1]:`–`,g;t[8]===m?g=t[9]:(g=(0,h.jsx)(Mc,{z:m}),t[8]=m,t[9]=g);let _;t[10]===Symbol.for(`react.memo_cache_sentinel`)?(_=(0,h.jsx)(`span`,{className:`schild mr-2 ml-0.5 text-lg font-bold text-text-3`,children:`T`}),t[10]=_):_=t[10];let v=i?u[0]:`–`,y;t[11]===v?y=t[12]:(y=(0,h.jsx)(Mc,{z:v}),t[11]=v,t[12]=y);let b=i?u[1]:`–`,x;t[13]===b?x=t[14]:(x=(0,h.jsx)(Mc,{z:b}),t[13]=b,t[14]=x);let S;t[15]===Symbol.for(`react.memo_cache_sentinel`)?(S=(0,h.jsx)(`span`,{className:`schild ml-0.5 text-lg font-bold text-text-3`,children:`H`}),t[15]=S):S=t[15];let C;t[16]!==y||t[17]!==x||t[18]!==p||t[19]!==g||t[20]!==d?(C=(0,h.jsxs)(`div`,{"aria-label":d,role:`img`,className:`flex h-[150px] max-w-full items-center gap-1.5 pb-5`,children:[p,g,_,y,x,S]}),t[16]=y,t[17]=x,t[18]=p,t[19]=g,t[20]=d,t[21]=C):C=t[21];let w;t[22]===Symbol.for(`react.memo_cache_sentinel`)?(w=(0,h.jsx)(`figcaption`,{className:`schild text-[15px] text-text-3`,children:`Ohne Neustart`}),t[22]=w):w=t[22];let T;return t[23]===C?T=t[24]:(T=(0,h.jsxs)(`figure`,{className:`m-0 flex min-w-0 flex-col items-center justify-end gap-1`,children:[C,w]}),t[23]=C,t[24]=T),T}function Pc(e){let t=(0,F.c)(47),{box:n}=e,r=uo(),i=r?.ram_used??n.ram_used,a=r?.ram_total??n.ram_total,o=r?.temp_cpu??n.temp_cpu,s=r?.temp_gpu??n.temp_gpu,c=n.platte,l=r?.uptime_s??n.uptime_s,u=i!=null&&a?i/a:null,d;t[0]===i?d=t[1]:(d=i==null?`–`:String(Math.round(Zs(i)??0)),t[0]=i,t[1]=d);let f;t[2]===a?f=t[3]:(f=a?`von ${Math.round(Zs(a)??0)} GB`:void 0,t[2]=a,t[3]=f);let p;t[4]!==u||t[5]!==i||t[6]!==a?(p=u==null?`Speicher unbekannt`:`Speicher: ${Qs(i)} von ${Qs(a)} belegt`,t[4]=u,t[5]=i,t[6]=a,t[7]=p):p=t[7];let m;t[8]!==u||t[9]!==d||t[10]!==f||t[11]!==p?(m=(0,h.jsx)(Cc,{beschriftung:`Speicher`,anteil:u,mitte:d,unter:f,ariaText:p}),t[8]=u,t[9]=d,t[10]=f,t[11]=p,t[12]=m):m=t[12];let g=o==null?null:o/100,_;t[13]===o?_=t[14]:(_=yc(o),t[13]=o,t[14]=_);let v;t[15]===Symbol.for(`react.memo_cache_sentinel`)?(v=[{von:.7,bis:.85,farbe:`var(--bernstein)`},{von:.85,bis:1,farbe:`var(--rot)`}],t[15]=v):v=t[15];let y;t[16]===o?y=t[17]:(y=o==null?`–`:`${Math.round(o)}°`,t[16]=o,t[17]=y);let b;t[18]===s?b=t[19]:(b=s==null?void 0:`GPU ${Math.round(s)}°`,t[18]=s,t[19]=b);let x;t[20]===o?x=t[21]:(x=o==null?`Temperatur unbekannt`:`Temperatur ${Math.round(o)} Grad`,t[20]=o,t[21]=x);let S;t[22]!==x||t[23]!==g||t[24]!==_||t[25]!==y||t[26]!==b?(S=(0,h.jsx)(Cc,{beschriftung:`Temperatur`,anteil:g,farbe:_,zonen:v,mitte:y,unter:b,ariaText:x}),t[22]=x,t[23]=g,t[24]=_,t[25]=y,t[26]=b,t[27]=S):S=t[27];let C=c?c.percent/100:null,w=c&&c.percent>=90?`var(--rot)`:c&&c.percent>=80?`var(--bernstein)`:`var(--cyan)`,T;t[28]===c?T=t[29]:(T=c?`${Math.round(c.percent)}%`:`–`,t[28]=c,t[29]=T);let ee;t[30]===c?ee=t[31]:(ee=c?`${Qs(c.used)} / ${Qs(c.total)}`:void 0,t[30]=c,t[31]=ee);let E;t[32]===c?E=t[33]:(E=c?`Platte zu ${Math.round(c.percent)} Prozent belegt`:`Platte unbekannt`,t[32]=c,t[33]=E);let te;t[34]!==C||t[35]!==w||t[36]!==T||t[37]!==ee||t[38]!==E?(te=(0,h.jsx)(Cc,{beschriftung:`Platte`,anteil:C,farbe:w,mitte:T,unter:ee,ariaText:E}),t[34]=C,t[35]=w,t[36]=T,t[37]=ee,t[38]=E,t[39]=te):te=t[39];let D;t[40]===l?D=t[41]:(D=(0,h.jsx)(Nc,{sekunden:l}),t[40]=l,t[41]=D);let ne;return t[42]!==S||t[43]!==te||t[44]!==D||t[45]!==m?(ne=(0,h.jsxs)(`section`,{"aria-label":`Instrumente`,className:`grid grid-cols-2 gap-x-4 gap-y-6 rounded-2xl border border-linie bg-panel px-4 py-5 lg:grid-cols-4 lg:px-6`,children:[m,S,te,D]}),t[42]=S,t[43]=te,t[44]=D,t[45]=m,t[46]=ne):ne=t[46],ne}var Fc={bestanden:`gruen`,durchgefallen:`rot`,wartet:`cyan`,neu:`cyan`};function Ic(e){let t=(0,F.c)(14),{radar:n}=e;if(!n?.kandidaten)return null;let r,i;t[0]===n.kandidaten?(r=t[1],i=t[2]):(r=n.kandidaten.filter(Rc),i=r.find(Lc)??r[0],t[0]=n.kandidaten,t[1]=r,t[2]=i);let a=i,o=r.length===1?``:`en`,s;t[3]!==r.length||t[4]!==o?(s=(0,h.jsxs)(`span`,{className:`schild text-sm text-cyan`,children:[`Radar · `,r.length,` Kandidat`,o]}),t[3]=r.length,t[4]=o,t[5]=s):s=t[5];let l;t[6]===a?l=t[7]:(l=a?(0,h.jsxs)(`span`,{className:`flex flex-wrap items-center gap-2 text-[15px]`,children:[(0,h.jsx)(`span`,{className:`ziffern`,children:a.name}),(0,h.jsxs)(`span`,{className:`text-text-2`,children:[`fürs `,a.rolle===`hirn`?`Hirn`:`Coden`]}),(0,h.jsx)(oc,{art:Fc[a.status]??`grau`,children:a.status})]}):(0,h.jsx)(`span`,{className:`text-[15px] text-text-2`,children:`Nichts Besseres in Sicht.`}),t[6]=a,t[7]=l);let u;t[8]!==s||t[9]!==l?(u=(0,h.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-1`,children:[s,l]}),t[8]=s,t[9]=l,t[10]=u):u=t[10];let d;t[11]===Symbol.for(`react.memo_cache_sentinel`)?(d=(0,h.jsx)(c,{variant:`info`,size:`sm`,asChild:!0,children:(0,h.jsx)(pa,{to:`/modelle`,hash:`radar`,children:`Ansehen`})}),t[11]=d):d=t[11];let f;return t[12]===u?f=t[13]:(f=(0,h.jsxs)(`div`,{className:`mt-auto flex flex-wrap items-center justify-between gap-3 rounded-xl border border-cyan-rand bg-cyan-grund px-4 py-3.5`,children:[u,d]}),t[12]=u,t[13]=f),f}function Lc(e){return e.status===`bestanden`}function Rc(e){return[`bestanden`,`wartet`,`neu`].includes(e.status)}function zc(){let e=(0,F.c)(32),{data:t,error:n,isPending:r}=Yo(),i=Qo();if(r){let t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t=(0,h.jsx)(sc,{text:`Die Box meldet sich gleich …`}),e[0]=t):t=e[0],t}if(n||!t){let t=`MC2 antwortet nicht: ${n?.message??`keine Daten`}`,r;return e[1]===t?r=e[2]:(r=(0,h.jsx)(sc,{fehler:!0,text:t}),e[1]=t,e[2]=r),r}let a=t.hinweise.length,o;e[3]!==t.lampen||e[4]!==t.zustand?(o=(0,h.jsx)(Ac,{zustand:t.zustand,lampen:t.lampen,onAnsehen:Bc}),e[3]=t.lampen,e[4]=t.zustand,e[5]=o):o=e[5];let s;e[6]===t.box?s=e[7]:(s=(0,h.jsx)(Pc,{box:t.box}),e[6]=t.box,e[7]=s);let c=a?`ziffern text-sm text-bernstein`:`ziffern text-sm text-gruen`,l=a?`${a} offen`:`alles erledigt`,u;e[8]!==c||e[9]!==l?(u=(0,h.jsx)(`span`,{className:c,children:l}),e[8]=c,e[9]=l,e[10]=u):u=e[10];let d;e[11]!==t.hinweise||e[12]!==t.verlauf?(d=(0,h.jsx)(nc,{hinweise:t.hinweise,verlauf:t.verlauf}),e[11]=t.hinweise,e[12]=t.verlauf,e[13]=d):d=e[13];let f;e[14]!==u||e[15]!==d?(f=(0,h.jsx)(Tc,{titel:`Checkliste`,id:`checkliste`,rechts:u,children:d}),e[14]=u,e[15]=d,e[16]=f):f=e[16];let p;e[17]!==t.flugplan.gelaufen||e[18]!==t.flugplan.geplant?(p=(0,h.jsx)(uc,{gelaufen:t.flugplan.gelaufen,geplant:t.flugplan.geplant}),e[17]=t.flugplan.gelaufen,e[18]=t.flugplan.geplant,e[19]=p):p=e[19];let m;e[20]===i.data?m=e[21]:(m=(0,h.jsx)(Ic,{radar:i.data}),e[20]=i.data,e[21]=m);let g;e[22]!==p||e[23]!==m?(g=(0,h.jsxs)(Tc,{titel:`Flugplan`,children:[p,m]}),e[22]=p,e[23]=m,e[24]=g):g=e[24];let _;e[25]!==f||e[26]!==g?(_=(0,h.jsxs)(`div`,{className:`grid gap-5 lg:grid-cols-[minmax(0,1.35fr)_minmax(0,1fr)] md:gap-6`,children:[f,g]}),e[25]=f,e[26]=g,e[27]=_):_=e[27];let v;return e[28]!==o||e[29]!==s||e[30]!==_?(v=(0,h.jsxs)(h.Fragment,{children:[o,s,_]}),e[28]=o,e[29]=s,e[30]=_,e[31]=v):v=e[31],v}function Bc(){return document.getElementById(`checkliste`)?.scrollIntoView({behavior:`smooth`,block:`start`})}var Vc=va({component:Uo,notFoundComponent:()=>(0,h.jsx)(Qi,{to:`/`})}),Hc=ga({getParentRoute:()=>Vc,path:`/`,component:zc}),Uc=ga({getParentRoute:()=>Vc,path:`/updates`,component:ya(()=>Mo(()=>import(`./Updates-3PYj6oWY.js`),__vite__mapDeps([7,1,3])),`UpdatesSeite`)}),Wc=ga({getParentRoute:()=>Vc,path:`/modelle`,component:ya(()=>Mo(()=>import(`./Modelle-PWfbWtFC.js`),__vite__mapDeps([8,1,2,3])),`ModelleSeite`)}),Gc=Ia({routeTree:Vc.addChildren([Hc,Uc,Wc]),defaultPreload:`intent`,defaultErrorComponent:Va}),Kc=`mc_neuladen_wegen_version`;function qc(){window.addEventListener(`vite:preloadError`,e=>{sessionStorage.getItem(Kc)||(e.preventDefault(),sessionStorage.setItem(Kc,`1`),window.location.reload())}),window.addEventListener(`load`,()=>{window.setTimeout(()=>sessionStorage.removeItem(Kc),5e3)})}qc();var Jc=new qe({defaultOptions:{queries:{retry:1,refetchOnWindowFocus:!1,staleTime:5e3}}});(0,Ba.createRoot)(document.getElementById(`root`)).render((0,h.jsx)(m.StrictMode,{children:(0,h.jsx)(v,{client:Jc,children:(0,h.jsx)(za,{router:Gc})})}));export{uo as A,z as C,I as D,us as E,_ as F,eo as M,Ja as N,R as O,ot as P,Yo as S,ts as T,ns as _,sc as a,ps as b,Qs as c,ls as d,B as f,Zo as g,Xo as h,oc as i,no as j,xo as k,$s as l,ds as m,Sc as n,qs as o,$o as p,xc as r,Zs as s,Tc as t,rs as u,Qo as v,cs as w,es as x,fs as y}; \ No newline at end of file +\r`.includes(e)?``:encodeURIComponent(e))),Un(e)}function Gn(e){let t=e.getLocation(),n=new Set,r=r=>{t=e.getLocation(),n.forEach(e=>e({location:t,action:r}))},i=n=>{e.notifyOnIndexChange??!0?r(n):t=e.getLocation()},a=async({task:n,navigateOpts:r,...i})=>{if(r?.ignoreBlocker??!1){n();return}let a=e.getBlockers?.()??[],o=i.type===`PUSH`||i.type===`REPLACE`;if(typeof document<`u`&&a.length&&o)for(let n of a){let r=Jn(i.path,i.state);if(await n.blockerFn({currentLocation:t,nextLocation:r,action:i.type})){e.onBlocked?.();return}}n()};return{get location(){return t},get length(){return e.getLength()},subscribers:n,subscribe:e=>(n.add(e),()=>{n.delete(e)}),push:(n,i,o)=>{let s=t.state[zn];i=Kn(s+1,i),a({task:()=>{e.pushState(n,i),r({type:`PUSH`})},navigateOpts:o,type:`PUSH`,path:n,state:i})},replace:(n,i,o)=>{let s=t.state[zn];i=Kn(s,i),a({task:()=>{e.replaceState(n,i),r({type:`REPLACE`})},navigateOpts:o,type:`REPLACE`,path:n,state:i})},go:(t,n)=>{a({task:()=>{e.go(t,n?.ignoreBlocker??!1),i({type:`GO`,index:t})},navigateOpts:n,type:`GO`})},back:t=>{a({task:()=>{e.back(t?.ignoreBlocker??!1),i({type:`BACK`})},navigateOpts:t,type:`BACK`})},forward:t=>{a({task:()=>{e.forward(t?.ignoreBlocker??!1),i({type:`FORWARD`})},navigateOpts:t,type:`FORWARD`})},canGoBack:()=>t.state[zn]!==0,createHref:t=>e.createHref(t),block:t=>{if(!e.setBlockers)return()=>{};let n=e.getBlockers?.()??[];return e.setBlockers([...n,t]),()=>{let n=e.getBlockers?.()??[];e.setBlockers?.(n.filter(e=>e!==t))}},flush:()=>e.flush?.(),destroy:()=>e.destroy?.(),notify:r,_getBlockers:()=>e.getBlockers?.()??[]}}function Kn(e,t){let n=Yn();return{...t,key:n,__TSR_key:n,[zn]:e}}function qn(e){let t=e?.window??(typeof document<`u`?window:void 0),n=t.history.pushState,r=t.history.replaceState,i=[],a=()=>i,o=e=>i=e,s=t=>Wn(e?.createHref?e.createHref(t):t),c=e?.parseLocation??(()=>Jn(`${t.location.pathname}${t.location.search}${t.location.hash}`,t.history.state));if(!t.history.state?.__TSR_key&&!t.history.state?.key){let e=Yn();t.history.replaceState({[zn]:0,key:e,__TSR_key:e},``)}let l=c(),u,d=!1,f=!1,p=!1,m=!1,h=()=>l,g,_=()=>{g&&(S._ignoreSubscribers=!0,(g[2]?t.history.pushState:t.history.replaceState)(g[1],``,g[0]),S._ignoreSubscribers=!1,g=void 0,u=void 0)},v=(t,n,r)=>{let i=e?.createHref?s(n):void 0,a=!!g;a||(u=l),l=Jn(n,r),g=[i??l.href,r,g?.[2]||t],a||queueMicrotask(()=>_())},y=e=>{l=c(),S.notify({type:e})},b=async()=>{if(m=!1,f){f=!1;return}let e=c(),n=e.state[zn]-l.state[zn],r=n===1,i=n===-1,o=!r&&!i||d;d=!1;let s=o?`GO`:i?`BACK`:`FORWARD`,u=o?{type:`GO`,index:n}:{type:i?`BACK`:`FORWARD`};if(p)p=!1;else{let r=a();if(typeof document<`u`&&r.length){for(let i of r)if(await i.blockerFn({currentLocation:l,nextLocation:e,action:s})){f=!0,t.history.go(-n),S.notify(u);return}}}l=c(),S.notify(u)},x=e=>{if(m){m=!1;return}let t=!1,n=a();if(typeof document<`u`&&n.length)for(let e of n){let n=e.enableBeforeUnload??!0;if(n===!0){t=!0;break}if(typeof n==`function`&&n()===!0){t=!0;break}}if(t)return e.preventDefault(),e.returnValue=``},S=Gn({getLocation:h,getLength:()=>t.history.length,pushState:(e,t)=>v(!0,e,t),replaceState:(e,t)=>v(!1,e,t),back:e=>(e&&(p=!0,m=!0),t.history.back()),forward:e=>{e&&(p=!0,m=!0),t.history.forward()},go:(e,n)=>{d=!0,n&&(p=!0,m=!0),t.history.go(e)},createHref:e=>s(e),flush:_,destroy:()=>{t.history.pushState=n,t.history.replaceState=r,t.removeEventListener(Vn,x,{capture:!0}),t.removeEventListener(Bn,b)},onBlocked:()=>{u&&l!==u&&(l=u)},getBlockers:a,setBlockers:o,notifyOnIndexChange:!1});return S._ignoreNextBeforeUnload=e=>{m=!1;try{e=new URL(e,t.document.baseURI).href,m=/^https?:/.test(e)&&(!e.includes(`#`)||e.split(`#`)[0]!==t.location.href.split(`#`)[0])}catch{}},t.addEventListener(Vn,x,{capture:!0}),t.addEventListener(Bn,b),t.history.pushState=function(...e){let r=n.apply(t.history,e);return S._ignoreSubscribers||y(`PUSH`),r},t.history.replaceState=function(...e){let n=r.apply(t.history,e);return S._ignoreSubscribers||y(`REPLACE`),n},S}function Jn(e,t){let n=Wn(e),r=n.indexOf(`#`),i=n.indexOf(`?`);if(!t){let e=Yn();t={[zn]:0,key:e,__TSR_key:e}}return{href:n,pathname:n.substring(0,r>0?i>0?Math.min(r,i):r:i>0?i:n.length),hash:r>-1?n.substring(r):``,search:i>-1?n.slice(i,r===-1?void 0:r):``,state:t}}function Yn(){return(Math.random()+1).toString(36).substring(7)}function Xn(e,t){return e.protocol!==`http:`&&e.protocol!==`https:`||e.origin!==t||!!e.username||!!e.password}function Zn(e){return e.pathname+e.search+e.hash}function Qn(e){return e.options.loader||e.options.beforeLoad||e.lazyFn||e.options.component?.preload||e.options.pendingComponent?.preload}function $n(e,t){return{fromLocation:t,toLocation:e,pathChanged:t?.pathname!==e.pathname,hrefChanged:t?.href!==e.href,hashChanged:t?.hash!==e.hash}}function er({key:e,__TSR_key:t,__TSR_index:n,__hashScrollIntoViewOptions:r,...i}){return i}function tr(e){return e.findIndex(e=>e.status===`error`||e.status===`notFound`||e._notFound)+1}function nr(e,t,n,r,i,a){r&&(t=t.slice(0,r)),i&&(n=n.slice(0,i));for(let r of t){if(a&&e._tx!==a)return;n.some(e=>e.routeId===r.routeId)||e.routesById[r.routeId].options.onLeave?.(r)}for(let r of n){if(a&&e._tx!==a)return;e.routesById[r.routeId].options[t.some(e=>e.routeId===r.routeId)?`onStay`:`onEnter`]?.(r)}}var rr=class{constructor(e,t){this.tempLocationKey=`${Math.round(Math.random()*1e7)}`,this._scroll={next:!0},this.subscribers=new Set,this._cache=new Map,this._committed=[],this.startTransition=async e=>(e(),!1),this.update=e=>{let t=this.options;this.options={...t,...e},this.isServer=this.options.isServer??!1??typeof document>`u`,this.staticLocations=new WeakMap,this.protocolAllowlist=new Set(this.options.protocolAllowlist),(!this.history||this.options.history&&this.options.history!==this.history)&&(this.history=this.options.history?this.options.history:qn()),this.origin=this.options.origin,this.origin||=window?.origin&&window.origin!==`null`?window.origin:`http://localhost`;let n=this.options.basepath??`/`,r=this.options.rewrite,i=this.basepath!==n||t?.rewrite!==r||t?.caseSensitive!==this.options.caseSensitive;if(i&&(this.basepath=n,this.rewrite=n!==`/`&&Pt(n)?Fn(n,this.options.caseSensitive,r):r),this.history&&this.updateLatestLocation(),this.options.routeTree!==this.routeTree){this.routeTree=this.options.routeTree;let e;e=this.buildRouteTree(),this.setRoutes(e)}if(this.stores)i&&this.stores.location.set(this.latestLocation);else if(this.latestLocation){let e=this.getStoreConfig(this);this.batch=e.batch,this.stores=Rn(this.latestLocation,e),en(this)}},this.updateLatestLocation=()=>{this.latestLocation=this.parseLocation(this.history.location,this.latestLocation)},this.buildRouteTree=()=>{let e=Tn(this.routeTree,this.options.caseSensitive);return this.options.routeMasks&&xn(this.options.routeMasks,e.processedTree),{...e,resolvePathCache:pn(1e3)}},this.subscribe=(e,t)=>{let n={eventType:e,fn:t};return this.subscribers.add(n),()=>{this.subscribers.delete(n)}},this.emit=e=>{for(let t of this.subscribers)if(t.eventType===e.type)try{t.fn(e)}catch(e){console.error(e)}},this.parseLocation=(e,t)=>{let n=({pathname:e,search:n,hash:r,href:i},a)=>{if(!this.rewrite&&!/[ \x00-\x1f\x7f\u0080-\uffff]/.test(e)){let i=this.options.parseSearch(n),o=this.options.stringifySearch(i);return{href:e+o+r,publicHref:e+o+r,pathname:Dt(e),external:!1,searchStr:o,search:ht(t?.search,i),hash:Dt(r.slice(1)),state:gt(t?.state,a)}}let o=In(this.rewrite,new URL(i,this.origin)),s=this.options.parseSearch(o.search),c=this.options.stringifySearch(s);return o.search=c,{href:o.href.replace(o.origin,``),publicHref:i,pathname:Dt(Un(o.pathname)),external:!!this.rewrite&&Xn(o,this.origin),searchStr:c,search:ht(t?.search,s),hash:Dt(o.hash.slice(1)),state:gt(t?.state,a)}},r=n(e,e.state),{__tempLocation:i,__tempKey:a}=r.state;if(i&&(!a||a===this.tempLocationKey)){let e=n(i,{...i.state,__tempLocation:void 0,key:r.state.key,__TSR_key:r.state.__TSR_key});return e.maskedLocation=r,e}return r},this.matchRoutes=(e,t,n)=>typeof e==`string`?this.matchRoutesInternal({pathname:e,search:t},n):this.matchRoutesInternal(e,t),this.getMatchedRoutes=e=>{let t=Object.create(null),n=wn(Nt(e),this.processedTree,!0);return n&&Object.assign(t,n.rawParams),[n?.branch||[this.routesById.__root__],t,n?.route]},this.buildLocation=e=>{{let t=this.staticLocations.get(e);if(t)return t}let t=!1,n=(n={})=>{if(n.href){let e=Jn(n.href,{});n={...n,to:In(this.rewrite,new URL(e.pathname,this.origin)).pathname,search:this.options.parseSearch(e.search),hash:e.hash.slice(1)}}let r=n._fromLocation||this._pendingLocation||this.latestLocation,i,a=()=>(t=!0,r),o=()=>(t=!0,i??=this.matchRoutesLightweight(r)),s=n.to?`${n.to}`:`.`,c=It(s[0]===`/`?``:n.unsafeRelative===`path`?a().pathname:n.from??o()[1],s,this.options.trailingSlash,this.resolvePathCache),l=this.routesByPath[Nt(c)],u=c.includes(`$`),d;if(l)d=l._branch??=On(l);else if(u)d=[];else{let[e,t,n]=this.getMatchedRoutes(c);d=e,this.options.notFoundRoute&&(!n||n.path!==`/`&&t[`**`])&&(d=[...d,this.options.notFoundRoute])}let f=u?l?._interpolation??vn(!1,{fullPath:c},0):void 0,p;for(let e of d){let t=e.options.params?.stringify??e.options.stringifyParams;if(t){let e=o()[3];if(p??=cr(n.params,e),!pt(p))break;p===e&&(p=Object.assign(mt(),p));try{Object.assign(p,t(p))}catch{}}}p??=cr(n.params,lr(n.params,f)?o()[3]:ur);let m=e.leaveParams?c:Un(Dt(f?Bt(c,f,p,this.pathParamsDecoder):c)),h=dr(d,e._includeValidateSearch),g=()=>{let t=o()[2];if(e._includeValidateSearch&&this.options.search?.strict){let e={};d.forEach(n=>{if(n.options.validateSearch)try{Object.assign(e,sr(n.options.validateSearch,{...e,...t}))}catch{}}),t=e}return t},_=h.length?fr(h,g(),n):n.search===!0?g():typeof n.search==`function`?n.search(g()):n.search||ur,v=this.options.stringifySearch(_),y=n.hash===!0?a().hash:typeof n.hash==`function`?n.hash(a().hash):n.hash||void 0,b=y?`#${y}`:``,x=n.state?n.state===!0?a().state:typeof n.state==`function`?n.state(a().state):n.state:ur,S=`${m}${v}${b}`,C,w,T=!1;if(this.rewrite){let e=new URL(S,this.origin),t=e.origin,n=Ln(this.rewrite,e);C=Zn(e),Xn(n,t)?(w=n.href,T=!0):w=Un(Zn(n))}else C=Ot(S),w=C;return{publicHref:w,href:C,pathname:m,search:_,searchStr:v,state:x,hash:y??``,external:T,unmaskOnReload:n.unmaskOnReload}},r=n(e);if(e.mask)r.maskedLocation=n({from:e.from,...e.mask});else if(this.options.routeMasks){let t=Sn(r.pathname,this.processedTree);if(t){let i=Object.assign(mt(),t.rawParams),{from:a,params:o,...s}=t.route,c=cr(o,i);r.maskedLocation=n({from:e.from,...s,params:c})}}return!t&&e._fromLocation&&!r.maskedLocation&&this.staticLocations.set(e,r),r},this.commitLocation=async({viewTransition:e,ignoreBlocker:t,...n})=>{let r=n.maskedLocation??n;if(r.external)return ir(this,r.publicHref,{replace:n.replace,ignoreBlocker:t});let i,a=Nt(this.latestLocation.href)===Nt(n.href)&&vt(er(n.state),er(this.latestLocation.state)),o=this._commitPromise,s,c=new Promise(e=>{s=e});if(c.resolve=()=>{s(),o?.resolve()},this._commitPromise=c,a)this.load();else{let{maskedLocation:r,hashScrollIntoView:a,...o}=n;r&&(o={...r,state:{...r.state,__tempKey:void 0,__tempLocation:{...o,search:o.searchStr,state:{...o.state,__tempKey:void 0,__tempLocation:void 0,__TSR_key:void 0,key:void 0}}}},(o.unmaskOnReload??this.options.unmaskOnReload??!1)&&(o.state.__tempKey=this.tempLocationKey)),o.state={...o.state,__hashScrollIntoViewOptions:a??this.options.defaultHashScrollIntoView??!0},this.shouldViewTransition=e,i=n.replace?`REPLACE`:`PUSH`,this.history[i===`REPLACE`?`replace`:`push`](o.publicHref,o.state,{ignoreBlocker:t}),this.history.subscribers.size||this.load({action:{type:i}})}return this._scroll.next=n.resetScroll??!0,this._commitPromise},this.buildAndCommitLocation=({replace:e,resetScroll:t,hashScrollIntoView:n,viewTransition:r,ignoreBlocker:i,...a}={})=>{let o=this.buildLocation({...a,_includeValidateSearch:!0});this._pendingLocation=o;let s=this.commitLocation({...o,viewTransition:r,replace:e,resetScroll:t,hashScrollIntoView:n,ignoreBlocker:i});return queueMicrotask(()=>{this._pendingLocation===o&&(this._pendingLocation=void 0)}),s},this.navigate=async({to:e,reloadDocument:t,href:n,publicHref:r,...i})=>{let a=n?wt(n):void 0;if(a||t){if(e!==void 0||!n){let t=this.buildLocation({to:e,...i}),a=t.maskedLocation??t;n??=a.publicHref,r??=a.publicHref}let t=!a&&r?r:n;return ir(this,t,i)}return this.buildAndCommitLocation({...i,href:n,to:e,_isNavigate:!0})},this.load=async e=>{this.updateLatestLocation(),e?.action&&(this._scroll.hash=e.action.type===`PUSH`||e.action.type===`REPLACE`),await ii(this,e)},this.startViewTransition=e=>{let t=this.shouldViewTransition??this.options.defaultViewTransition;if(this.shouldViewTransition=void 0,t&&typeof document.startViewTransition==`function`){let n;if(typeof t==`object`&&window.CSS?.supports?.(`selector(:active-view-transition-type(a))`)){let r=this.latestLocation,i=this.stores.resolvedLocation.get(),a=typeof t.types==`function`?t.types($n(r,i)):t.types;if(a===!1)return e();n={update:e,types:a}}else n=e;return document.startViewTransition(n).updateCallbackDone}return e()},this.invalidate=e=>{let t=this._committed,n=e?.filter,r=this._preloads,i=new Set,a=e=>{(!n||n(e))&&i.add(e.id)};t.forEach(a),this._cache.forEach(a),r?.forEach(e=>e.forEach(a)),this._tx?.[3].forEach(a);let o=[];for(let[e,t]of r??[])t.some(e=>i.has(e.id))&&(r.delete(e),o.push(e));let s=t=>{if(i.has(t.id)){let n=this.routesById[t.routeId],r={...t,invalid:!0,...(e?.forcePending||t.status===`error`||t.status===`notFound`)&&Qn(n)?{status:`pending`,error:void 0}:void 0};return t._flight=void 0,r}return t};this._committed=t.map(s);for(let[t,n]of this._cache)i.has(t)&&(n.invalid=!0,e?.forcePending&&(n.status=`pending`));for(let e of i)this._flights?.delete(e);for(let e of o)e.abort();return this.shouldViewTransition=!1,this.load({sync:e?.sync})},this.resolveRedirect=e=>{let t=e.options,n=e.headers.get(`Location`)||t.href;if(!n){let e=this.buildLocation(t);n=(e.maskedLocation??e).publicHref||`/`}let r;if(Tt.test(n)||(r=wt(n))&&!this.protocolAllowlist.has(r))throw Error(`Redirect blocked: unsafe protocol`);if(r===`http:`||r===`https:`){let e=new URL(n);e.pathname.startsWith(`//`)?n=e.href:Xn(e,this.origin)||(n=Zn(e),r=void 0)}return r&&(t.reloadDocument=!0),t.href=n,e.headers.set(`Location`,n),e},this.clearCache=e=>{let t=this._cache,n=this._preloads,r=e?.filter,i=[],a=[];for(let[e,n]of t)(!r||r(n))&&(a.push(e),i.push(n));let o=[];for(let[e,t]of n??[])(!r||t.some(r))&&(o.push(e),i.push(...t));for(let e of a)t.delete(e);for(let e of o)n.delete(e);for(let e of i){let t=e._flight;e._flight=void 0,t&&!--t[2]&&(this._flights?.get(e.id)===t&&this._flights.delete(e.id),o.push(t[1]))}for(let e of o)e.abort()},this.loadRouteChunk=_r,this.preloadRoute=e=>ai(this,e),this.matchRoute=(e,t)=>{let n={...e,to:e.to?It(e.from||``,e.to,this.options.trailingSlash,this.resolvePathCache):void 0,params:e.params||{},leaveParams:!0},r=this.buildLocation(n),i=this.stores.status.get()===`pending`;if(t?.pending&&!i)return!1;let a=t?.pending??!i?this.latestLocation:this.stores.resolvedLocation.get()||this.stores.location.get(),o=Cn(r.pathname,t?.caseSensitive??!1,t?.fuzzy??!1,a.pathname,this.processedTree);return!o||e.params&&!vt(o.rawParams,e.params,!0)?!1:t?.includeSearch??!0?vt(a.search,r.search,!0)?o.rawParams:!1:o.rawParams},this.getStoreConfig=t,e.pathParamsAllowedCharacters?.length&&(this.pathParamsDecoder=Lt(e.pathParamsAllowedCharacters)),this.update({defaultPreloadDelay:50,defaultPendingMs:1e3,defaultPendingMinMs:500,context:void 0,...e,caseSensitive:e.caseSensitive??!1,notFoundMode:e.notFoundMode??`fuzzy`,stringifySearch:e.stringifySearch??sn,parseSearch:e.parseSearch??on,protocolAllowlist:e.protocolAllowlist??Ct}),self.__TSR_ROUTER__=this}isShell(){return!!this.options.isShell}get state(){return this.stores.__store.get()}setRoutes(e){Object.assign(this,e),this.lightweightCache=new WeakMap,this.staticLocations=new WeakMap;let t=this.options.notFoundRoute;t&&(t.init(99999999999),this.routesById[t.id]!==t&&(t._interpolation=vn(!1,t,0)),this.routesById[t.id]=t)}matchRoutesInternal(e,t){let[n,r,i]=this.getMatchedRoutes(e.pathname),a=n,o=!1;(i?i.path!==`/`&&r[`**`]:Nt(e.pathname))&&(this.options.notFoundRoute?a=[...a,this.options.notFoundRoute]:o=!0);let s=o?pr(this.options.notFoundMode,a):void 0,c=Array(a.length),l=this._committed,u=(e,t)=>{let n=l[t];return n?.routeId===e.id?n:e===this.options.notFoundRoute?l.find(t=>t.routeId===e.id):void 0},d;for(let n=0;ntypeof t!=`string`&&!ft.call(e,t[1]))}var ur=Object.freeze({});function dr(e,t){let n=[];for(let r=0;r{let n=t(i.preSearchFilters?i.preSearchFilters.reduce((e,t)=>t(e),e):e);return i.postSearchFilters?i.postSearchFilters.reduce((e,t)=>t(e),n):n});let a=i.validateSearch;t&&a&&n.push(({search:e,next:t,meta:n})=>{let r=t(e);try{let e=sr(a,r);if(n&&e)for(let t in e)t in r||(n.defaulted||=new Map).set(t,e[t]);return{...r,...e}}catch{}return r})}return n}function fr(e,t,n){let r=(t,i,a)=>{if(t>=e.length){if(!n.search)return{};if(n.search===!0)return i;let e=dt(n.search,i);return a&&(a.explicit=e),e}return e[t]({search:i,next:(e,n)=>{if(n){let n=a||{};return{search:r(t+1,e,n),meta:n}}return r(t+1,e,a)},meta:a})};return r(0,t)}function pr(e,t){if(e!==`root`){let e;for(let n=t.length-1;n>=0;n--){let r=t[n];if(r.options.notFoundComponent)return r.id;e||=r.children&&r.id}if(e)return e}return un}function mr(e,t){let n=e.options.params?.parse??e.options.parseParams;n&&Object.assign(t,n(t))}function hr(e,t){return e.options[t]?.preload?.()}function gr(e,t){let n=hr(e,`component`),r=hr(e,`pendingComponent`);return t&&(r?r=r.then(t):t()),n&&r?Promise.all([n,r]).then(()=>{}):n??r}function _r(e,t,n){let r=()=>t===!1?void 0:t?hr(e,t):gr(e,n),i=e._lazy;if(i)return i===!0?r():i.then(r);if(!e.lazyFn)return r();let a=e.lazyFn().then(t=>{{let{id:n,...r}=t.options;Object.assign(e.options,r),e._lazy=!0}},t=>{throw e._lazy=void 0,t});return e._lazy=a,a.then(r)}function vr(e){let t=e.findIndex(e=>e.status!==`success`||e._notFound)+1;return t&&t{let i=()=>r(t);t.addEventListener(`abort`,i,{once:!0}),Promise.resolve(e).then(n,r).then(()=>t.removeEventListener(`abort`,i))})}function Er(e,t){return e.routesById[t.routeId]}function Dr(e,t,n){return fn(e)?[Sr,e]:Vt(e)?(e.routeId||=n,[xr,e]):t?(typeof e?.then==`function`&&(e=Error(`A Promise was thrown`,{cause:e})),[br,e]):[yr,e]}function Or(e,t){let n=Dr(t,!0,e.id);if(n[0]!==br)return n;try{e.options.onError?.(n[1])}catch(t){n=Dr(t,!0,e.id)}return n}function kr(e,t,n,r,i){return i[0].signal.aborted?Cr:Gr(e,t,n,Or(n,r),i)}async function Ar(e,t,n,r,i,a){let[o,s]=t,c=n[0].signal,l=!!n[3];for(let i=n[6]??0;ie.navigate({...t,_fromLocation:o}),buildLocation:e.buildLocation,cause:l?`preload`:r.cause,abortController:n[0],preload:l,matches:s,routeId:u.id};try{let e=r._ctx||=u.options.context?u.options.context({...f,deps:r.loaderDeps,context:d})||{}:void 0;r.context={...d,...e}}catch(a){return Mr(e,r),[i,kr(e,t,u,a,n)]}if(c.aborted)return[i,Cr];let p=r.paramsError??r.searchError;if(p!==void 0)return Mr(e,r),[i,kr(e,t,u,p,n)];let m=u.options.beforeLoad;if(!m)continue;let h=r.status;i>=a&&(r.status=`pending`,n[7]?.());try{Fr(e,r,`beforeLoad`,n[0]);let a=m({...f,search:r.search,context:r.context,...e.options.additionalContext}),o=await(typeof a?.then==`function`?Tr(a,c):a);if(c.aborted)return[i,Cr];let s=Gr(e,t,u,Dr(o,!1,u.id),n);if(s[0]!==yr)return Mr(e,r),[i,s];r.context={...r.context,...o}}catch(a){return Mr(e,r),[i,kr(e,t,u,a,n)]}finally{r.status=h,Fr(e,r,!1,n[0])}}i()}function jr(e,t,n){if(!(!n||--n[2])){if(e._flights?.get(t.id)===n){let n=e._tx;if(n&&!n[0].signal.aborted&&!n[3].includes(t)&&n[3].some(e=>e.id===t.id)&&n[3].some(e=>e.isFetching===`beforeLoad`))return;e._flights.delete(t.id)}return n[1]}}function Mr(e,t){let n=t._flight;t._flight=void 0,jr(e,t,n)?.abort()}function Nr(e,t,n,r){let i=[];for(let a of t)if(!n?.includes(a)){let t=a._flight;if(a._flight=void 0,r&&t?.[2]===1&&e._flights?.get(a.id)===t&&n?.some(e=>e.id===a.id))t[2]=0;else{let n=jr(e,a,t);n&&i.push(n)}}for(let e of i)e.abort()}function Pr(e){for(let t of e){let e=t._flight;e&&e[2]++}}function Fr(e,t,n,r){if(t.isFetching=n,r&&e._tx?.[0]!==r)return;let i=e.stores.byRoute.get(t.routeId),a=i?.get();a?.id===t.id&&i.set({...a,isFetching:n})}function Ir(e,t,n,r,i,a,o){let s=t[0];return{params:n.params,location:s,navigate:t=>e.navigate({...t,_fromLocation:s}),cause:o?`preload`:n.cause,abortController:i,preload:o,deps:n.loaderDeps,parentMatchPromise:a,context:n.context,route:r,...e.options.additionalContext}}async function Lr(e,t,n,r,i,a,o){let s=o[0],c=s.signal;if(c.aborted)return Cr;if(!i)return[yr,void 0];let l=n._flight;Fr(e,n,`loader`,s);try{if(!l){let s=new AbortController;l=[Promise.resolve().then(()=>i(Ir(e,t,n,r,s,a,!!o[3]))).then(e=>Dr(e,!1,r.id),e=>Dr(e,!0,r.id)).then(t=>(t[0]!==yr&&e._flights?.get(n.id)===l&&(e._flights.delete(n.id),l[2]||s.abort()),t[0]===br&&l[2]?Or(r,t[1]):t)),s,1],(e._flights??=new Map).set(n.id,l)}return n._flight=l,n.abortController=l[1],Gr(e,t,r,await Tr(l[0],c),o)}catch(t){if(t!==c||!c.aborted)throw t;return Mr(e,n),Cr}finally{Fr(e,n,!1,s)}}function Rr(e,t,n){t[0]!==Sr&&(e.status=`success`,e.error=void 0,t[0]===yr?(e.loaderData=t[1],e.invalid=!1,e.updatedAt=Date.now(),e.preload=n):e.invalid=!0)}function zr(e,t,n){let r=e._cache.get(t.id);if(r!==n||e._committed.some(e=>e.id===t.id&&e._flight===t._flight))return;let i={...t,_notFound:void 0,context:{}};i._flight&&i._flight[2]++,e._cache.set(t.id,i),r&&Mr(e,r)}function Br(e,t){return t[0]===br||t[0]===xr?{...e,status:t[0]===br?`error`:`notFound`,error:t[1],_flight:void 0}:e}function Vr(e,t,n,r,i,a,o){let s=t[1][n],c=Er(e,s),l=!!a[3],u=e._cache.get(s.id),d,f=!1,p;try{if(s.status===`success`&&(d=c.options.shouldReload,typeof d==`function`&&(d=d(Ir(e,t,s,c,a[0],i,l))),a[0].signal.aborted&&(p=Cr)),!p){if(s.status!==`success`)f=!0;else{let t=l||s.preload?c.options.preloadStaleTime??e.options.defaultPreloadStaleTime??3e4:c.options.staleTime??e.options.defaultStaleTime??0;f=!!(s.invalid||d||d===void 0&&Date.now()-s.updatedAt>=t&&(a[5]||s.cause===`enter`||a[2].some(e=>e.routeId===s.routeId&&e.id!==s.id)))}}}catch(n){s.invalid=!0,Mr(e,s),p=kr(e,t,c,n,a)}let m=c.options.loader,h=typeof m==`function`,g=h?m:m?.handler,_=!l||c.options.preload!==!1,v=_&&m?e._flights?.get(s.id):void 0;v===s._flight||p?v=void 0:v&&!f&&!l&&d===void 0?f=!0:f||(v=void 0);let y=!(!m||!f||s.status!==`success`||l||a[4]||((h?void 0:m.staleReloadMode)??e.options.defaultStaleReloadMode)===`blocking`),b=f&&_,x=b&&!y&&(s.status!==`success`||!!m),S=n>=o?a[7]:void 0,C=c.lazyFn&&c._lazy!==!0?S:void 0;if(b&&!m&&(s.invalid=!1,s.updatedAt=Date.now()),v&&v[2]++,x){let t=s._flight;s._flight=v,jr(e,s,t)?.abort(),n>=o&&(s.status=`pending`),S?.()}b||(s.isFetching=!1);let w=!p&&x?Lr(e,t,s,c,g,i,a).then(t=>(Rr(s,t,l),t[0]===yr&&(m&&!a[0].signal.aborted&&zr(e,s,u),n>=o&&(s.status=`pending`)),t)):Promise.resolve(p??[yr,s.loaderData]),T=(async()=>{try{let e=_r(c,void 0,C);e&&await Tr(e,a[0].signal)}catch(r){if(!t[1].some((e,t)=>t<=n&&(e.status===`error`||e.status===`notFound`||e._notFound)))return[n,kr(e,t,c,r,a)]}let r=await w;x&&r[0]===yr&&s.status===`pending`&&!a[0].signal.aborted&&(s.status=`success`,S?.())})();if(r.push([n,w,T]),!y)return w.then(e=>Br(s,e));let ee={...s,status:`pending`,preload:!1,_flight:v};s.invalid=!1,s.isFetching=`loader`;let E=Lr(e,t,ee,c,g,i,a).then(e=>(s.isFetching=!1,Rr(ee,e,!1),e));return(t[2]??=[]).push([n,E,T,ee]),E.then(e=>Br(ee,e))}async function Hr(e,t,n,r,i=0){let a=n?.[1][1],o=a?.routeId?t.findIndex(e=>e.routeId===a.routeId):n?.[0]??t.length-1;o<0&&(o=0);for(let n=o;n>=0;n--){let i=Er(e,t[n]);try{let e=_r(i,!1);e&&await Tr(e,r)}catch(e){if(e===r&&r.aborted)throw e}if(i.options.notFoundComponent)return n}return a?.routeId?o:i}function Ur(e,t){t[2]&&=(Nr(e,t[2].map(e=>e[3])),void 0)}async function Wr(e,t,n,r){let i;try{await Promise.all(e.map(e=>e[1].then(async t=>{let a=e[0];if(!(r&&a>=await r)){if(t[0]>=Sr)throw[a,t];!i&&t[0]!==yr&&(i=[a,t],await Promise.all((n??[]).map(e=>{if(!(e[0]<=a))return e[1].then(t=>{if(t[0]===Sr)throw[e[0],t]})})))}})))}catch(e){return e}return t??i}function Gr(e,t,n,r,i,a){for(;r[0]===Sr;){let o=r[1],s=o.options;try{if((s.href||o.headers.has(`Location`))&&(e.resolveRedirect(o),s.reloadDocument)||(s.reloadDocument?i[3]:i[1]>=20))return r;let n=e.buildLocation({...s,_fromLocation:t[0],_includeValidateSearch:!0}),a=n.maskedLocation??n;if(a.external){let t=o.clone();return t.options={...s},t.headers.set(`Location`,a.publicHref),e.resolveRedirect(t),i[3]?[Sr,t]:[Sr,t,a]}return[Sr,o,n]}catch(e){r=a?[br,e]:Or(n,e),a=!0}}return r}async function Kr(e,t,n,r,i,a){let o=t[1],s=await i,c=!1,l=o.findIndex(e=>e._notFound),u=t=>t[1][0]===xr?Hr(e,o,t,r.signal):t[0],d=l<0?o.length:l;if((s?.[1][0]??0)>=Sr)d=0;else if(s){d=s[2]??=await u(s);for(let e of n){if(e[0]>=d)break;let t=await e[1];if(t[0]!==yr&&t[0]=d)break;let t=await e[2];if(t){s=t;break}}if((s?.[1][0]??0)>=Sr){let n=s[1];if(n[0]!==Sr||n[1].options.reloadDocument||n[2])return Ur(e,t),n;c=!0,s=[0,[br,Error(`Too many redirects`)]]}let f=s?s[2]??await u(s):l;if(f>=0){let i=s?.[1],l=i?.[0],u=o[f],d=i?.[1],p=()=>{i&&(u._notFound=void 0,l===br?u.status=`error`:(d.routeId=u.routeId,u.routeId===e.routeTree.id?(u.status=`success`,u._notFound=!0):u.status=`notFound`),u.error=d,u.isFetching=!1)};p(),i||a?.();let m=Er(e,u);try{await Tr(i?Promise.resolve().then(()=>_r(m,l===br?`errorComponent`:`notFoundComponent`)):Promise.all([_r(m),_r(m,`notFoundComponent`)]),r.signal)}catch(n){if(n===r.signal&&r.signal.aborted)return Ur(e,t),Cr}i?c&&(r.abort(),await Promise.all([...n.map(e=>e[1]),...n.map(e=>e[2]),...(t[2]??[]).map(e=>e[1])]),Ur(e,t),Nr(e,o),p()):u.status=`success`}return t}async function qr(e,t,n,r=0,i=t[1].length){let a=t[1];for(let t=r;te._notFound);if(e.options.notFoundMode!==`root`&&s>=0){let t=await Hr(e,n,void 0,a,s);n[s]._notFound=void 0,n[t]._notFound=!0,s=t}let c=s<0?n.length:s+1,l=0;for(;l{for(let t=d;t=Sr&&(c=0);p()}if(!a.aborted&&!r[3]){let t=[];for(let[n,r]of e._flights??[])r[2]||(e._flights.delete(n),t.push(r[1]));for(let e of t)e.abort()}let h=Kr(e,i,u,r[0],Wr(u,m,i[2]),r[7]);i[2]?.length&&(i[3]=Wr(i[2],void 0,void 0,h.then(e=>wr(e)?0:vr(n).length,()=>0))),o=await h}catch(t){if(Ur(e,i),t===a&&a.aborted)return Cr;throw t}return wr(o)?o:qr(e,o,a,r[6]===n.length?r[6]:0)}function Yr(e,t){if(e._tx!==t)return;let n=t[3],r=e.stores.matches.get(),i=e._pending;for(let a=0;a0){i[3]=setTimeout(()=>Yr(e,t),n);return}i[2]=0}let m=n.map(e=>({...e,_flight:void 0}));m[a].status=`pending`;let h=i[4]=e.startTransition(()=>e.stores.setMatches(m),m).then(t=>(t&&e._pending===i&&i[4]===h&&!i[2]&&(i[2]=Date.now()+f),t));return}}function Xr(e,t){let n=e._pending;(e._tx===t||!e._tx?.[3].some(e=>e.id===n?.[1]))&&(clearTimeout(n?.[3]),e._pending=void 0)}async function Zr(e,t){let n=e._pending;if(!n)return;clearTimeout(n[3]);let r=n[2]-Date.now();if(!n[4]||r<=0||!vr(t[3]).some(e=>e.id===n[1]))return;let i;try{await Tr(new Promise(e=>{i=setTimeout(e,r)}),t[0].signal)}catch{}clearTimeout(i)}function Qr(e,t){e._committed=t,e.stores.setMatches(t)}function $r(e,t,n,r){let i=e._committed,a=e._lifecycleEnd,o=e._cache;for(let e of n)e.preload=!1,r&&(e._assetEnd=void 0);let s=vr(n).length,c=new Map;{let t=Date.now(),r=new Set;for(let e=0;e=(n.preload?i.options.preloadGcTime??e.options.defaultPreloadGcTime??3e5:i.options.gcTime??e.options.defaultGcTime??3e5)||c.set(n.id,o.get(n.id)===n?n:{...n,_flight:void 0,isFetching:!1,context:{}})}}t[3]=[],e._cache=c;let l=e._lifecycleEnd=tr(n);Qr(e,n),Nr(e,[...o.values(),...i].filter(e=>e._flight&&c.get(e.id)!==e),n),nr(e,i,n,a,l,t)}async function ei(e,t){let n=e._tx;for(;n&&n!==t;)t=n,await n[5],n=e._tx}function ti(e,t,n){let r=n[1].options,i=n[2];if(!i)return e.navigate({...r,replace:!0,ignoreBlocker:!0});if(r.reloadDocument)return e.navigate({href:(i.maskedLocation??i).publicHref,reloadDocument:!0,replace:!0,ignoreBlocker:!0});i._redirects=t[1]+1,e._pendingLocation=i;let a=e.commitLocation({...i,viewTransition:r.viewTransition,replace:!0,resetScroll:r.resetScroll,hashScrollIntoView:r.hashScrollIntoView,ignoreBlocker:!0});return queueMicrotask(()=>{e._pendingLocation===i&&(e._pendingLocation=void 0)}),a}async function ni(e,t,n,r,i){let a=n.map(e=>({...e}));Pr(a);for(let t of r)Mr(e,a[t[0]]),a[t[0]]=t[3];let o=[t[2],a],s;try{s=await Kr(e,o,r,t[0],i)}catch(t){throw Nr(e,a),t}if(wr(s)){Nr(e,a),s[0]===Sr&&e._tx===t&&e._committed===n&&await ti(e,t,s);return}if(await qr(e,s,t[0].signal),e._tx!==t||e._committed!==n){Nr(e,a);return}for(let t of a){let n=e._cache.get(t.id);n?._flight&&n._flight===t._flight&&(e._cache.delete(t.id),Mr(e,n))}Qr(e,a),Nr(e,n,a)}async function ri(e,t,n,r,i,a){let o=await Jr(e,t[2],t[3],[t[0],t[1],e._committed,void 0,i,n,a,r]);if(wr(o)){let n=o[0]===Sr&&e._tx===t;if((!n||o[1].options.reloadDocument)&&Xr(e,t),Nr(e,t[3]),t[3]=[],!n)return;if(e._tx!==t){Xr(e,t);return}await ti(e,t,o);return}let s=o[1];if(e._tx===t&&await Zr(e,t),e._tx!==t){Xr(e,t),Nr(e,s),Ur(e,o);return}let c=t[2],l=$n(c,e.stores.resolvedLocation.get()),u=o[2];await e.startViewTransition(async()=>{if(e._tx===t&&await Zr(e,t),e._tx!==t){Xr(e,t),Nr(e,s),Ur(e,o);return}let n=await e.startTransition(()=>{Xr(e,t),$r(e,t,s,a),e._tx===t&&(e.emit({type:`onLoad`,...l}),e._tx===t&&e.emit({type:`onBeforeRouteMount`,...l}))},s);if(e._tx!==t){Ur(e,o);return}u?.length&&ni(e,t,s,u,o[3]).catch(console.error),e.batch(()=>{e.stores.resolvedLocation.set(c),e.stores.status.set(`idle`),e._tx===t&&e.emit({type:`onResolved`,...l}),n&&e._tx===t&&e.emit({type:`onRendered`,...l})}),e._tx===t&&(e._commitPromise?.resolve(),e._commitPromise=void 0)})}async function ii(e,t){let n=e._tx,r=e.stores.resolvedLocation.get(),i=r??e.stores.location.get(),a=e.latestLocation,o=e._pendingLocation,s=o?.href===a.href?o._redirects??0:0,c=e._handoff,l=c?.[0](),u=new AbortController,d=e._preflight;if(e._preflight=u,l||c?.[1](),d?.abort(),!u.signal.aborted){let t=$n(a,r);e.emit({type:`onBeforeNavigate`,...t}),u.signal.aborted||e.emit({type:`onBeforeLoad`,...t})}if(u.signal.aborted){await ei(e,n);return}let f=i.href===a.href,p=u,m=e.matchRoutes(a,{_controller:u});Pr(m);let h=l?c[1](m):void 0;if(h?p=l:l?.abort(),u.signal.aborted){Nr(e,m),await ei(e,n);return}e._preflight=void 0;let g,_=()=>ri(e,y,f,()=>Yr(e,y),t?.sync,h),v=t?.sync?new Promise(e=>g=e):Promise.resolve().then(_),y=[p,s,a,m,Date.now(),v.then(()=>ei(e,y))];if(e._tx=y,n){for(let t of e.stores.matches.get()){if(e._tx!==y)break;t.isFetching&&Fr(e,t,!1)}n[0].abort(),Nr(e,n[3],y[3],!0)}if(e._tx!==y){Nr(e,y[3]),y[3]=[],g?.(),await ei(e,y);return}e.batch(()=>{e.stores.status.set(`pending`),e.stores.location.set(a)}),(h||!e._committed.length&&m[0]?.status!==`success`&&!m.some(e=>e._notFound))&&Yr(e,y),g?.(_()),await y[5]}async function ai(e,t){let n=e.buildLocation(t);for(let t=0;;t++){let r=e._committed,i=new AbortController,a,o,s;try{try{a=e.matchRoutes(n,{_controller:i}),Pr(a),o=(e._preloads??=new Map).set(i,a),s=await Jr(e,n,a,[i,t,r,!0])}finally{o&&(o=o.delete(i),Nr(e,a)),i.abort()}if(!wr(s))return s[1];if(!o||s.length<3)return;n=s[2]}catch(e){Vt(e)||console.error(e);return}}}var oi=`Error preloading route! ☝️`,si=class{get to(){return this._to}get id(){return this._id}get path(){return this._path}get fullPath(){return this._fullPath}constructor(e){if(this.init=e=>{this.originalIndex=e,this._branch=void 0;let t=this.options,n=!t?.path&&!t?.id;this.parentRoute=this.options.getParentRoute?.(),n?this._path=un:this.parentRoute||At();let r=n?un:t?.path;r&&r!==`/`&&(r=Mt(r));let i=t?.id||r,a=n?un:jt((this.parentRoute.id===`__root__`?``:this.parentRoute.id)+`/`+(i??``));r===`__root__`&&(r=`/`);let o=a===`__root__`?`/`:r===void 0?this.parentRoute.fullPath:jt(this.parentRoute.fullPath+`/`+r);this._path=r,this._id=a,this._fullPath=o,this._to=Nt(o)},this.addChildren=e=>this._addFileChildren(e),this._addFileChildren=e=>(Array.isArray(e)&&(this.children=e),typeof e==`object`&&e&&(this.children=Object.values(e)),this),this._addFileTypes=()=>this,this.updateLoader=e=>(Object.assign(this.options,e),this),this.update=e=>(Object.assign(this.options,e),this),this.lazy=e=>(this.lazyFn=e,this),this.redirect=e=>dn({from:this.fullPath,...e}),this.options=e||{},this.isRoot=!e?.getParentRoute,e?.id&&e?.path)throw Error(`Route cannot have both an 'id' and a 'path' option.`)}},ci=class extends si{constructor(e){super(e)}},li=class extends m.Component{constructor(...e){super(...e),this.state={error:0},this.reset=()=>{this.setState({error:0})}}static getDerivedStateFromProps(e,t){let n=e.getResetKey();return t.error&&t.resetKey!==n?{resetKey:n,error:0}:{resetKey:n}}static getDerivedStateFromError(e){return{error:[e]}}componentDidCatch(e,t){this.props.onCatch?.(e,t)}render(){let e=this.state.error;return e?m.createElement(this.props.errorComponent??ui,{error:e[0],reset:this.reset}):this.props.children}};function ui({error:e}){let[t,n]=m.useState(!1);return(0,h.jsxs)(`div`,{style:{padding:`.5rem`,maxWidth:`100%`},children:[(0,h.jsxs)(`div`,{style:{display:`flex`,alignItems:`center`,gap:`.5rem`},children:[(0,h.jsx)(`strong`,{style:{fontSize:`1rem`},children:`Something went wrong!`}),(0,h.jsx)(`button`,{style:{appearance:`none`,fontSize:`.6em`,border:`1px solid currentColor`,padding:`.1rem .2rem`,fontWeight:`bold`,borderRadius:`.25rem`},onClick:()=>n(e=>!e),children:t?`Hide Error`:`Show Error`})]}),(0,h.jsx)(`div`,{style:{height:`.25rem`}}),t?(0,h.jsx)(`div`,{children:(0,h.jsx)(`pre`,{style:{fontSize:`.7em`,border:`1px solid red`,borderRadius:`.25rem`,padding:`.3rem`,color:`red`,overflow:`auto`},children:e?.message?(0,h.jsx)(`code`,{children:e.message}):null})}):null]})}var di=()=>!0,fi=()=>!1;function pi({children:e,fallback:t=null}){return(0,h.jsx)(m.Fragment,{children:mi()?e:t})}function mi(e=!0){return m.useSyncExternalStore(hi,di,e?fi:di)}function hi(){return()=>{}}var gi=m.createContext(null);function _i(e){return m.useContext(gi)}var vi=m.createContext(void 0),yi=m.createContext(void 0);function bi({update:e,notify:t,unwatched:n}){return{link:r,unlink:i,propagate:a,checkDirty:o,shallowPropagate:s};function r(e,t,n){let r=t.depsTail;if(r!==void 0&&r.dep===e)return;let i=r===void 0?t.deps:r.nextDep;if(i!==void 0&&i.dep===e){i.version=n,t.depsTail=i;return}let a=e.subsTail;if(a!==void 0&&a.version===n&&a.sub===t)return;let o=t.depsTail=e.subsTail={version:n,dep:e,sub:t,prevDep:r,nextDep:i,prevSub:a,nextSub:void 0};i!==void 0&&(i.prevDep=o),r===void 0?t.deps=o:r.nextDep=o,a===void 0?e.subs=o:a.nextSub=o}function i(e,t=e.sub){let r=e.dep,i=e.prevDep,a=e.nextDep,o=e.nextSub,s=e.prevSub;return a===void 0?t.depsTail=i:a.prevDep=i,i===void 0?t.deps=a:i.nextDep=a,o===void 0?r.subsTail=s:o.prevSub=s,s===void 0?(r.subs=o)===void 0&&n(r):s.nextSub=o,a}function a(e){let n=e.nextSub,r;top:do{let i=e.sub,a=i.flags;if(a&60?a&12?a&4?!(a&48)&&c(e,i)?(i.flags=a|40,a&=1):a=0:i.flags=a&-9|32:a=0:i.flags=a|32,a&2&&t(i),a&1){let t=i.subs;if(t!==void 0){let i=(e=t).nextSub;i!==void 0&&(r={value:n,prev:r},n=i);continue}}if((e=n)!==void 0){n=e.nextSub;continue}for(;r!==void 0;)if(e=r.value,r=r.prev,e!==void 0){n=e.nextSub;continue top}break}while(1)}function o(t,n){let r,i=0,a=!1;top:do{let o=t.dep,c=o.flags;if(n.flags&16)a=!0;else if((c&17)==17){if(e(o)){let e=o.subs;e.nextSub!==void 0&&s(e),a=!0}}else if((c&33)==33){(t.nextSub!==void 0||t.prevSub!==void 0)&&(r={value:t,prev:r}),t=o.deps,n=o,++i;continue}if(!a){let e=t.nextDep;if(e!==void 0){t=e;continue}}for(;i--;){let i=n.subs,o=i.nextSub!==void 0;if(o?(t=r.value,r=r.prev):t=i,a){if(e(n)){o&&s(i),n=t.sub;continue}a=!1}else n.flags&=-33;n=t.sub;let c=t.nextDep;if(c!==void 0){t=c;continue top}}return a}while(1)}function s(e){do{let n=e.sub,r=n.flags;(r&48)==32&&(n.flags=r|16,(r&6)==2&&t(n))}while((e=e.nextSub)!==void 0)}function c(e,t){let n=t.depsTail;for(;n!==void 0;){if(n===e)return!0;n=n.prevDep}return!1}}function xi(e,t,n){let r=typeof e==`object`,i=r?e:void 0;return{next:(r?e.next:e)?.bind(i),error:(r?e.error:t)?.bind(i),complete:(r?e.complete:n)?.bind(i)}}var Si=[],Ci=0,{link:wi,unlink:Ti,propagate:Ei,checkDirty:Di,shallowPropagate:Oi}=bi({update(e){return e._update()},notify(e){Si[Ai++]=e,e.flags&=-3},unwatched(e){e.depsTail!==void 0&&(e.depsTail=void 0,e.flags=17,Pi(e))}}),ki=0,Ai=0,ji,Mi=0;function Ni(e){try{++Mi,e()}finally{--Mi||Fi()}}function Pi(e){let t=e.depsTail,n=t===void 0?e.deps:t.nextDep;for(;n!==void 0;)n=Ti(n,e)}function Fi(){if(!(Mi>0)){for(;ki{i.get(),n.current?t.next?.(i._snapshot):n.current=!0});return{unsubscribe:()=>{r.stop()}}},_update(e){let a=ji,o=t?.compare??Object.is;if(n)ji=i,++Ci,i.depsTail=void 0;else if(e===void 0)return!1;n&&(i.flags=5);try{let t=i._snapshot,a=typeof e==`function`?e(t):e===void 0&&n?r(t):e;return t===void 0||!o(t,a)?(i._snapshot=a,!0):!1}finally{ji=a,n&&(i.flags&=-5),Pi(i)}}};return n?(i.flags=17,i.get=function(){let e=i.flags;if(e&16||e&32&&Di(i.deps,i)){if(i._update()){let e=i.subs;e!==void 0&&Oi(e)}}else e&32&&(i.flags=e&-33);return ji!==void 0&&wi(i,ji,Ci),i._snapshot}):i.set=function(e){if(i._update(e)){let e=i.subs;e!==void 0&&(Ei(e),Oi(e),Fi())}},i}function Li(e){let t=()=>{let t=ji;ji=n,++Ci,n.depsTail=void 0,n.flags=6;try{return e()}finally{ji=t,n.flags&=-5,Pi(n)}},n={deps:void 0,depsTail:void 0,subs:void 0,subsTail:void 0,flags:6,notify(){let e=this.flags;e&16||e&32&&Di(this.deps,this)?t():this.flags=2},stop(){this.flags=0,this.depsTail=void 0,Pi(this)}};return t(),n}var Ri=n((e=>{var t=l();function n(e,t){return e===t&&(e!==0||1/e==1/t)||e!==e&&t!==t}var r=typeof Object.is==`function`?Object.is:n,i=t.useState,a=t.useEffect,o=t.useLayoutEffect,s=t.useDebugValue;function c(e,t){var n=t(),r=i({inst:{value:n,getSnapshot:t}}),c=r[0].inst,l=r[1];return o(function(){c.value=n,c.getSnapshot=t,u(c)&&l({inst:c})},[e,n,t]),a(function(){return u(c)&&l({inst:c}),e(function(){u(c)&&l({inst:c})})},[e]),s(n),n}function u(e){var t=e.getSnapshot;e=e.value;try{var n=t();return!r(e,n)}catch{return!0}}function d(e,t){return t()}var f=typeof window>`u`||window.document===void 0||window.document.createElement===void 0?d:c;e.useSyncExternalStore=t.useSyncExternalStore===void 0?f:t.useSyncExternalStore})),zi=n(((e,t)=>{t.exports=Ri()})),Bi=n((e=>{var t=l(),n=zi();function r(e,t){return e===t&&(e!==0||1/e==1/t)||e!==e&&t!==t}var i=typeof Object.is==`function`?Object.is:r,a=n.useSyncExternalStore,o=t.useRef,s=t.useEffect,c=t.useMemo,u=t.useDebugValue;e.useSyncExternalStoreWithSelector=function(e,t,n,r,l){var d=o(null);if(d.current===null){var f={hasValue:!1,value:null};d.current=f}else f=d.current;d=c(function(){function e(e){if(!a){if(a=!0,o=e,e=r(e),l!==void 0&&f.hasValue){var t=f.value;if(l(t,e))return s=t}return s=e}if(t=s,i(o,e))return t;var n=r(e);return l!==void 0&&l(t,n)?(o=e,t):(o=e,s=n)}var a=!1,o,s,c=n===void 0?null:n;return[function(){return e(t())},c===null?void 0:function(){return e(c())}]},[t,n,r,l]);var p=a(e,d[0],d[1]);return s(function(){f.hasValue=!0,f.value=p},[p]),u(p),p}})),Vi=n(((e,t)=>{t.exports=Bi()}))();function Hi(e,t){return e===t}function Ui(e,t=e=>e,n){let r=n?.compare??Hi,i=(0,m.useCallback)(t=>{let{unsubscribe:n}=e.subscribe(t);return n},[e]),a=(0,m.useCallback)(()=>e.get(),[e]);return(0,Vi.useSyncExternalStoreWithSelector)(i,a,a,t,r)}var Wi={};function Gi(e,t){let n=m.useRef();return r=>{let i=e?.select?e.select(r):r;return e?.structuralSharing??t.options.defaultStructuralSharing?n.current=gt(n.current,i):i}}function Ki(e){let t=_i(),n=m.useContext(e.from?yi:vi),r=e.from??n,i=t.stores.getMatchStore(r),a=Gi(e,t),o=Ui(i,e=>e?a(e):Wi);if(o!==Wi)return o;(e.shouldThrow??!0)&&At()}function qi(e){return Ki({from:e.from,strict:e.strict,structuralSharing:e.structuralSharing,select:t=>e.select?e.select(t.loaderData):t.loaderData})}function Ji(e){let{select:t,...n}=e;return Ki({...n,select:e=>t?t(e.loaderDeps):e.loaderDeps})}function Yi(e){return Ki({from:e.from,shouldThrow:e.shouldThrow,structuralSharing:e.structuralSharing,strict:e.strict,select:t=>{let n=e.strict===!1?t.params:t._strictParams;return e.select?e.select(n):n}})}function Xi(e){return Ki({from:e.from,strict:e.strict,shouldThrow:e.shouldThrow,structuralSharing:e.structuralSharing,select:t=>e.select?e.select(t.search):t.search})}function Zi(e){let t=_i();return m.useCallback(n=>t.navigate({...n,from:n.from??e?.from}),[e?.from,t])}function Qi(e){let t=_i(),n=Zi(),r=m.useRef(null);return lt(()=>{r.current!==e&&(n(e),r.current=e)},[t,e,n]),null}function $i(e){return Ki({...e,select:t=>e.select?e.select(t.context):t.context})}function ea(...e){let t=m.useRef(e),n=t.current;return e.forEach((e,t)=>{vt(n[t],e,!1,!0)||(n[t]=e)}),t.current}function ta(e,t){e.preloadRoute(t).catch(e=>{console.warn(e),console.warn(oi)})}var na={compare:(e,t)=>e[0]===t[0]&&e[1]===t[1]};function ra(e,t){let n=typeof e==`string`&&wt(e);if(n)return t.has(n)?e:null}function ia(e,t,n,r,i){let a=Ft(e.pathname,r),o=Ft(t.pathname,r);return(n?.exact?a!==o:!a.startsWith(o)||a.length!==o.length&&a[o.length]!==`/`)||(n?.includeSearch??!0)&&!vt(e.search,t.search,!n?.exact,n?.explicitUndefined)?!1:!n?.includeHash||i&&e.hash===t.hash}function aa(e,t,n){let r=_i(),i=m.useRef(null),a=m.useCallback(e=>{if(i.current=e,typeof t==`function`)return t(e);t&&(t.current=e)},[t]),{activeOptions:o,to:s,preload:c,preloadDelay:l,hashScrollIntoView:u,replace:d,startTransition:f,resetScroll:p,viewTransition:h,ignoreBlocker:g,disabled:_,target:v,onClick:y,onBlur:b,onFocus:x,onMouseEnter:S,onMouseLeave:C,onTouchStart:w}=e,T=mi(!!o?.includeHash),[ee,E,te]=ea(e.search,e.params,o),[D,ne]=m.useMemo(()=>[e,{...e}],[r,e.from,e._fromLocation,e.hash,e.to,ee,E,e.state,e.mask,e.unsafeRelative]),re=m.useCallback(e=>{let t=ra(s,r.protocolAllowlist);if(t!==void 0)return[t??void 0];D._fromLocation||(ne._fromLocation=e);let n=r.buildLocation(ne),i=fa(n,r,_);return[i,!_&&(!i||wt(i))?void 0:ia(e,n,te,r.basepath,T)]},[te,_,T,D,ne,r,s]),[ie,ae]=Ui(r.stores.location,re,na),oe=ae===void 0?ie:void 0,se=_||ie===void 0,ce=m.useRef(!1),le=e.reloadDocument||oe||se?!1:c??r.options.defaultPreload,ue=l??r.options.defaultPreloadDelay??0,de=m.useCallback(e=>{let t=e?.isIntersecting;if(!(t??le===`intent`)){t===!1&&P(i);return}if(!ue){ta(r,D);return}N.has(i)||N.set(i,setTimeout(()=>{N.delete(i),ta(r,D)},ue))},[r,D,i,le,ue]);m.useEffect(()=>{le===`render`&&!ce.current&&(ce.current=!0,ta(r,D));let e;return le===`viewport`&&i.current&&typeof IntersectionObserver==`function`&&(e=new IntersectionObserver(e=>de(e.pop()),{rootMargin:`100px`}),e.observe(i.current)),()=>{e?.disconnect(),P(i)}},[r,D,le,de,i]);let fe=la(e,n);if(fe.ref=t?a:i,oe)return fe.href=oe,fe;let pe=e=>{let t=v??e.currentTarget.getAttribute(`target`);!se&&!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&(!t||t===`_self`)&&e.button===0&&(e.preventDefault(),r.navigate({...D,replace:d,resetScroll:p,hashScrollIntoView:u,startTransition:f,viewTransition:h,ignoreBlocker:g}))},me=()=>{le===`intent`&&ta(r,D)},he=()=>{le===`intent`&&P(i)};return fe.onClick=da(y,pe),fe.onBlur=da(b,he),fe.onFocus=da(x,de),fe.onMouseEnter=da(S,de),fe.onMouseLeave=da(C,he),fe.onTouchStart=da(w,me),ua(fe,e,ae,ie,se,n)}var oa={},sa={className:`active`},ca=new Set([`to`,`params`,`search`,`hash`,`state`,`mask`,`from`,`unsafeRelative`,`_fromLocation`,`reloadDocument`,`preload`,`preloadDelay`,`preloadIntentProximity`,`hashScrollIntoView`,`replace`,`startTransition`,`resetScroll`,`viewTransition`,`ignoreBlocker`,`activeProps`,`inactiveProps`,`activeOptions`,`_asChild`]);function la(e,t){let n={};for(let r in e)ca.has(r)||r===`type`&&t!==void 0||r===`disabled`&&t===`a`||(n[r]=e[r]);return n}function ua(e,t,n,r,i,a){let{activeProps:o,inactiveProps:s,className:c,style:l,target:u}=t,d=dt(n?o:s,{})??(n?sa:oa);Object.assign(e,d),e.href=r,a!==`a`&&(e.disabled=i),e.target=u;let f=d.style;(l||f)&&(e.style=l&&f?{...l,...f}:l||f);let p=d.className;return(c||p)&&(e.className=c?p?`${c} ${p}`:c:p),i&&(e.role=`link`,e[`aria-disabled`]=!0),n&&(e[`data-status`]=`active`,e[`aria-current`]=`page`),e}var N=new WeakMap,P=e=>{clearTimeout(N.get(e)),N.delete(e)},da=(e,t)=>e?n=>n.defaultPrevented||(e(n),n.defaultPrevented||t(n)):t;function fa(e,t,n){if(n)return;let r=e.maskedLocation??e,i=r.external?r.publicHref:t.history.createHref(r.publicHref)||`/`;if(!r.external&&i===r.publicHref||!Et(i,t.protocolAllowlist))return i}var pa=m.memo(m.forwardRef((e,t)=>{let n=e._asChild||`a`,r=aa(e,t,n),i=typeof e.children==`function`?e.children({isActive:r[`data-status`]===`active`}):e.children;return m.createElement(n,r,i)}),ma);function ma(e,t){let n=0;for(let r in t)if(n++,e[r]!==t[r]&&(!ca.has(r)||!vt(e[r],t[r],!1,!0)))return!1;for(let t in e)n--;return n===0}var ha=class extends si{constructor(e){super(e),this.useMatch=e=>Ki({...e,from:this.id}),this.useRouteContext=e=>$i({...e,from:this.id}),this.useSearch=e=>Xi({...e,from:this.id}),this.useParams=e=>Yi({...e,from:this.id}),this.useLoaderDeps=e=>Ji({...e,from:this.id}),this.useLoaderData=e=>qi({...e,from:this.id}),this.useNavigate=()=>Zi({from:this.fullPath}),this.Link=m.forwardRef((e,t)=>(0,h.jsx)(pa,{ref:t,from:this.fullPath,...e}))}};function ga(e){return new ha(e)}var _a=class extends ci{constructor(e){super(e),this.useMatch=e=>Ki({...e,from:this.id}),this.useRouteContext=e=>$i({...e,from:this.id}),this.useSearch=e=>Xi({...e,from:this.id}),this.useParams=e=>Yi({...e,from:this.id}),this.useLoaderDeps=e=>Ji({...e,from:this.id}),this.useLoaderData=e=>qi({...e,from:this.id}),this.useNavigate=()=>Zi({from:this.fullPath}),this.Link=m.forwardRef((e,t)=>(0,h.jsx)(pa,{ref:t,from:this.fullPath,...e}))}};function va(e){return new _a(e)}function ya(e,t){let n,r,i,a=()=>(n||=(i=void 0,e().then(e=>{n=void 0,o.preload=void 0,r=e[t??`default`]}).catch(e=>{n=void 0,i=e})),n),o=function(e){if(i){if(yt(i)&&typeof sessionStorage<`u`){let e=`tanstack_router_reload:${i.message}`;if(!sessionStorage.getItem(e))throw sessionStorage.setItem(e,`1`),window.location.reload(),new Promise(()=>{})}throw i}if(!r){if(ct)ct(a());else throw a()}return m.createElement(r,e)};return o.preload=a,o}function ba(e){let t=_i(),n=`not-found-${Ui(t.stores.location,e=>e.pathname)}-${Ui(t.stores.status)}`;return(0,h.jsx)(li,{getResetKey:()=>n,onCatch:(t,n)=>{if(Vt(t))e.onCatch?.(t,n);else throw t},errorComponent:({error:t})=>{if(Vt(t))return e.fallback?.(t);throw t},children:e.children})}function xa(){return(0,h.jsx)(`p`,{children:`Not Found`})}function Sa(e){return(0,h.jsx)(h.Fragment,{children:e.children})}function Ca(e,t,n){return t.options.notFoundComponent?(0,h.jsx)(t.options.notFoundComponent,{...n}):e.options.defaultNotFoundComponent?(0,h.jsx)(e.options.defaultNotFoundComponent,{...n}):(0,h.jsx)(xa,{})}function wa(e,t){let n=t?.options.pendingComponent??e.options.defaultPendingComponent;return n?(0,h.jsx)(n,{}):null}var Ta=(e,t)=>e[0]===t[0]&&e[1]===t[1],Ea=(e,t,n)=>!t.isRoot||t.options.shellComponent||t.options.wrapInSuspense||n===!1||n===`data-only`||!e.ssr,Da=m.memo(function({routeId:e}){let t=_i();return(0,h.jsx)(Oa,{router:t,match:Ui(t.stores.getMatchStore(e))})});function Oa({router:e,match:t}){let n=e.routesById[t.routeId],r=wa(e,n),i=n.options.errorComponent??e.options.defaultErrorComponent,a=n.options.onCatch??e.options.defaultOnCatch,o=n.isRoot?n.options.notFoundComponent??e.options.notFoundRoute?.options.component:n.options.notFoundComponent,s=t.ssr===!1||t.ssr===`data-only`,c=Ea(e,n,t.ssr)&&(n.options.wrapInSuspense??r??(n.options.errorComponent?.preload||s))?m.Suspense:Sa,l=i?li:Sa,u=o?ba:Sa;return(0,h.jsxs)(n.isRoot?n.options.shellComponent??Sa:Sa,{children:[(0,h.jsx)(vi.Provider,{value:t.routeId,children:(0,h.jsx)(c,{fallback:r,children:(0,h.jsx)(l,{getResetKey:()=>t,errorComponent:i,onCatch:(e,n)=>{if(Vt(e))throw e.routeId??=t.routeId,e;a?.(e,n)},children:(0,h.jsx)(u,{fallback:e=>{if(e.routeId??=t.routeId,e.routeId!==t.routeId)throw e;return m.createElement(o,e)},children:s?(0,h.jsx)(pi,{fallback:r,children:(0,h.jsx)(ka,{match:t})}):(0,h.jsx)(ka,{match:t})})})})}),null]})}var ka=m.memo(function({match:e}){let t=_i(),n=e.routeId,r=t.routesById[n],i=m.useMemo(()=>{let i=(r.options.remountDeps??t.options.defaultRemountDeps)?.({routeId:n,loaderDeps:e.loaderDeps,params:e._strictParams,search:e._strictSearch});return i?JSON.stringify(i):void 0},[n,e.loaderDeps,e._strictParams,e._strictSearch,r.options.remountDeps,t.options.defaultRemountDeps]),a=m.useMemo(()=>{let e=r.options.component??t.options.defaultComponent;return e?(0,h.jsx)(e,{},i):(0,h.jsx)(Aa,{})},[i,r.options.component,t.options.defaultComponent]);if(e.status===`pending`){if(t.ssr&&!Ea(t,r,e.ssr))return a;if(t._tx)throw t._tx[5];return wa(t,r)}if(e.status===`notFound`)return Ca(t,r,e.error);if(e.status===`error`)throw e.error;return a}),Aa=m.memo(function(){let e=_i(),t=m.useContext(vi),n,r,i;{let a=e.stores.getMatchStore(t);[n,r]=Ui(a,e=>[!!e._notFound,e.error],{compare:Ta}),i=Ui(e.stores.ids,e=>e[e.indexOf(t)+1])}if(n)return Ca(e,e.routesById[t],r);if(!i)return null;let a=(0,h.jsx)(Da,{routeId:i});return t===`__root__`?(0,h.jsx)(m.Suspense,{fallback:wa(e),children:a}):a});function ja(e,t){let n=e[1];e.length=0,n?.(t)}function Ma({t:e}){let t=_i(),n=t._rendered??=[];return t.startTransition=(r,i)=>new Promise(a=>{ja(n,!1),n.push(i,a),e(t),m.startTransition(r)}),lt(()=>{let e=t.history.subscribe(t.load);t.updateLatestLocation();let r=t.latestLocation,i=t.buildLocation({to:r.pathname,search:!0,params:!0,hash:!0,state:!0,_includeValidateSearch:!0});if(Nt(r.publicHref)!==Nt(i.publicHref))return t.commitLocation({...i,replace:!0,ignoreBlocker:!0}),e;let a=t.stores.resolvedLocation.get();return a?.href===r.href&&a.state.__TSR_key===r.state.__TSR_key?n.push(t.stores.matches.get(),e=>{e&&t.emit({type:`onRendered`,...$n(a,a)})}):t._tx||t.load({sync:!0}).catch(console.error),e},[t,t.history]),null}function Na(){let e=_i(),t=e.routesById[un],n=wa(e,t),r=e.ssr?Sa:m.Suspense,i=(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(Ma,{t:m.useState()[1]}),(0,h.jsx)(r,{fallback:n,children:(0,h.jsx)(Pa,{})})]});return e.options.InnerWrap?(0,h.jsx)(e.options.InnerWrap,{children:i}):i}function Pa(){let e=_i(),t=e._rendered,n=Ui(e.stores.matches,e=>t[0]??e),r=n[0],i=r?.routeId;lt(()=>{t[0]===n&&ja(t,!0)},[t,n]);let a=i?(0,h.jsx)(Da,{routeId:i}):null;return(0,h.jsx)(vi.Provider,{value:i,children:e.options.disableGlobalCatchBoundary?a:(0,h.jsx)(li,{getResetKey:()=>r,onCatch:void 0,children:a})})}var Fa=e=>({createMutableStore:Ii,createReadonlyStore:Ii,batch:Ni}),Ia=e=>new La(e),La=class extends rr{constructor(e){super(e,Fa)}};function Ra({router:e,children:t,...n}){pt(n)&&e.update({...e.options,...n,context:{...e.options.context,...n.context}});let r=(0,h.jsx)(gi.Provider,{value:e,children:t});return e.options.Wrap?(0,h.jsx)(e.options.Wrap,{children:r}):r}function za({router:e,...t}){return(0,h.jsx)(Ra,{router:e,...t,children:(0,h.jsx)(Na,{})})}var Ba=p(),F=s();function Va(e){let t=(0,F.c)(6),{error:n}=e,r;t[0]===Symbol.for(`react.memo_cache_sentinel`)?(r=(0,h.jsx)(`p`,{className:`schild text-lg text-rot`,children:`Diese Ansicht ist abgestürzt`}),t[0]=r):r=t[0];let i=n instanceof Error?n.message:String(n),a;t[1]===i?a=t[2]:(a=(0,h.jsx)(`p`,{className:`text-[15px]`,children:i}),t[1]=i,t[2]=a);let o;t[3]===Symbol.for(`react.memo_cache_sentinel`)?(o=(0,h.jsx)(`button`,{type:`button`,onClick:Ha,className:`schild h-11 rounded-lg border border-rot-rand px-5 text-sm text-foreground hover:bg-[#3a1512]`,children:`Neu laden`}),t[3]=o):o=t[3];let s;return t[4]===a?s=t[5]:(s=(0,h.jsxs)(`div`,{role:`alert`,className:`flex flex-col items-start gap-3 rounded-2xl border border-rot-rand bg-rot-grund p-6 text-rot-text`,children:[r,a,o]}),t[4]=a,t[5]=s),s}function Ha(){return window.location.reload()}var Ua={name:`cpu`,size:24,node:[[`path`,{d:`M12 20v2`,key:`1lh1kg`}],[`path`,{d:`M12 2v2`,key:`tus03m`}],[`path`,{d:`M17 20v2`,key:`1rnc9c`}],[`path`,{d:`M17 2v2`,key:`11trls`}],[`path`,{d:`M2 12h2`,key:`1t8f8n`}],[`path`,{d:`M2 17h2`,key:`7oei6x`}],[`path`,{d:`M2 7h2`,key:`asdhe0`}],[`path`,{d:`M20 12h2`,key:`1q8mjw`}],[`path`,{d:`M20 17h2`,key:`1fpfkl`}],[`path`,{d:`M20 7h2`,key:`1o8tra`}],[`path`,{d:`M7 20v2`,key:`4gnj0m`}],[`path`,{d:`M7 2v2`,key:`1i4yhu`}],[`rect`,{x:`4`,y:`4`,width:`16`,height:`16`,rx:`2`,key:`1vbyd7`}],[`rect`,{x:`8`,y:`8`,width:`8`,height:`8`,rx:`1`,key:`z9xiuo`}]]};Ua.node;var Wa=o(Ua),Ga={name:`ellipsis`,size:24,node:[[`circle`,{cx:`12`,cy:`12`,r:`1`,key:`41hilf`}],[`circle`,{cx:`19`,cy:`12`,r:`1`,key:`1wjl8i`}],[`circle`,{cx:`5`,cy:`12`,r:`1`,key:`1pcz8c`}]],aliases:[`more-horizontal`]};Ga.node;var Ka=o(Ga),qa={name:`external-link`,size:24,node:[[`path`,{d:`M15 3h6v6`,key:`1q9fwt`}],[`path`,{d:`M10 14 21 3`,key:`gplh6r`}],[`path`,{d:`M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6`,key:`a6xqqp`}]]};qa.node;var Ja=o(qa),Ya={name:`house`,size:24,node:[[`path`,{d:`M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8`,key:`5wwlr5`}],[`path`,{d:`M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z`,key:`r6nss1`}]],aliases:[`home`]};Ya.node;var Xa=o(Ya),Za={name:`refresh-cw`,size:24,node:[[`path`,{d:`M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8`,key:`v9h5vc`}],[`path`,{d:`M21 3v5h-5`,key:`1q7to0`}],[`path`,{d:`M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16`,key:`3uifl3`}],[`path`,{d:`M8 16H3v5`,key:`1cv678`}]]};Za.node;var Qa=o(Za),$a={name:`scroll-text`,size:24,node:[[`path`,{d:`M15 12h-5`,key:`r7krc0`}],[`path`,{d:`M15 8h-5`,key:`1khuty`}],[`path`,{d:`M19 17V5a2 2 0 0 0-2-2H4`,key:`zz82l3`}],[`path`,{d:`M8 21h12a2 2 0 0 0 2-2v-1a1 1 0 0 0-1-1H11a1 1 0 0 0-1 1v1a2 2 0 1 1-4 0V5a2 2 0 1 0-4 0v2a1 1 0 0 0 1 1h3`,key:`1ph1d7`}]]};$a.node;var eo=o($a),to={name:`settings`,size:24,node:[[`path`,{d:`M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915`,key:`1i5ecw`}],[`circle`,{cx:`12`,cy:`12`,r:`3`,key:`1v7zrd`}]]};to.node;var no=o(to),ro=`verbinde`,io=null,ao=new Set,oo=()=>ao.forEach(e=>e());function so(e){return ao.add(e),()=>{ao.delete(e)}}var co=()=>ro===`live`,lo=()=>(0,m.useSyncExternalStore)(so,ho),uo=()=>(0,m.useSyncExternalStore)(so,go);function fo(e){io=e,oo()}function po(e){e!==ro&&(ro=e,oo())}function mo(){let e=_();(0,m.useEffect)(()=>{let t=new EventSource(`/api/stream`);return t.onopen=()=>{po(`live`),e.invalidateQueries()},t.onerror=()=>po(`getrennt`),t.addEventListener(`invalidate`,t=>{try{let n=JSON.parse(t.data)?.keys??[];for(let t of n)e.invalidateQueries({queryKey:[t]})}catch{}}),t.addEventListener(`metrik`,e=>{try{fo(JSON.parse(e.data))}catch{}}),()=>{t.close(),po(`getrennt`)}},[e])}function ho(){return ro}function go(){return io}var _o=[],vo=1,yo=new Set,bo=()=>yo.forEach(e=>e());function xo(e,t){let n=vo++;_o=[..._o,{id:n,art:e,text:t}].slice(-4),bo(),e!==`fehler`&&window.setTimeout(()=>So(n),6e3)}function So(e){_o=_o.filter(t=>t.id!==e),bo()}var Co=()=>(0,m.useSyncExternalStore)(wo,To);function wo(e){return yo.add(e),()=>{yo.delete(e)}}function To(){return _o}var Eo={erfolg:`border-gruen-rand bg-gruen-grund text-gruen-text`,fehler:`border-rot-rand bg-rot-grund text-rot-text`,info:`border-cyan-rand bg-cyan-grund text-cyan-text`};function Do(){let e=(0,F.c)(4),t=Co(),n;e[0]===t?n=e[1]:(n=t.map(Oo),e[0]=t,e[1]=n);let r;return e[2]===n?r=e[3]:(r=(0,h.jsx)(`div`,{"aria-live":`polite`,className:`pointer-events-none fixed right-4 bottom-24 left-4 z-50 flex flex-col items-end gap-2 md:bottom-6 md:left-auto md:w-[420px]`,children:n}),e[2]=n,e[3]=r),r}function Oo(t){return(0,h.jsxs)(`div`,{role:t.art===`fehler`?`alert`:`status`,className:i(`pointer-events-auto flex w-full items-start gap-3 rounded-xl border px-4 py-3 text-[15px] shadow-lg`,Eo[t.art]),children:[(0,h.jsx)(`span`,{className:`min-w-0 flex-1`,children:t.text}),(0,h.jsx)(`button`,{type:`button`,onClick:()=>So(t.id),"aria-label":`Meldung schließen`,className:`-m-2 p-2 opacity-70 hover:opacity-100`,children:(0,h.jsx)(e,{className:`size-4`})})]},t.id)}var ko=`modulepreload`,Ao=function(e){return`/`+e},jo={},Mo=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function s(e){return import.meta.resolve?import.meta.resolve(e):new URL(e,import.meta.url).href}r=o(t.map(t=>{if(t=Ao(t,n),t=s(t),t in jo)return;jo[t]=!0;let r=t.endsWith(`.css`);for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}let i=document.createElement(`link`);if(i.rel=r?`stylesheet`:ko,r||(i.as=`script`),i.crossOrigin=``,i.href=t,a&&i.setAttribute(`nonce`,a),document.head.appendChild(i),r)return new Promise((e,n)=>{i.addEventListener(`load`,e),i.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}).filter(e=>e!==void 0))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},No=(0,m.lazy)(()=>Mo(()=>import(`./Dienste-DEn0Zjkq.js`).then(e=>({default:e.Dienste})),__vite__mapDeps([0,1,2,3]))),Po=(0,m.lazy)(()=>Mo(()=>import(`./Einstellungen-BwCmWl9x.js`).then(e=>({default:e.Einstellungen})),__vite__mapDeps([4,1,2,3]))),Fo=(0,m.lazy)(()=>Mo(()=>import(`./MehrMenue-CXteqmy8.js`).then(e=>({default:e.MehrMenue})),__vite__mapDeps([5,1,2,3]))),Io=[{to:`/`,label:`Start`,Icon:Xa},{to:`/updates`,label:`Updates`,Icon:Qa},{to:`/modelle`,label:`Modelle`,Icon:Wa}],Lo=new Intl.DateTimeFormat(`de-DE`,{hour:`2-digit`,minute:`2-digit`,timeZone:`Europe/Berlin`}),Ro=new Intl.DateTimeFormat(`de-DE`,{weekday:`short`,day:`2-digit`,month:`2-digit`,timeZone:`Europe/Berlin`});function zo(){let e=(0,F.c)(13),[t,n]=(0,m.useState)(Bo),r,i;e[0]===Symbol.for(`react.memo_cache_sentinel`)?(r=()=>{let e=window.setInterval(()=>n(new Date),2e4);return()=>window.clearInterval(e)},i=[],e[0]=r,e[1]=i):(r=e[0],i=e[1]),(0,m.useEffect)(r,i);let a;e[2]===t?a=e[3]:(a=Lo.format(t),e[2]=t,e[3]=a);let o;e[4]===a?o=e[5]:(o=(0,h.jsx)(`span`,{className:`ziffern text-2xl font-medium`,children:a}),e[4]=a,e[5]=o);let s;e[6]===t?s=e[7]:(s=Ro.format(t).replace(`,`,``),e[6]=t,e[7]=s);let c;e[8]===s?c=e[9]:(c=(0,h.jsx)(`span`,{className:`schild text-[13px] text-text-3`,children:s}),e[8]=s,e[9]=c);let l;return e[10]!==o||e[11]!==c?(l=(0,h.jsxs)(`div`,{className:`flex flex-col items-end leading-tight`,children:[o,c]}),e[10]=o,e[11]=c,e[12]=l):l=e[12],l}function Bo(){return new Date}function Vo(){let e=(0,F.c)(9),t=lo(),n=t===`live`,r=n?`bg-gruen shadow-[0_0_8px_rgba(61,220,138,0.7)]`:`bg-bernstein`,a;e[0]===r?a=e[1]:(a=i(`size-2 rounded-full`,r),e[0]=r,e[1]=a);let o;e[2]===a?o=e[3]:(o=(0,h.jsx)(`span`,{className:a}),e[2]=a,e[3]=o);let s=n?`Box online`:t===`verbinde`?`Verbinde`:`Getrennt`,c;e[4]===s?c=e[5]:(c=(0,h.jsx)(`span`,{children:s}),e[4]=s,e[5]=c);let l;return e[6]!==o||e[7]!==c?(l=(0,h.jsxs)(`div`,{className:`schild flex items-center gap-2 text-[15px] text-text-3`,"aria-live":`polite`,children:[o,c]}),e[6]=o,e[7]=c,e[8]=l):l=e[8],l}function Ho(){let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t=(0,h.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,h.jsxs)(`svg`,{width:`34`,height:`34`,viewBox:`0 0 34 34`,fill:`none`,"aria-hidden":!0,children:[(0,h.jsx)(`rect`,{x:`1.5`,y:`1.5`,width:`31`,height:`31`,rx:`8`,stroke:`var(--linie-stark)`,strokeWidth:`2`}),(0,h.jsx)(`path`,{d:`M7 18h5l3-7 4 13 3-6h5`,stroke:`var(--bernstein)`,strokeWidth:`2.2`,strokeLinecap:`round`,strokeLinejoin:`round`})]}),(0,h.jsx)(`span`,{className:`font-anzeige text-[28px] leading-none font-bold tracking-[0.06em]`,children:`MC2`}),(0,h.jsx)(`span`,{className:`hidden h-6 w-px bg-linie sm:block`}),(0,h.jsx)(`span`,{className:`schild hidden text-base tracking-[0.22em] text-text-3 sm:block`,children:`Box-Wart`})]}),e[0]=t):t=e[0],t}function Uo(){let e=(0,F.c)(26);mo();let[t,n]=(0,m.useState)(null),r;e[0]===Symbol.for(`react.memo_cache_sentinel`)?(r=()=>n(null),e[0]=r):r=e[0];let i=r,a;e[1]===Symbol.for(`react.memo_cache_sentinel`)?(a=(0,h.jsx)(Ho,{}),e[1]=a):a=e[1];let o;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(o=(0,h.jsx)(`nav`,{"aria-label":`Hauptnavigation`,className:`hidden gap-1 rounded-xl border border-linie bg-[#121518] p-1 md:flex`,children:Io.map(Go)}),e[2]=o):o=e[2];let s;e[3]===Symbol.for(`react.memo_cache_sentinel`)?(s=(0,h.jsx)(`div`,{className:`hidden lg:block`,children:(0,h.jsx)(Vo,{})}),e[3]=s):s=e[3];let c;e[4]===Symbol.for(`react.memo_cache_sentinel`)?(c=(0,h.jsx)(`a`,{href:`/hermes-ui/`,target:`_blank`,rel:`noopener`,className:`flex size-11 items-center justify-center rounded-lg text-text-2 hover:bg-erhaben hover:text-foreground`,title:`Hermes-Dashboard öffnen`,"aria-label":`Hermes-Dashboard öffnen`,children:(0,h.jsx)(Ja,{className:`size-5`})}),e[4]=c):c=e[4];let l;e[5]===Symbol.for(`react.memo_cache_sentinel`)?(l=()=>n(`dienste`),e[5]=l):l=e[5];let u;e[6]===Symbol.for(`react.memo_cache_sentinel`)?(u=(0,h.jsx)(`button`,{type:`button`,onClick:l,className:`flex size-11 items-center justify-center rounded-lg text-text-2 hover:bg-erhaben hover:text-foreground`,title:`Dienste und Protokolle`,"aria-label":`Dienste und Protokolle`,children:(0,h.jsx)(eo,{className:`size-5`})}),e[6]=u):u=e[6];let d;e[7]===Symbol.for(`react.memo_cache_sentinel`)?(d=()=>n(`einstellungen`),e[7]=d):d=e[7];let f;e[8]===Symbol.for(`react.memo_cache_sentinel`)?(f=(0,h.jsxs)(`header`,{className:`flex items-center justify-between gap-4 md:gap-6`,children:[a,o,(0,h.jsxs)(`div`,{className:`flex items-center gap-4 md:gap-5`,children:[s,(0,h.jsxs)(`div`,{className:`hidden items-center gap-1 md:flex`,children:[c,u,(0,h.jsx)(`button`,{type:`button`,onClick:d,className:`flex size-11 items-center justify-center rounded-lg text-text-2 hover:bg-erhaben hover:text-foreground`,title:`Einstellungen`,"aria-label":`Einstellungen`,children:(0,h.jsx)(no,{className:`size-5`})})]}),(0,h.jsx)(zo,{})]})]}),e[8]=f):f=e[8];let p;e[9]===Symbol.for(`react.memo_cache_sentinel`)?(p=(0,h.jsx)(`main`,{className:`flex min-w-0 flex-col gap-5 md:gap-6`,children:(0,h.jsx)(Aa,{})}),e[9]=p):p=e[9];let g;e[10]===Symbol.for(`react.memo_cache_sentinel`)?(g=Io.map(Wo),e[10]=g):g=e[10];let _;e[11]===Symbol.for(`react.memo_cache_sentinel`)?(_=()=>n(`mehr`),e[11]=_):_=e[11];let v;e[12]===Symbol.for(`react.memo_cache_sentinel`)?(v=(0,h.jsxs)(`nav`,{"aria-label":`Hauptnavigation`,className:`fixed inset-x-0 bottom-0 z-40 grid grid-cols-4 gap-1 border-t border-linie bg-[#0e1119]/95 px-2 pt-2 pb-[calc(0.75rem+env(safe-area-inset-bottom))] backdrop-blur md:hidden`,children:[g,(0,h.jsxs)(`button`,{type:`button`,onClick:_,className:`schild flex h-14 flex-col items-center justify-center gap-1 rounded-lg text-xs text-text-3`,children:[(0,h.jsx)(Ka,{className:`size-5`,"aria-hidden":!0}),`Mehr`]})]}),e[12]=v):v=e[12];let y;e[13]===t?y=e[14]:(y=t===`mehr`&&(0,h.jsx)(Fo,{verbindung:(0,h.jsx)(Vo,{}),onDienste:()=>n(`dienste`),onEinstellungen:()=>n(`einstellungen`),onSchliessen:i}),e[13]=t,e[14]=y);let b;e[15]===t?b=e[16]:(b=t===`dienste`&&(0,h.jsx)(No,{offen:!0,onSchliessen:i}),e[15]=t,e[16]=b);let x;e[17]===t?x=e[18]:(x=t===`einstellungen`&&(0,h.jsx)(Po,{offen:!0,onSchliessen:i}),e[17]=t,e[18]=x);let S;e[19]!==y||e[20]!==b||e[21]!==x?(S=(0,h.jsxs)(m.Suspense,{fallback:null,children:[y,b,x]}),e[19]=y,e[20]=b,e[21]=x,e[22]=S):S=e[22];let C;e[23]===Symbol.for(`react.memo_cache_sentinel`)?(C=(0,h.jsx)(Do,{}),e[23]=C):C=e[23];let w;return e[24]===S?w=e[25]:(w=(0,h.jsxs)(`div`,{className:`mx-auto flex min-h-dvh w-full max-w-[1440px] flex-col gap-5 px-4 pt-4 pb-28 sm:px-6 md:gap-6 md:px-10 md:pt-8 md:pb-10`,children:[f,p,v,S,C]}),e[24]=S,e[25]=w),w}function Wo(e){let{to:t,label:n,Icon:r}=e;return(0,h.jsxs)(pa,{to:t,className:`schild flex h-14 flex-col items-center justify-center gap-1 rounded-lg text-xs text-text-3`,activeProps:{className:`bg-erhaben !text-foreground`},activeOptions:{exact:!0},children:[(0,h.jsx)(r,{className:`size-5`,"aria-hidden":!0}),n]},t)}function Go(e){let{to:t,label:n}=e;return(0,h.jsx)(pa,{to:t,className:`schild flex h-11 items-center rounded-[9px] border border-transparent px-5 text-base text-text-3 hover:text-foreground`,activeProps:{className:`!border-linie-stark bg-erhaben !text-foreground`},activeOptions:{exact:!0},children:n},t)}var Ko=class extends Error{status;detail;constructor(e,t){super(t),this.status=e,this.detail=t,this.name=`ApiFehler`}};function qo(e,t){if(e&&typeof e==`object`&&`detail`in e){let t=e.detail;if(typeof t==`string`)return t;if(Array.isArray(t))return t.map(e=>e.msg??String(e)).join(`; `)}return`Die Box antwortet mit Fehler ${t}.`}async function I(e,t={}){let n;try{n=await fetch(e,{...t,headers:{"Content-Type":`application/json`,Accept:`application/json`,...t.headers}})}catch{throw new Ko(0,`MC2 ist nicht erreichbar. Läuft die Box?`)}let r=await n.text(),i=r?L(r):null;if(!n.ok)throw new Ko(n.status,qo(i,n.status));if(typeof i==`string`)throw new Ko(n.status,`Die Box antwortet nicht mit Daten.`);return i}function L(e){try{return JSON.parse(e)}catch{return e}}var R=(e,t)=>I(e,{method:`POST`,body:t===void 0?void 0:JSON.stringify(t)}),Jo=e=>()=>co()?e*5:e,Yo=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={queryKey:[`start`],queryFn:ms,refetchInterval:hs},e[0]=t):t=e[0],ot(t)},Xo=()=>{let e=(0,F.c)(2),t;e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t=[`models`],e[0]=t):t=e[0];let n;return e[1]===Symbol.for(`react.memo_cache_sentinel`)?(n={queryKey:t,queryFn:gs,refetchInterval:Jo(3e4)},e[1]=n):n=e[1],ot(n)},Zo=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={queryKey:[`nutzung`],queryFn:_s,refetchInterval:6e5},e[0]=t):t=e[0],ot(t)},Qo=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={queryKey:[`radar`],queryFn:vs,retry:!1,refetchInterval:3e5},e[0]=t):t=e[0],ot(t)},$o=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={queryKey:[`jobs`],queryFn:ys,refetchInterval:xs},e[0]=t):t=e[0],ot(t)},es=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={queryKey:[`sicherungen`],queryFn:Ss},e[0]=t):t=e[0],ot(t)},z=e=>{let t=(0,F.c)(7),n,r;t[0]===e?(n=t[1],r=t[2]):(n=[`update-details`,e],r=()=>I(`/api/maintenance/update-details?kind=${e}`),t[0]=e,t[1]=n,t[2]=r);let i=!!e,a;return t[3]!==n||t[4]!==r||t[5]!==i?(a={queryKey:n,queryFn:r,enabled:i,staleTime:6e5},t[3]=n,t[4]=r,t[5]=i,t[6]=a):a=t[6],ot(a)},ts=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={queryKey:[`updates-verlauf`],queryFn:Cs},e[0]=t):t=e[0],ot(t)},ns=e=>{let t=(0,F.c)(7),n,r;t[0]===e?(n=t[1],r=t[2]):(n=[`protokoll`,e],r=()=>I(`/api/maintenance/logs?service=${encodeURIComponent(e??``)}&lines=200`),t[0]=e,t[1]=n,t[2]=r);let i=!!e,a;return t[3]!==n||t[4]!==r||t[5]!==i?(a={queryKey:n,queryFn:r,enabled:i},t[3]=n,t[4]=r,t[5]=i,t[6]=a):a=t[6],ot(a)},rs=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={queryKey:[`dienste`],queryFn:ws},e[0]=t):t=e[0],ot(t)};function is(e,t){let n=(0,F.c)(6),r=_(),i;n[0]!==t||n[1]!==r?(i=(e,n)=>{let i=e;i&&i.ok===!1?xo(`fehler`,i.detail||i.err||`Das hat nicht geklappt.`):xo(`erfolg`,t.erfolg(n,e));for(let e of t.neuLaden)r.invalidateQueries({queryKey:[e]})},n[0]=t,n[1]=r,n[2]=i):i=n[2];let a;return n[3]!==e||n[4]!==i?(a={mutationFn:e,onSuccess:i,onError:as},n[3]=e,n[4]=i,n[5]=a):a=n[5],st(a)}function as(e){return xo(`fehler`,e.message)}var os=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={erfolg:Es,neuLaden:[`start`]},e[0]=t):t=e[0],is(Ts,t)},ss={alle:`/api/maintenance/update-all`,pruefen:`/api/maintenance/check-updates`,os:`/api/maintenance/os-update`,engine:`/api/maintenance/engine-update`,swap:`/api/maintenance/swap-update`,hermes:`/api/maintenance/hermes-update`},cs=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={erfolg:Os,neuLaden:[`jobs`,`start`]},e[0]=t):t=e[0],is(Ds,t)},ls=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={erfolg:As,neuLaden:[`start`]},e[0]=t):t=e[0],is(ks,t)},B=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={erfolg:Ms,neuLaden:[`sicherungen`,`start`]},e[0]=t):t=e[0],is(js,t)},us=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={erfolg:Ps,neuLaden:[`sicherungen`]},e[0]=t):t=e[0],is(Ns,t)},ds=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={erfolg:Is,neuLaden:[`models`,`start`]},e[0]=t):t=e[0],is(Fs,t)},fs=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={erfolg:Rs,neuLaden:[`radar`,`models`,`start`]},e[0]=t):t=e[0],is(Ls,t)},ps=()=>{let e=(0,F.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={erfolg:Bs,neuLaden:[`radar`]},e[0]=t):t=e[0],is(zs,t)};function ms(){return I(`/api/start`)}function hs(e){return e.state.data&&!e.state.data.updates.gelesen?4e3:Jo(2e4)()}function gs(){return I(`/api/models`)}function _s(){return I(`/api/modelle/nutzung`)}function vs(){return I(`/api/radar`)}function ys(){return I(`/api/jobs`)}function bs(e){return e.state===`running`||e.state===`queued`}function xs(e){return e.state.data?.jobs.some(bs)?2e3:Jo(3e4)()}function Ss(){return I(`/api/zeitmaschine`)}function Cs(){return I(`/api/updates/verlauf`)}function ws(){return I(`/api/system/services`)}function Ts(e){let{hinweis:t,aktion:n}=e;return R(`/api/hinweise/${encodeURIComponent(t)}/aktion/${n}`)}function Es(e){return`${e.label}: erledigt. Der Wächter prüft in einer Minute nach.`}function Ds(e){return R(ss[e])}function Os(e){return e===`pruefen`?`Suche nach Neuem läuft.`:`Update läuft. Den Fortschritt siehst du unten.`}function ks(e){return R(`/api/updates/festgehalten/${encodeURIComponent(e)}/freigeben`)}function As(e,t){return t.text??`Freigegeben.`}function js(){return R(`/api/system/backup`)}function Ms(){return`Sicherung erstellt.`}function Ns(e){return R(`/api/zeitmaschine/restore`,{file:e})}function Ps(){return`Zurückspielen läuft. Die Dienste starten gleich neu.`}function Fs(e){return R(`/api/models/${encodeURIComponent(e)}/load`)}function Is(e){return`${e} wird geladen.`}function Ls(e){let{id:t,aktion:n}=e;return R(`/api/radar/${encodeURIComponent(t)}/${n}`)}function Rs(e){return e.aktion===`uebernehmen`?`${e.name} übernommen.`:`${e.name} verworfen.`}function zs(){return R(`/api/radar/suche`)}function Bs(){return`Radar sucht nach neuen Modellen.`}var Vs=`Europe/Berlin`,Hs=new Intl.DateTimeFormat(`de-DE`,{hour:`2-digit`,minute:`2-digit`,timeZone:Vs}),Us=new Intl.DateTimeFormat(`de-DE`,{weekday:`short`,timeZone:Vs}),Ws=new Intl.DateTimeFormat(`de-DE`,{day:`2-digit`,month:`2-digit`,timeZone:Vs}),Gs=new Intl.DateTimeFormat(`en-CA`,{timeZone:Vs});function Ks(e){return Gs.format(e)}function qs(e,t=new Date){let n=new Date(e);if(Number.isNaN(n.getTime()))return`–`;let r=Ks(t),i=Ks(new Date(t.getTime()-864e5)),a=Ks(new Date(t.getTime()+864e5)),o=Ks(n),s=Hs.format(n);return o===r?`HEUTE ${s}`:o===i?`GESTERN ${s}`:o===a?`MORGEN ${s}`:Math.abs(n.getTime()-t.getTime())<5616e5?`${Us.format(n).replace(`.`,``).toUpperCase()} ${s}`:`${Ws.format(n)} ${s}`}function Js(e,t=new Date){let n=new Date(e*1e3);return Ks(n)===Ks(t)?`seit heute ${Hs.format(n)}`:`seit ${Ws.format(n)}, ${Hs.format(n)}`}function Ys(e,t=Date.now()){let n=Math.max(0,Math.round(t/1e3-e));if(n<60)return`vor ${n} s`;if(n<3600)return`vor ${Math.round(n/60)} min`;if(n<86400)return`vor ${Math.round(n/3600)} h`;let r=Math.round(n/86400);return`vor ${r} ${r===1?`Tag`:`Tagen`}`}function Xs(e){return e==null||e<0?null:[Math.floor(e/86400),Math.floor(e%86400/3600)]}var Zs=e=>e==null?null:e/1024**3;function Qs(e,t=0){let n=Zs(e);return n==null?`–`:n>=1e3?`${(n/1024).toFixed(1).replace(`.`,`,`)} TB`:`${n.toFixed(t).replace(`.`,`,`)} GB`}var $s=e=>e.toLocaleString(`de-DE`),ec=(0,m.lazy)(()=>Mo(()=>import(`./Protokollfenster-CDb28asU.js`).then(e=>({default:e.Protokollfenster})),__vite__mapDeps([6,1,2,3])));function tc({h:e}){let t=os(),[n,r]=(0,m.useState)(null),a=e.stufe===`rot`;async function o(n,i){if(n===`protokoll`){try{let t=await R(`/api/hinweise/${encodeURIComponent(e.id)}/aktion/protokoll`);r({titel:e.titel,text:t.text||t.out||t.err||`Kein Protokoll vorhanden.`})}catch(e){xo(`fehler`,e.message)}return}t.mutate({hinweis:e.id,aktion:n,label:i})}return(0,h.jsxs)(`article`,{className:`flex flex-col gap-2.5 border-t border-linie pt-4`,children:[(0,h.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,h.jsx)(`h3`,{className:`min-w-0 font-sans text-[17px] leading-snug font-semibold`,children:e.titel}),(0,h.jsx)(`span`,{"aria-hidden":!0,className:`hidden h-0 flex-grow border-b-2 border-dotted border-linie-stark sm:block`}),(0,h.jsx)(`span`,{className:i(`schild shrink-0 text-base`,a?`text-rot`:`text-bernstein`),children:a?`Jetzt`:`Prüfen`})]}),(0,h.jsxs)(`p`,{className:`ziffern text-[13px] text-text-3`,children:[Js(e.seit),` · zuletzt `,Ys(e.zuletzt)]}),e.text&&(0,h.jsx)(`p`,{className:`text-[15px] leading-relaxed break-words text-text-2`,children:e.text}),e.aktionen.length>0&&(0,h.jsx)(`div`,{className:`flex flex-wrap gap-2.5 pt-1`,children:e.aktionen.map((e,n)=>(0,h.jsx)(c,{variant:n===0&&e.id!==`protokoll`?`default`:`outline`,size:`sm`,disabled:t.isPending,onClick:()=>o(e.id,e.label),children:e.label},e.id))}),n&&(0,h.jsx)(m.Suspense,{fallback:null,children:(0,h.jsx)(ec,{offen:!0,titel:n.titel,text:n.text,onSchliessen:()=>r(null)})})]})}function nc(e){let t=(0,F.c)(12),{hinweise:n,verlauf:r}=e,i;t[0]===Symbol.for(`react.memo_cache_sentinel`)?(i=new Date().toDateString(),t[0]=i):i=t[0];let a=i,o;if(t[1]!==n.length||t[2]!==r){o=Symbol.for(`react.early_return_sentinel`);bb0:{let e;t[4]===Symbol.for(`react.memo_cache_sentinel`)?(e=e=>(e.art===`erledigt`||e.art===`auto`)&&new Date(e.ts*1e3).toDateString()===a,t[4]=e):e=t[4];let i=r.filter(e);if(n.length===0){let e;t[5]===Symbol.for(`react.memo_cache_sentinel`)?(e=(0,h.jsx)(`p`,{className:`text-[15px] text-text-2`,children:`Keine offenen Punkte. Der Wächter prüft jede Minute.`}),t[5]=e):e=t[5];let n=i.length>0&&(0,h.jsx)(`ul`,{className:`flex flex-col gap-1 text-sm text-text-3`,children:i.slice(0,4).map(ic)}),r;t[6]===n?r=t[7]:(r=(0,h.jsxs)(`div`,{className:`flex flex-col gap-2 border-t border-linie pt-4`,children:[e,n]}),t[6]=n,t[7]=r),o=r;break bb0}}t[1]=n.length,t[2]=r,t[3]=o}else o=t[3];if(o!==Symbol.for(`react.early_return_sentinel`))return o;let s;t[8]===n?s=t[9]:(s=n.map(rc),t[8]=n,t[9]=s);let c;return t[10]===s?c=t[11]:(c=(0,h.jsx)(`div`,{className:`flex flex-col gap-4`,children:s}),t[10]=s,t[11]=c),c}function rc(e){return(0,h.jsx)(tc,{h:e},e.id)}function ic(e){return(0,h.jsxs)(`li`,{children:[(0,h.jsx)(`span`,{className:`ziffern`,children:Ys(e.ts)}),` · `,e.text]},`${e.id}-${e.ts}`)}var ac={gruen:`border-gruen-rand bg-gruen-grund text-gruen`,bernstein:`border-bernstein/60 bg-bernstein-grund text-bernstein`,cyan:`border-cyan-rand bg-cyan-grund text-cyan`,rot:`border-rot-rand bg-rot-grund text-rot-text`,grau:`border-linie bg-erhaben text-text-2`};function oc(e){let t=(0,F.c)(5),{art:n,children:r}=e,a=ac[n===void 0?`grau`:n],o;t[0]===a?o=t[1]:(o=i(`schild inline-flex h-7 items-center rounded-full border px-2.5 text-xs whitespace-nowrap`,a),t[0]=a,t[1]=o);let s;return t[2]!==r||t[3]!==o?(s=(0,h.jsx)(`span`,{className:o,children:r}),t[2]=r,t[3]=o,t[4]=s):s=t[4],s}function sc(e){let t=(0,F.c)(6),{fehler:n,text:r}=e,a=n?`alert`:`status`,o=n?`border-rot-rand bg-rot-grund text-rot-text`:`border-linie bg-panel text-text-2`,s;t[0]===o?s=t[1]:(s=i(`rounded-2xl border px-5 py-8 text-center text-[15px]`,o),t[0]=o,t[1]=s);let c;return t[2]!==a||t[3]!==s||t[4]!==r?(c=(0,h.jsx)(`div`,{role:a,className:s,children:r}),t[2]=a,t[3]=s,t[4]=r,t[5]=c):c=t[5],c}var cc={erledigt:{text:`Erledigt`,farbe:`text-gruen`},fehler:{text:`Fehler`,farbe:`text-rot`},geplant:{text:`Geplant`,farbe:`text-text-3`}};function lc(e){let t=(0,F.c)(18),{e:n}=e,r=cc[n.status]??cc.geplant,a=n.status===`geplant`&&/update/i.test(n.titel)?`text-cyan`:r.farbe,o;t[0]===n.zeit?o=t[1]:(o=qs(n.zeit),t[0]=n.zeit,t[1]=o);let s;t[2]===o?s=t[3]:(s=(0,h.jsx)(`span`,{className:`ziffern text-sm text-text-3`,children:o}),t[2]=o,t[3]=s);let c;t[4]===n.text?c=t[5]:(c=n.text&&(0,h.jsxs)(`span`,{className:`text-text-3`,children:[`, `,n.text]}),t[4]=n.text,t[5]=c);let l;t[6]!==n.titel||t[7]!==c?(l=(0,h.jsxs)(`span`,{className:`min-w-0 text-base`,children:[n.titel,c]}),t[6]=n.titel,t[7]=c,t[8]=l):l=t[8];let u;t[9]===a?u=t[10]:(u=i(`schild text-[13px]`,a),t[9]=a,t[10]=u);let d;t[11]!==r.text||t[12]!==u?(d=(0,h.jsx)(`span`,{className:u,children:r.text}),t[11]=r.text,t[12]=u,t[13]=d):d=t[13];let f;return t[14]!==s||t[15]!==l||t[16]!==d?(f=(0,h.jsxs)(`li`,{className:`grid grid-cols-[112px_minmax(0,1fr)_auto] items-center gap-3 border-t border-linie py-2.5`,children:[s,l,d]}),t[14]=s,t[15]=l,t[16]=d,t[17]=f):f=t[17],f}function uc(e){let t=(0,F.c)(6),{gelaufen:n,geplant:r}=e,i;t[0]!==n||t[1]!==r?(i=[...n,...r.slice(0,5)],t[0]=n,t[1]=r,t[2]=i):i=t[2];let a=i;if(a.length===0){let e;return t[3]===Symbol.for(`react.memo_cache_sentinel`)?(e=(0,h.jsx)(`p`,{className:`text-[15px] text-text-2`,children:`Heute ist noch nichts gelaufen, und nichts ist geplant.`}),t[3]=e):e=t[3],e}let o;return t[4]===a?o=t[5]:(o=(0,h.jsx)(`ol`,{className:`m-0 flex list-none flex-col p-0`,children:a.map(dc)}),t[4]=a,t[5]=o),o}function dc(e){return(0,h.jsx)(lc,{e},`${e.titel}-${e.zeit}`)}var fc=100,pc=95,mc=210,hc=240;function gc(e,t){let n=e*Math.PI/180;return[fc+t*Math.cos(n),pc-t*Math.sin(n)]}var _c=e=>Math.round(e*100)/100;function vc(e,t,n){let r=Math.max(0,Math.min(1,e)),i=Math.max(r,Math.min(1,t)),[a,o]=gc(mc-hc*r,n),[s,c]=gc(mc-hc*i,n),l=+((i-r)*hc>180);return`M ${_c(a)} ${_c(o)} A ${n} ${n} 0 ${l} 1 ${_c(s)} ${_c(c)}`}function yc(e){return e==null?`var(--text-3)`:e>=85?`var(--rot)`:e>=70?`var(--bernstein)`:`var(--gruen)`}function bc(e){if(!e.waechter_wach)return{art:`stumm`,oben:`Wächter`,mitte:`SCHWEIGT`,unten:`Seit über 5 Minuten kein Prüflauf`};if(e.update_laeuft)return{art:`info`,oben:`Wartung`,mitte:`UPDATE LÄUFT`,unten:`Hinweise ruhen bis zum Ende`};if(e.anzahl===0)return{art:`ok`,oben:`Alles`,mitte:`IN ORDNUNG`,unten:`Keine offenen Hinweise`};let t=`${e.anzahl} HINWEIS${e.anzahl===1?``:`E`}`;return e.stufe===`rot`?{art:`rot`,oben:`Störung`,mitte:t,unten:`Drücken zum Ansehen`}:{art:`gelb`,oben:`Achtung`,mitte:t,unten:`Drücken zum Ansehen`}}function xc(e,t){if(!t)return{laeuft:`…`,neu:null};if(e===`os`)return{laeuft:`Ubuntu`,neu:t.count?`${t.count} Pakete`:null};if(e===`hermes`)return{laeuft:t.installed_version?`v${t.installed_version}`:`–`,neu:t.behind?`+${t.behind.toLocaleString(`de-DE`)} Änderungen`:null};let n=e===`engine`?`b`:`v`;return{laeuft:t.installed_build==null?`–`:`${n}${t.installed_build}`,neu:t.latest_build!=null&&t.installed_build!=null&&t.latest_build>t.installed_build?`${n}${t.latest_build}`:null}}function Sc(e){let t=e.aliases.map(e=>e.toLowerCase());return t.includes(`hermes`)||t.includes(`fast`)?`hirn`:t.includes(`coder`)?`coder`:null}var Cc={neu:`Neu`,wartet:`Wartet`,getestet:`Gemessen`,bestanden:`Bestanden`,durchgefallen:`Durchgefallen`,uebernommen:`Übernommen`,verworfen:`Verworfen`};function wc(e,t=``){if(e==null||e===``)return`–`;let n=typeof e==`number`?e.toLocaleString(`de-DE`,{maximumFractionDigits:+(e<10)}):String(e);return t?`${n} ${t}`:n}function Tc(e){let t=(0,F.c)(25),{anteil:n,farbe:r,zonen:i,mitte:a,unter:o,beschriftung:s,ariaText:c}=e,l=r===void 0?`var(--cyan)`:r,u;t[0]===i?u=t[1]:(u=i===void 0?[]:i,t[0]=i,t[1]=u);let d=u,f=n!=null&&n>.004,p;t[2]===Symbol.for(`react.memo_cache_sentinel`)?(p=(0,h.jsx)(`path`,{d:vc(0,1,75),fill:`none`,stroke:`var(--linie)`,strokeWidth:12,strokeLinecap:`round`}),t[2]=p):p=t[2];let m;t[3]===d?m=t[4]:(m=d.map(Ec),t[3]=d,t[4]=m);let g;t[5]!==n||t[6]!==l||t[7]!==f?(g=f&&(0,h.jsx)(`path`,{d:vc(0,n,75),fill:`none`,stroke:l,strokeWidth:12,strokeLinecap:`round`}),t[5]=n,t[6]=l,t[7]=f,t[8]=g):g=t[8];let _;t[9]===Symbol.for(`react.memo_cache_sentinel`)?(_={fontSize:34,fontWeight:500,fill:`var(--foreground)`},t[9]=_):_=t[9];let v;t[10]===a?v=t[11]:(v=(0,h.jsx)(`text`,{x:`100`,y:`100`,textAnchor:`middle`,className:`ziffern`,style:_,children:a}),t[10]=a,t[11]=v);let y;t[12]===o?y=t[13]:(y=o&&(0,h.jsx)(`text`,{x:`100`,y:`122`,textAnchor:`middle`,style:{fontFamily:`var(--font-anzeige)`,fontSize:14,fontWeight:600,letterSpacing:`0.12em`,fill:`var(--text-3)`},children:o.toUpperCase()}),t[12]=o,t[13]=y);let b;t[14]!==c||t[15]!==m||t[16]!==g||t[17]!==v||t[18]!==y?(b=(0,h.jsxs)(`svg`,{viewBox:`0 0 200 150`,className:`h-auto w-full max-w-[200px]`,role:`img`,"aria-label":c,children:[p,m,g,v,y]}),t[14]=c,t[15]=m,t[16]=g,t[17]=v,t[18]=y,t[19]=b):b=t[19];let x;t[20]===s?x=t[21]:(x=(0,h.jsx)(`figcaption`,{className:`schild text-[15px] text-text-3`,children:s}),t[20]=s,t[21]=x);let S;return t[22]!==b||t[23]!==x?(S=(0,h.jsxs)(`figure`,{className:`m-0 flex min-w-0 flex-col items-center gap-1`,children:[b,x]}),t[22]=b,t[23]=x,t[24]=S):S=t[24],S}function Ec(e){return(0,h.jsx)(`path`,{d:vc(e.von,e.bis,86),fill:`none`,stroke:e.farbe,strokeWidth:4,strokeLinecap:`round`},`${e.von}-${e.bis}`)}function Dc(e){let t=(0,F.c)(11),{titel:n,rechts:r,children:a,className:o,id:s}=e,c;t[0]===o?c=t[1]:(c=i(`flex min-w-0 flex-col gap-4 rounded-2xl border border-linie bg-panel p-5 sm:p-6`,o),t[0]=o,t[1]=c);let l;t[2]!==r||t[3]!==n?(l=(n||r)&&(0,h.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-3`,children:[n&&(0,h.jsx)(`h2`,{className:`schild text-lg font-bold tracking-[0.22em] text-foreground`,children:n}),r]}),t[2]=r,t[3]=n,t[4]=l):l=t[4];let u;return t[5]!==a||t[6]!==s||t[7]!==c||t[8]!==l||t[9]!==n?(u=(0,h.jsxs)(`section`,{id:s,"aria-label":n,className:c,children:[l,a]}),t[5]=a,t[6]=s,t[7]=c,t[8]=l,t[9]=n,t[10]=u):u=t[10],u}var Oc={ok:{feld:`border-gruen-rand bg-gruen-grund`,name:`text-gruen`,wert:`text-gruen-text`},aus:{feld:`border-aus-rand bg-aus-grund`,name:`text-aus-text`,wert:`text-text-3`},warn:{feld:`border-bernstein bg-bernstein-lampe lampe-atmet`,name:`text-bernstein`,wert:`text-[#f2c46b]`},info:{feld:`border-cyan-rand bg-cyan-grund`,name:`text-cyan`,wert:`text-cyan-text`},fehler:{feld:`border-rot bg-rot-grund shadow-[0_0_18px_rgba(255,90,79,0.35)]`,name:`text-rot`,wert:`text-rot-text`}},kc={ok:`in Ordnung`,aus:`aus`,warn:`braucht Aufmerksamkeit`,info:`Info`,fehler:`Störung`};function Ac(e){let t=(0,F.c)(19),{lampe:n}=e,r=Oc[n.zustand]??Oc.aus,a;t[0]===r.feld?a=t[1]:(a=i(`flex min-h-[58px] flex-col items-center justify-center gap-0.5 rounded-lg border px-2 py-2 text-center`,r.feld),t[0]=r.feld,t[1]=a);let o;t[2]===r.name?o=t[3]:(o=i(`schild text-[17px] leading-none font-bold tracking-[0.18em]`,r.name),t[2]=r.name,t[3]=o);let s;t[4]!==n.label||t[5]!==o?(s=(0,h.jsx)(`span`,{className:o,children:n.label}),t[4]=n.label,t[5]=o,t[6]=s):s=t[6];let c;t[7]===r.wert?c=t[8]:(c=i(`ziffern text-xs uppercase`,r.wert),t[7]=r.wert,t[8]=c);let l;t[9]!==n.wert||t[10]!==c?(l=(0,h.jsx)(`span`,{className:c,children:n.wert}),t[9]=n.wert,t[10]=c,t[11]=l):l=t[11];let u=kc[n.zustand],d;t[12]===u?d=t[13]:(d=(0,h.jsx)(`span`,{className:`sr-only`,children:u}),t[12]=u,t[13]=d);let f;return t[14]!==a||t[15]!==s||t[16]!==l||t[17]!==d?(f=(0,h.jsxs)(`li`,{className:a,children:[s,l,d]}),t[14]=a,t[15]=s,t[16]=l,t[17]=d,t[18]=f):f=t[18],f}var jc={ok:`border-gruen-rand bg-gruen-grund text-gruen`,info:`border-cyan-rand bg-cyan-grund text-cyan`,stumm:`border-aus-rand bg-aus-grund text-aus-text`,gelb:`border-2 border-bernstein bg-bernstein-grund text-bernstein-hell lampe-atmet`,rot:`border-2 border-rot bg-rot-grund text-rot shadow-[0_0_32px_rgba(255,90,79,0.3)]`};function Mc(e){let t=(0,F.c)(26),{zustand:n,lampen:r,onAnsehen:a}=e,o;t[0]===n?o=t[1]:(o=bc(n),t[0]=n,t[1]=o);let s=o,c=s.art===`gelb`||s.art===`rot`,l=!c,u=`${s.oben} ${s.mitte}`,d=jc[s.art],f=c?`cursor-pointer`:`cursor-default`,p;t[2]!==d||t[3]!==f?(p=i(`flex min-h-[130px] flex-col items-center justify-center gap-1 rounded-2xl border px-4 py-4 font-anzeige transition-colors`,d,f),t[2]=d,t[3]=f,t[4]=p):p=t[4];let m;t[5]===s.oben?m=t[6]:(m=(0,h.jsx)(`span`,{className:`schild text-sm tracking-[0.26em]`,children:s.oben}),t[5]=s.oben,t[6]=m);let g;t[7]===s.mitte?g=t[8]:(g=(0,h.jsx)(`span`,{className:`text-[40px] leading-none font-bold tracking-[0.04em] sm:text-[44px]`,children:s.mitte}),t[7]=s.mitte,t[8]=g);let _;t[9]===s.unten?_=t[10]:(_=(0,h.jsx)(`span`,{className:`font-sans text-sm opacity-80`,children:s.unten}),t[9]=s.unten,t[10]=_);let v;t[11]!==a||t[12]!==l||t[13]!==u||t[14]!==p||t[15]!==m||t[16]!==g||t[17]!==_?(v=(0,h.jsxs)(`button`,{type:`button`,onClick:a,disabled:l,"aria-label":u,className:p,children:[m,g,_]}),t[11]=a,t[12]=l,t[13]=u,t[14]=p,t[15]=m,t[16]=g,t[17]=_,t[18]=v):v=t[18];let y;t[19]===r?y=t[20]:(y=r.map(Nc),t[19]=r,t[20]=y);let b;t[21]===y?b=t[22]:(b=(0,h.jsx)(`ul`,{className:`grid grid-cols-2 gap-2.5 rounded-2xl border border-linie bg-panel p-3 sm:grid-cols-4`,children:y}),t[21]=y,t[22]=b);let x;return t[23]!==v||t[24]!==b?(x=(0,h.jsxs)(`section`,{"aria-label":`Warnpanel`,className:`grid gap-4 md:grid-cols-[260px_minmax(0,1fr)] md:gap-5`,children:[v,b]}),t[23]=v,t[24]=b,t[25]=x):x=t[25],x}function Nc(e){return(0,h.jsx)(Ac,{lampe:e},e.id)}function Pc(e){let t=(0,F.c)(2),{z:n}=e,r;return t[0]===n?r=t[1]:(r=(0,h.jsx)(`span`,{className:`ziffern inline-flex h-14 w-[38px] items-center justify-center rounded-md border border-[#2a3036] bg-[#0b0d0f] text-[32px] font-medium`,children:n}),t[0]=n,t[1]=r),r}function Fc(e){let t=(0,F.c)(25),{sekunden:n}=e,r;t[0]===n?r=t[1]:(r=Xs(n),t[0]=n,t[1]=r);let i=r,a=String(Math.min(i?.[0]??0,99)),o;t[2]===a?o=t[3]:(o=a.padStart(2,`0`),t[2]=a,t[3]=o);let s=o,c=String(i?.[1]??0),l;t[4]===c?l=t[5]:(l=c.padStart(2,`0`),t[4]=c,t[5]=l);let u=l,d=i?`Laufzeit ohne Neustart: ${i[0]} Tage, ${i[1]} Stunden`:`Laufzeit unbekannt`,f=i?s[0]:`–`,p;t[6]===f?p=t[7]:(p=(0,h.jsx)(Pc,{z:f}),t[6]=f,t[7]=p);let m=i?s[1]:`–`,g;t[8]===m?g=t[9]:(g=(0,h.jsx)(Pc,{z:m}),t[8]=m,t[9]=g);let _;t[10]===Symbol.for(`react.memo_cache_sentinel`)?(_=(0,h.jsx)(`span`,{className:`schild mr-2 ml-0.5 text-lg font-bold text-text-3`,children:`T`}),t[10]=_):_=t[10];let v=i?u[0]:`–`,y;t[11]===v?y=t[12]:(y=(0,h.jsx)(Pc,{z:v}),t[11]=v,t[12]=y);let b=i?u[1]:`–`,x;t[13]===b?x=t[14]:(x=(0,h.jsx)(Pc,{z:b}),t[13]=b,t[14]=x);let S;t[15]===Symbol.for(`react.memo_cache_sentinel`)?(S=(0,h.jsx)(`span`,{className:`schild ml-0.5 text-lg font-bold text-text-3`,children:`H`}),t[15]=S):S=t[15];let C;t[16]!==y||t[17]!==x||t[18]!==p||t[19]!==g||t[20]!==d?(C=(0,h.jsxs)(`div`,{"aria-label":d,role:`img`,className:`flex h-[150px] max-w-full items-center gap-1.5 pb-5`,children:[p,g,_,y,x,S]}),t[16]=y,t[17]=x,t[18]=p,t[19]=g,t[20]=d,t[21]=C):C=t[21];let w;t[22]===Symbol.for(`react.memo_cache_sentinel`)?(w=(0,h.jsx)(`figcaption`,{className:`schild text-[15px] text-text-3`,children:`Ohne Neustart`}),t[22]=w):w=t[22];let T;return t[23]===C?T=t[24]:(T=(0,h.jsxs)(`figure`,{className:`m-0 flex min-w-0 flex-col items-center justify-end gap-1`,children:[C,w]}),t[23]=C,t[24]=T),T}function Ic(e){let t=(0,F.c)(47),{box:n}=e,r=uo(),i=r?.ram_used??n.ram_used,a=r?.ram_total??n.ram_total,o=r?.temp_cpu??n.temp_cpu,s=r?.temp_gpu??n.temp_gpu,c=n.platte,l=r?.uptime_s??n.uptime_s,u=i!=null&&a?i/a:null,d;t[0]===i?d=t[1]:(d=i==null?`–`:String(Math.round(Zs(i)??0)),t[0]=i,t[1]=d);let f;t[2]===a?f=t[3]:(f=a?`von ${Math.round(Zs(a)??0)} GB`:void 0,t[2]=a,t[3]=f);let p;t[4]!==u||t[5]!==i||t[6]!==a?(p=u==null?`Speicher unbekannt`:`Speicher: ${Qs(i)} von ${Qs(a)} belegt`,t[4]=u,t[5]=i,t[6]=a,t[7]=p):p=t[7];let m;t[8]!==u||t[9]!==d||t[10]!==f||t[11]!==p?(m=(0,h.jsx)(Tc,{beschriftung:`Speicher`,anteil:u,mitte:d,unter:f,ariaText:p}),t[8]=u,t[9]=d,t[10]=f,t[11]=p,t[12]=m):m=t[12];let g=o==null?null:o/100,_;t[13]===o?_=t[14]:(_=yc(o),t[13]=o,t[14]=_);let v;t[15]===Symbol.for(`react.memo_cache_sentinel`)?(v=[{von:.7,bis:.85,farbe:`var(--bernstein)`},{von:.85,bis:1,farbe:`var(--rot)`}],t[15]=v):v=t[15];let y;t[16]===o?y=t[17]:(y=o==null?`–`:`${Math.round(o)}°`,t[16]=o,t[17]=y);let b;t[18]===s?b=t[19]:(b=s==null?void 0:`GPU ${Math.round(s)}°`,t[18]=s,t[19]=b);let x;t[20]===o?x=t[21]:(x=o==null?`Temperatur unbekannt`:`Temperatur ${Math.round(o)} Grad`,t[20]=o,t[21]=x);let S;t[22]!==x||t[23]!==g||t[24]!==_||t[25]!==y||t[26]!==b?(S=(0,h.jsx)(Tc,{beschriftung:`Temperatur`,anteil:g,farbe:_,zonen:v,mitte:y,unter:b,ariaText:x}),t[22]=x,t[23]=g,t[24]=_,t[25]=y,t[26]=b,t[27]=S):S=t[27];let C=c?c.percent/100:null,w=c&&c.percent>=90?`var(--rot)`:c&&c.percent>=80?`var(--bernstein)`:`var(--cyan)`,T;t[28]===c?T=t[29]:(T=c?`${Math.round(c.percent)}%`:`–`,t[28]=c,t[29]=T);let ee;t[30]===c?ee=t[31]:(ee=c?`${Qs(c.used)} / ${Qs(c.total)}`:void 0,t[30]=c,t[31]=ee);let E;t[32]===c?E=t[33]:(E=c?`Platte zu ${Math.round(c.percent)} Prozent belegt`:`Platte unbekannt`,t[32]=c,t[33]=E);let te;t[34]!==C||t[35]!==w||t[36]!==T||t[37]!==ee||t[38]!==E?(te=(0,h.jsx)(Tc,{beschriftung:`Platte`,anteil:C,farbe:w,mitte:T,unter:ee,ariaText:E}),t[34]=C,t[35]=w,t[36]=T,t[37]=ee,t[38]=E,t[39]=te):te=t[39];let D;t[40]===l?D=t[41]:(D=(0,h.jsx)(Fc,{sekunden:l}),t[40]=l,t[41]=D);let ne;return t[42]!==S||t[43]!==te||t[44]!==D||t[45]!==m?(ne=(0,h.jsxs)(`section`,{"aria-label":`Instrumente`,className:`grid grid-cols-2 gap-x-4 gap-y-6 rounded-2xl border border-linie bg-panel px-4 py-5 lg:grid-cols-4 lg:px-6`,children:[m,S,te,D]}),t[42]=S,t[43]=te,t[44]=D,t[45]=m,t[46]=ne):ne=t[46],ne}var Lc={bestanden:`gruen`,durchgefallen:`rot`,wartet:`cyan`,neu:`cyan`};function Rc(e){let t=(0,F.c)(14),{radar:n}=e;if(!n?.kandidaten)return null;let r,i;t[0]===n.kandidaten?(r=t[1],i=t[2]):(r=n.kandidaten.filter(Bc),i=r.find(zc)??r[0],t[0]=n.kandidaten,t[1]=r,t[2]=i);let a=i,o=r.length===1?``:`en`,s;t[3]!==r.length||t[4]!==o?(s=(0,h.jsxs)(`span`,{className:`schild text-sm text-cyan`,children:[`Radar · `,r.length,` Kandidat`,o]}),t[3]=r.length,t[4]=o,t[5]=s):s=t[5];let l;t[6]===a?l=t[7]:(l=a?(0,h.jsxs)(`span`,{className:`flex flex-wrap items-center gap-2 text-[15px]`,children:[(0,h.jsx)(`span`,{className:`ziffern`,children:a.name}),(0,h.jsxs)(`span`,{className:`text-text-2`,children:[`fürs `,a.rolle===`hirn`?`Hirn`:`Coden`]}),(0,h.jsx)(oc,{art:Lc[a.status]??`grau`,children:Cc[a.status]??a.status})]}):(0,h.jsx)(`span`,{className:`text-[15px] text-text-2`,children:`Nichts Besseres in Sicht.`}),t[6]=a,t[7]=l);let u;t[8]!==s||t[9]!==l?(u=(0,h.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-1`,children:[s,l]}),t[8]=s,t[9]=l,t[10]=u):u=t[10];let d;t[11]===Symbol.for(`react.memo_cache_sentinel`)?(d=(0,h.jsx)(c,{variant:`info`,size:`sm`,asChild:!0,children:(0,h.jsx)(pa,{to:`/modelle`,hash:`radar`,children:`Ansehen`})}),t[11]=d):d=t[11];let f;return t[12]===u?f=t[13]:(f=(0,h.jsxs)(`div`,{className:`mt-auto flex flex-wrap items-center justify-between gap-3 rounded-xl border border-cyan-rand bg-cyan-grund px-4 py-3.5`,children:[u,d]}),t[12]=u,t[13]=f),f}function zc(e){return e.status===`bestanden`}function Bc(e){return[`bestanden`,`wartet`,`neu`].includes(e.status)}function Vc(){let e=(0,F.c)(32),{data:t,error:n,isPending:r}=Yo(),i=Qo();if(r){let t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t=(0,h.jsx)(sc,{text:`Die Box meldet sich gleich …`}),e[0]=t):t=e[0],t}if(n||!t){let t=`MC2 antwortet nicht: ${n?.message??`keine Daten`}`,r;return e[1]===t?r=e[2]:(r=(0,h.jsx)(sc,{fehler:!0,text:t}),e[1]=t,e[2]=r),r}let a=t.hinweise.length,o;e[3]!==t.lampen||e[4]!==t.zustand?(o=(0,h.jsx)(Mc,{zustand:t.zustand,lampen:t.lampen,onAnsehen:Hc}),e[3]=t.lampen,e[4]=t.zustand,e[5]=o):o=e[5];let s;e[6]===t.box?s=e[7]:(s=(0,h.jsx)(Ic,{box:t.box}),e[6]=t.box,e[7]=s);let c=a?`ziffern text-sm text-bernstein`:`ziffern text-sm text-gruen`,l=a?`${a} offen`:`alles erledigt`,u;e[8]!==c||e[9]!==l?(u=(0,h.jsx)(`span`,{className:c,children:l}),e[8]=c,e[9]=l,e[10]=u):u=e[10];let d;e[11]!==t.hinweise||e[12]!==t.verlauf?(d=(0,h.jsx)(nc,{hinweise:t.hinweise,verlauf:t.verlauf}),e[11]=t.hinweise,e[12]=t.verlauf,e[13]=d):d=e[13];let f;e[14]!==u||e[15]!==d?(f=(0,h.jsx)(Dc,{titel:`Checkliste`,id:`checkliste`,rechts:u,children:d}),e[14]=u,e[15]=d,e[16]=f):f=e[16];let p;e[17]!==t.flugplan.gelaufen||e[18]!==t.flugplan.geplant?(p=(0,h.jsx)(uc,{gelaufen:t.flugplan.gelaufen,geplant:t.flugplan.geplant}),e[17]=t.flugplan.gelaufen,e[18]=t.flugplan.geplant,e[19]=p):p=e[19];let m;e[20]===i.data?m=e[21]:(m=(0,h.jsx)(Rc,{radar:i.data}),e[20]=i.data,e[21]=m);let g;e[22]!==p||e[23]!==m?(g=(0,h.jsxs)(Dc,{titel:`Flugplan`,children:[p,m]}),e[22]=p,e[23]=m,e[24]=g):g=e[24];let _;e[25]!==f||e[26]!==g?(_=(0,h.jsxs)(`div`,{className:`grid gap-5 lg:grid-cols-[minmax(0,1.35fr)_minmax(0,1fr)] md:gap-6`,children:[f,g]}),e[25]=f,e[26]=g,e[27]=_):_=e[27];let v;return e[28]!==o||e[29]!==s||e[30]!==_?(v=(0,h.jsxs)(h.Fragment,{children:[o,s,_]}),e[28]=o,e[29]=s,e[30]=_,e[31]=v):v=e[31],v}function Hc(){return document.getElementById(`checkliste`)?.scrollIntoView({behavior:`smooth`,block:`start`})}var Uc=va({component:Uo,notFoundComponent:()=>(0,h.jsx)(Qi,{to:`/`})}),Wc=ga({getParentRoute:()=>Uc,path:`/`,component:Vc}),Gc=ga({getParentRoute:()=>Uc,path:`/updates`,component:ya(()=>Mo(()=>import(`./Updates-DPFIId2v.js`),__vite__mapDeps([7,1,8,3])),`UpdatesSeite`)}),Kc=ga({getParentRoute:()=>Uc,path:`/modelle`,component:ya(()=>Mo(()=>import(`./Modelle-CHK2sw1N.js`),__vite__mapDeps([9,1,2,3,8])),`ModelleSeite`)}),qc=Ia({routeTree:Uc.addChildren([Wc,Gc,Kc]),defaultPreload:`intent`,defaultErrorComponent:Va}),Jc=`mc_neuladen_wegen_version`;function Yc(){window.addEventListener(`vite:preloadError`,e=>{sessionStorage.getItem(Jc)||(e.preventDefault(),sessionStorage.setItem(Jc,`1`),window.location.reload())}),window.addEventListener(`load`,()=>{window.setTimeout(()=>sessionStorage.removeItem(Jc),5e3)})}Yc();var Xc=new qe({defaultOptions:{queries:{retry:1,refetchOnWindowFocus:!1,staleTime:5e3}}});(0,Ba.createRoot)(document.getElementById(`root`)).render((0,h.jsx)(m.StrictMode,{children:(0,h.jsx)(v,{client:Xc,children:(0,h.jsx)(za,{router:qc})})}));export{R as A,es as C,ts as D,cs as E,Ja as F,ot as I,_ as L,uo as M,no as N,us as O,eo as P,ps as S,z as T,Xo as _,xc as a,Qo as b,qs as c,$s as d,rs as f,ds as g,$o as h,Sc as i,xo as j,I as k,Zs as l,B as m,Cc as n,oc as o,ls as p,wc as r,sc as s,Dc as t,Qs as u,Zo as v,Yo as w,fs as x,ns as y}; \ No newline at end of file diff --git a/frontend/dist/index.html b/frontend/dist/index.html index 2900192..b80ed26 100644 --- a/frontend/dist/index.html +++ b/frontend/dist/index.html @@ -7,9 +7,9 @@ MC2 · Box-Wart - + - +
diff --git a/frontend/src/lib/anzeige.ts b/frontend/src/lib/anzeige.ts index c3686fb..01df897 100644 --- a/frontend/src/lib/anzeige.ts +++ b/frontend/src/lib/anzeige.ts @@ -83,3 +83,20 @@ export function rolleVon(m: Modell): "hirn" | "coder" | null { if (a.includes("coder")) return "coder" return null } + +// --- Modell-Radar --------------------------------------------------------------------- + +/** Status eines Radar-Kandidaten in Worten fürs Cockpit. */ +export const RADAR_STATUS_TEXT: Record = { + neu: "Neu", wartet: "Wartet", getestet: "Gemessen", bestanden: "Bestanden", + durchgefallen: "Durchgefallen", uebernommen: "Übernommen", verworfen: "Verworfen", +} + +/** Messwert des Radar-Vergleichs lesbar machen (Zahlen deutsch, eine Nachkommastelle). */ +export function messwert(wert: unknown, einheit = ""): string { + if (wert == null || wert === "") return "–" + const text = typeof wert === "number" + ? wert.toLocaleString("de-DE", { maximumFractionDigits: wert < 10 ? 1 : 0 }) + : String(wert) + return einheit ? `${text} ${einheit}` : text +} diff --git a/frontend/src/views/Modelle.tsx b/frontend/src/views/Modelle.tsx index 46bed15..7f55b5f 100644 --- a/frontend/src/views/Modelle.tsx +++ b/frontend/src/views/Modelle.tsx @@ -1,14 +1,15 @@ import { useState } from "react" import { Search } from "lucide-react" +import { Bestaetigen } from "@/components/cockpit/Bestaetigen" import { Chip, type ChipArt, Zustandsfeld } from "@/components/cockpit/Chip" import { Panel } from "@/components/cockpit/Panel" import { Button } from "@/components/ui/button" import { useModellLaden, useModelle, useNutzung, useRadar, useRadarAktion, useRadarSuche, useStart, } from "@/lib/abfragen" -import { rolleVon } from "@/lib/anzeige" +import { messwert, RADAR_STATUS_TEXT, rolleVon } from "@/lib/anzeige" import { useLetzteMetrik } from "@/lib/strom" -import type { Modell, Nutzung, RadarKandidat } from "@/lib/typen" +import type { Modell, Nutzung, RadarKandidat, RadarTest } from "@/lib/typen" import { flugplanZeit, gb, gbText, zahl } from "@/lib/zeit" import { ModellSuche } from "./ModellSuche" @@ -122,39 +123,94 @@ function NutzungsPanel({ nutzung }: { nutzung: Nutzung | undefined }) { const STATUS_ART: Record = { bestanden: "gruen", durchgefallen: "rot", wartet: "cyan", neu: "cyan", getestet: "grau", uebernommen: "gruen", verworfen: "grau", } +const URTEIL_FARBE: Record = { besser: "text-gruen", schlechter: "text-rot-text", gleich: "text-text-2" } -function Kandidat({ k }: { k: RadarKandidat }) { +type Vergleichszeile = { kandidat: unknown; baseline: unknown; einheit?: string; urteil?: string } + +/** Die Messwerte hinter dem Urteil: Kandidat gegen das heutige Modell der Rolle. */ +function Vergleich({ test }: { test: RadarTest }) { + const zeilen = Object.entries(test.vergleich ?? {}) as [string, Vergleichszeile][] + if (zeilen.length === 0) return null + return ( +
+
+ Messwert + Kandidat + Heute +
+ {zeilen.map(([name, z]) => ( +
+ {name} + + {messwert(z.kandidat, z.einheit)} + + {messwert(z.baseline, z.einheit)} +
+ ))} +
+ ) +} + +function Kandidat({ k, test, heute }: { k: RadarKandidat; test: RadarTest | undefined; heute: string | undefined }) { const aktion = useRadarAktion() - const offen = ["bestanden", "wartet", "neu"].includes(k.status) + const [frage, setFrage] = useState(null) + const offen = ["bestanden", "wartet", "neu", "getestet"].includes(k.status) + const hirn = k.rolle === "hirn" return (
  • {k.name} - {k.rolle === "hirn" ? "fürs Hirn" : "fürs Coden"} + {hirn ? "fürs Hirn" : "fürs Coden"} {k.eng ? "passt knapp" : k.passt ? "passt" : "passt nicht"} - {k.status} + {RADAR_STATUS_TEXT[k.status] ?? k.status}

    {k.groesse_gb != null ? `${k.groesse_gb.toLocaleString("de-DE")} GB. ` : ""} {k.begruendung}

    + {test && ["bestanden", "durchgefallen"].includes(k.status) && } {offen && (
    {k.status === "bestanden" && ( - )} -
    )} + setFrage(null)} + onJa={() => { + aktion.mutate({ id: k.id, aktion: "uebernehmen", name: k.name }) + setFrage(null) + }} + /> + setFrage(null)} + onJa={() => { + aktion.mutate({ id: k.id, aktion: "verwerfen", name: k.name }) + setFrage(null) + }} + />
  • ) } -function RadarPanel() { +function RadarPanel({ hirn, coder }: { hirn: string | undefined; coder: string | undefined }) { const radar = useRadar() const suche = useRadarSuche() if (radar.isError) { @@ -181,7 +237,14 @@ function RadarPanel() {

    Nichts Besseres in Sicht.

    ) : (
      - {d.kandidaten.map((k) => )} + {d.kandidaten.map((k) => ( + t.kandidat === k.id)} + heute={k.rolle === "hirn" ? hirn : coder} + /> + ))}
    )} {d && d.tests.length > 0 && ( @@ -223,7 +286,7 @@ export function ModelleSeite() {
    - +
    {vorn.name} fürs {vorn.rolle === "hirn" ? "Hirn" : "Coden"} - {vorn.status} + {RADAR_STATUS_TEXT[vorn.status] ?? vorn.status} ) : ( Nichts Besseres in Sicht.