diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000000000000000000000000000000000..ad2ea862f73da9a3c18343f006b9361ebfa885c7 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,13 @@ +__pycache__ +*.pyc +*.pyo +.Python +*.egg +*.egg-info +.env +.venv +venv/ +node_modules/ +*.log +.DS_Store +.git diff --git a/.gitattributes b/.gitattributes index a6344aac8c09253b3b630fb776ae94478aa0275b..c8543b9f0b93c56b140ff9d15f8f72c5cf16c3c4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,35 +1,10 @@ -*.7z filter=lfs diff=lfs merge=lfs -text -*.arrow filter=lfs diff=lfs merge=lfs -text +chroma_db/chroma.sqlite3 filter=lfs diff=lfs merge=lfs -text +chroma_db/**/*.bin filter=lfs diff=lfs merge=lfs -text +chroma_db/*.sqlite3 filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +*.jpg filter=lfs diff=lfs merge=lfs -text +*.jpeg filter=lfs diff=lfs merge=lfs -text +*.gif filter=lfs diff=lfs merge=lfs -text *.bin filter=lfs diff=lfs merge=lfs -text -*.bz2 filter=lfs diff=lfs merge=lfs -text -*.ckpt filter=lfs diff=lfs merge=lfs -text -*.ftz filter=lfs diff=lfs merge=lfs -text -*.gz filter=lfs diff=lfs merge=lfs -text -*.h5 filter=lfs diff=lfs merge=lfs -text -*.joblib filter=lfs diff=lfs merge=lfs -text -*.lfs.* filter=lfs diff=lfs merge=lfs -text -*.mlmodel filter=lfs diff=lfs merge=lfs -text -*.model filter=lfs diff=lfs merge=lfs -text -*.msgpack filter=lfs diff=lfs merge=lfs -text -*.npy filter=lfs diff=lfs merge=lfs -text -*.npz filter=lfs diff=lfs merge=lfs -text -*.onnx filter=lfs diff=lfs merge=lfs -text -*.ot filter=lfs diff=lfs merge=lfs -text -*.parquet filter=lfs diff=lfs merge=lfs -text -*.pb filter=lfs diff=lfs merge=lfs -text +*.sqlite3 filter=lfs diff=lfs merge=lfs -text *.pickle filter=lfs diff=lfs merge=lfs -text -*.pkl filter=lfs diff=lfs merge=lfs -text -*.pt filter=lfs diff=lfs merge=lfs -text -*.pth filter=lfs diff=lfs merge=lfs -text -*.rar filter=lfs diff=lfs merge=lfs -text -*.safetensors filter=lfs diff=lfs merge=lfs -text -saved_model/**/* filter=lfs diff=lfs merge=lfs -text -*.tar.* filter=lfs diff=lfs merge=lfs -text -*.tar filter=lfs diff=lfs merge=lfs -text -*.tflite filter=lfs diff=lfs merge=lfs -text -*.tgz filter=lfs diff=lfs merge=lfs -text -*.wasm filter=lfs diff=lfs merge=lfs -text -*.xz filter=lfs diff=lfs merge=lfs -text -*.zip filter=lfs diff=lfs merge=lfs -text -*.zst filter=lfs diff=lfs merge=lfs -text -*tfevents* filter=lfs diff=lfs merge=lfs -text diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..4f77d2cd3cb5aba31b6683b368b6cbd2dac598c5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,45 @@ +# =========================================================================== +# Learn Pathophysiology — WC3 Edition +# Multi-stage build: Vue frontend + FastAPI backend +# Deploy: HuggingFace Spaces (Docker SDK) +# =========================================================================== + +# ---------- Stage 1: Build Vue Frontend ---------- +FROM node:20-slim AS frontend-build + +WORKDIR /build +COPY frontend/package.json frontend/package-lock.json* ./ +RUN npm install +COPY frontend/ ./ +RUN npm run build +# Output goes to /build/dist/ + +# ---------- Stage 2: Python Backend + Serve Static ---------- +FROM python:3.11-slim + +WORKDIR /app + +# Install Python deps +COPY backend/requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# Copy backend code +COPY backend/ ./ + +# Copy built frontend from stage 1 +COPY --from=frontend-build /build/dist ./static/ + +# Copy chroma_db (must be present in docker build context) +COPY chroma_db/ ./chroma_db/ + +# Environment +ENV PORT=7860 +ENV CHROMA_DIR=/app/chroma_db +# Auth (set via HuggingFace Spaces secrets) +# ENV GOOGLE_CLIENT_ID=... +# ENV JWT_SECRET=... +# ENV GEMINI_API_KEY=... + +EXPOSE 7860 + +CMD ["uvicorn", "api:app", "--host", "0.0.0.0", "--port", "7860"] diff --git a/README.md b/README.md index 8f31d89392010bec70a72ca70a51ef3a1ad4c234..a1bb064ab98e9ccdb6ca6e42bcdc4866e27bee19 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,93 @@ --- title: Learn Pathophysiology -emoji: 🏃 -colorFrom: blue -colorTo: gray +emoji: ⚔️ +colorFrom: purple +colorTo: red sdk: docker +app_port: 7860 pinned: false -license: apache-2.0 -short_description: MVP for an AI enabled pathophysiology learning app --- -Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference +# Learn Pathophysiology - WC3 Edition ⚔️ + +AI-powered chatbot for learning **Pathophysiology** with authentic **Warcraft 3** styling! + +![WC3 Style](https://img.shields.io/badge/Style-Warcraft%203-orange) +![AI Powered](https://img.shields.io/badge/AI-Gemini-blue) +![Language](https://img.shields.io/badge/Language-Croatian-red) + +## 🎮 Features + +### 💬 AI Chat +Ask questions about Pathophysiology in Croatian and get detailed, RAG-powered answers grounded in the official Gamulin textbook. + +### 📸 Image Analysis +Upload textbook pages and get AI-powered analysis, explanations, and Q&A. + +### 🎨 WC3-Themed Interface +Choose from 4 authentic Warcraft 3 race themes: +- **Human** - Blue/silver Alliance theme +- **Orc** - Red/brown Horde theme +- **Night Elf** - Purple/teal nature theme +- **Undead** - Green/dark Scourge theme + +### 🤖 Multi-Model Support +- **Gemini 3 Flash Preview** - Fastest, newest model +- **Gemini 2.5 Flash** - Fast and reliable +- **Gemini 2.5 Pro** - Most capable for complex questions + +### 📚 RAG-Powered +All answers are grounded in the official **Patofiziologija (Gamulin, Marušić, Kovač)** textbook, with citations to page numbers. + +## 🏗️ Technology Stack + +- **Frontend**: Vue 3 + TypeScript + Custom WC3 UI library +- **Backend**: FastAPI (Python) +- **AI**: Google Gemini API +- **RAG**: ChromaDB vector database +- **Deployment**: Docker + +## 🎓 For Medical Students + +This app is specifically designed for medical students at **University of Split School of Medicine** to help master Pathophysiology through: + +1. **Interactive Q&A** - Ask anything about Pathophysiology +2. **Contextual Learning** - Get explanations grounded in your textbook +3. **Image Analysis** - Understand complex diagrams and pages +4. **Citation Support** - See exactly where information comes from + +## 🚀 Usage + +Simply: +1. Select your preferred AI model (top-left sidebar) +2. Choose your favorite WC3 race theme +3. Start chatting or upload an image! + +### Example Questions (in Croatian): +- "Što je hipertenzija i kako nastaje?" +- "Objasni patofiziologiju dijabetesa tipa 2" +- "Kako funkcionira renin-angiotenzin-aldosteron sustav?" + +## 🌐 Open Source + +This project is open source! Check out the code on GitHub: +- Frontend: Vue 3 + TypeScript with custom WC3 UI components +- Backend: FastAPI with Gemini AI integration +- RAG: ChromaDB with Gemini embeddings + +## 📝 Credits + +- **UI Design**: Inspired by Warcraft 3 (Blizzard Entertainment) +- **Content**: Based on Patofiziologija textbook by Gamulin, Marušić, Kovač +- **AI**: Powered by Google Gemini +- **Development**: University of Split School of Medicine project + +## ⚠️ Disclaimer + +This is an educational tool. Always verify medical information with official sources and your professors. The AI can make mistakes! + +--- + +**Built with ❤️ and Warcraft 3 nostalgia** + +*For the Alliance! For the Horde! For passing exams!* ⚔️📚 diff --git a/backend/api.py b/backend/api.py new file mode 100644 index 0000000000000000000000000000000000000000..c3fccc472adb4cc38274cd4bb7c92a0a600fe15e --- /dev/null +++ b/backend/api.py @@ -0,0 +1,441 @@ +""" +Learn Pathophysiology - FastAPI Backend + +Serves RAG + LLM API endpoints and Vue frontend static files. +Deploy: HuggingFace Spaces (Docker) or run locally. +""" + +import os +import secrets +import logging +from pathlib import Path +from datetime import datetime, timezone, timedelta + +import jwt +from fastapi import FastAPI, UploadFile, File, Form, HTTPException, Depends, Request +from fastapi.middleware.cors import CORSMiddleware +from fastapi.staticfiles import StaticFiles +from fastapi.responses import FileResponse +from pydantic import BaseModel +from dotenv import load_dotenv +from google import genai +from google.genai import types +from google.oauth2 import id_token as google_id_token +from google.auth.transport import requests as google_requests +import chromadb + +load_dotenv() + +logger = logging.getLogger(__name__) + +# ============================================================================= +# CONFIGURATION +# ============================================================================= + +GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY", "") +CHROMA_DIR = os.environ.get("CHROMA_DIR", "../chroma_db") +COLLECTION_NAME = "pathophysiology" +EMBEDDING_MODEL = "gemini-embedding-001" +DEFAULT_MODEL = "gemini-3-flash-preview" +RAG_TOP_K = 5 + +# Auth +GOOGLE_CLIENT_ID = os.environ.get("GOOGLE_CLIENT_ID", "") +JWT_SECRET = os.environ.get("JWT_SECRET", secrets.token_urlsafe(32)) +JWT_ALGORITHM = "HS256" +JWT_EXPIRY_DAYS = 7 +AUTH_ENABLED = bool(GOOGLE_CLIENT_ID) # disable auth if no client ID + +AVAILABLE_MODELS = { + "gemini-3-flash-preview": { + "name": "Gemini 3 Flash", + "description": "Najnoviji i najbrzi model", + "icon": "swords", + "wc3_name": "Blademaster", + "tier": "fast", + }, + "gemini-2.5-flash": { + "name": "Gemini 2.5 Flash", + "description": "Brz i pouzdan", + "icon": "bow", + "wc3_name": "Shadow Hunter", + "tier": "fast", + }, + "gemini-2.5-pro": { + "name": "Gemini 2.5 Pro", + "description": "Najpametniji za kompleksne zadatke", + "icon": "mage", + "wc3_name": "Archmage", + "tier": "smart", + }, +} + +SYSTEM_PROMPT = """Ti si "Learn Pathophysiology AI", strucni asistent za ucenje patofiziologije +za studente medicine. + +ULOGA: +- Objasnjavaš patofiziološke koncepte jasno i precizno +- Koristiš primjere i analogije kad je moguce +- Povezuješ koncepte s klinickom praksom +- Odgovaraš na hrvatskom jeziku + +KONTEKST IZ BAZE ZNANJA: +{rag_context} + +PRAVILA: +1. Uvijek citiraj izvor kad koristiš informacije iz konteksta +2. Ako nisi siguran, reci to otvoreno +3. Koristi medicinsku terminologiju, ali objasni kompleksne termine +4. Budi koncizan ali potpun u odgovorima +5. Odgovaraj na hrvatskom jeziku""" + +# ============================================================================= +# SINGLETONS +# ============================================================================= + +_genai_client = None +_chroma_collection = None + + +def get_client(): + global _genai_client + if _genai_client is None: + if not GEMINI_API_KEY: + raise HTTPException(status_code=500, detail="GEMINI_API_KEY not configured") + _genai_client = genai.Client(api_key=GEMINI_API_KEY) + return _genai_client + + +def get_collection(): + global _chroma_collection + if _chroma_collection is None: + chroma_path = Path(CHROMA_DIR) + if not chroma_path.exists(): + # Try relative to this file + alt_path = Path(__file__).parent.parent.parent / "chroma_db" + if alt_path.exists(): + chroma_path = alt_path + else: + return None + try: + client = chromadb.PersistentClient(path=str(chroma_path)) + _chroma_collection = client.get_collection(COLLECTION_NAME) + except Exception as e: + logger.error(f"ChromaDB error: {e}") + return None + return _chroma_collection + + +# ============================================================================= +# AUTH HELPERS +# ============================================================================= + +def create_jwt(email: str, name: str, picture: str = "") -> str: + payload = { + "sub": email, + "name": name, + "picture": picture, + "iat": datetime.now(timezone.utc), + "exp": datetime.now(timezone.utc) + timedelta(days=JWT_EXPIRY_DAYS), + } + return jwt.encode(payload, JWT_SECRET, algorithm=JWT_ALGORITHM) + + +def decode_jwt(token: str) -> dict | None: + try: + return jwt.decode(token, JWT_SECRET, algorithms=[JWT_ALGORITHM]) + except jwt.ExpiredSignatureError: + return None + except jwt.InvalidTokenError: + return None + + +async def require_auth(request: Request): + """FastAPI dependency — returns user dict or raises 401.""" + if not AUTH_ENABLED: + return {"sub": "anonymous", "name": "Local User"} + + auth_header = request.headers.get("Authorization", "") + if not auth_header.startswith("Bearer "): + raise HTTPException(status_code=401, detail="Not authenticated") + + token = auth_header[7:] + user = decode_jwt(token) + if not user: + raise HTTPException(status_code=401, detail="Invalid or expired token") + return user + + +# ============================================================================= +# RAG FUNCTIONS +# ============================================================================= + +def embed_query(text: str) -> list[float]: + c = get_client() + result = c.models.embed_content(model=EMBEDDING_MODEL, contents=text) + return result.embeddings[0].values + + +def query_rag(query_text: str, top_k: int = RAG_TOP_K): + coll = get_collection() + if coll is None: + return "Nema dostupnog konteksta.", [] + + try: + query_embedding = embed_query(query_text) + results = coll.query( + query_embeddings=[query_embedding], + n_results=top_k, + include=["documents", "metadatas", "distances"] + ) + + contexts = [] + citations = [] + + if results and results["documents"] and results["documents"][0]: + for idx, (doc, meta, dist) in enumerate(zip( + results["documents"][0], + results["metadatas"][0], + results["distances"][0] + )): + contexts.append(doc) + similarity = max(0, 1 - dist / 2) + citations.append({ + "text": doc[:600] + "..." if len(doc) > 600 else doc, + "score": round(similarity, 3), + "source": meta.get("source", "Baza znanja"), + "page_num": meta.get("page_num", "?"), + "rank": idx + 1, + }) + + formatted = "\n\n---\n\n".join(contexts) if contexts else "Nema konteksta." + return formatted, citations + except Exception as e: + logger.error(f"RAG error: {e}") + return "Nema dostupnog konteksta.", [] + + +def generate_chat_response(message: str, history: list, model_name: str = ""): + model_name = model_name or DEFAULT_MODEL + if model_name not in AVAILABLE_MODELS: + model_name = DEFAULT_MODEL + + c = get_client() + rag_context, citations = query_rag(message) + system_prompt = SYSTEM_PROMPT.format(rag_context=rag_context) + + contents = [system_prompt] + for msg in (history or [])[-10:]: + role = msg.get("role", "user") + content = msg.get("content", "") + if role == "user": + contents.append(f"Student: {content}") + else: + contents.append(f"Asistent: {content}") + contents.append(f"Student: {message}") + + response = c.models.generate_content( + model=model_name, + contents="\n\n".join(contents), + config=types.GenerateContentConfig( + temperature=0.7, + max_output_tokens=8192, + top_p=0.9, + ) + ) + return response.text, citations + + +def do_analyze_image(image_bytes: bytes, question: str = "", model_name: str = ""): + model_name = model_name or DEFAULT_MODEL + if model_name not in AVAILABLE_MODELS: + model_name = DEFAULT_MODEL + + c = get_client() + + # Extract keywords from image + extract_resp = c.models.generate_content( + model=model_name, + contents=[ + types.Part.from_bytes(data=image_bytes, mime_type="image/jpeg"), + "Izvuci glavni topic i kljucne rijeci s ove stranice. Odgovori kratko." + ], + config=types.GenerateContentConfig(temperature=0.3, max_output_tokens=200) + ) + + rag_context, citations = query_rag(extract_resp.text, top_k=3) + + if question: + prompt = ( + f"Analiziraj ovu stranicu iz materijala za patofiziologiju " + f"i odgovori na pitanje studenta.\n\n" + f"PITANJE: {question}\n\n" + f"KONTEKST IZ BAZE ZNANJA:\n{rag_context}\n\n" + f"Odgovori detaljno na hrvatskom jeziku." + ) + else: + prompt = ( + f"Analiziraj ovu stranicu iz materijala za patofiziologiju.\n\n" + f"1. Prepoznaj glavni topic\n2. Izvuci kljucne pojmove\n" + f"3. Sazmi glavne tocke\n4. Objasni klinicku vaznost\n\n" + f"KONTEKST IZ BAZE ZNANJA:\n{rag_context}\n\n" + f"Odgovori na hrvatskom jeziku." + ) + + response = c.models.generate_content( + model=model_name, + contents=[ + types.Part.from_bytes(data=image_bytes, mime_type="image/jpeg"), + prompt + ], + config=types.GenerateContentConfig(temperature=0.5, max_output_tokens=8192) + ) + return response.text, citations + + +# ============================================================================= +# FASTAPI APP +# ============================================================================= + +app = FastAPI(title="Learn Pathophysiology API", version="1.0.0") + +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + + +# --- Request / Response Models --- + +class ChatRequest(BaseModel): + message: str + model: str = "" + history: list = [] + + +# --- Auth Models --- + +class GoogleAuthRequest(BaseModel): + credential: str # Google ID token + + +# --- Auth Endpoints --- + +@app.get("/api/auth/config") +async def auth_config(): + """Tell the frontend if auth is required and the Google Client ID.""" + return { + "auth_enabled": AUTH_ENABLED, + "google_client_id": GOOGLE_CLIENT_ID if AUTH_ENABLED else None, + } + + +@app.post("/api/auth/google") +async def auth_google(req: GoogleAuthRequest): + """Verify Google ID token and return a JWT session token.""" + if not AUTH_ENABLED: + raise HTTPException(status_code=400, detail="Auth not enabled") + + try: + idinfo = google_id_token.verify_oauth2_token( + req.credential, + google_requests.Request(), + GOOGLE_CLIENT_ID, + ) + + email = idinfo.get("email", "") + name = idinfo.get("name", email) + picture = idinfo.get("picture", "") + + token = create_jwt(email, name, picture) + return { + "token": token, + "user": {"email": email, "name": name, "picture": picture}, + } + except ValueError as e: + logger.error(f"Google auth failed: {e}") + raise HTTPException(status_code=401, detail="Invalid Google token") + + +@app.get("/api/auth/me") +async def auth_me(user=Depends(require_auth)): + """Return the current user's info from their JWT.""" + return { + "email": user.get("sub", ""), + "name": user.get("name", ""), + "picture": user.get("picture", ""), + } + + +# --- API Endpoints (public) --- + +@app.get("/api/health") +async def health(): + coll = get_collection() + return { + "status": "ok", + "chroma_docs": coll.count() if coll else 0, + "has_api_key": bool(GEMINI_API_KEY), + } + + +@app.get("/api/models") +async def list_models(): + return {"models": AVAILABLE_MODELS, "default": DEFAULT_MODEL} + + +@app.get("/api/stats") +async def stats(): + coll = get_collection() + return { + "documents": coll.count() if coll else 0, + "collection": COLLECTION_NAME, + } + + +# --- API Endpoints (protected) --- + +@app.post("/api/chat") +async def chat(req: ChatRequest, user=Depends(require_auth)): + try: + model = req.model or DEFAULT_MODEL + reply, citations = generate_chat_response(req.message, req.history, model) + return {"reply": reply, "citations": citations, "model_used": model} + except Exception as e: + logger.error(f"Chat error: {e}") + raise HTTPException(status_code=500, detail=str(e)) + + +@app.post("/api/analyze-image") +async def analyze_image_endpoint( + image: UploadFile = File(...), + question: str = Form(""), + model: str = Form(""), + user=Depends(require_auth), +): + try: + model_name = model or DEFAULT_MODEL + image_bytes = await image.read() + analysis, citations = do_analyze_image(image_bytes, question, model_name) + return {"analysis": analysis, "citations": citations, "model_used": model_name} + except Exception as e: + logger.error(f"Image analysis error: {e}") + raise HTTPException(status_code=500, detail=str(e)) + + +# --- Serve Vue Frontend (production) --- +static_dir = Path(__file__).parent / "static" +if static_dir.exists(): + @app.get("/") + async def serve_index(): + return FileResponse(str(static_dir / "index.html")) + + app.mount("/", StaticFiles(directory=str(static_dir), html=True), name="static") + + +if __name__ == "__main__": + import uvicorn + uvicorn.run("api:app", host="0.0.0.0", port=7860, reload=True) diff --git a/backend/requirements.txt b/backend/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..7da0e7e6c44b597fb644f8eb3cef5474f8ee67ac --- /dev/null +++ b/backend/requirements.txt @@ -0,0 +1,8 @@ +fastapi>=0.110.0 +uvicorn[standard]>=0.27.0 +google-genai>=1.0.0 +google-auth>=2.0.0 +chromadb>=0.5.0 +python-dotenv>=1.0.0 +python-multipart>=0.0.9 +pyjwt>=2.0.0 \ No newline at end of file diff --git a/backend/static/any/hud_time_indicator.png b/backend/static/any/hud_time_indicator.png new file mode 100644 index 0000000000000000000000000000000000000000..80ea672ea033903fb79a4ca2b2bae75a4f0dfeb8 --- /dev/null +++ b/backend/static/any/hud_time_indicator.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3278868b0512fc4c6feaeef519d0c337e6e77f215859ac4ab97993e1c189c864 +size 131312 diff --git a/backend/static/any/resource_icons/gold.png b/backend/static/any/resource_icons/gold.png new file mode 100644 index 0000000000000000000000000000000000000000..3331ff942581ea01af1dceb5a410d9e52e366643 --- /dev/null +++ b/backend/static/any/resource_icons/gold.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc3ff9674247028ebe34ac1e8c84bd97ca821199e1bfa4f7c0c635cca3fe0cd4 +size 1837 diff --git a/backend/static/any/resource_icons/lumber.png b/backend/static/any/resource_icons/lumber.png new file mode 100644 index 0000000000000000000000000000000000000000..f544107eb78781a58f552dfcba1dab3566922c98 --- /dev/null +++ b/backend/static/any/resource_icons/lumber.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:650c574ce17ab7766f9d8cbf2bd6c3b5b1281954925d7d35bba9219dc8c81896 +size 1588 diff --git a/backend/static/any/resource_icons/supply.png b/backend/static/any/resource_icons/supply.png new file mode 100644 index 0000000000000000000000000000000000000000..f2e2dffae19b88b7f658fba3583368d194f898cc --- /dev/null +++ b/backend/static/any/resource_icons/supply.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:11202af9a7fc0b73be772be538b5ab1f142f915c49a81a762b12623e90074309 +size 1405 diff --git a/backend/static/assets/index-BSpkv-VB.js b/backend/static/assets/index-BSpkv-VB.js new file mode 100644 index 0000000000000000000000000000000000000000..8f756439aeb6344e66d934bdbfd646df366a2143 --- /dev/null +++ b/backend/static/assets/index-BSpkv-VB.js @@ -0,0 +1,72 @@ +var wl=Object.defineProperty;var kl=(e,t,n)=>t in e?wl(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var Z=(e,t,n)=>kl(e,typeof t!="symbol"?t+"":t,n);(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const r of document.querySelectorAll('link[rel="modulepreload"]'))s(r);new MutationObserver(r=>{for(const i of r)if(i.type==="childList")for(const o of i.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&s(o)}).observe(document,{childList:!0,subtree:!0});function n(r){const i={};return r.integrity&&(i.integrity=r.integrity),r.referrerPolicy&&(i.referrerPolicy=r.referrerPolicy),r.crossOrigin==="use-credentials"?i.credentials="include":r.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function s(r){if(r.ep)return;r.ep=!0;const i=n(r);fetch(r.href,i)}})();/** +* @vue/shared v3.5.28 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function ks(e){const t=Object.create(null);for(const n of e.split(","))t[n]=1;return n=>n in t}const B={},yt=[],Te=()=>{},Ur=()=>!1,On=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),Ss=e=>e.startsWith("onUpdate:"),re=Object.assign,Ts=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},Sl=Object.prototype.hasOwnProperty,V=(e,t)=>Sl.call(e,t),I=Array.isArray,_t=e=>en(e)==="[object Map]",Vr=e=>en(e)==="[object Set]",ir=e=>en(e)==="[object Date]",M=e=>typeof e=="function",te=e=>typeof e=="string",$e=e=>typeof e=="symbol",G=e=>e!==null&&typeof e=="object",Kr=e=>(G(e)||M(e))&&M(e.then)&&M(e.catch),qr=Object.prototype.toString,en=e=>qr.call(e),Tl=e=>en(e).slice(8,-1),Wr=e=>en(e)==="[object Object]",Cs=e=>te(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,jt=ks(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Ln=e=>{const t=Object.create(null);return(n=>t[n]||(t[n]=e(n)))},Cl=/-\w/g,We=Ln(e=>e.replace(Cl,t=>t.slice(1).toUpperCase())),$l=/\B([A-Z])/g,it=Ln(e=>e.replace($l,"-$1").toLowerCase()),Gr=Ln(e=>e.charAt(0).toUpperCase()+e.slice(1)),Jn=Ln(e=>e?`on${Gr(e)}`:""),ye=(e,t)=>!Object.is(e,t),mn=(e,...t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:s,value:n})},$s=e=>{const t=parseFloat(e);return isNaN(t)?e:t};let lr;const Mn=()=>lr||(lr=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function zn(e){if(I(e)){const t={};for(let n=0;n{if(n){const s=n.split(Al);s.length>1&&(t[s[0].trim()]=s[1].trim())}}),t}function rt(e){let t="";if(te(e))t=e;else if(I(e))for(let n=0;n!!(e&&e.__v_isRef===!0),ne=e=>te(e)?e:e==null?"":I(e)||G(e)&&(e.toString===qr||!M(e.toString))?Qr(e)?ne(e.value):JSON.stringify(e,Xr,2):String(e),Xr=(e,t)=>Qr(t)?Xr(e,t.value):_t(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[s,r],i)=>(n[Qn(s,i)+" =>"]=r,n),{})}:Vr(t)?{[`Set(${t.size})`]:[...t.values()].map(n=>Qn(n))}:$e(t)?Qn(t):G(t)&&!I(t)&&!Wr(t)?String(t):t,Qn=(e,t="")=>{var n;return $e(e)?`Symbol(${(n=e.description)!=null?n:t})`:e};function Ml(e){return e==null?"initial":typeof e=="string"?e===""?" ":e:String(e)}/** +* @vue/reactivity v3.5.28 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let xe;class zl{constructor(t=!1){this.detached=t,this._active=!0,this._on=0,this.effects=[],this.cleanups=[],this._isPaused=!1,this.__v_skip=!0,this.parent=xe,!t&&xe&&(this.index=(xe.scopes||(xe.scopes=[])).push(this)-1)}get active(){return this._active}pause(){if(this._active){this._isPaused=!0;let t,n;if(this.scopes)for(t=0,n=this.scopes.length;t0&&--this._on===0&&(xe=this.prevScope,this.prevScope=void 0)}stop(t){if(this._active){this._active=!1;let n,s;for(n=0,s=this.effects.length;n0)return;if(Nt){let t=Nt;for(Nt=void 0;t;){const n=t.next;t.next=void 0,t.flags&=-9,t=n}}let e;for(;Ft;){let t=Ft;for(Ft=void 0;t;){const n=t.next;if(t.next=void 0,t.flags&=-9,t.flags&1)try{t.trigger()}catch(s){e||(e=s)}t=n}}if(e)throw e}function ni(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function si(e){let t,n=e.depsTail,s=n;for(;s;){const r=s.prevDep;s.version===-1?(s===n&&(n=r),Es(s),jl(s)):t=s,s.dep.activeLink=s.prevActiveLink,s.prevActiveLink=void 0,s=r}e.deps=t,e.depsTail=n}function os(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(ri(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function ri(e){if(e.flags&4&&!(e.flags&16)||(e.flags&=-17,e.globalVersion===Gt)||(e.globalVersion=Gt,!e.isSSR&&e.flags&128&&(!e.deps&&!e._dirty||!os(e))))return;e.flags|=2;const t=e.dep,n=X,s=Ce;X=e,Ce=!0;try{ni(e);const r=e.fn(e._value);(t.version===0||ye(r,e._value))&&(e.flags|=128,e._value=r,t.version++)}catch(r){throw t.version++,r}finally{X=n,Ce=s,si(e),e.flags&=-3}}function Es(e,t=!1){const{dep:n,prevSub:s,nextSub:r}=e;if(s&&(s.nextSub=r,e.prevSub=void 0),r&&(r.prevSub=s,e.nextSub=void 0),n.subs===e&&(n.subs=s,!s&&n.computed)){n.computed.flags&=-5;for(let i=n.computed.deps;i;i=i.nextDep)Es(i,!0)}!t&&!--n.sc&&n.map&&n.map.delete(n.key)}function jl(e){const{prevDep:t,nextDep:n}=e;t&&(t.nextDep=n,e.prevDep=void 0),n&&(n.prevDep=t,e.nextDep=void 0)}let Ce=!0;const ii=[];function Ge(){ii.push(Ce),Ce=!1}function Ze(){const e=ii.pop();Ce=e===void 0?!0:e}function or(e){const{cleanup:t}=e;if(e.cleanup=void 0,t){const n=X;X=void 0;try{t()}finally{X=n}}}let Gt=0;class Fl{constructor(t,n){this.sub=t,this.dep=n,this.version=n.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class Dn{constructor(t){this.computed=t,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0,this.__v_skip=!0}track(t){if(!X||!Ce||X===this.computed)return;let n=this.activeLink;if(n===void 0||n.sub!==X)n=this.activeLink=new Fl(X,this),X.deps?(n.prevDep=X.depsTail,X.depsTail.nextDep=n,X.depsTail=n):X.deps=X.depsTail=n,li(n);else if(n.version===-1&&(n.version=this.version,n.nextDep)){const s=n.nextDep;s.prevDep=n.prevDep,n.prevDep&&(n.prevDep.nextDep=s),n.prevDep=X.depsTail,n.nextDep=void 0,X.depsTail.nextDep=n,X.depsTail=n,X.deps===n&&(X.deps=s)}return n}trigger(t){this.version++,Gt++,this.notify(t)}notify(t){As();try{for(let n=this.subs;n;n=n.prevSub)n.sub.notify()&&n.sub.dep.notify()}finally{Ps()}}}function li(e){if(e.dep.sc++,e.sub.flags&4){const t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let s=t.deps;s;s=s.nextDep)li(s)}const n=e.dep.subs;n!==e&&(e.prevSub=n,n&&(n.nextSub=e)),e.dep.subs=e}}const as=new WeakMap,ht=Symbol(""),cs=Symbol(""),Zt=Symbol("");function ae(e,t,n){if(Ce&&X){let s=as.get(e);s||as.set(e,s=new Map);let r=s.get(n);r||(s.set(n,r=new Dn),r.map=s,r.key=n),r.track()}}function He(e,t,n,s,r,i){const o=as.get(e);if(!o){Gt++;return}const l=a=>{a&&a.trigger()};if(As(),t==="clear")o.forEach(l);else{const a=I(e),c=a&&Cs(n);if(a&&n==="length"){const u=Number(s);o.forEach((p,d)=>{(d==="length"||d===Zt||!$e(d)&&d>=u)&&l(p)})}else switch((n!==void 0||o.has(void 0))&&l(o.get(n)),c&&l(o.get(Zt)),t){case"add":a?c&&l(o.get("length")):(l(o.get(ht)),_t(e)&&l(o.get(cs)));break;case"delete":a||(l(o.get(ht)),_t(e)&&l(o.get(cs)));break;case"set":_t(e)&&l(o.get(ht));break}}Ps()}function bt(e){const t=U(e);return t===e?t:(ae(t,"iterate",Zt),Se(e)?t:t.map(Re))}function jn(e){return ae(e=U(e),"iterate",Zt),e}function tt(e,t){return Je(e)?Tt(pt(e)?Re(t):t):Re(t)}const Nl={__proto__:null,[Symbol.iterator](){return Yn(this,Symbol.iterator,e=>tt(this,e))},concat(...e){return bt(this).concat(...e.map(t=>I(t)?bt(t):t))},entries(){return Yn(this,"entries",e=>(e[1]=tt(this,e[1]),e))},every(e,t){return Fe(this,"every",e,t,void 0,arguments)},filter(e,t){return Fe(this,"filter",e,t,n=>n.map(s=>tt(this,s)),arguments)},find(e,t){return Fe(this,"find",e,t,n=>tt(this,n),arguments)},findIndex(e,t){return Fe(this,"findIndex",e,t,void 0,arguments)},findLast(e,t){return Fe(this,"findLast",e,t,n=>tt(this,n),arguments)},findLastIndex(e,t){return Fe(this,"findLastIndex",e,t,void 0,arguments)},forEach(e,t){return Fe(this,"forEach",e,t,void 0,arguments)},includes(...e){return es(this,"includes",e)},indexOf(...e){return es(this,"indexOf",e)},join(e){return bt(this).join(e)},lastIndexOf(...e){return es(this,"lastIndexOf",e)},map(e,t){return Fe(this,"map",e,t,void 0,arguments)},pop(){return It(this,"pop")},push(...e){return It(this,"push",e)},reduce(e,...t){return ar(this,"reduce",e,t)},reduceRight(e,...t){return ar(this,"reduceRight",e,t)},shift(){return It(this,"shift")},some(e,t){return Fe(this,"some",e,t,void 0,arguments)},splice(...e){return It(this,"splice",e)},toReversed(){return bt(this).toReversed()},toSorted(e){return bt(this).toSorted(e)},toSpliced(...e){return bt(this).toSpliced(...e)},unshift(...e){return It(this,"unshift",e)},values(){return Yn(this,"values",e=>tt(this,e))}};function Yn(e,t,n){const s=jn(e),r=s[t]();return s!==e&&!Se(e)&&(r._next=r.next,r.next=()=>{const i=r._next();return i.done||(i.value=n(i.value)),i}),r}const Bl=Array.prototype;function Fe(e,t,n,s,r,i){const o=jn(e),l=o!==e&&!Se(e),a=o[t];if(a!==Bl[t]){const p=a.apply(e,i);return l?Re(p):p}let c=n;o!==e&&(l?c=function(p,d){return n.call(this,tt(e,p),d,e)}:n.length>2&&(c=function(p,d){return n.call(this,p,d,e)}));const u=a.call(o,c,s);return l&&r?r(u):u}function ar(e,t,n,s){const r=jn(e);let i=n;return r!==e&&(Se(e)?n.length>3&&(i=function(o,l,a){return n.call(this,o,l,a,e)}):i=function(o,l,a){return n.call(this,o,tt(e,l),a,e)}),r[t](i,...s)}function es(e,t,n){const s=U(e);ae(s,"iterate",Zt);const r=s[t](...n);return(r===-1||r===!1)&&Ms(n[0])?(n[0]=U(n[0]),s[t](...n)):r}function It(e,t,n=[]){Ge(),As();const s=U(e)[t].apply(e,n);return Ps(),Ze(),s}const Hl=ks("__proto__,__v_isRef,__isVue"),oi=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter($e));function Ul(e){$e(e)||(e=String(e));const t=U(this);return ae(t,"has",e),t.hasOwnProperty(e)}class ai{constructor(t=!1,n=!1){this._isReadonly=t,this._isShallow=n}get(t,n,s){if(n==="__v_skip")return t.__v_skip;const r=this._isReadonly,i=this._isShallow;if(n==="__v_isReactive")return!r;if(n==="__v_isReadonly")return r;if(n==="__v_isShallow")return i;if(n==="__v_raw")return s===(r?i?Yl:hi:i?fi:ui).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(s)?t:void 0;const o=I(t);if(!r){let a;if(o&&(a=Nl[n]))return a;if(n==="hasOwnProperty")return Ul}const l=Reflect.get(t,n,ue(t)?t:s);if(($e(n)?oi.has(n):Hl(n))||(r||ae(t,"get",n),i))return l;if(ue(l)){const a=o&&Cs(n)?l:l.value;return r&&G(a)?fs(a):a}return G(l)?r?fs(l):Os(l):l}}class ci extends ai{constructor(t=!1){super(!1,t)}set(t,n,s,r){let i=t[n];const o=I(t)&&Cs(n);if(!this._isShallow){const c=Je(i);if(!Se(s)&&!Je(s)&&(i=U(i),s=U(s)),!o&&ue(i)&&!ue(s))return c||(i.value=s),!0}const l=o?Number(n)e,hn=e=>Reflect.getPrototypeOf(e);function Gl(e,t,n){return function(...s){const r=this.__v_raw,i=U(r),o=_t(i),l=e==="entries"||e===Symbol.iterator&&o,a=e==="keys"&&o,c=r[e](...s),u=n?us:t?Tt:Re;return!t&&ae(i,"iterate",a?cs:ht),re(Object.create(c),{next(){const{value:p,done:d}=c.next();return d?{value:p,done:d}:{value:l?[u(p[0]),u(p[1])]:u(p),done:d}}})}}function pn(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function Zl(e,t){const n={get(r){const i=this.__v_raw,o=U(i),l=U(r);e||(ye(r,l)&&ae(o,"get",r),ae(o,"get",l));const{has:a}=hn(o),c=t?us:e?Tt:Re;if(a.call(o,r))return c(i.get(r));if(a.call(o,l))return c(i.get(l));i!==o&&i.get(r)},get size(){const r=this.__v_raw;return!e&&ae(U(r),"iterate",ht),r.size},has(r){const i=this.__v_raw,o=U(i),l=U(r);return e||(ye(r,l)&&ae(o,"has",r),ae(o,"has",l)),r===l?i.has(r):i.has(r)||i.has(l)},forEach(r,i){const o=this,l=o.__v_raw,a=U(l),c=t?us:e?Tt:Re;return!e&&ae(a,"iterate",ht),l.forEach((u,p)=>r.call(i,c(u),c(p),o))}};return re(n,e?{add:pn("add"),set:pn("set"),delete:pn("delete"),clear:pn("clear")}:{add(r){!t&&!Se(r)&&!Je(r)&&(r=U(r));const i=U(this);return hn(i).has.call(i,r)||(i.add(r),He(i,"add",r,r)),this},set(r,i){!t&&!Se(i)&&!Je(i)&&(i=U(i));const o=U(this),{has:l,get:a}=hn(o);let c=l.call(o,r);c||(r=U(r),c=l.call(o,r));const u=a.call(o,r);return o.set(r,i),c?ye(i,u)&&He(o,"set",r,i):He(o,"add",r,i),this},delete(r){const i=U(this),{has:o,get:l}=hn(i);let a=o.call(i,r);a||(r=U(r),a=o.call(i,r)),l&&l.call(i,r);const c=i.delete(r);return a&&He(i,"delete",r,void 0),c},clear(){const r=U(this),i=r.size!==0,o=r.clear();return i&&He(r,"clear",void 0,void 0),o}}),["keys","values","entries",Symbol.iterator].forEach(r=>{n[r]=Gl(r,e,t)}),n}function Is(e,t){const n=Zl(e,t);return(s,r,i)=>r==="__v_isReactive"?!e:r==="__v_isReadonly"?e:r==="__v_raw"?s:Reflect.get(V(n,r)&&r in s?n:s,r,i)}const Jl={get:Is(!1,!1)},Ql={get:Is(!1,!0)},Xl={get:Is(!0,!1)};const ui=new WeakMap,fi=new WeakMap,hi=new WeakMap,Yl=new WeakMap;function eo(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function to(e){return e.__v_skip||!Object.isExtensible(e)?0:eo(Tl(e))}function Os(e){return Je(e)?e:Ls(e,!1,Kl,Jl,ui)}function no(e){return Ls(e,!1,Wl,Ql,fi)}function fs(e){return Ls(e,!0,ql,Xl,hi)}function Ls(e,t,n,s,r){if(!G(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const i=to(e);if(i===0)return e;const o=r.get(e);if(o)return o;const l=new Proxy(e,i===2?s:n);return r.set(e,l),l}function pt(e){return Je(e)?pt(e.__v_raw):!!(e&&e.__v_isReactive)}function Je(e){return!!(e&&e.__v_isReadonly)}function Se(e){return!!(e&&e.__v_isShallow)}function Ms(e){return e?!!e.__v_raw:!1}function U(e){const t=e&&e.__v_raw;return t?U(t):e}function so(e){return!V(e,"__v_skip")&&Object.isExtensible(e)&&Zr(e,"__v_skip",!0),e}const Re=e=>G(e)?Os(e):e,Tt=e=>G(e)?fs(e):e;function ue(e){return e?e.__v_isRef===!0:!1}function W(e){return ro(e,!1)}function ro(e,t){return ue(e)?e:new io(e,t)}class io{constructor(t,n){this.dep=new Dn,this.__v_isRef=!0,this.__v_isShallow=!1,this._rawValue=n?t:U(t),this._value=n?t:Re(t),this.__v_isShallow=n}get value(){return this.dep.track(),this._value}set value(t){const n=this._rawValue,s=this.__v_isShallow||Se(t)||Je(t);t=s?t:U(t),ye(t,n)&&(this._rawValue=t,this._value=s?t:Re(t),this.dep.trigger())}}function pi(e){return ue(e)?e.value:e}const lo={get:(e,t,n)=>t==="__v_raw"?e:pi(Reflect.get(e,t,n)),set:(e,t,n,s)=>{const r=e[t];return ue(r)&&!ue(n)?(r.value=n,!0):Reflect.set(e,t,n,s)}};function di(e){return pt(e)?e:new Proxy(e,lo)}class oo{constructor(t){this.__v_isRef=!0,this._value=void 0;const n=this.dep=new Dn,{get:s,set:r}=t(n.track.bind(n),n.trigger.bind(n));this._get=s,this._set=r}get value(){return this._value=this._get()}set value(t){this._set(t)}}function ao(e){return new oo(e)}class co{constructor(t,n,s){this.fn=t,this.setter=n,this._value=void 0,this.dep=new Dn(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=Gt-1,this.next=void 0,this.effect=this,this.__v_isReadonly=!n,this.isSSR=s}notify(){if(this.flags|=16,!(this.flags&8)&&X!==this)return ti(this,!0),!0}get value(){const t=this.dep.track();return ri(this),t&&(t.version=this.dep.version),this._value}set value(t){this.setter&&this.setter(t)}}function uo(e,t,n=!1){let s,r;return M(e)?s=e:(s=e.get,r=e.set),new co(s,r,n)}const dn={},_n=new WeakMap;let ft;function fo(e,t=!1,n=ft){if(n){let s=_n.get(n);s||_n.set(n,s=[]),s.push(e)}}function ho(e,t,n=B){const{immediate:s,deep:r,once:i,scheduler:o,augmentJob:l,call:a}=n,c=E=>r?E:Se(E)||r===!1||r===0?Ue(E,1):Ue(E);let u,p,d,b,w=!1,_=!1;if(ue(e)?(p=()=>e.value,w=Se(e)):pt(e)?(p=()=>c(e),w=!0):I(e)?(_=!0,w=e.some(E=>pt(E)||Se(E)),p=()=>e.map(E=>{if(ue(E))return E.value;if(pt(E))return c(E);if(M(E))return a?a(E,2):E()})):M(e)?t?p=a?()=>a(e,2):e:p=()=>{if(d){Ge();try{d()}finally{Ze()}}const E=ft;ft=u;try{return a?a(e,3,[b]):e(b)}finally{ft=E}}:p=Te,t&&r){const E=p,ee=r===!0?1/0:r;p=()=>Ue(E(),ee)}const N=Dl(),L=()=>{u.stop(),N&&N.active&&Ts(N.effects,u)};if(i&&t){const E=t;t=(...ee)=>{E(...ee),L()}}let R=_?new Array(e.length).fill(dn):dn;const D=E=>{if(!(!(u.flags&1)||!u.dirty&&!E))if(t){const ee=u.run();if(r||w||(_?ee.some((ke,oe)=>ye(ke,R[oe])):ye(ee,R))){d&&d();const ke=ft;ft=u;try{const oe=[ee,R===dn?void 0:_&&R[0]===dn?[]:R,b];R=ee,a?a(t,3,oe):t(...oe)}finally{ft=ke}}}else u.run()};return l&&l(D),u=new Yr(p),u.scheduler=o?()=>o(D,!1):D,b=E=>fo(E,!1,u),d=u.onStop=()=>{const E=_n.get(u);if(E){if(a)a(E,4);else for(const ee of E)ee();_n.delete(u)}},t?s?D(!0):R=u.run():o?o(D.bind(null,!0),!0):u.run(),L.pause=u.pause.bind(u),L.resume=u.resume.bind(u),L.stop=L,L}function Ue(e,t=1/0,n){if(t<=0||!G(e)||e.__v_skip||(n=n||new Map,(n.get(e)||0)>=t))return e;if(n.set(e,t),t--,ue(e))Ue(e.value,t,n);else if(I(e))for(let s=0;s{Ue(s,t,n)});else if(Wr(e)){for(const s in e)Ue(e[s],t,n);for(const s of Object.getOwnPropertySymbols(e))Object.prototype.propertyIsEnumerable.call(e,s)&&Ue(e[s],t,n)}return e}/** +* @vue/runtime-core v3.5.28 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function tn(e,t,n,s){try{return s?e(...s):e()}catch(r){Fn(r,t,n)}}function je(e,t,n,s){if(M(e)){const r=tn(e,t,n,s);return r&&Kr(r)&&r.catch(i=>{Fn(i,t,n)}),r}if(I(e)){const r=[];for(let i=0;i>>1,r=pe[s],i=Jt(r);i=Jt(n)?pe.push(e):pe.splice(go(t),0,e),e.flags|=1,bi()}}function bi(){wn||(wn=gi.then(yi))}function vi(e){I(e)?wt.push(...e):nt&&e.id===-1?nt.splice(vt+1,0,e):e.flags&1||(wt.push(e),e.flags|=1),bi()}function cr(e,t,n=Me+1){for(;nJt(n)-Jt(s));if(wt.length=0,nt){nt.push(...t);return}for(nt=t,vt=0;vte.id==null?e.flags&2?-1:1/0:e.id;function yi(e){try{for(Me=0;Me{s._d&&xr(-1);const i=kn(t);let o;try{o=e(...r)}finally{kn(i),s._d&&xr(1)}return o};return s._n=!0,s._c=!0,s._d=!0,s}function wi(e,t){if(ce===null)return e;const n=Kn(ce),s=e.dirs||(e.dirs=[]);for(let r=0;r1)return n&&M(t)?t.call(s&&s.proxy):t}}const mo=Symbol.for("v-scx"),bo=()=>Bt(mo);function vo(e,t){return Ds(e,null,{flush:"sync"})}function Ht(e,t,n){return Ds(e,t,n)}function Ds(e,t,n=B){const{immediate:s,deep:r,flush:i,once:o}=n,l=re({},n),a=t&&s||!t&&i!=="post";let c;if(Xt){if(i==="sync"){const b=bo();c=b.__watcherHandles||(b.__watcherHandles=[])}else if(!a){const b=()=>{};return b.stop=Te,b.resume=Te,b.pause=Te,b}}const u=de;l.call=(b,w,_)=>je(b,u,w,_);let p=!1;i==="post"?l.scheduler=b=>{ve(b,u&&u.suspense)}:i!=="sync"&&(p=!0,l.scheduler=(b,w)=>{w?b():zs(b)}),l.augmentJob=b=>{t&&(b.flags|=4),p&&(b.flags|=2,u&&(b.id=u.uid,b.i=u))};const d=ho(e,t,l);return Xt&&(c?c.push(d):a&&d()),d}function xo(e,t,n){const s=this.proxy,r=te(e)?e.includes(".")?Si(s,e):()=>s[e]:e.bind(s,s);let i;M(t)?i=t:(i=t.handler,n=t);const o=sn(this),l=Ds(r,i.bind(s),n);return o(),l}function Si(e,t){const n=t.split(".");return()=>{let s=e;for(let r=0;re.__isTeleport,wo=Symbol("_leaveCb");function js(e,t){e.shapeFlag&6&&e.component?(e.transition=t,js(e.component.subTree,t)):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function Xe(e,t){return M(e)?re({name:e.name},t,{setup:e}):e}function Ti(e){e.ids=[e.ids[0]+e.ids[2]+++"-",0,0]}function ur(e,t){let n;return!!((n=Object.getOwnPropertyDescriptor(e,t))&&!n.configurable)}const Sn=new WeakMap;function Ut(e,t,n,s,r=!1){if(I(e)){e.forEach((_,N)=>Ut(_,t&&(I(t)?t[N]:t),n,s,r));return}if(kt(s)&&!r){s.shapeFlag&512&&s.type.__asyncResolved&&s.component.subTree.component&&Ut(e,t,n,s.component.subTree);return}const i=s.shapeFlag&4?Kn(s.component):s.el,o=r?null:i,{i:l,r:a}=e,c=t&&t.r,u=l.refs===B?l.refs={}:l.refs,p=l.setupState,d=U(p),b=p===B?Ur:_=>ur(u,_)?!1:V(d,_),w=(_,N)=>!(N&&ur(u,N));if(c!=null&&c!==a){if(fr(t),te(c))u[c]=null,b(c)&&(p[c]=null);else if(ue(c)){const _=t;w(c,_.k)&&(c.value=null),_.k&&(u[_.k]=null)}}if(M(a))tn(a,l,12,[o,u]);else{const _=te(a),N=ue(a);if(_||N){const L=()=>{if(e.f){const R=_?b(a)?p[a]:u[a]:w()||!e.k?a.value:u[e.k];if(r)I(R)&&Ts(R,i);else if(I(R))R.includes(i)||R.push(i);else if(_)u[a]=[i],b(a)&&(p[a]=u[a]);else{const D=[i];w(a,e.k)&&(a.value=D),e.k&&(u[e.k]=D)}}else _?(u[a]=o,b(a)&&(p[a]=o)):N&&(w(a,e.k)&&(a.value=o),e.k&&(u[e.k]=o))};if(o){const R=()=>{L(),Sn.delete(e)};R.id=-1,Sn.set(e,R),ve(R,n)}else fr(e),L()}}}function fr(e){const t=Sn.get(e);t&&(t.flags|=8,Sn.delete(e))}Mn().requestIdleCallback;Mn().cancelIdleCallback;const kt=e=>!!e.type.__asyncLoader,Ci=e=>e.type.__isKeepAlive;function ko(e,t){$i(e,"a",t)}function So(e,t){$i(e,"da",t)}function $i(e,t,n=de){const s=e.__wdc||(e.__wdc=()=>{let r=n;for(;r;){if(r.isDeactivated)return;r=r.parent}return e()});if(Nn(t,s,n),n){let r=n.parent;for(;r&&r.parent;)Ci(r.parent.vnode)&&To(s,t,n,r),r=r.parent}}function To(e,t,n,s){const r=Nn(t,e,s,!0);Bn(()=>{Ts(s[t],r)},n)}function Nn(e,t,n=de,s=!1){if(n){const r=n[e]||(n[e]=[]),i=t.__weh||(t.__weh=(...o)=>{Ge();const l=sn(n),a=je(t,n,e,o);return l(),Ze(),a});return s?r.unshift(i):r.push(i),i}}const Ye=e=>(t,n=de)=>{(!Xt||e==="sp")&&Nn(e,(...s)=>t(...s),n)},Co=Ye("bm"),nn=Ye("m"),Ri=Ye("bu"),$o=Ye("u"),Ro=Ye("bum"),Bn=Ye("um"),Ao=Ye("sp"),Po=Ye("rtg"),Eo=Ye("rtc");function Io(e,t=de){Nn("ec",e,t)}const Oo=Symbol.for("v-ndc");function Tn(e,t,n,s){let r;const i=n,o=I(e);if(o||te(e)){const l=o&&pt(e);let a=!1,c=!1;l&&(a=!Se(e),c=Je(e),e=jn(e)),r=new Array(e.length);for(let u=0,p=e.length;ut(l,a,void 0,i));else{const l=Object.keys(e);r=new Array(l.length);for(let a=0,c=l.length;a0;return z(),Ve(ie,null,[se("slot",n,s)],c?-2:64)}let i=e[t];i&&i._c&&(i._d=!1),z();const o=i&&Pi(i(n)),l=n.key||o&&o.key,a=Ve(ie,{key:(l&&!$e(l)?l:`_${t}`)+(!o&&s?"_fb":"")},o||[],o&&e._===1?64:-2);return a.scopeId&&(a.slotScopeIds=[a.scopeId+"-s"]),i&&i._c&&(i._d=!0),a}function Pi(e){return e.some(t=>Bs(t)?!(t.type===Qe||t.type===ie&&!Pi(t.children)):!0)?e:null}const hs=e=>e?Qi(e)?Kn(e):hs(e.parent):null,Vt=re(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>hs(e.parent),$root:e=>hs(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>Ii(e),$forceUpdate:e=>e.f||(e.f=()=>{zs(e.update)}),$nextTick:e=>e.n||(e.n=mi.bind(e.proxy)),$watch:e=>xo.bind(e)}),ts=(e,t)=>e!==B&&!e.__isScriptSetup&&V(e,t),Lo={get({_:e},t){if(t==="__v_skip")return!0;const{ctx:n,setupState:s,data:r,props:i,accessCache:o,type:l,appContext:a}=e;if(t[0]!=="$"){const d=o[t];if(d!==void 0)switch(d){case 1:return s[t];case 2:return r[t];case 4:return n[t];case 3:return i[t]}else{if(ts(s,t))return o[t]=1,s[t];if(r!==B&&V(r,t))return o[t]=2,r[t];if(V(i,t))return o[t]=3,i[t];if(n!==B&&V(n,t))return o[t]=4,n[t];ds&&(o[t]=0)}}const c=Vt[t];let u,p;if(c)return t==="$attrs"&&ae(e.attrs,"get",""),c(e);if((u=l.__cssModules)&&(u=u[t]))return u;if(n!==B&&V(n,t))return o[t]=4,n[t];if(p=a.config.globalProperties,V(p,t))return p[t]},set({_:e},t,n){const{data:s,setupState:r,ctx:i}=e;return ts(r,t)?(r[t]=n,!0):s!==B&&V(s,t)?(s[t]=n,!0):V(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(i[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:s,appContext:r,props:i,type:o}},l){let a;return!!(n[l]||e!==B&&l[0]!=="$"&&V(e,l)||ts(t,l)||V(i,l)||V(s,l)||V(Vt,l)||V(r.config.globalProperties,l)||(a=o.__cssModules)&&a[l])},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:V(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};function Cn(e){return I(e)?e.reduce((t,n)=>(t[n]=null,t),{}):e}function ps(e,t){return!e||!t?e||t:I(e)&&I(t)?e.concat(t):re({},Cn(e),Cn(t))}let ds=!0;function Mo(e){const t=Ii(e),n=e.proxy,s=e.ctx;ds=!1,t.beforeCreate&&hr(t.beforeCreate,e,"bc");const{data:r,computed:i,methods:o,watch:l,provide:a,inject:c,created:u,beforeMount:p,mounted:d,beforeUpdate:b,updated:w,activated:_,deactivated:N,beforeDestroy:L,beforeUnmount:R,destroyed:D,unmounted:E,render:ee,renderTracked:ke,renderTriggered:oe,errorCaptured:et,serverPrefetch:on,expose:lt,inheritAttrs:Rt,components:an,directives:cn,filters:Gn}=t;if(c&&zo(c,s,null),o)for(const Y in o){const J=o[Y];M(J)&&(s[Y]=J.bind(n))}if(r){const Y=r.call(n,n);G(Y)&&(e.data=Os(Y))}if(ds=!0,i)for(const Y in i){const J=i[Y],ot=M(J)?J.bind(n,n):M(J.get)?J.get.bind(n,n):Te,un=!M(J)&&M(J.set)?J.set.bind(n):Te,at=rn({get:ot,set:un});Object.defineProperty(s,Y,{enumerable:!0,configurable:!0,get:()=>at.value,set:Ae=>at.value=Ae})}if(l)for(const Y in l)Ei(l[Y],s,n,Y);if(a){const Y=M(a)?a.call(n):a;Reflect.ownKeys(Y).forEach(J=>{ki(J,Y[J])})}u&&hr(u,e,"c");function fe(Y,J){I(J)?J.forEach(ot=>Y(ot.bind(n))):J&&Y(J.bind(n))}if(fe(Co,p),fe(nn,d),fe(Ri,b),fe($o,w),fe(ko,_),fe(So,N),fe(Io,et),fe(Eo,ke),fe(Po,oe),fe(Ro,R),fe(Bn,E),fe(Ao,on),I(lt))if(lt.length){const Y=e.exposed||(e.exposed={});lt.forEach(J=>{Object.defineProperty(Y,J,{get:()=>n[J],set:ot=>n[J]=ot,enumerable:!0})})}else e.exposed||(e.exposed={});ee&&e.render===Te&&(e.render=ee),Rt!=null&&(e.inheritAttrs=Rt),an&&(e.components=an),cn&&(e.directives=cn),on&&Ti(e)}function zo(e,t,n=Te){I(e)&&(e=gs(e));for(const s in e){const r=e[s];let i;G(r)?"default"in r?i=Bt(r.from||s,r.default,!0):i=Bt(r.from||s):i=Bt(r),ue(i)?Object.defineProperty(t,s,{enumerable:!0,configurable:!0,get:()=>i.value,set:o=>i.value=o}):t[s]=i}}function hr(e,t,n){je(I(e)?e.map(s=>s.bind(t.proxy)):e.bind(t.proxy),t,n)}function Ei(e,t,n,s){let r=s.includes(".")?Si(n,s):()=>n[s];if(te(e)){const i=t[e];M(i)&&Ht(r,i)}else if(M(e))Ht(r,e.bind(n));else if(G(e))if(I(e))e.forEach(i=>Ei(i,t,n,s));else{const i=M(e.handler)?e.handler.bind(n):t[e.handler];M(i)&&Ht(r,i,e)}}function Ii(e){const t=e.type,{mixins:n,extends:s}=t,{mixins:r,optionsCache:i,config:{optionMergeStrategies:o}}=e.appContext,l=i.get(t);let a;return l?a=l:!r.length&&!n&&!s?a=t:(a={},r.length&&r.forEach(c=>$n(a,c,o,!0)),$n(a,t,o)),G(t)&&i.set(t,a),a}function $n(e,t,n,s=!1){const{mixins:r,extends:i}=t;i&&$n(e,i,n,!0),r&&r.forEach(o=>$n(e,o,n,!0));for(const o in t)if(!(s&&o==="expose")){const l=Do[o]||n&&n[o];e[o]=l?l(e[o],t[o]):t[o]}return e}const Do={data:pr,props:dr,emits:dr,methods:zt,computed:zt,beforeCreate:he,created:he,beforeMount:he,mounted:he,beforeUpdate:he,updated:he,beforeDestroy:he,beforeUnmount:he,destroyed:he,unmounted:he,activated:he,deactivated:he,errorCaptured:he,serverPrefetch:he,components:zt,directives:zt,watch:Fo,provide:pr,inject:jo};function pr(e,t){return t?e?function(){return re(M(e)?e.call(this,this):e,M(t)?t.call(this,this):t)}:t:e}function jo(e,t){return zt(gs(e),gs(t))}function gs(e){if(I(e)){const t={};for(let n=0;n{let u,p=B,d;return vo(()=>{const b=e[r];ye(u,b)&&(u=b,c())}),{get(){return a(),n.get?n.get(u):u},set(b){const w=n.set?n.set(b):b;if(!ye(w,u)&&!(p!==B&&ye(b,p)))return;const _=s.vnode.props;_&&(t in _||r in _||i in _)&&(`onUpdate:${t}`in _||`onUpdate:${r}`in _||`onUpdate:${i}`in _)||(u=b,c()),s.emit(`update:${t}`,w),ye(b,w)&&ye(b,p)&&!ye(w,d)&&c(),p=b,d=w}}});return l[Symbol.iterator]=()=>{let a=0;return{next(){return a<2?{value:a++?o||B:l,done:!1}:{done:!0}}}},l}const Li=(e,t)=>t==="modelValue"||t==="model-value"?e.modelModifiers:e[`${t}Modifiers`]||e[`${We(t)}Modifiers`]||e[`${it(t)}Modifiers`];function Ho(e,t,...n){if(e.isUnmounted)return;const s=e.vnode.props||B;let r=n;const i=t.startsWith("update:"),o=i&&Li(s,t.slice(7));o&&(o.trim&&(r=n.map(u=>te(u)?u.trim():u)),o.number&&(r=n.map($s)));let l,a=s[l=Jn(t)]||s[l=Jn(We(t))];!a&&i&&(a=s[l=Jn(it(t))]),a&&je(a,e,6,r);const c=s[l+"Once"];if(c){if(!e.emitted)e.emitted={};else if(e.emitted[l])return;e.emitted[l]=!0,je(c,e,6,r)}}const Uo=new WeakMap;function Mi(e,t,n=!1){const s=n?Uo:t.emitsCache,r=s.get(e);if(r!==void 0)return r;const i=e.emits;let o={},l=!1;if(!M(e)){const a=c=>{const u=Mi(c,t,!0);u&&(l=!0,re(o,u))};!n&&t.mixins.length&&t.mixins.forEach(a),e.extends&&a(e.extends),e.mixins&&e.mixins.forEach(a)}return!i&&!l?(G(e)&&s.set(e,null),null):(I(i)?i.forEach(a=>o[a]=null):re(o,i),G(e)&&s.set(e,o),o)}function Hn(e,t){return!e||!On(t)?!1:(t=t.slice(2).replace(/Once$/,""),V(e,t[0].toLowerCase()+t.slice(1))||V(e,it(t))||V(e,t))}function gr(e){const{type:t,vnode:n,proxy:s,withProxy:r,propsOptions:[i],slots:o,attrs:l,emit:a,render:c,renderCache:u,props:p,data:d,setupState:b,ctx:w,inheritAttrs:_}=e,N=kn(e);let L,R;try{if(n.shapeFlag&4){const E=r||s,ee=E;L=ze(c.call(ee,E,u,p,b,d,w)),R=l}else{const E=t;L=ze(E.length>1?E(p,{attrs:l,slots:o,emit:a}):E(p,null)),R=t.props?l:Vo(l)}}catch(E){qt.length=0,Fn(E,e,1),L=se(Qe)}let D=L;if(R&&_!==!1){const E=Object.keys(R),{shapeFlag:ee}=D;E.length&&ee&7&&(i&&E.some(Ss)&&(R=Ko(R,i)),D=Ct(D,R,!1,!0))}return n.dirs&&(D=Ct(D,null,!1,!0),D.dirs=D.dirs?D.dirs.concat(n.dirs):n.dirs),n.transition&&js(D,n.transition),L=D,kn(N),L}const Vo=e=>{let t;for(const n in e)(n==="class"||n==="style"||On(n))&&((t||(t={}))[n]=e[n]);return t},Ko=(e,t)=>{const n={};for(const s in e)(!Ss(s)||!(s.slice(9)in t))&&(n[s]=e[s]);return n};function qo(e,t,n){const{props:s,children:r,component:i}=e,{props:o,children:l,patchFlag:a}=t,c=i.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&a>=0){if(a&1024)return!0;if(a&16)return s?mr(s,o,c):!!o;if(a&8){const u=t.dynamicProps;for(let p=0;pObject.create(Di),Fi=e=>Object.getPrototypeOf(e)===Di;function Go(e,t,n,s=!1){const r={},i=ji();e.propsDefaults=Object.create(null),Ni(e,t,r,i);for(const o in e.propsOptions[0])o in r||(r[o]=void 0);n?e.props=s?r:no(r):e.type.props?e.props=r:e.props=i,e.attrs=i}function Zo(e,t,n,s){const{props:r,attrs:i,vnode:{patchFlag:o}}=e,l=U(r),[a]=e.propsOptions;let c=!1;if((s||o>0)&&!(o&16)){if(o&8){const u=e.vnode.dynamicProps;for(let p=0;p{a=!0;const[d,b]=Bi(p,t,!0);re(o,d),b&&l.push(...b)};!n&&t.mixins.length&&t.mixins.forEach(u),e.extends&&u(e.extends),e.mixins&&e.mixins.forEach(u)}if(!i&&!a)return G(e)&&s.set(e,yt),yt;if(I(i))for(let u=0;ue==="_"||e==="_ctx"||e==="$stable",Ns=e=>I(e)?e.map(ze):[ze(e)],Qo=(e,t,n)=>{if(t._n)return t;const s=dt((...r)=>Ns(t(...r)),n);return s._c=!1,s},Hi=(e,t,n)=>{const s=e._ctx;for(const r in e){if(Fs(r))continue;const i=e[r];if(M(i))t[r]=Qo(r,i,s);else if(i!=null){const o=Ns(i);t[r]=()=>o}}},Ui=(e,t)=>{const n=Ns(t);e.slots.default=()=>n},Vi=(e,t,n)=>{for(const s in t)(n||!Fs(s))&&(e[s]=t[s])},Xo=(e,t,n)=>{const s=e.slots=ji();if(e.vnode.shapeFlag&32){const r=t._;r?(Vi(s,t,n),n&&Zr(s,"_",r,!0)):Hi(t,s)}else t&&Ui(e,t)},Yo=(e,t,n)=>{const{vnode:s,slots:r}=e;let i=!0,o=B;if(s.shapeFlag&32){const l=t._;l?n&&l===1?i=!1:Vi(r,t,n):(i=!t.$stable,Hi(t,r)),o=t}else t&&(Ui(e,t),o={default:1});if(i)for(const l in r)!Fs(l)&&o[l]==null&&delete r[l]},ve=ra;function ea(e){return ta(e)}function ta(e,t){const n=Mn();n.__VUE__=!0;const{insert:s,remove:r,patchProp:i,createElement:o,createText:l,createComment:a,setText:c,setElementText:u,parentNode:p,nextSibling:d,setScopeId:b=Te,insertStaticContent:w}=e,_=(f,h,g,y=null,m=null,v=null,C=void 0,S=null,k=!!h.dynamicChildren)=>{if(f===h)return;f&&!Ot(f,h)&&(y=fn(f),Ae(f,m,v,!0),f=null),h.patchFlag===-2&&(k=!1,h.dynamicChildren=null);const{type:x,ref:P,shapeFlag:$}=h;switch(x){case Un:N(f,h,g,y);break;case Qe:L(f,h,g,y);break;case Kt:f==null&&R(h,g,y,C);break;case ie:an(f,h,g,y,m,v,C,S,k);break;default:$&1?ee(f,h,g,y,m,v,C,S,k):$&6?cn(f,h,g,y,m,v,C,S,k):($&64||$&128)&&x.process(f,h,g,y,m,v,C,S,k,Pt)}P!=null&&m?Ut(P,f&&f.ref,v,h||f,!h):P==null&&f&&f.ref!=null&&Ut(f.ref,null,v,f,!0)},N=(f,h,g,y)=>{if(f==null)s(h.el=l(h.children),g,y);else{const m=h.el=f.el;h.children!==f.children&&c(m,h.children)}},L=(f,h,g,y)=>{f==null?s(h.el=a(h.children||""),g,y):h.el=f.el},R=(f,h,g,y)=>{[f.el,f.anchor]=w(f.children,h,g,y,f.el,f.anchor)},D=({el:f,anchor:h},g,y)=>{let m;for(;f&&f!==h;)m=d(f),s(f,g,y),f=m;s(h,g,y)},E=({el:f,anchor:h})=>{let g;for(;f&&f!==h;)g=d(f),r(f),f=g;r(h)},ee=(f,h,g,y,m,v,C,S,k)=>{if(h.type==="svg"?C="svg":h.type==="math"&&(C="mathml"),f==null)ke(h,g,y,m,v,C,S,k);else{const x=f.el&&f.el._isVueCE?f.el:null;try{x&&x._beginPatch(),on(f,h,m,v,C,S,k)}finally{x&&x._endPatch()}}},ke=(f,h,g,y,m,v,C,S)=>{let k,x;const{props:P,shapeFlag:$,transition:A,dirs:O}=f;if(k=f.el=o(f.type,v,P&&P.is,P),$&8?u(k,f.children):$&16&&et(f.children,k,null,y,m,ns(f,v),C,S),O&&ct(f,null,y,"created"),oe(k,f,f.scopeId,C,y),P){for(const Q in P)Q!=="value"&&!jt(Q)&&i(k,Q,null,P[Q],v,y);"value"in P&&i(k,"value",null,P.value,v),(x=P.onVnodeBeforeMount)&&Oe(x,y,f)}O&&ct(f,null,y,"beforeMount");const j=na(m,A);j&&A.beforeEnter(k),s(k,h,g),((x=P&&P.onVnodeMounted)||j||O)&&ve(()=>{x&&Oe(x,y,f),j&&A.enter(k),O&&ct(f,null,y,"mounted")},m)},oe=(f,h,g,y,m)=>{if(g&&b(f,g),y)for(let v=0;v{for(let x=k;x{const S=h.el=f.el;let{patchFlag:k,dynamicChildren:x,dirs:P}=h;k|=f.patchFlag&16;const $=f.props||B,A=h.props||B;let O;if(g&&ut(g,!1),(O=A.onVnodeBeforeUpdate)&&Oe(O,g,h,f),P&&ct(h,f,g,"beforeUpdate"),g&&ut(g,!0),($.innerHTML&&A.innerHTML==null||$.textContent&&A.textContent==null)&&u(S,""),x?lt(f.dynamicChildren,x,S,g,y,ns(h,m),v):C||J(f,h,S,null,g,y,ns(h,m),v,!1),k>0){if(k&16)Rt(S,$,A,g,m);else if(k&2&&$.class!==A.class&&i(S,"class",null,A.class,m),k&4&&i(S,"style",$.style,A.style,m),k&8){const j=h.dynamicProps;for(let Q=0;Q{O&&Oe(O,g,h,f),P&&ct(h,f,g,"updated")},y)},lt=(f,h,g,y,m,v,C)=>{for(let S=0;S{if(h!==g){if(h!==B)for(const v in h)!jt(v)&&!(v in g)&&i(f,v,h[v],null,m,y);for(const v in g){if(jt(v))continue;const C=g[v],S=h[v];C!==S&&v!=="value"&&i(f,v,S,C,m,y)}"value"in g&&i(f,"value",h.value,g.value,m)}},an=(f,h,g,y,m,v,C,S,k)=>{const x=h.el=f?f.el:l(""),P=h.anchor=f?f.anchor:l("");let{patchFlag:$,dynamicChildren:A,slotScopeIds:O}=h;O&&(S=S?S.concat(O):O),f==null?(s(x,g,y),s(P,g,y),et(h.children||[],g,P,m,v,C,S,k)):$>0&&$&64&&A&&f.dynamicChildren&&f.dynamicChildren.length===A.length?(lt(f.dynamicChildren,A,g,m,v,C,S),(h.key!=null||m&&h===m.subTree)&&Ki(f,h,!0)):J(f,h,g,P,m,v,C,S,k)},cn=(f,h,g,y,m,v,C,S,k)=>{h.slotScopeIds=S,f==null?h.shapeFlag&512?m.ctx.activate(h,g,y,C,k):Gn(h,g,y,m,v,C,k):Ys(f,h,k)},Gn=(f,h,g,y,m,v,C)=>{const S=f.component=ha(f,y,m);if(Ci(f)&&(S.ctx.renderer=Pt),pa(S,!1,C),S.asyncDep){if(m&&m.registerDep(S,fe,C),!f.el){const k=S.subTree=se(Qe);L(null,k,h,g),f.placeholder=k.el}}else fe(S,f,h,g,m,v,C)},Ys=(f,h,g)=>{const y=h.component=f.component;if(qo(f,h,g))if(y.asyncDep&&!y.asyncResolved){Y(y,h,g);return}else y.next=h,y.update();else h.el=f.el,y.vnode=h},fe=(f,h,g,y,m,v,C)=>{const S=()=>{if(f.isMounted){let{next:$,bu:A,u:O,parent:j,vnode:Q}=f;{const Ee=qi(f);if(Ee){$&&($.el=Q.el,Y(f,$,C)),Ee.asyncDep.then(()=>{ve(()=>{f.isUnmounted||x()},m)});return}}let q=$,me;ut(f,!1),$?($.el=Q.el,Y(f,$,C)):$=Q,A&&mn(A),(me=$.props&&$.props.onVnodeBeforeUpdate)&&Oe(me,j,$,Q),ut(f,!0);const be=gr(f),Pe=f.subTree;f.subTree=be,_(Pe,be,p(Pe.el),fn(Pe),f,m,v),$.el=be.el,q===null&&Wo(f,be.el),O&&ve(O,m),(me=$.props&&$.props.onVnodeUpdated)&&ve(()=>Oe(me,j,$,Q),m)}else{let $;const{el:A,props:O}=h,{bm:j,m:Q,parent:q,root:me,type:be}=f,Pe=kt(h);ut(f,!1),j&&mn(j),!Pe&&($=O&&O.onVnodeBeforeMount)&&Oe($,q,h),ut(f,!0);{me.ce&&me.ce._hasShadowRoot()&&me.ce._injectChildStyle(be);const Ee=f.subTree=gr(f);_(null,Ee,g,y,f,m,v),h.el=Ee.el}if(Q&&ve(Q,m),!Pe&&($=O&&O.onVnodeMounted)){const Ee=h;ve(()=>Oe($,q,Ee),m)}(h.shapeFlag&256||q&&kt(q.vnode)&&q.vnode.shapeFlag&256)&&f.a&&ve(f.a,m),f.isMounted=!0,h=g=y=null}};f.scope.on();const k=f.effect=new Yr(S);f.scope.off();const x=f.update=k.run.bind(k),P=f.job=k.runIfDirty.bind(k);P.i=f,P.id=f.uid,k.scheduler=()=>zs(P),ut(f,!0),x()},Y=(f,h,g)=>{h.component=f;const y=f.vnode.props;f.vnode=h,f.next=null,Zo(f,h.props,y,g),Yo(f,h.children,g),Ge(),cr(f),Ze()},J=(f,h,g,y,m,v,C,S,k=!1)=>{const x=f&&f.children,P=f?f.shapeFlag:0,$=h.children,{patchFlag:A,shapeFlag:O}=h;if(A>0){if(A&128){un(x,$,g,y,m,v,C,S,k);return}else if(A&256){ot(x,$,g,y,m,v,C,S,k);return}}O&8?(P&16&&At(x,m,v),$!==x&&u(g,$)):P&16?O&16?un(x,$,g,y,m,v,C,S,k):At(x,m,v,!0):(P&8&&u(g,""),O&16&&et($,g,y,m,v,C,S,k))},ot=(f,h,g,y,m,v,C,S,k)=>{f=f||yt,h=h||yt;const x=f.length,P=h.length,$=Math.min(x,P);let A;for(A=0;A<$;A++){const O=h[A]=k?Be(h[A]):ze(h[A]);_(f[A],O,g,null,m,v,C,S,k)}x>P?At(f,m,v,!0,!1,$):et(h,g,y,m,v,C,S,k,$)},un=(f,h,g,y,m,v,C,S,k)=>{let x=0;const P=h.length;let $=f.length-1,A=P-1;for(;x<=$&&x<=A;){const O=f[x],j=h[x]=k?Be(h[x]):ze(h[x]);if(Ot(O,j))_(O,j,g,null,m,v,C,S,k);else break;x++}for(;x<=$&&x<=A;){const O=f[$],j=h[A]=k?Be(h[A]):ze(h[A]);if(Ot(O,j))_(O,j,g,null,m,v,C,S,k);else break;$--,A--}if(x>$){if(x<=A){const O=A+1,j=OA)for(;x<=$;)Ae(f[x],m,v,!0),x++;else{const O=x,j=x,Q=new Map;for(x=j;x<=A;x++){const _e=h[x]=k?Be(h[x]):ze(h[x]);_e.key!=null&&Q.set(_e.key,x)}let q,me=0;const be=A-j+1;let Pe=!1,Ee=0;const Et=new Array(be);for(x=0;x=be){Ae(_e,m,v,!0);continue}let Ie;if(_e.key!=null)Ie=Q.get(_e.key);else for(q=j;q<=A;q++)if(Et[q-j]===0&&Ot(_e,h[q])){Ie=q;break}Ie===void 0?Ae(_e,m,v,!0):(Et[Ie-j]=x+1,Ie>=Ee?Ee=Ie:Pe=!0,_(_e,h[Ie],g,null,m,v,C,S,k),me++)}const nr=Pe?sa(Et):yt;for(q=nr.length-1,x=be-1;x>=0;x--){const _e=j+x,Ie=h[_e],sr=h[_e+1],rr=_e+1{const{el:v,type:C,transition:S,children:k,shapeFlag:x}=f;if(x&6){at(f.component.subTree,h,g,y);return}if(x&128){f.suspense.move(h,g,y);return}if(x&64){C.move(f,h,g,Pt);return}if(C===ie){s(v,h,g);for(let $=0;$S.enter(v),m);else{const{leave:$,delayLeave:A,afterLeave:O}=S,j=()=>{f.ctx.isUnmounted?r(v):s(v,h,g)},Q=()=>{v._isLeaving&&v[wo](!0),$(v,()=>{j(),O&&O()})};A?A(v,j,Q):Q()}else s(v,h,g)},Ae=(f,h,g,y=!1,m=!1)=>{const{type:v,props:C,ref:S,children:k,dynamicChildren:x,shapeFlag:P,patchFlag:$,dirs:A,cacheIndex:O}=f;if($===-2&&(m=!1),S!=null&&(Ge(),Ut(S,null,g,f,!0),Ze()),O!=null&&(h.renderCache[O]=void 0),P&256){h.ctx.deactivate(f);return}const j=P&1&&A,Q=!kt(f);let q;if(Q&&(q=C&&C.onVnodeBeforeUnmount)&&Oe(q,h,f),P&6)_l(f.component,g,y);else{if(P&128){f.suspense.unmount(g,y);return}j&&ct(f,null,h,"beforeUnmount"),P&64?f.type.remove(f,h,g,Pt,y):x&&!x.hasOnce&&(v!==ie||$>0&&$&64)?At(x,h,g,!1,!0):(v===ie&&$&384||!m&&P&16)&&At(k,h,g),y&&er(f)}(Q&&(q=C&&C.onVnodeUnmounted)||j)&&ve(()=>{q&&Oe(q,h,f),j&&ct(f,null,h,"unmounted")},g)},er=f=>{const{type:h,el:g,anchor:y,transition:m}=f;if(h===ie){yl(g,y);return}if(h===Kt){E(f);return}const v=()=>{r(g),m&&!m.persisted&&m.afterLeave&&m.afterLeave()};if(f.shapeFlag&1&&m&&!m.persisted){const{leave:C,delayLeave:S}=m,k=()=>C(g,v);S?S(f.el,v,k):k()}else v()},yl=(f,h)=>{let g;for(;f!==h;)g=d(f),r(f),f=g;r(h)},_l=(f,h,g)=>{const{bum:y,scope:m,job:v,subTree:C,um:S,m:k,a:x}=f;vr(k),vr(x),y&&mn(y),m.stop(),v&&(v.flags|=8,Ae(C,f,h,g)),S&&ve(S,h),ve(()=>{f.isUnmounted=!0},h)},At=(f,h,g,y=!1,m=!1,v=0)=>{for(let C=v;C{if(f.shapeFlag&6)return fn(f.component.subTree);if(f.shapeFlag&128)return f.suspense.next();const h=d(f.anchor||f.el),g=h&&h[yo];return g?d(g):h};let Zn=!1;const tr=(f,h,g)=>{let y;f==null?h._vnode&&(Ae(h._vnode,null,null,!0),y=h._vnode.component):_(h._vnode||null,f,h,null,null,null,g),h._vnode=f,Zn||(Zn=!0,cr(y),xi(),Zn=!1)},Pt={p:_,um:Ae,m:at,r:er,mt:Gn,mc:et,pc:J,pbc:lt,n:fn,o:e};return{render:tr,hydrate:void 0,createApp:Bo(tr)}}function ns({type:e,props:t},n){return n==="svg"&&e==="foreignObject"||n==="mathml"&&e==="annotation-xml"&&t&&t.encoding&&t.encoding.includes("html")?void 0:n}function ut({effect:e,job:t},n){n?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function na(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function Ki(e,t,n=!1){const s=e.children,r=t.children;if(I(s)&&I(r))for(let i=0;i>1,e[n[l]]0&&(t[s]=n[i-1]),n[i]=s)}}for(i=n.length,o=n[i-1];i-- >0;)n[i]=o,o=t[o];return n}function qi(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:qi(t)}function vr(e){if(e)for(let t=0;te.__isSuspense;function ra(e,t){t&&t.pendingBranch?I(e)?t.effects.push(...e):t.effects.push(e):vi(e)}const ie=Symbol.for("v-fgt"),Un=Symbol.for("v-txt"),Qe=Symbol.for("v-cmt"),Kt=Symbol.for("v-stc"),qt=[];let we=null;function z(e=!1){qt.push(we=e?null:[])}function ia(){qt.pop(),we=qt[qt.length-1]||null}let Qt=1;function xr(e,t=!1){Qt+=e,e<0&&we&&t&&(we.hasOnce=!0)}function Zi(e){return e.dynamicChildren=Qt>0?we||yt:null,ia(),Qt>0&&we&&we.push(e),e}function F(e,t,n,s,r,i){return Zi(T(e,t,n,s,r,i,!0))}function Ve(e,t,n,s,r){return Zi(se(e,t,n,s,r,!0))}function Bs(e){return e?e.__v_isVNode===!0:!1}function Ot(e,t){return e.type===t.type&&e.key===t.key}const Ji=({key:e})=>e??null,vn=({ref:e,ref_key:t,ref_for:n})=>(typeof e=="number"&&(e=""+e),e!=null?te(e)||ue(e)||M(e)?{i:ce,r:e,k:t,f:!!n}:e:null);function T(e,t=null,n=null,s=0,r=null,i=e===ie?0:1,o=!1,l=!1){const a={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&Ji(t),ref:t&&vn(t),scopeId:_i,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:i,patchFlag:s,dynamicProps:r,dynamicChildren:null,appContext:null,ctx:ce};return l?(Hs(a,n),i&128&&e.normalize(a)):n&&(a.shapeFlag|=te(n)?8:16),Qt>0&&!o&&we&&(a.patchFlag>0||i&6)&&a.patchFlag!==32&&we.push(a),a}const se=la;function la(e,t=null,n=null,s=0,r=null,i=!1){if((!e||e===Oo)&&(e=Qe),Bs(e)){const l=Ct(e,t,!0);return n&&Hs(l,n),Qt>0&&!i&&we&&(l.shapeFlag&6?we[we.indexOf(e)]=l:we.push(l)),l.patchFlag=-2,l}if(ba(e)&&(e=e.__vccOpts),t){t=oa(t);let{class:l,style:a}=t;l&&!te(l)&&(t.class=rt(l)),G(a)&&(Ms(a)&&!I(a)&&(a=re({},a)),t.style=zn(a))}const o=te(e)?1:Gi(e)?128:_o(e)?64:G(e)?4:M(e)?2:0;return T(e,t,n,s,r,o,i,!0)}function oa(e){return e?Ms(e)||Fi(e)?re({},e):e:null}function Ct(e,t,n=!1,s=!1){const{props:r,ref:i,patchFlag:o,children:l,transition:a}=e,c=t?ca(r||{},t):r,u={__v_isVNode:!0,__v_skip:!0,type:e.type,props:c,key:c&&Ji(c),ref:t&&t.ref?n&&i?I(i)?i.concat(vn(t)):[i,vn(t)]:vn(t):i,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:l,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==ie?o===-1?16:o|16:o,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:a,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&Ct(e.ssContent),ssFallback:e.ssFallback&&Ct(e.ssFallback),placeholder:e.placeholder,el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce};return a&&s&&js(u,a.clone(u)),u}function De(e=" ",t=0){return se(Un,null,e,t)}function aa(e,t){const n=se(Kt,null,e);return n.staticCount=t,n}function le(e="",t=!1){return t?(z(),Ve(Qe,null,e)):se(Qe,null,e)}function ze(e){return e==null||typeof e=="boolean"?se(Qe):I(e)?se(ie,null,e.slice()):Bs(e)?Be(e):se(Un,null,String(e))}function Be(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:Ct(e)}function Hs(e,t){let n=0;const{shapeFlag:s}=e;if(t==null)t=null;else if(I(t))n=16;else if(typeof t=="object")if(s&65){const r=t.default;r&&(r._c&&(r._d=!1),Hs(e,r()),r._c&&(r._d=!0));return}else{n=32;const r=t._;!r&&!Fi(t)?t._ctx=ce:r===3&&ce&&(ce.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else M(t)?(t={default:t,_ctx:ce},n=32):(t=String(t),s&64?(n=16,t=[De(t)]):n=8);e.children=t,e.shapeFlag|=n}function ca(...e){const t={};for(let n=0;nde||ce;let Rn,bs;{const e=Mn(),t=(n,s)=>{let r;return(r=e[n])||(r=e[n]=[]),r.push(s),i=>{r.length>1?r.forEach(o=>o(i)):r[0](i)}};Rn=t("__VUE_INSTANCE_SETTERS__",n=>de=n),bs=t("__VUE_SSR_SETTERS__",n=>Xt=n)}const sn=e=>{const t=de;return Rn(e),e.scope.on(),()=>{e.scope.off(),Rn(t)}},yr=()=>{de&&de.scope.off(),Rn(null)};function Qi(e){return e.vnode.shapeFlag&4}let Xt=!1;function pa(e,t=!1,n=!1){t&&bs(t);const{props:s,children:r}=e.vnode,i=Qi(e);Go(e,s,i,t),Xo(e,r,n||t);const o=i?da(e,t):void 0;return t&&bs(!1),o}function da(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,Lo);const{setup:s}=n;if(s){Ge();const r=e.setupContext=s.length>1?ma(e):null,i=sn(e),o=tn(s,e,0,[e.props,r]),l=Kr(o);if(Ze(),i(),(l||e.sp)&&!kt(e)&&Ti(e),l){if(o.then(yr,yr),t)return o.then(a=>{_r(e,a)}).catch(a=>{Fn(a,e,0)});e.asyncDep=o}else _r(e,o)}else Xi(e)}function _r(e,t,n){M(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:G(t)&&(e.setupState=di(t)),Xi(e)}function Xi(e,t,n){const s=e.type;e.render||(e.render=s.render||Te);{const r=sn(e);Ge();try{Mo(e)}finally{Ze(),r()}}}const ga={get(e,t){return ae(e,"get",""),e[t]}};function ma(e){const t=n=>{e.exposed=n||{}};return{attrs:new Proxy(e.attrs,ga),slots:e.slots,emit:e.emit,expose:t}}function Kn(e){return e.exposed?e.exposeProxy||(e.exposeProxy=new Proxy(di(so(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in Vt)return Vt[n](e)},has(t,n){return n in t||n in Vt}})):e.proxy}function ba(e){return M(e)&&"__vccOpts"in e}const rn=(e,t)=>uo(e,t,Xt),va="3.5.28";/** +* @vue/runtime-dom v3.5.28 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let vs;const wr=typeof window<"u"&&window.trustedTypes;if(wr)try{vs=wr.createPolicy("vue",{createHTML:e=>e})}catch{}const Yi=vs?e=>vs.createHTML(e):e=>e,xa="http://www.w3.org/2000/svg",ya="http://www.w3.org/1998/Math/MathML",Ne=typeof document<"u"?document:null,kr=Ne&&Ne.createElement("template"),_a={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,s)=>{const r=t==="svg"?Ne.createElementNS(xa,e):t==="mathml"?Ne.createElementNS(ya,e):n?Ne.createElement(e,{is:n}):Ne.createElement(e);return e==="select"&&s&&s.multiple!=null&&r.setAttribute("multiple",s.multiple),r},createText:e=>Ne.createTextNode(e),createComment:e=>Ne.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Ne.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,s,r,i){const o=n?n.previousSibling:t.lastChild;if(r&&(r===i||r.nextSibling))for(;t.insertBefore(r.cloneNode(!0),n),!(r===i||!(r=r.nextSibling)););else{kr.innerHTML=Yi(s==="svg"?`${e}`:s==="mathml"?`${e}`:e);const l=kr.content;if(s==="svg"||s==="mathml"){const a=l.firstChild;for(;a.firstChild;)l.appendChild(a.firstChild);l.removeChild(a)}t.insertBefore(l,n)}return[o?o.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},wa=Symbol("_vtc");function ka(e,t,n){const s=e[wa];s&&(t=(t?[t,...s]:[...s]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const Sr=Symbol("_vod"),Sa=Symbol("_vsh"),el=Symbol("");function tl(e){const t=Vn();if(!t)return;const n=t.ut=(r=e(t.proxy))=>{Array.from(document.querySelectorAll(`[data-v-owner="${t.uid}"]`)).forEach(i=>An(i,r))},s=()=>{const r=e(t.proxy);t.ce?An(t.ce,r):xs(t.subTree,r),n(r)};Ri(()=>{vi(s)}),nn(()=>{Ht(s,Te,{flush:"post"});const r=new MutationObserver(s);r.observe(t.subTree.el.parentNode,{childList:!0}),Bn(()=>r.disconnect())})}function xs(e,t){if(e.shapeFlag&128){const n=e.suspense;e=n.activeBranch,n.pendingBranch&&!n.isHydrating&&n.effects.push(()=>{xs(n.activeBranch,t)})}for(;e.component;)e=e.component.subTree;if(e.shapeFlag&1&&e.el)An(e.el,t);else if(e.type===ie)e.children.forEach(n=>xs(n,t));else if(e.type===Kt){let{el:n,anchor:s}=e;for(;n&&(An(n,t),n!==s);)n=n.nextSibling}}function An(e,t){if(e.nodeType===1){const n=e.style;let s="";for(const r in t){const i=Ml(t[r]);n.setProperty(`--${r}`,i),s+=`--${r}: ${i};`}n[el]=s}}const Ta=/(?:^|;)\s*display\s*:/;function Ca(e,t,n){const s=e.style,r=te(n);let i=!1;if(n&&!r){if(t)if(te(t))for(const o of t.split(";")){const l=o.slice(0,o.indexOf(":")).trim();n[l]==null&&xn(s,l,"")}else for(const o in t)n[o]==null&&xn(s,o,"");for(const o in n)o==="display"&&(i=!0),xn(s,o,n[o])}else if(r){if(t!==n){const o=s[el];o&&(n+=";"+o),s.cssText=n,i=Ta.test(n)}}else t&&e.removeAttribute("style");Sr in e&&(e[Sr]=i?s.display:"",e[Sa]&&(s.display="none"))}const Tr=/\s*!important$/;function xn(e,t,n){if(I(n))n.forEach(s=>xn(e,t,s));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const s=$a(e,t);Tr.test(n)?e.setProperty(it(s),n.replace(Tr,""),"important"):e[s]=n}}const Cr=["Webkit","Moz","ms"],ss={};function $a(e,t){const n=ss[t];if(n)return n;let s=We(t);if(s!=="filter"&&s in e)return ss[t]=s;s=Gr(s);for(let r=0;rrs||(Ea.then(()=>rs=0),rs=Date.now());function Oa(e,t){const n=s=>{if(!s._vts)s._vts=Date.now();else if(s._vts<=n.attached)return;je(La(s,n.value),t,5,[s])};return n.value=e,n.attached=Ia(),n}function La(e,t){if(I(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(s=>r=>!r._stopped&&s&&s(r))}else return t}const Ir=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,Ma=(e,t,n,s,r,i)=>{const o=r==="svg";t==="class"?ka(e,s,o):t==="style"?Ca(e,n,s):On(t)?Ss(t)||Aa(e,t,n,s,i):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):za(e,t,s,o))?(Ar(e,t,s),!e.tagName.includes("-")&&(t==="value"||t==="checked"||t==="selected")&&Rr(e,t,s,o,i,t!=="value")):e._isVueCE&&(/[A-Z]/.test(t)||!te(s))?Ar(e,We(t),s,i,t):(t==="true-value"?e._trueValue=s:t==="false-value"&&(e._falseValue=s),Rr(e,t,s,o))};function za(e,t,n,s){if(s)return!!(t==="innerHTML"||t==="textContent"||t in e&&Ir(t)&&M(n));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="autocorrect"||t==="sandbox"&&e.tagName==="IFRAME"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const r=e.tagName;if(r==="IMG"||r==="VIDEO"||r==="CANVAS"||r==="SOURCE")return!1}return Ir(t)&&te(n)?!1:t in e}const Or=e=>{const t=e.props["onUpdate:modelValue"]||!1;return I(t)?n=>mn(t,n):t};function Da(e){e.target.composing=!0}function Lr(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const is=Symbol("_assign");function Mr(e,t,n){return t&&(e=e.trim()),n&&(e=$s(e)),e}const nl={created(e,{modifiers:{lazy:t,trim:n,number:s}},r){e[is]=Or(r);const i=s||r.props&&r.props.type==="number";xt(e,t?"change":"input",o=>{o.target.composing||e[is](Mr(e.value,n,i))}),(n||i)&&xt(e,"change",()=>{e.value=Mr(e.value,n,i)}),t||(xt(e,"compositionstart",Da),xt(e,"compositionend",Lr),xt(e,"change",Lr))},mounted(e,{value:t}){e.value=t??""},beforeUpdate(e,{value:t,oldValue:n,modifiers:{lazy:s,trim:r,number:i}},o){if(e[is]=Or(o),e.composing)return;const l=(i||e.type==="number")&&!/^0\d/.test(e.value)?$s(e.value):e.value,a=t??"";l!==a&&(document.activeElement===e&&e.type!=="range"&&(s&&t===n||r&&e.value.trim()===a)||(e.value=a))}},ja=["ctrl","shift","alt","meta"],Fa={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>ja.some(n=>e[`${n}Key`]&&!t.includes(n))},Na=(e,t)=>{if(!e)return e;const n=e._withMods||(e._withMods={}),s=t.join(".");return n[s]||(n[s]=((r,...i)=>{for(let o=0;o{const t=Ha().createApp(...e),{mount:n}=t;return t.mount=s=>{const r=Ka(s);if(!r)return;const i=t._component;!M(i)&&!i.render&&!i.template&&(i.template=r.innerHTML),r.nodeType===1&&(r.textContent="");const o=n(r,!1,Va(r));return r instanceof Element&&(r.removeAttribute("v-cloak"),r.setAttribute("data-v-app","")),o},t});function Va(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function Ka(e){return te(e)?document.querySelector(e):e}const sl="/api",Us="lp_auth_token";function rl(){return localStorage.getItem(Us)}function qa(e){localStorage.setItem(Us,e)}function Dr(){localStorage.removeItem(Us)}function il(){const e=rl();return e?{Authorization:`Bearer ${e}`}:{}}async function $t(e,t){const n=await fetch(`${sl}${e}`,{headers:{"Content-Type":"application/json",...il()},...t});if(!n.ok){const s=await n.json().catch(()=>({detail:n.statusText}));throw new Error(s.detail||`HTTP ${n.status}`)}return n.json()}async function Wa(){return $t("/auth/config")}async function Ga(e){return $t("/auth/google",{method:"POST",body:JSON.stringify({credential:e})})}async function Za(){return $t("/auth/me")}async function Ja(){return $t("/models")}async function Qa(){return $t("/stats")}async function Xa(e,t,n){return $t("/chat",{method:"POST",body:JSON.stringify({message:e,model:t,history:n.map(s=>({role:s.role,content:s.content}))})})}async function Ya(e,t,n){const s=new FormData;s.append("image",e),s.append("question",t),s.append("model",n);const r=await fetch(`${sl}/analyze-image`,{method:"POST",body:s,headers:il()});if(!r.ok){const i=await r.json().catch(()=>({detail:r.statusText}));throw new Error(i.detail||`HTTP ${r.status}`)}return r.json()}var st=(e=>(e.HUMAN="hum",e.NIGHT_ELF="nel",e.ORC="orc",e.UNDEAD="und",e))(st||{});const ll="wc3ui-config",ec=Xe({props:{theme:{type:String,default:st.HUMAN}},setup(e,t){const s={theme:rn(()=>e.theme)};return ki(ll,s),()=>Ai(t.slots,"default")}});function ol(){const e=Bt(ll);return{theme:rn(()=>(e==null?void 0:e.theme.value)??st.HUMAN)}}function tc(e,t="any"){return`/${t}/${e}`}function Dt(e,t){return`url(${tc(e,t)})`}const nc=["disabled"],sc={class:"btn__capt"},Yt=Xe({__name:"Button",props:{size:{type:String,default:()=>"d"},disabled:{type:Boolean,default:()=>!1},captionColor:{type:String,default:()=>"#f8f8f7"}},setup(e){tl(r=>({v854fa1ce:s.value.default,v548a9e4c:t.captionColor,ba36690e:s.value.hoverBg,v4e4c04fa:s.value.pressed,v512606b8:s.value.disabled}));const t=e,{theme:n}=ol(),s=rn(()=>({default:Dt("btn_default.png",n.value),hoverBg:Dt("btn_hover_bg.png",n.value),pressed:Dt("btn_pressed.png",n.value),disabled:Dt("btn_disabled.png",n.value)}));return(r,i)=>(z(),F("label",null,[T("input",{type:"button",hidden:"",disabled:t.disabled},null,8,nc),T("div",{class:rt(`btn btn--${t.size}`)},[T("span",sc,[Ai(r.$slots,"default")])],2)]))}}),rc=Xe({__name:"Cursor",props:{state:{type:String,default:()=>"default"}},setup(e){tl(l=>({v7b062dde:i.value}));const t=e,{theme:n}=ol(),s=W(null),r=W(null),i=rn(()=>Dt("cursor.png",n.value));function o(l){s.value&&(s.value.style.transform=`translate(${l.pageX}px, ${l.pageY}px)`)}return nn(()=>{var l,a;if(r.value=(a=(l=Vn())==null?void 0:l.proxy)==null?void 0:a.$el.parentElement,!(r!=null&&r.value))throw new Error('[warcraft-3-ui]: Cursor - element from "to" prop not found or something went wrong');r.value.addEventListener("mousemove",o),r.value.classList.add("cursored")}),Bn(()=>{r.value&&(r.value.removeEventListener("mousemove",o),r.value.classList.remove("cursored"))}),(l,a)=>(z(),F("div",{ref_key:"cursorEl",ref:s,class:"cursor__container"},[T("div",{class:rt(`cursor cursor--${t.state}`)},null,2)],512))}}),ic={key:0,class:"user-badge"},lc=["src"],oc={class:"user-info"},ac={class:"user-name"},cc={key:1,class:"gold-divider"},uc=["value"],fc=["value"],hc={key:2,class:"model-caption"},pc=["value"],dc=["value"],gc={class:"wc3-checkbox"},mc=["checked"],bc={style:{"margin-top":"0.75rem",height:"32px","min-width":"100%"}},vc={class:"resource-bar"},xc=Xe({__name:"SidePanel",props:ps({models:{},stats:{},user:{}},{model:{required:!0},modelModifiers:{},showCitations:{type:Boolean,required:!0},showCitationsModifiers:{},race:{required:!0},raceModifiers:{}}),emits:ps(["clear-chat","logout"],["update:model","update:showCitations","update:race"]),setup(e,{emit:t}){const n=bn(e,"model"),s=bn(e,"showCitations"),r=bn(e,"race"),i=t,o=[{key:st.HUMAN,label:"Human"},{key:st.ORC,label:"Orc"},{key:st.NIGHT_ELF,label:"Night Elf"},{key:st.UNDEAD,label:"Undead"}];return(l,a)=>(z(),F("div",null,[e.user?(z(),F("div",ic,[e.user.picture?(z(),F("img",{key:0,src:e.user.picture,class:"user-avatar",referrerpolicy:"no-referrer",alt:""},null,8,lc)):le("",!0),T("div",oc,[T("span",ac,ne(e.user.name),1),T("button",{class:"logout-btn",onClick:a[0]||(a[0]=c=>i("logout"))},"Odjavi se")])])):le("",!0),e.user?(z(),F("div",cc)):le("",!0),a[7]||(a[7]=T("h2",null,"Odaberi model",-1)),T("select",{class:"wc3-select",value:n.value,onChange:a[1]||(a[1]=c=>n.value=c.target.value)},[(z(!0),F(ie,null,Tn(e.models,(c,u)=>(z(),F("option",{key:u,value:u},ne(c.name),9,fc))),128))],40,uc),e.models[n.value]?(z(),F("p",hc,ne(e.models[n.value].description),1)):le("",!0),a[8]||(a[8]=T("div",{class:"gold-divider"},null,-1)),a[9]||(a[9]=T("h2",null,"Tema",-1)),T("select",{class:"wc3-select",value:r.value,onChange:a[2]||(a[2]=c=>r.value=c.target.value)},[(z(),F(ie,null,Tn(o,c=>T("option",{key:c.key,value:c.key},ne(c.label),9,dc)),64))],40,pc),a[10]||(a[10]=T("div",{class:"gold-divider"},null,-1)),a[11]||(a[11]=T("h2",null,"Opcije",-1)),T("label",gc,[T("input",{type:"checkbox",checked:s.value,onChange:a[3]||(a[3]=c=>s.value=c.target.checked)},null,40,mc),a[5]||(a[5]=De(" Prikazi izvore ",-1))]),T("div",bc,[se(Yt,{size:"s",onClick:a[4]||(a[4]=c=>i("clear-chat"))},{default:dt(()=>[...a[6]||(a[6]=[De(" Novi razgovor ",-1)])]),_:1})]),a[12]||(a[12]=T("div",{class:"gold-divider"},null,-1)),a[13]||(a[13]=T("h2",null,"Baza znanja",-1)),T("div",vc,ne(e.stats.documents.toLocaleString())+" dokumenata ",1),a[14]||(a[14]=T("div",{class:"sidebar-footer"},[T("div",{class:"gold-divider"}),De(" Learn Pathophysiology"),T("br"),De(" Powered by Gemini AI ")],-1))]))}});function Vs(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var mt=Vs();function al(e){mt=e}var Wt={exec:()=>null};function K(e,t=""){let n=typeof e=="string"?e:e.source;const s={replace:(r,i)=>{let o=typeof i=="string"?i:i.source;return o=o.replace(ge.caret,"$1"),n=n.replace(r,o),s},getRegex:()=>new RegExp(n,t)};return s}var ge={codeRemoveIndent:/^(?: {1,4}| {0,3}\t)/gm,outputLinkReplace:/\\([\[\]])/g,indentCodeCompensation:/^(\s+)(?:```)/,beginningSpace:/^\s+/,endingHash:/#$/,startingSpaceChar:/^ /,endingSpaceChar:/ $/,nonSpaceChar:/[^ ]/,newLineCharGlobal:/\n/g,tabCharGlobal:/\t/g,multipleSpaceGlobal:/\s+/g,blankLine:/^[ \t]*$/,doubleBlankLine:/\n[ \t]*\n[ \t]*$/,blockquoteStart:/^ {0,3}>/,blockquoteSetextReplace:/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \t]?/gm,listReplaceTabs:/^\t+/,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\[[ xX]\] /,listReplaceTask:/^\[[ xX]\] +/,anyLine:/\n.*\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\||\| *$/g,tableRowBlankLine:/\n[ \t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^/i,startPreScriptTag:/^<(pre|code|kbd|script)(\s|>)/i,endPreScriptTag:/^<\/(pre|code|kbd|script)(\s|>)/i,startAngleBracket:/^$/,pedanticHrefTitle:/^([^'"]*[^\s])\s+(['"])(.*)\2/,unicodeAlphaNumeric:/[\p{L}\p{N}]/u,escapeTest:/[&<>"']/,escapeReplace:/[&<>"']/g,escapeTestNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,escapeReplaceNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,unescapeTest:/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig,caret:/(^|[^\[])\^/g,percentDecode:/%25/g,findPipe:/\|/g,splitPipe:/ \|/,slashPipe:/\\\|/g,carriageReturn:/\r\n|\r/g,spaceLine:/^ +$/gm,notSpaceStart:/^\S*/,endingNewline:/\n$/,listItemRegex:e=>new RegExp(`^( {0,3}${e})((?:[ ][^\\n]*)?(?:\\n|$))`),nextBulletRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`),hrRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),fencesBeginRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}(?:\`\`\`|~~~)`),headingBeginRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}#`),htmlBeginRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}<(?:[a-z].*>|!--)`,"i")},yc=/^(?:[ \t]*(?:\n|$))+/,_c=/^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/,wc=/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,ln=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,kc=/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,Ks=/(?:[*+-]|\d{1,9}[.)])/,cl=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/,ul=K(cl).replace(/bull/g,Ks).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/\|table/g,"").getRegex(),Sc=K(cl).replace(/bull/g,Ks).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/table/g,/ {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex(),qs=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,Tc=/^[^\n]+/,Ws=/(?!\s*\])(?:\\.|[^\[\]\\])+/,Cc=K(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label",Ws).replace("title",/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),$c=K(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g,Ks).getRegex(),qn="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",Gs=/|$))/,Rc=K("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))","i").replace("comment",Gs).replace("tag",qn).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),fl=K(qs).replace("hr",ln).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",qn).getRegex(),Ac=K(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph",fl).getRegex(),Zs={blockquote:Ac,code:_c,def:Cc,fences:wc,heading:kc,hr:ln,html:Rc,lheading:ul,list:$c,newline:yc,paragraph:fl,table:Wt,text:Tc},jr=K("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr",ln).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("blockquote"," {0,3}>").replace("code","(?: {4}| {0,3} )[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",qn).getRegex(),Pc={...Zs,lheading:Sc,table:jr,paragraph:K(qs).replace("hr",ln).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("table",jr).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",qn).getRegex()},Ec={...Zs,html:K(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment",Gs).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:Wt,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:K(qs).replace("hr",ln).replace("heading",` *#{1,6} *[^ +]`).replace("lheading",ul).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},Ic=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,Oc=/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,hl=/^( {2,}|\\)\n(?!\s*$)/,Lc=/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\]*?>/g,gl=/^(?:\*+(?:((?!\*)punct)|[^\s*]))|^_+(?:((?!_)punct)|([^\s_]))/,Fc=K(gl,"u").replace(/punct/g,Wn).getRegex(),Nc=K(gl,"u").replace(/punct/g,dl).getRegex(),ml="^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)",Bc=K(ml,"gu").replace(/notPunctSpace/g,pl).replace(/punctSpace/g,Js).replace(/punct/g,Wn).getRegex(),Hc=K(ml,"gu").replace(/notPunctSpace/g,Dc).replace(/punctSpace/g,zc).replace(/punct/g,dl).getRegex(),Uc=K("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)","gu").replace(/notPunctSpace/g,pl).replace(/punctSpace/g,Js).replace(/punct/g,Wn).getRegex(),Vc=K(/\\(punct)/,"gu").replace(/punct/g,Wn).getRegex(),Kc=K(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),qc=K(Gs).replace("(?:-->|$)","-->").getRegex(),Wc=K("^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^").replace("comment",qc).replace("attribute",/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),Pn=/(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/,Gc=K(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]*(?:\n[ \t]*)?)(title))?\s*\)/).replace("label",Pn).replace("href",/<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]*/).replace("title",/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),bl=K(/^!?\[(label)\]\[(ref)\]/).replace("label",Pn).replace("ref",Ws).getRegex(),vl=K(/^!?\[(ref)\](?:\[\])?/).replace("ref",Ws).getRegex(),Zc=K("reflink|nolink(?!\\()","g").replace("reflink",bl).replace("nolink",vl).getRegex(),Qs={_backpedal:Wt,anyPunctuation:Vc,autolink:Kc,blockSkip:jc,br:hl,code:Oc,del:Wt,emStrongLDelim:Fc,emStrongRDelimAst:Bc,emStrongRDelimUnd:Uc,escape:Ic,link:Gc,nolink:vl,punctuation:Mc,reflink:bl,reflinkSearch:Zc,tag:Wc,text:Lc,url:Wt},Jc={...Qs,link:K(/^!?\[(label)\]\((.*?)\)/).replace("label",Pn).getRegex(),reflink:K(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",Pn).getRegex()},ys={...Qs,emStrongRDelimAst:Hc,emStrongLDelim:Nc,url:K(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,"i").replace("email",/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),_backpedal:/(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,del:/^(~~?)(?=[^\s~])((?:\\.|[^\\])*?(?:\\.|[^\s~\\]))\1(?=[^~]|$)/,text:/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\":">",'"':""","'":"'"},Fr=e=>Xc[e];function Le(e,t){if(t){if(ge.escapeTest.test(e))return e.replace(ge.escapeReplace,Fr)}else if(ge.escapeTestNoEncode.test(e))return e.replace(ge.escapeReplaceNoEncode,Fr);return e}function Nr(e){try{e=encodeURI(e).replace(ge.percentDecode,"%")}catch{return null}return e}function Br(e,t){var i;const n=e.replace(ge.findPipe,(o,l,a)=>{let c=!1,u=l;for(;--u>=0&&a[u]==="\\";)c=!c;return c?"|":" |"}),s=n.split(ge.splitPipe);let r=0;if(s[0].trim()||s.shift(),s.length>0&&!((i=s.at(-1))!=null&&i.trim())&&s.pop(),t)if(s.length>t)s.splice(t);else for(;s.length0?-2:-1}function Hr(e,t,n,s,r){const i=t.href,o=t.title||null,l=e[1].replace(r.other.outputLinkReplace,"$1");s.state.inLink=!0;const a={type:e[0].charAt(0)==="!"?"image":"link",raw:n,href:i,title:o,text:l,tokens:s.inlineTokens(l)};return s.state.inLink=!1,a}function eu(e,t,n){const s=e.match(n.other.indentCodeCompensation);if(s===null)return t;const r=s[1];return t.split(` +`).map(i=>{const o=i.match(n.other.beginningSpace);if(o===null)return i;const[l]=o;return l.length>=r.length?i.slice(r.length):i}).join(` +`)}var En=class{constructor(e){Z(this,"options");Z(this,"rules");Z(this,"lexer");this.options=e||mt}space(e){const t=this.rules.block.newline.exec(e);if(t&&t[0].length>0)return{type:"space",raw:t[0]}}code(e){const t=this.rules.block.code.exec(e);if(t){const n=t[0].replace(this.rules.other.codeRemoveIndent,"");return{type:"code",raw:t[0],codeBlockStyle:"indented",text:this.options.pedantic?n:Mt(n,` +`)}}}fences(e){const t=this.rules.block.fences.exec(e);if(t){const n=t[0],s=eu(n,t[3]||"",this.rules);return{type:"code",raw:n,lang:t[2]?t[2].trim().replace(this.rules.inline.anyPunctuation,"$1"):t[2],text:s}}}heading(e){const t=this.rules.block.heading.exec(e);if(t){let n=t[2].trim();if(this.rules.other.endingHash.test(n)){const s=Mt(n,"#");(this.options.pedantic||!s||this.rules.other.endingSpaceChar.test(s))&&(n=s.trim())}return{type:"heading",raw:t[0],depth:t[1].length,text:n,tokens:this.lexer.inline(n)}}}hr(e){const t=this.rules.block.hr.exec(e);if(t)return{type:"hr",raw:Mt(t[0],` +`)}}blockquote(e){const t=this.rules.block.blockquote.exec(e);if(t){let n=Mt(t[0],` +`).split(` +`),s="",r="";const i=[];for(;n.length>0;){let o=!1;const l=[];let a;for(a=0;a1,r={type:"list",raw:"",ordered:s,start:s?+n.slice(0,-1):"",loose:!1,items:[]};n=s?`\\d{1,9}\\${n.slice(-1)}`:`\\${n}`,this.options.pedantic&&(n=s?n:"[*+-]");const i=this.rules.other.listItemRegex(n);let o=!1;for(;e;){let a=!1,c="",u="";if(!(t=i.exec(e))||this.rules.block.hr.test(e))break;c=t[0],e=e.substring(c.length);let p=t[2].split(` +`,1)[0].replace(this.rules.other.listReplaceTabs,L=>" ".repeat(3*L.length)),d=e.split(` +`,1)[0],b=!p.trim(),w=0;if(this.options.pedantic?(w=2,u=p.trimStart()):b?w=t[1].length+1:(w=t[2].search(this.rules.other.nonSpaceChar),w=w>4?1:w,u=p.slice(w),w+=t[1].length),b&&this.rules.other.blankLine.test(d)&&(c+=d+` +`,e=e.substring(d.length+1),a=!0),!a){const L=this.rules.other.nextBulletRegex(w),R=this.rules.other.hrRegex(w),D=this.rules.other.fencesBeginRegex(w),E=this.rules.other.headingBeginRegex(w),ee=this.rules.other.htmlBeginRegex(w);for(;e;){const ke=e.split(` +`,1)[0];let oe;if(d=ke,this.options.pedantic?(d=d.replace(this.rules.other.listReplaceNesting," "),oe=d):oe=d.replace(this.rules.other.tabCharGlobal," "),D.test(d)||E.test(d)||ee.test(d)||L.test(d)||R.test(d))break;if(oe.search(this.rules.other.nonSpaceChar)>=w||!d.trim())u+=` +`+oe.slice(w);else{if(b||p.replace(this.rules.other.tabCharGlobal," ").search(this.rules.other.nonSpaceChar)>=4||D.test(p)||E.test(p)||R.test(p))break;u+=` +`+d}!b&&!d.trim()&&(b=!0),c+=ke+` +`,e=e.substring(ke.length+1),p=oe.slice(w)}}r.loose||(o?r.loose=!0:this.rules.other.doubleBlankLine.test(c)&&(o=!0));let _=null,N;this.options.gfm&&(_=this.rules.other.listIsTask.exec(u),_&&(N=_[0]!=="[ ] ",u=u.replace(this.rules.other.listReplaceTask,""))),r.items.push({type:"list_item",raw:c,task:!!_,checked:N,loose:!1,text:u,tokens:[]}),r.raw+=c}const l=r.items.at(-1);if(l)l.raw=l.raw.trimEnd(),l.text=l.text.trimEnd();else return;r.raw=r.raw.trimEnd();for(let a=0;ap.type==="space"),u=c.length>0&&c.some(p=>this.rules.other.anyLine.test(p.raw));r.loose=u}if(r.loose)for(let a=0;a({text:a,tokens:this.lexer.inline(a),header:!1,align:i.align[c]})));return i}}lheading(e){const t=this.rules.block.lheading.exec(e);if(t)return{type:"heading",raw:t[0],depth:t[2].charAt(0)==="="?1:2,text:t[1],tokens:this.lexer.inline(t[1])}}paragraph(e){const t=this.rules.block.paragraph.exec(e);if(t){const n=t[1].charAt(t[1].length-1)===` +`?t[1].slice(0,-1):t[1];return{type:"paragraph",raw:t[0],text:n,tokens:this.lexer.inline(n)}}}text(e){const t=this.rules.block.text.exec(e);if(t)return{type:"text",raw:t[0],text:t[0],tokens:this.lexer.inline(t[0])}}escape(e){const t=this.rules.inline.escape.exec(e);if(t)return{type:"escape",raw:t[0],text:t[1]}}tag(e){const t=this.rules.inline.tag.exec(e);if(t)return!this.lexer.state.inLink&&this.rules.other.startATag.test(t[0])?this.lexer.state.inLink=!0:this.lexer.state.inLink&&this.rules.other.endATag.test(t[0])&&(this.lexer.state.inLink=!1),!this.lexer.state.inRawBlock&&this.rules.other.startPreScriptTag.test(t[0])?this.lexer.state.inRawBlock=!0:this.lexer.state.inRawBlock&&this.rules.other.endPreScriptTag.test(t[0])&&(this.lexer.state.inRawBlock=!1),{type:"html",raw:t[0],inLink:this.lexer.state.inLink,inRawBlock:this.lexer.state.inRawBlock,block:!1,text:t[0]}}link(e){const t=this.rules.inline.link.exec(e);if(t){const n=t[2].trim();if(!this.options.pedantic&&this.rules.other.startAngleBracket.test(n)){if(!this.rules.other.endAngleBracket.test(n))return;const i=Mt(n.slice(0,-1),"\\");if((n.length-i.length)%2===0)return}else{const i=Yc(t[2],"()");if(i===-2)return;if(i>-1){const l=(t[0].indexOf("!")===0?5:4)+t[1].length+i;t[2]=t[2].substring(0,i),t[0]=t[0].substring(0,l).trim(),t[3]=""}}let s=t[2],r="";if(this.options.pedantic){const i=this.rules.other.pedanticHrefTitle.exec(s);i&&(s=i[1],r=i[3])}else r=t[3]?t[3].slice(1,-1):"";return s=s.trim(),this.rules.other.startAngleBracket.test(s)&&(this.options.pedantic&&!this.rules.other.endAngleBracket.test(n)?s=s.slice(1):s=s.slice(1,-1)),Hr(t,{href:s&&s.replace(this.rules.inline.anyPunctuation,"$1"),title:r&&r.replace(this.rules.inline.anyPunctuation,"$1")},t[0],this.lexer,this.rules)}}reflink(e,t){let n;if((n=this.rules.inline.reflink.exec(e))||(n=this.rules.inline.nolink.exec(e))){const s=(n[2]||n[1]).replace(this.rules.other.multipleSpaceGlobal," "),r=t[s.toLowerCase()];if(!r){const i=n[0].charAt(0);return{type:"text",raw:i,text:i}}return Hr(n,r,n[0],this.lexer,this.rules)}}emStrong(e,t,n=""){let s=this.rules.inline.emStrongLDelim.exec(e);if(!s||s[3]&&n.match(this.rules.other.unicodeAlphaNumeric))return;if(!(s[1]||s[2]||"")||!n||this.rules.inline.punctuation.exec(n)){const i=[...s[0]].length-1;let o,l,a=i,c=0;const u=s[0][0]==="*"?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(u.lastIndex=0,t=t.slice(-1*e.length+i);(s=u.exec(t))!=null;){if(o=s[1]||s[2]||s[3]||s[4]||s[5]||s[6],!o)continue;if(l=[...o].length,s[3]||s[4]){a+=l;continue}else if((s[5]||s[6])&&i%3&&!((i+l)%3)){c+=l;continue}if(a-=l,a>0)continue;l=Math.min(l,l+a+c);const p=[...s[0]][0].length,d=e.slice(0,i+s.index+p+l);if(Math.min(i,l)%2){const w=d.slice(1,-1);return{type:"em",raw:d,text:w,tokens:this.lexer.inlineTokens(w)}}const b=d.slice(2,-2);return{type:"strong",raw:d,text:b,tokens:this.lexer.inlineTokens(b)}}}}codespan(e){const t=this.rules.inline.code.exec(e);if(t){let n=t[2].replace(this.rules.other.newLineCharGlobal," ");const s=this.rules.other.nonSpaceChar.test(n),r=this.rules.other.startingSpaceChar.test(n)&&this.rules.other.endingSpaceChar.test(n);return s&&r&&(n=n.substring(1,n.length-1)),{type:"codespan",raw:t[0],text:n}}}br(e){const t=this.rules.inline.br.exec(e);if(t)return{type:"br",raw:t[0]}}del(e){const t=this.rules.inline.del.exec(e);if(t)return{type:"del",raw:t[0],text:t[2],tokens:this.lexer.inlineTokens(t[2])}}autolink(e){const t=this.rules.inline.autolink.exec(e);if(t){let n,s;return t[2]==="@"?(n=t[1],s="mailto:"+n):(n=t[1],s=n),{type:"link",raw:t[0],text:n,href:s,tokens:[{type:"text",raw:n,text:n}]}}}url(e){var n;let t;if(t=this.rules.inline.url.exec(e)){let s,r;if(t[2]==="@")s=t[0],r="mailto:"+s;else{let i;do i=t[0],t[0]=((n=this.rules.inline._backpedal.exec(t[0]))==null?void 0:n[0])??"";while(i!==t[0]);s=t[0],t[1]==="www."?r="http://"+t[0]:r=t[0]}return{type:"link",raw:t[0],text:s,href:r,tokens:[{type:"text",raw:s,text:s}]}}}inlineText(e){const t=this.rules.inline.text.exec(e);if(t){const n=this.lexer.state.inRawBlock;return{type:"text",raw:t[0],text:t[0],escaped:n}}}},Ke=class _s{constructor(t){Z(this,"tokens");Z(this,"options");Z(this,"state");Z(this,"tokenizer");Z(this,"inlineQueue");this.tokens=[],this.tokens.links=Object.create(null),this.options=t||mt,this.options.tokenizer=this.options.tokenizer||new En,this.tokenizer=this.options.tokenizer,this.tokenizer.options=this.options,this.tokenizer.lexer=this,this.inlineQueue=[],this.state={inLink:!1,inRawBlock:!1,top:!0};const n={other:ge,block:gn.normal,inline:Lt.normal};this.options.pedantic?(n.block=gn.pedantic,n.inline=Lt.pedantic):this.options.gfm&&(n.block=gn.gfm,this.options.breaks?n.inline=Lt.breaks:n.inline=Lt.gfm),this.tokenizer.rules=n}static get rules(){return{block:gn,inline:Lt}}static lex(t,n){return new _s(n).lex(t)}static lexInline(t,n){return new _s(n).inlineTokens(t)}lex(t){t=t.replace(ge.carriageReturn,` +`),this.blockTokens(t,this.tokens);for(let n=0;n(l=c.call({lexer:this},t,n))?(t=t.substring(l.raw.length),n.push(l),!0):!1))continue;if(l=this.tokenizer.space(t)){t=t.substring(l.raw.length);const c=n.at(-1);l.raw.length===1&&c!==void 0?c.raw+=` +`:n.push(l);continue}if(l=this.tokenizer.code(t)){t=t.substring(l.raw.length);const c=n.at(-1);(c==null?void 0:c.type)==="paragraph"||(c==null?void 0:c.type)==="text"?(c.raw+=` +`+l.raw,c.text+=` +`+l.text,this.inlineQueue.at(-1).src=c.text):n.push(l);continue}if(l=this.tokenizer.fences(t)){t=t.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.heading(t)){t=t.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.hr(t)){t=t.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.blockquote(t)){t=t.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.list(t)){t=t.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.html(t)){t=t.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.def(t)){t=t.substring(l.raw.length);const c=n.at(-1);(c==null?void 0:c.type)==="paragraph"||(c==null?void 0:c.type)==="text"?(c.raw+=` +`+l.raw,c.text+=` +`+l.raw,this.inlineQueue.at(-1).src=c.text):this.tokens.links[l.tag]||(this.tokens.links[l.tag]={href:l.href,title:l.title});continue}if(l=this.tokenizer.table(t)){t=t.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.lheading(t)){t=t.substring(l.raw.length),n.push(l);continue}let a=t;if((o=this.options.extensions)!=null&&o.startBlock){let c=1/0;const u=t.slice(1);let p;this.options.extensions.startBlock.forEach(d=>{p=d.call({lexer:this},u),typeof p=="number"&&p>=0&&(c=Math.min(c,p))}),c<1/0&&c>=0&&(a=t.substring(0,c+1))}if(this.state.top&&(l=this.tokenizer.paragraph(a))){const c=n.at(-1);s&&(c==null?void 0:c.type)==="paragraph"?(c.raw+=` +`+l.raw,c.text+=` +`+l.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=c.text):n.push(l),s=a.length!==t.length,t=t.substring(l.raw.length);continue}if(l=this.tokenizer.text(t)){t=t.substring(l.raw.length);const c=n.at(-1);(c==null?void 0:c.type)==="text"?(c.raw+=` +`+l.raw,c.text+=` +`+l.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=c.text):n.push(l);continue}if(t){const c="Infinite loop on byte: "+t.charCodeAt(0);if(this.options.silent){console.error(c);break}else throw new Error(c)}}return this.state.top=!0,n}inline(t,n=[]){return this.inlineQueue.push({src:t,tokens:n}),n}inlineTokens(t,n=[]){var l,a,c;let s=t,r=null;if(this.tokens.links){const u=Object.keys(this.tokens.links);if(u.length>0)for(;(r=this.tokenizer.rules.inline.reflinkSearch.exec(s))!=null;)u.includes(r[0].slice(r[0].lastIndexOf("[")+1,-1))&&(s=s.slice(0,r.index)+"["+"a".repeat(r[0].length-2)+"]"+s.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex))}for(;(r=this.tokenizer.rules.inline.anyPunctuation.exec(s))!=null;)s=s.slice(0,r.index)+"++"+s.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);for(;(r=this.tokenizer.rules.inline.blockSkip.exec(s))!=null;)s=s.slice(0,r.index)+"["+"a".repeat(r[0].length-2)+"]"+s.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);let i=!1,o="";for(;t;){i||(o=""),i=!1;let u;if((a=(l=this.options.extensions)==null?void 0:l.inline)!=null&&a.some(d=>(u=d.call({lexer:this},t,n))?(t=t.substring(u.raw.length),n.push(u),!0):!1))continue;if(u=this.tokenizer.escape(t)){t=t.substring(u.raw.length),n.push(u);continue}if(u=this.tokenizer.tag(t)){t=t.substring(u.raw.length),n.push(u);continue}if(u=this.tokenizer.link(t)){t=t.substring(u.raw.length),n.push(u);continue}if(u=this.tokenizer.reflink(t,this.tokens.links)){t=t.substring(u.raw.length);const d=n.at(-1);u.type==="text"&&(d==null?void 0:d.type)==="text"?(d.raw+=u.raw,d.text+=u.text):n.push(u);continue}if(u=this.tokenizer.emStrong(t,s,o)){t=t.substring(u.raw.length),n.push(u);continue}if(u=this.tokenizer.codespan(t)){t=t.substring(u.raw.length),n.push(u);continue}if(u=this.tokenizer.br(t)){t=t.substring(u.raw.length),n.push(u);continue}if(u=this.tokenizer.del(t)){t=t.substring(u.raw.length),n.push(u);continue}if(u=this.tokenizer.autolink(t)){t=t.substring(u.raw.length),n.push(u);continue}if(!this.state.inLink&&(u=this.tokenizer.url(t))){t=t.substring(u.raw.length),n.push(u);continue}let p=t;if((c=this.options.extensions)!=null&&c.startInline){let d=1/0;const b=t.slice(1);let w;this.options.extensions.startInline.forEach(_=>{w=_.call({lexer:this},b),typeof w=="number"&&w>=0&&(d=Math.min(d,w))}),d<1/0&&d>=0&&(p=t.substring(0,d+1))}if(u=this.tokenizer.inlineText(p)){t=t.substring(u.raw.length),u.raw.slice(-1)!=="_"&&(o=u.raw.slice(-1)),i=!0;const d=n.at(-1);(d==null?void 0:d.type)==="text"?(d.raw+=u.raw,d.text+=u.text):n.push(u);continue}if(t){const d="Infinite loop on byte: "+t.charCodeAt(0);if(this.options.silent){console.error(d);break}else throw new Error(d)}}return n}},In=class{constructor(e){Z(this,"options");Z(this,"parser");this.options=e||mt}space(e){return""}code({text:e,lang:t,escaped:n}){var i;const s=(i=(t||"").match(ge.notSpaceStart))==null?void 0:i[0],r=e.replace(ge.endingNewline,"")+` +`;return s?'
'+(n?r:Le(r,!0))+`
+`:"
"+(n?r:Le(r,!0))+`
+`}blockquote({tokens:e}){return`
+${this.parser.parse(e)}
+`}html({text:e}){return e}heading({tokens:e,depth:t}){return`${this.parser.parseInline(e)} +`}hr(e){return`
+`}list(e){const t=e.ordered,n=e.start;let s="";for(let o=0;o +`+s+" +`}listitem(e){var n;let t="";if(e.task){const s=this.checkbox({checked:!!e.checked});e.loose?((n=e.tokens[0])==null?void 0:n.type)==="paragraph"?(e.tokens[0].text=s+" "+e.tokens[0].text,e.tokens[0].tokens&&e.tokens[0].tokens.length>0&&e.tokens[0].tokens[0].type==="text"&&(e.tokens[0].tokens[0].text=s+" "+Le(e.tokens[0].tokens[0].text),e.tokens[0].tokens[0].escaped=!0)):e.tokens.unshift({type:"text",raw:s+" ",text:s+" ",escaped:!0}):t+=s+" "}return t+=this.parser.parse(e.tokens,!!e.loose),`
  • ${t}
  • +`}checkbox({checked:e}){return"'}paragraph({tokens:e}){return`

    ${this.parser.parseInline(e)}

    +`}table(e){let t="",n="";for(let r=0;r${s}`),` + +`+t+` +`+s+`
    +`}tablerow({text:e}){return` +${e} +`}tablecell(e){const t=this.parser.parseInline(e.tokens),n=e.header?"th":"td";return(e.align?`<${n} align="${e.align}">`:`<${n}>`)+t+` +`}strong({tokens:e}){return`${this.parser.parseInline(e)}`}em({tokens:e}){return`${this.parser.parseInline(e)}`}codespan({text:e}){return`${Le(e,!0)}`}br(e){return"
    "}del({tokens:e}){return`${this.parser.parseInline(e)}`}link({href:e,title:t,tokens:n}){const s=this.parser.parseInline(n),r=Nr(e);if(r===null)return s;e=r;let i='
    ",i}image({href:e,title:t,text:n,tokens:s}){s&&(n=this.parser.parseInline(s,this.parser.textRenderer));const r=Nr(e);if(r===null)return Le(n);e=r;let i=`${n}{const a=o[l].flat(1/0);n=n.concat(this.walkTokens(a,t))}):o.tokens&&(n=n.concat(this.walkTokens(o.tokens,t)))}}return n}use(...e){const t=this.defaults.extensions||{renderers:{},childTokens:{}};return e.forEach(n=>{const s={...n};if(s.async=this.defaults.async||s.async||!1,n.extensions&&(n.extensions.forEach(r=>{if(!r.name)throw new Error("extension name required");if("renderer"in r){const i=t.renderers[r.name];i?t.renderers[r.name]=function(...o){let l=r.renderer.apply(this,o);return l===!1&&(l=i.apply(this,o)),l}:t.renderers[r.name]=r.renderer}if("tokenizer"in r){if(!r.level||r.level!=="block"&&r.level!=="inline")throw new Error("extension level must be 'block' or 'inline'");const i=t[r.level];i?i.unshift(r.tokenizer):t[r.level]=[r.tokenizer],r.start&&(r.level==="block"?t.startBlock?t.startBlock.push(r.start):t.startBlock=[r.start]:r.level==="inline"&&(t.startInline?t.startInline.push(r.start):t.startInline=[r.start]))}"childTokens"in r&&r.childTokens&&(t.childTokens[r.name]=r.childTokens)}),s.extensions=t),n.renderer){const r=this.defaults.renderer||new In(this.defaults);for(const i in n.renderer){if(!(i in r))throw new Error(`renderer '${i}' does not exist`);if(["options","parser"].includes(i))continue;const o=i,l=n.renderer[o],a=r[o];r[o]=(...c)=>{let u=l.apply(r,c);return u===!1&&(u=a.apply(r,c)),u||""}}s.renderer=r}if(n.tokenizer){const r=this.defaults.tokenizer||new En(this.defaults);for(const i in n.tokenizer){if(!(i in r))throw new Error(`tokenizer '${i}' does not exist`);if(["options","rules","lexer"].includes(i))continue;const o=i,l=n.tokenizer[o],a=r[o];r[o]=(...c)=>{let u=l.apply(r,c);return u===!1&&(u=a.apply(r,c)),u}}s.tokenizer=r}if(n.hooks){const r=this.defaults.hooks||new yn;for(const i in n.hooks){if(!(i in r))throw new Error(`hook '${i}' does not exist`);if(["options","block"].includes(i))continue;const o=i,l=n.hooks[o],a=r[o];yn.passThroughHooks.has(i)?r[o]=c=>{if(this.defaults.async)return Promise.resolve(l.call(r,c)).then(p=>a.call(r,p));const u=l.call(r,c);return a.call(r,u)}:r[o]=(...c)=>{let u=l.apply(r,c);return u===!1&&(u=a.apply(r,c)),u}}s.hooks=r}if(n.walkTokens){const r=this.defaults.walkTokens,i=n.walkTokens;s.walkTokens=function(o){let l=[];return l.push(i.call(this,o)),r&&(l=l.concat(r.call(this,o))),l}}this.defaults={...this.defaults,...s}}),this}setOptions(e){return this.defaults={...this.defaults,...e},this}lexer(e,t){return Ke.lex(e,t??this.defaults)}parser(e,t){return qe.parse(e,t??this.defaults)}parseMarkdown(e){return(n,s)=>{const r={...s},i={...this.defaults,...r},o=this.onError(!!i.silent,!!i.async);if(this.defaults.async===!0&&r.async===!1)return o(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));if(typeof n>"u"||n===null)return o(new Error("marked(): input parameter is undefined or null"));if(typeof n!="string")return o(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(n)+", string expected"));i.hooks&&(i.hooks.options=i,i.hooks.block=e);const l=i.hooks?i.hooks.provideLexer():e?Ke.lex:Ke.lexInline,a=i.hooks?i.hooks.provideParser():e?qe.parse:qe.parseInline;if(i.async)return Promise.resolve(i.hooks?i.hooks.preprocess(n):n).then(c=>l(c,i)).then(c=>i.hooks?i.hooks.processAllTokens(c):c).then(c=>i.walkTokens?Promise.all(this.walkTokens(c,i.walkTokens)).then(()=>c):c).then(c=>a(c,i)).then(c=>i.hooks?i.hooks.postprocess(c):c).catch(o);try{i.hooks&&(n=i.hooks.preprocess(n));let c=l(n,i);i.hooks&&(c=i.hooks.processAllTokens(c)),i.walkTokens&&this.walkTokens(c,i.walkTokens);let u=a(c,i);return i.hooks&&(u=i.hooks.postprocess(u)),u}catch(c){return o(c)}}}onError(e,t){return n=>{if(n.message+=` +Please report this to https://github.com/markedjs/marked.`,e){const s="

    An error occurred:

    "+Le(n.message+"",!0)+"
    ";return t?Promise.resolve(s):s}if(t)return Promise.reject(n);throw n}}},gt=new tu;function H(e,t){return gt.parse(e,t)}H.options=H.setOptions=function(e){return gt.setOptions(e),H.defaults=gt.defaults,al(H.defaults),H};H.getDefaults=Vs;H.defaults=mt;H.use=function(...e){return gt.use(...e),H.defaults=gt.defaults,al(H.defaults),H};H.walkTokens=function(e,t){return gt.walkTokens(e,t)};H.parseInline=gt.parseInline;H.Parser=qe;H.parser=qe.parse;H.Renderer=In;H.TextRenderer=Xs;H.Lexer=Ke;H.lexer=Ke.lex;H.Tokenizer=En;H.Hooks=yn;H.parse=H;H.options;H.setOptions;H.use;H.walkTokens;H.parseInline;qe.parse;Ke.lex;const nu={key:0,class:"citations-panel"},su={class:"citation-header"},ru={style:{"margin-left":"0.75rem"}},iu={style:{"margin-left":"auto",display:"inline-flex","align-items":"center",gap:"0.3rem"}},lu={style:{"font-size":"0.75rem",color:"var(--wc3-text-dim)"}},ou={class:"citation-text"},xl=Xe({__name:"CitationPanel",props:{citations:{}},setup(e){const t=W(!1);function n(r){return r>=.8?"#44aa44":r>=.6?"#aaaa44":"#aa7744"}function s(r){return`${Math.round(r*100)}%`}return(r,i)=>(z(),F("div",null,[T("button",{class:"citations-toggle",onClick:i[0]||(i[0]=o=>t.value=!t.value)}," 📜 Izvori ("+ne(e.citations.length)+") "+ne(t.value?"▲":"▼"),1),t.value?(z(),F("div",nu,[(z(!0),F(ie,null,Tn(e.citations,o=>(z(),F("div",{key:o.rank,class:"citation-item"},[T("div",su,[T("span",null,"#"+ne(o.rank),1),T("span",ru," 📄 "+ne(o.source)+" — str. "+ne(o.page_num),1),T("span",iu,[T("span",{style:zn([{display:"inline-block",height:"8px","border-radius":"2px"},{width:s(o.score),background:n(o.score),minWidth:"20px"}])},null,4),T("span",lu,ne((o.score*100).toFixed(0))+"% ",1)])]),T("div",ou,ne(o.text),1)]))),128))])):le("",!0)]))}}),au={class:"chat-area"},cu={key:0,style:{"text-align":"center","margin-top":"3rem"}},uu=["innerHTML"],fu={key:0,class:"msg-meta"},hu={key:1,class:"loading"},pu={key:2,class:"error-msg"},du={class:"chat-input-bar"},gu=["disabled"],mu={class:"chat-send-btn"},bu=Xe({__name:"ChatView",props:ps({model:{},showCitations:{type:Boolean}},{history:{required:!0},historyModifiers:{}}),emits:["update:history"],setup(e){const t=e,n=bn(e,"history"),s=W(""),r=W(!1),i=W(""),o=W(null);H.setOptions({breaks:!0,gfm:!0});function l(p){return H.parse(p)}async function a(){await mi(),o.value&&(o.value.scrollTop=o.value.scrollHeight)}Ht(()=>n.value.length,a);async function c(){const p=s.value.trim();if(!(!p||r.value)){s.value="",i.value="",n.value.push({role:"user",content:p}),await a(),r.value=!0;try{const d=await Xa(p,t.model,n.value);n.value.push({role:"assistant",content:d.reply,citations:d.citations,model_used:d.model_used})}catch(d){i.value=d.message||"Greska pri slanju poruke"}finally{r.value=!1,await a()}}}function u(p){p.key==="Enter"&&!p.shiftKey&&(p.preventDefault(),c())}return(p,d)=>(z(),F("div",au,[T("div",{class:"messages-container",ref_key:"messagesEl",ref:o},[n.value.length===0?(z(),F("div",cu,[...d[1]||(d[1]=[T("div",{style:{"font-size":"3rem","margin-bottom":"0.75rem"}},"📜",-1),T("p",{style:{"font-family":"var(--font-heading)",color:"var(--wc3-gold)","font-size":"1rem"}}," Dobrodosli! ",-1),T("p",{style:{color:"var(--wc3-text-dim)","font-size":"0.9rem","max-width":"400px",margin:"0.5rem auto"}}," Postavi pitanje o patofiziologiji. ",-1)])])):le("",!0),(z(!0),F(ie,null,Tn(n.value,(b,w)=>{var _;return z(),F("div",{key:w,class:rt(["msg",b.role])},[T("div",{innerHTML:l(b.content)},null,8,uu),b.model_used?(z(),F("div",fu,ne(b.model_used),1)):le("",!0),b.role==="assistant"&&e.showCitations&&((_=b.citations)!=null&&_.length)?(z(),Ve(xl,{key:1,citations:b.citations},null,8,["citations"])):le("",!0)],2)}),128)),r.value?(z(),F("div",hu,[...d[2]||(d[2]=[T("span",null,"Generiranje odgovora",-1),T("span",{class:"dot-pulse"},[T("span"),T("span"),T("span")],-1)])])):le("",!0),i.value?(z(),F("div",pu,"⚠️ "+ne(i.value),1)):le("",!0)],512),T("div",du,[wi(T("input",{class:"wc3-input","onUpdate:modelValue":d[0]||(d[0]=b=>s.value=b),onKeydown:u,placeholder:"Postavi pitanje o patofiziologiji...",disabled:r.value},null,40,gu),[[nl,s.value]]),T("div",mu,[se(Yt,{size:"s",onClick:c,disabled:r.value||!s.value.trim()},{default:dt(()=>[...d[3]||(d[3]=[De(" Posalji ",-1)])]),_:1},8,["disabled"])])])]))}}),vu=(e,t)=>{const n=e.__vccOpts||e;for(const[s,r]of t)n[s]=r;return n},xu=vu(bu,[["__scopeId","data-v-b84b5170"]]),yu={class:"image-tab"},_u={key:0},wu=["src"],ku={key:0,style:{"margin-bottom":"1rem"}},Su={key:1,style:{"margin-bottom":"1.5rem",height:"38px","min-width":"160px",display:"inline-block"}},Tu={key:2,class:"loading"},Cu={key:3,class:"error-msg",style:{"margin-bottom":"1rem"}},$u={key:4,class:"analysis-result"},Ru=["innerHTML"],Au=Xe({__name:"ImageView",props:{model:{},showCitations:{type:Boolean}},setup(e){const t=e,n=W(null),s=W(""),r=W(""),i=W(""),o=W([]),l=W(!1),a=W(""),c=W(null);function u(w){return H.parse(w)}function p(w){var N;const _=w.target;(N=_.files)!=null&&N[0]&&(n.value=_.files[0],s.value=URL.createObjectURL(_.files[0]),i.value="",o.value=[],a.value="")}function d(w){var _;w.preventDefault(),(_=w.dataTransfer)!=null&&_.files[0]&&(n.value=w.dataTransfer.files[0],s.value=URL.createObjectURL(w.dataTransfer.files[0]),i.value="",o.value=[],a.value="")}async function b(){if(!(!n.value||l.value)){l.value=!0,a.value="",i.value="",o.value=[];try{const w=await Ya(n.value,r.value,t.model);i.value=w.analysis,o.value=w.citations}catch(w){a.value=w.message||"Greska pri analizi slike"}finally{l.value=!1}}}return(w,_)=>(z(),F("div",yu,[T("div",{class:"upload-zone",onClick:_[0]||(_[0]=N=>{var L;return(L=c.value)==null?void 0:L.click()}),onDrop:d,onDragover:_[1]||(_[1]=Na(()=>{},["prevent"]))},[T("input",{ref_key:"fileInput",ref:c,type:"file",accept:"image/*",onChange:p},null,544),s.value?(z(),F("img",{key:1,src:s.value,class:"image-preview",alt:"Preview"},null,8,wu)):(z(),F("div",_u,[..._[3]||(_[3]=[T("div",{class:"icon"},"📄",-1),T("p",null,"Klikni ili povuci sliku ovdje",-1),T("p",{style:{"font-size":"0.8rem",color:"var(--wc3-text-muted)"}}," Uploadaj stranicu za analizu ",-1)])]))],32),n.value?(z(),F("div",ku,[wi(T("input",{class:"wc3-input","onUpdate:modelValue":_[2]||(_[2]=N=>r.value=N),placeholder:"Postavi pitanje o slici (opcionalno)..."},null,512),[[nl,r.value]])])):le("",!0),n.value?(z(),F("div",Su,[se(Yt,{size:"s",onClick:b,disabled:l.value},{default:dt(()=>[De(ne(l.value?"Analiziram...":"Analiziraj sliku"),1)]),_:1},8,["disabled"])])):le("",!0),l.value?(z(),F("div",Tu,[..._[4]||(_[4]=[T("span",null,"Analiziranje",-1),T("span",{class:"dot-pulse"},[T("span"),T("span"),T("span")],-1)])])):le("",!0),a.value?(z(),F("div",Cu,"⚠️ "+ne(a.value),1)):le("",!0),i.value?(z(),F("div",$u,[T("div",{innerHTML:u(i.value)},null,8,Ru),e.showCitations&&o.value.length?(z(),Ve(xl,{key:0,citations:o.value,style:{"margin-top":"0.75rem"}},null,8,["citations"])):le("",!0)])):le("",!0)]))}}),Pu={class:"login-page"},Eu={class:"login-card"},Iu={class:"login-frame"},Ou={key:0,class:"login-error"},Lu=Xe({__name:"LoginPage",props:{googleClientId:{}},emits:["google-login"],setup(e,{emit:t}){const n=e,s=t,r=W("");nn(()=>{if(document.getElementById("gsi-script")){i();return}const l=document.createElement("script");l.id="gsi-script",l.src="https://accounts.google.com/gsi/client",l.async=!0,l.defer=!0,l.onload=i,l.onerror=()=>{r.value="Failed to load Google Sign-In. Check your internet connection."},document.head.appendChild(l)});function i(){var a,c;const l=window;if(!((c=(a=l.google)==null?void 0:a.accounts)!=null&&c.id)){setTimeout(i,100);return}l.google.accounts.id.initialize({client_id:n.googleClientId,callback:o,auto_select:!1}),l.google.accounts.id.renderButton(document.getElementById("g-signin-btn"),{theme:"filled_black",size:"large",shape:"rectangular",text:"signin_with",width:300})}function o(l){l.credential?s("google-login",l.credential):r.value="Google sign-in failed. Please try again."}return(l,a)=>(z(),F("div",Pu,[T("div",Eu,[T("div",Iu,[a[0]||(a[0]=aa('

    Learn Pathophysiology

    AI asistent za učenje patofiziologije

    ',6)),r.value?(z(),F("p",Ou,ne(r.value),1)):le("",!0),a[1]||(a[1]=T("div",{class:"gold-divider"},null,-1)),a[2]||(a[2]=T("p",{class:"login-footer"},[De(" Powered by Gemini AI"),T("br"),T("span",{class:"login-footer-dim"},"WC3 Edition")],-1))])])]))}}),Mu={key:0,class:"loading-splash"},zu={class:"app-shell"},Du={class:"sidebar"},ju={class:"main-content"},Fu={class:"tab-bar"},Nu={class:"tab-btn-wrap"},Bu={class:"tab-btn-wrap"},Hu=Xe({__name:"App",setup(e){const t=W(!0),n=W(!1),s=W(""),r=W(null),i=W(!1),o=W("chat"),l=W("gemini-3-flash-preview"),a=W(!0),c=W({}),u=W({documents:0,collection:""}),p=W([]),d=W(st.UNDEAD);nn(async()=>{try{const L=await Wa();if(n.value=L.auth_enabled,s.value=L.google_client_id||"",L.auth_enabled&&rl())try{const R=await Za();r.value=R,i.value=!0}catch{Dr()}L.auth_enabled||(i.value=!0),i.value&&await b()}catch(L){console.error("Init error:",L)}finally{t.value=!1}});async function b(){const[L,R]=await Promise.all([Ja(),Qa()]);c.value=L.models,l.value=L.default,u.value=R}async function w(L){try{const R=await Ga(L);qa(R.token),r.value=R.user,i.value=!0,await b()}catch(R){console.error("Login error:",R)}}function _(){Dr(),r.value=null,i.value=!1,p.value=[]}function N(){p.value=[]}return(L,R)=>t.value?(z(),F("div",Mu,[...R[6]||(R[6]=[T("div",{class:"loading-splash__icon"},"⚔️",-1),T("div",{class:"loading-splash__text"},"Loading...",-1)])])):n.value&&!i.value?(z(),Ve(Lu,{key:1,googleClientId:s.value,onGoogleLogin:w},null,8,["googleClientId"])):(z(),Ve(pi(ec),{key:2,theme:d.value},{default:dt(()=>[se(rc),T("div",zu,[T("aside",Du,[se(xc,{model:l.value,"onUpdate:model":R[0]||(R[0]=D=>l.value=D),showCitations:a.value,"onUpdate:showCitations":R[1]||(R[1]=D=>a.value=D),race:d.value,"onUpdate:race":R[2]||(R[2]=D=>d.value=D),models:c.value,stats:u.value,user:r.value,onClearChat:N,onLogout:_},null,8,["model","showCitations","race","models","stats","user"])]),T("main",ju,[R[9]||(R[9]=T("header",{class:"app-header"},[T("div",{class:"header-frame"},[T("h1",null,"Learn Pathophysiology"),T("p",{class:"subtitle"},"AI asistent za ucenje patofiziologije")])],-1)),T("nav",Fu,[T("div",Nu,[se(Yt,{size:"s",class:rt(["tab-trigger",{active:o.value==="chat"}]),onClick:R[3]||(R[3]=D=>o.value="chat")},{default:dt(()=>[...R[7]||(R[7]=[De(" Chat ",-1)])]),_:1},8,["class"])]),T("div",Bu,[se(Yt,{size:"s",class:rt(["tab-trigger",{active:o.value==="image"}]),onClick:R[4]||(R[4]=D=>o.value="image")},{default:dt(()=>[...R[8]||(R[8]=[De(" Analiza slike ",-1)])]),_:1},8,["class"])])]),o.value==="chat"?(z(),Ve(xu,{key:0,history:p.value,"onUpdate:history":R[5]||(R[5]=D=>p.value=D),model:l.value,showCitations:a.value},null,8,["history","model","showCitations"])):(z(),Ve(Au,{key:1,model:l.value,showCitations:a.value},null,8,["model","showCitations"]))])])]),_:1},8,["theme"]))}});Ua(Hu).mount("#app"); diff --git a/backend/static/assets/index-BzhPXs6E.css b/backend/static/assets/index-BzhPXs6E.css new file mode 100644 index 0000000000000000000000000000000000000000..0469bb75d8fdfc29968044790b5da8981dcc7161 --- /dev/null +++ b/backend/static/assets/index-BzhPXs6E.css @@ -0,0 +1 @@ +@charset "UTF-8";.btn{width:100%;height:100%;position:relative;background:var(--v854fa1ce) no-repeat;background-size:100% 100%;color:var(--v548a9e4c);-webkit-user-select:none;user-select:none;-webkit-mask-image:var(--v854fa1ce);-webkit-mask-size:100% 100%}.btn__capt{width:100%;position:absolute;text-align:center;bottom:0}.btn--d{font-size:14px;letter-spacing:.5px;line-height:180%}.btn--s{height:32px;line-height:32px;min-width:100px}.btn--m{height:48px;line-height:48px;min-width:200px}*:not([disabled])+.btn:hover:before{content:"";position:absolute;width:100%;height:100%;background:var(--ba36690e) no-repeat;background-size:100% 100%;left:0;top:0;mix-blend-mode:screen}*:not([disabled])+.btn:active{background-image:var(--v4e4c04fa)}*:not([disabled])+.btn:active .btn__capt{left:3px;bottom:-2px}[disabled]+.btn{background-image:var(--v512606b8);pointer-events:all!important;color:#646464}.cursored,.cursored *{cursor:none}.cursor{position:relative;width:32px;height:32px;background:var(--v7b062dde) no-repeat}.cursor__container{top:0;left:0;position:fixed;z-index:99;pointer-events:none}.cursor--default-active{animation:cursor-active .5s steps(8) infinite}.cursor--pointer{background-position:-32px -96px}.cursor--pointer-active{animation:cursor-pointer .5s steps(8) infinite}.cursor--pointer-denied{background-position:-64px -96px}.cursor--hold{background-position:-128px -96px}.cursor--arrow-top{animation:cursor-arrow .1s steps(3) infinite;transform:rotate(-90deg)}.cursor--arrow-right{animation:cursor-arrow .1s steps(3) infinite}.cursor--arrow-bottom{animation:cursor-arrow .1s steps(3) infinite;transform:rotate(90deg)}.cursor--arrow-left{animation:cursor-arrow .1s steps(3) infinite;transform:rotate(-180deg)}@keyframes cursor-active{0%{background-position:0 0}to{background-position:-256px 0}}@keyframes cursor-pointer{0%{background-position:0 -64px}to{background-position:-256px -64px}}@keyframes cursor-arrow{0%{background-position:-160px -96px}to{background-position:-256px -96px}}.chat-area[data-v-b84b5170]{flex:1;overflow:hidden;display:flex;flex-direction:column}.messages-container[data-v-b84b5170]{flex:1;overflow-y:auto;padding:1rem 1.5rem;display:flex;flex-direction:column;gap:.75rem}.login-page{width:100vw;height:100vh;display:flex;align-items:center;justify-content:center;background:radial-gradient(ellipse at center,#12122a,#0a0a16,#050510)}.login-card{width:100%;max-width:420px;padding:2rem}.login-frame{background:linear-gradient(180deg,#13132a,#0d0d1f);border:2px solid var(--wc3-gold-dim, #8b7b4f);border-radius:6px;padding:2.5rem 2rem;text-align:center;box-shadow:0 0 40px #c8aa6e14,inset 0 1px #c8aa6e1a}.login-icon{font-size:3rem;margin-bottom:.75rem;filter:drop-shadow(0 0 10px rgba(200,170,110,.4))}.login-frame h1{font-family:var(--font-display, "Cinzel Decorative", serif);font-size:1.6rem;font-weight:900;background:linear-gradient(180deg,#f0d060,#c8aa6e,#8b7b4f);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;letter-spacing:2px;margin-bottom:.25rem}.login-frame .subtitle{font-family:var(--font-body, "Crimson Text", serif);color:var(--wc3-text-dim, #7a6e5a);font-style:italic;font-size:.95rem}.login-prompt{font-family:var(--font-heading, "Cinzel", serif);color:var(--wc3-gold, #c8aa6e);font-size:.9rem;letter-spacing:1.5px;text-transform:uppercase;margin-bottom:1.25rem}.g-btn-container{display:flex;justify-content:center;min-height:44px;margin-bottom:.5rem}.login-error{color:#f66;font-size:.85rem;margin-top:.75rem}.login-footer{font-size:.8rem;color:var(--wc3-text-dim, #7a6e5a);font-style:italic;line-height:1.6}.login-footer-dim{color:var(--wc3-text-muted, #555060);font-size:.75rem}:root{--wc3-bg: #0a0a0f;--wc3-bg-panel: #0f0f1a;--wc3-gold: #c8aa6e;--wc3-gold-bright: #f0d060;--wc3-gold-dim: #8b7b4f;--wc3-text: #d4c4a0;--wc3-text-light: #f0e6d0;--wc3-text-dim: #7a6e5a;--wc3-text-muted: #555060;--wc3-border: #5a4a2a;--wc3-border-dim: #3a2e1e;--wc3-red-soft: rgba(140, 40, 40, .25);--wc3-blue-soft: rgba(30, 50, 90, .35);--font-heading: "Cinzel", serif;--font-display: "Cinzel Decorative", "Cinzel", serif;--font-body: "Crimson Text", serif;--sidebar-w: 270px}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html,body{height:100%;overflow:hidden;background:var(--wc3-bg);color:var(--wc3-text);font-family:var(--font-body);line-height:1.6}#app{height:100vh}::-webkit-scrollbar{width:8px}::-webkit-scrollbar-track{background:#0000004d}::-webkit-scrollbar-thumb{background:linear-gradient(180deg,var(--wc3-gold-dim),#4a3a20);border-radius:2px}::-webkit-scrollbar-thumb:hover{background:var(--wc3-gold)}.app-shell{display:flex;height:100vh;overflow:hidden}.sidebar{width:var(--sidebar-w);min-width:var(--sidebar-w);background:linear-gradient(180deg,#0f0f22,#0a0a18);border-right:2px solid var(--wc3-border);display:flex;flex-direction:column;overflow-y:auto;padding:1rem;box-shadow:2px 0 20px #00000080}.main-content{flex:1;display:flex;flex-direction:column;overflow:hidden;background:radial-gradient(ellipse at top center,#12122a,#0a0a16 60%,#070710)}.app-header{text-align:center;padding:1.25rem 1rem .5rem;flex-shrink:0}.header-frame h1{font-family:var(--font-display);font-size:2rem;font-weight:900;background:linear-gradient(180deg,#f0d060,#c8aa6e,#8b7b4f);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;letter-spacing:3px;filter:drop-shadow(0 2px 4px rgba(0,0,0,.8))}.header-frame .subtitle{font-family:var(--font-body);color:var(--wc3-text-dim);font-style:italic;font-size:.95rem;margin-top:.15rem}.gold-divider{height:1px;background:linear-gradient(90deg,transparent,var(--wc3-gold-dim),transparent);margin:.75rem 0;border:none}.tab-bar{display:flex;gap:.5rem;padding:.35rem 1.5rem;border-bottom:1px solid var(--wc3-border-dim);flex-shrink:0}.tab-btn-wrap{height:32px;min-width:120px}.tab-trigger.active{filter:brightness(1.3)}.msg{max-width:85%;padding:.85rem 1.15rem;border-radius:6px;line-height:1.65;font-size:1rem;border:1px solid transparent;animation:fadeSlide .25s ease}@keyframes fadeSlide{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.msg.user{align-self:flex-end;background:linear-gradient(135deg,#8c282859,#5a191940);border-color:#c850504d;color:var(--wc3-text-light)}.msg.assistant{align-self:flex-start;background:linear-gradient(135deg,#141e4173,#0f14324d);border-color:#6482c840;color:var(--wc3-text-light)}.msg h1,.msg h2,.msg h3,.msg h4{font-family:var(--font-heading);color:var(--wc3-gold);margin:.75rem 0 .35rem}.msg h1{font-size:1.3rem}.msg h2{font-size:1.15rem}.msg h3{font-size:1.05rem}.msg p{margin:.4rem 0}.msg strong{color:var(--wc3-gold-bright)}.msg em{font-style:italic}.msg ul,.msg ol{padding-left:1.25rem;margin:.4rem 0}.msg li{margin:.2rem 0}.msg code{background:#c8aa6e14;border:1px solid var(--wc3-border-dim);padding:.1rem .4rem;border-radius:3px;font-size:.9em;color:var(--wc3-gold)}.msg pre{background:#0000004d;border:1px solid var(--wc3-border-dim);border-radius:4px;padding:.75rem;overflow-x:auto;margin:.5rem 0}.msg pre code{background:none;border:none;padding:0}.msg blockquote{border-left:3px solid var(--wc3-gold-dim);padding-left:.75rem;margin:.5rem 0;color:var(--wc3-text);font-style:italic}.msg hr{border:none;height:1px;background:linear-gradient(90deg,transparent,var(--wc3-gold-dim),transparent);margin:.75rem 0}.msg-meta{font-size:.8rem;color:var(--wc3-text-dim);font-style:italic;margin-top:.4rem}.wc3-select{width:100%;padding:.5rem .75rem;font-family:var(--font-body);font-size:.95rem;color:var(--wc3-text-light);background:linear-gradient(180deg,#1a1a32,#13132a);border:1px solid var(--wc3-gold-dim);border-radius:2px;outline:none;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23c8aa6e' d='M6 8L1 3h10z'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right .75rem center}.wc3-select:hover{border-color:var(--wc3-gold)}.wc3-select:focus{border-color:var(--wc3-gold);box-shadow:0 0 8px #c8aa6e33}.wc3-select option{background:var(--wc3-bg-panel);color:var(--wc3-text)}.wc3-input{width:100%;padding:.6rem .85rem;font-family:var(--font-body);font-size:1rem;color:var(--wc3-text-light);background:linear-gradient(180deg,#12122a,#0f0f24);border:1px solid var(--wc3-border);border-radius:2px;outline:none;box-shadow:inset 0 2px 6px #0000004d;transition:border-color .15s}.wc3-input:focus{border-color:var(--wc3-gold);box-shadow:inset 0 2px 6px #0000004d,0 0 8px #c8aa6e26}.wc3-input::placeholder{color:var(--wc3-text-muted)}.wc3-checkbox{display:flex;align-items:center;gap:.5rem;cursor:pointer;font-family:var(--font-body);color:var(--wc3-text);font-size:.95rem}.wc3-checkbox input[type=checkbox]{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:18px;height:18px;background:#13132a;border:1px solid var(--wc3-gold-dim);border-radius:2px;cursor:pointer;position:relative}.wc3-checkbox input[type=checkbox]:checked{border-color:var(--wc3-gold)}.wc3-checkbox input[type=checkbox]:checked:after{content:"✓";position:absolute;top:-1px;left:2px;color:var(--wc3-gold-bright);font-size:14px;font-weight:700}.loading{display:flex;align-items:center;gap:.6rem;padding:.75rem 1rem;color:var(--wc3-gold);font-family:var(--font-heading);font-size:.85rem;font-style:italic;animation:fadeSlide .3s ease}.dot-pulse{display:inline-flex;gap:4px}.dot-pulse span{width:6px;height:6px;border-radius:50%;background:var(--wc3-gold);animation:pulse 1.2s infinite ease-in-out}.dot-pulse span:nth-child(2){animation-delay:.2s}.dot-pulse span:nth-child(3){animation-delay:.4s}@keyframes pulse{0%,80%,to{opacity:.2;transform:scale(.8)}40%{opacity:1;transform:scale(1.1)}}.error-msg{background:#b4282826;border:1px solid #cc3333;color:#f88;padding:.6rem .85rem;border-radius:4px;font-size:.9rem}.resource-bar{background:linear-gradient(180deg,#1a1a30,#112);border:1px solid var(--wc3-border);border-radius:3px;padding:.45rem .75rem;text-align:center;font-family:var(--font-heading);font-size:.8rem;color:var(--wc3-gold);letter-spacing:1px}.sidebar h2{font-family:var(--font-heading);color:var(--wc3-gold);font-size:.85rem;letter-spacing:2px;text-transform:uppercase;text-shadow:0 0 8px rgba(200,170,110,.2);padding-bottom:.4rem;border-bottom:1px solid var(--wc3-border-dim);margin-top:.75rem;margin-bottom:.5rem}.sidebar h2:first-child{margin-top:0}.model-caption{font-size:.85rem;color:var(--wc3-text-dim);font-style:italic;margin-top:.25rem}.sidebar-footer{margin-top:auto;padding-top:.75rem;text-align:center;font-size:.75rem;color:var(--wc3-text-muted);font-style:italic;line-height:1.6}.chat-input-bar{display:flex;gap:.5rem;padding:.75rem 1.5rem;background:linear-gradient(180deg,var(--wc3-bg-panel),var(--wc3-bg));border-top:1px solid var(--wc3-border);flex-shrink:0;align-items:center}.chat-input-bar .wc3-input{flex:1}.chat-send-btn{height:38px;min-width:100px}.citations-toggle{font-family:var(--font-heading);font-size:.8rem;color:var(--wc3-gold-dim);background:none;border:1px solid var(--wc3-border-dim);border-radius:3px;padding:.35rem .75rem;cursor:pointer;margin-top:.5rem;transition:all .15s}.citations-toggle:hover{border-color:var(--wc3-gold);color:var(--wc3-gold)}.citations-panel{margin-top:.5rem;border:1px solid var(--wc3-border-dim);border-radius:4px;background:#0003;padding:.75rem;animation:fadeSlide .2s ease}.citation-item{padding:.5rem 0;border-bottom:1px solid var(--wc3-border-dim)}.citation-item:last-child{border-bottom:none}.citation-header{font-family:var(--font-heading);font-size:.8rem;color:var(--wc3-gold);margin-bottom:.25rem;display:flex;align-items:center;flex-wrap:wrap;gap:.25rem}.citation-text{font-size:.85rem;color:var(--wc3-text);font-style:italic;border-left:2px solid var(--wc3-gold-dim);padding-left:.6rem;margin-top:.25rem;line-height:1.5}.image-tab{flex:1;overflow-y:auto;padding:1.5rem}.upload-zone{border:2px dashed var(--wc3-border);border-radius:6px;padding:2rem;text-align:center;cursor:pointer;transition:all .15s;background:#00000026;margin-bottom:1rem}.upload-zone:hover{border-color:var(--wc3-gold);background:#c8aa6e08}.upload-zone input[type=file]{display:none}.upload-zone .icon{font-size:2.5rem;margin-bottom:.5rem}.upload-zone p{color:var(--wc3-text-dim);font-size:.95rem}.image-preview{max-width:100%;max-height:300px;border:1px solid var(--wc3-border);border-radius:4px;margin-bottom:1rem}.analysis-result{background:linear-gradient(135deg,#141e4173,#0f14324d);border:1px solid rgba(100,130,200,.25);border-radius:6px;padding:1rem 1.25rem;line-height:1.65}.loading-splash{width:100vw;height:100vh;display:flex;flex-direction:column;align-items:center;justify-content:center;background:radial-gradient(ellipse at center,#12122a,#0a0a16,#050510);color:var(--wc3-gold, #c8aa6e)}.loading-splash__icon{font-size:3rem;margin-bottom:1rem;animation:pulse 1.5s ease-in-out infinite}.loading-splash__text{font-family:var(--font-heading, "Cinzel", serif);font-size:1rem;letter-spacing:3px;text-transform:uppercase}@keyframes pulse{0%,to{opacity:.5;transform:scale(1)}50%{opacity:1;transform:scale(1.1)}}.user-badge{display:flex;align-items:center;gap:.6rem;padding:.4rem 0}.user-avatar{width:32px;height:32px;border-radius:50%;border:1.5px solid var(--wc3-gold-dim, #8b7b4f);flex-shrink:0}.user-info{display:flex;flex-direction:column;min-width:0}.user-name{font-family:var(--font-heading, "Cinzel", serif);color:var(--wc3-gold, #c8aa6e);font-size:.75rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.logout-btn{background:none;border:none;color:var(--wc3-text-dim, #7a6e5a);font-size:.65rem;cursor:pointer;text-align:left;padding:0;font-family:var(--font-body, "Crimson Text", serif);text-decoration:underline;text-underline-offset:2px}.logout-btn:hover{color:var(--wc3-gold, #c8aa6e)}@media(max-width:768px){.sidebar{display:none}:root{--sidebar-w: 0px}.header-frame h1{font-size:1.4rem}} diff --git a/backend/static/hum/btn_default.png b/backend/static/hum/btn_default.png new file mode 100644 index 0000000000000000000000000000000000000000..f6aae268ec016594a8f28c4b685fa47bfc0ef3a2 --- /dev/null +++ b/backend/static/hum/btn_default.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b416cf7964b1cdc7314d69371f104aaf6c29b848c9a0081bf10dbdd205c240f6 +size 3167 diff --git a/backend/static/hum/btn_disabled.png b/backend/static/hum/btn_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..8e3b59389550a457a3c2938e291b09a8b069dde7 --- /dev/null +++ b/backend/static/hum/btn_disabled.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:39fc64b1fba442258573c9bc5d7cdeff62bdc12b87094102dbd6e4fc2ce3c090 +size 2374 diff --git a/backend/static/hum/btn_hover_bg.png b/backend/static/hum/btn_hover_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..74a8d04413768cbdeb1630f51d154309b5046d4a --- /dev/null +++ b/backend/static/hum/btn_hover_bg.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e9aac267b934c1bfe003de12535ae96c6d7ecc0b59092b77cf4096f20754de31 +size 1305 diff --git a/backend/static/hum/btn_pressed.png b/backend/static/hum/btn_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..ff3f31e05d42681708a6581f81eaf6b3b3f93aad --- /dev/null +++ b/backend/static/hum/btn_pressed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3238ac55d25929e5758809e494f8b66da0e21620d0fe4a2fa6d98c9b76573e67 +size 2658 diff --git a/backend/static/hum/cursor.png b/backend/static/hum/cursor.png new file mode 100644 index 0000000000000000000000000000000000000000..fceb684c1be69bb7bd0a0636f44d47bb7b620d9e --- /dev/null +++ b/backend/static/hum/cursor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f172e678d25df73e367fbe6fc2a134014c71b4951c6a4404370b5a4211adf004 +size 18047 diff --git a/backend/static/hum/hud_footer.png b/backend/static/hum/hud_footer.png new file mode 100644 index 0000000000000000000000000000000000000000..8013cbcfc1f7b06036396d8823e7337edc1f2994 --- /dev/null +++ b/backend/static/hum/hud_footer.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d7194e7ebd0766414715c48726143a91435e6f11b4cdcf0eff769a3c53c584de +size 213087 diff --git a/backend/static/hum/hud_header.png b/backend/static/hum/hud_header.png new file mode 100644 index 0000000000000000000000000000000000000000..c7691f78cb65841ab091648ccc7a8a6b351c307b --- /dev/null +++ b/backend/static/hum/hud_header.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b2e75eda4fe37055da8f956a28947f98d9ff8892c6b69df3512c7ee768cc9b30 +size 31698 diff --git a/backend/static/hum/hud_inv_mock.png b/backend/static/hum/hud_inv_mock.png new file mode 100644 index 0000000000000000000000000000000000000000..2f869a630d6d1df4b5f91e9910e70e55025b58fc --- /dev/null +++ b/backend/static/hum/hud_inv_mock.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5099d37633d83fa5feba9279ceb1f087e4e696efbc0bd462c62c0bc7b38e8732 +size 95509 diff --git a/backend/static/hum/hud_inv_mock_slot.png b/backend/static/hum/hud_inv_mock_slot.png new file mode 100644 index 0000000000000000000000000000000000000000..20c354aefac942a7416e434f4068e83813672e6c --- /dev/null +++ b/backend/static/hum/hud_inv_mock_slot.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7504e8e821ee070fb6a1cd53521bbfdab6be788bfe184905959dfc95b8a03cc4 +size 4492 diff --git a/backend/static/index.html b/backend/static/index.html new file mode 100644 index 0000000000000000000000000000000000000000..f82d16c96a4fe856eecf0a98ab491a79167d99f9 --- /dev/null +++ b/backend/static/index.html @@ -0,0 +1,17 @@ + + + + + + Learn Pathophysiology — WC3 Edition + + + + + + + + +
    + + diff --git a/backend/static/nel/btn_default.png b/backend/static/nel/btn_default.png new file mode 100644 index 0000000000000000000000000000000000000000..a45be6417cd285cbc884cd6d1275ecc9d3597b97 --- /dev/null +++ b/backend/static/nel/btn_default.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c7a3600ade27dfc4df2e7b14739efc9b53f3d8cd772f0f0b7836f4e75d6bfbb9 +size 3084 diff --git a/backend/static/nel/btn_disabled.png b/backend/static/nel/btn_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..2b27df635642b16d3846d378e5b04f7dedb4fd44 --- /dev/null +++ b/backend/static/nel/btn_disabled.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8e86445a348b78733d086f210b51c0e723212f9c1ae7a8d5b7186330558e2db7 +size 1766 diff --git a/backend/static/nel/btn_hover_bg.png b/backend/static/nel/btn_hover_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..219e834e553345d5f6848a4ef1e0f5358760b336 --- /dev/null +++ b/backend/static/nel/btn_hover_bg.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7f7e43d86e4bd6918ee37ab7eb1f6780e8f0424c4a452bf06da4511bc601becd +size 1332 diff --git a/backend/static/nel/btn_pressed.png b/backend/static/nel/btn_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..45319d3dfff500d8d96632784fa2eb9f87694f9f --- /dev/null +++ b/backend/static/nel/btn_pressed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6e15a1ea2bd8a3ac4420feb03e97969330cae16b64e4332a815740d391566da9 +size 2692 diff --git a/backend/static/nel/cursor.png b/backend/static/nel/cursor.png new file mode 100644 index 0000000000000000000000000000000000000000..0f77afedf7008f7a8df57b79bb77d3fa129623b3 --- /dev/null +++ b/backend/static/nel/cursor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ca3b098a8516e5a770280965e10b0708637e811514ae986a4888e59d5a52ca8 +size 15202 diff --git a/backend/static/nel/hud_footer.png b/backend/static/nel/hud_footer.png new file mode 100644 index 0000000000000000000000000000000000000000..55211f9df7dc1705fbc8f5a3d324e68411087fa9 --- /dev/null +++ b/backend/static/nel/hud_footer.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd0d75f008dffad62ad2e961f70ab4bfc10e9a9f468d6e94d7173a41699e4752 +size 263968 diff --git a/backend/static/nel/hud_header.png b/backend/static/nel/hud_header.png new file mode 100644 index 0000000000000000000000000000000000000000..cedf82a343b3717d8d070d66f7130394af81ef9e --- /dev/null +++ b/backend/static/nel/hud_header.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6f479ba78e5d64fb0a97f3edae8b8757d8bc8296ae5332763088666d9b9836df +size 92718 diff --git a/backend/static/nel/hud_inv_mock.png b/backend/static/nel/hud_inv_mock.png new file mode 100644 index 0000000000000000000000000000000000000000..677edb6e2e6ee0a5f940de2dde6bc68e0ef8d531 --- /dev/null +++ b/backend/static/nel/hud_inv_mock.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d25e96c77ba51df9d16a636d675a3eb23278ce9daef42acbde170a62aa9f83b1 +size 49391 diff --git a/backend/static/nel/hud_inv_mock_slot.png b/backend/static/nel/hud_inv_mock_slot.png new file mode 100644 index 0000000000000000000000000000000000000000..949b9489b2a3144c1fad3017797161edbd93d32e --- /dev/null +++ b/backend/static/nel/hud_inv_mock_slot.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6f4504fe032ec6e1931e04e8bd85f1dabb2426fa1b7cfd9e4485fb1c2546d5e4 +size 4637 diff --git a/backend/static/orc/btn_default.png b/backend/static/orc/btn_default.png new file mode 100644 index 0000000000000000000000000000000000000000..bb59fe3d74c3bcee954865c4764b082157410688 --- /dev/null +++ b/backend/static/orc/btn_default.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ad8feca70abe0d0e6a7aa948c9dc9d66283e3720649b84e2970dfcad3590eb3 +size 2781 diff --git a/backend/static/orc/btn_disabled.png b/backend/static/orc/btn_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..be757aba6ac2b01ea857dc6402220cc97fd255b2 --- /dev/null +++ b/backend/static/orc/btn_disabled.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:953bf14a95dcb6b6120175ce4ed4b0f850fd8a1fbf65cd5f12b3a23ce5b4dbe2 +size 2105 diff --git a/backend/static/orc/btn_hover_bg.png b/backend/static/orc/btn_hover_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..d6e5cdbb3d729976270c31e2c5a7b5342dbc73ae --- /dev/null +++ b/backend/static/orc/btn_hover_bg.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa21591323e8830d6aeb5ff09e192c0023032cc133d088730e334d8e3f0059f1 +size 1434 diff --git a/backend/static/orc/btn_pressed.png b/backend/static/orc/btn_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..2c73b6d33e8f169afb443f8fd756fd017381defd --- /dev/null +++ b/backend/static/orc/btn_pressed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c014794f3f81d2509b47fef837a8bcd733d858c3bda04ce91ca96c742e9eb3eb +size 2524 diff --git a/backend/static/orc/cursor.png b/backend/static/orc/cursor.png new file mode 100644 index 0000000000000000000000000000000000000000..2b0a7e202d2c50811028155192500c4e296fb54d --- /dev/null +++ b/backend/static/orc/cursor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cbc2565a8a6cff22a1ea7bebcbc671d350b0bf96fd4bf5b7aeedf5a10696a5ce +size 15108 diff --git a/backend/static/orc/hud_footer.png b/backend/static/orc/hud_footer.png new file mode 100644 index 0000000000000000000000000000000000000000..30b7b6f4f2608d3b2eaca5a2a84467263dfb9d99 --- /dev/null +++ b/backend/static/orc/hud_footer.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5625f71d24f621a80e4b653d57bae65251d7016a09004491731205743ab8a8e1 +size 280808 diff --git a/backend/static/orc/hud_header.png b/backend/static/orc/hud_header.png new file mode 100644 index 0000000000000000000000000000000000000000..8dba453d4fd3deb907044bddb09c8a2f59dcc8c3 --- /dev/null +++ b/backend/static/orc/hud_header.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3db8b4b92958cd53c42aecc535e9729df0d7a778b4b063bdca8b621a41680b5b +size 39433 diff --git a/backend/static/orc/hud_inv_mock.png b/backend/static/orc/hud_inv_mock.png new file mode 100644 index 0000000000000000000000000000000000000000..e87fa5cb31b95686738c27af37def22729e83eca --- /dev/null +++ b/backend/static/orc/hud_inv_mock.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:05bcdfd6f0bc91cec360252704579c866da8dbcd42bac7dcd5a6b29e04bb39f1 +size 52513 diff --git a/backend/static/orc/hud_inv_mock_slot.png b/backend/static/orc/hud_inv_mock_slot.png new file mode 100644 index 0000000000000000000000000000000000000000..5ab724b2430c6afb987a0c7f1c39ffe96407f11a --- /dev/null +++ b/backend/static/orc/hud_inv_mock_slot.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c20e037e2cb9a5f1b6e7ccfada6ac58f4eb0fa9b95dfe991c802bc50dcce3b2e +size 4310 diff --git a/backend/static/und/btn_default.png b/backend/static/und/btn_default.png new file mode 100644 index 0000000000000000000000000000000000000000..926b3e719c04adec848d8cf8a27b0d21aca7995d --- /dev/null +++ b/backend/static/und/btn_default.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fe550270021fc6e1604d7e0bb682576027715c4de76f1f69cab6830cbc8835f2 +size 2734 diff --git a/backend/static/und/btn_disabled.png b/backend/static/und/btn_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..6b2ecf73a4ca2a1713d1340bdbac799e8cf42148 --- /dev/null +++ b/backend/static/und/btn_disabled.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fce814c28c0ed48785d5c3b007ac4e4d8f6c765934f5dcdceb385901fcfe579e +size 2046 diff --git a/backend/static/und/btn_hover_bg.png b/backend/static/und/btn_hover_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..71e3531770c314008b5c55a4e3f984dc103282c8 --- /dev/null +++ b/backend/static/und/btn_hover_bg.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:31995399159e873676e69b7841d79a505c292830003ca8db5d142c0a4e9845e7 +size 1181 diff --git a/backend/static/und/btn_pressed.png b/backend/static/und/btn_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..9250bf7963fcaf45a81e3b8af68640f1d7a604bf --- /dev/null +++ b/backend/static/und/btn_pressed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0869ec9b3b9a2bedc9a3c245b4e3c7d35ff31891bb7cc7d6680f42f5650d4dc1 +size 2427 diff --git a/backend/static/und/cursor.png b/backend/static/und/cursor.png new file mode 100644 index 0000000000000000000000000000000000000000..abbd589d6f92af59c008adcc3063cfa0668d37a4 --- /dev/null +++ b/backend/static/und/cursor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:10b68c7b7c875df547097add45409b8391e07a6d21df789a4b4700d18896e621 +size 12682 diff --git a/backend/static/und/hud_footer.png b/backend/static/und/hud_footer.png new file mode 100644 index 0000000000000000000000000000000000000000..0ca5731280023f043da66805ecf7d917801f5089 --- /dev/null +++ b/backend/static/und/hud_footer.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b07074fdec92b009badb60d64f39aab2f26b5ab96f1983d551562309094bb725 +size 292403 diff --git a/backend/static/und/hud_header.png b/backend/static/und/hud_header.png new file mode 100644 index 0000000000000000000000000000000000000000..7028cc7359c2adf58bee0ed99052aab9d43306e7 --- /dev/null +++ b/backend/static/und/hud_header.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3129bf0f86a4d8e48f3d5fd817bd90d29545483f595c762da95ad2cc20f52d45 +size 29892 diff --git a/backend/static/und/hud_inv_mock.png b/backend/static/und/hud_inv_mock.png new file mode 100644 index 0000000000000000000000000000000000000000..6148f8da4512ff370487f94b6da73693a645ba7c --- /dev/null +++ b/backend/static/und/hud_inv_mock.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad3ca01b9ef3306c65f55c7c4057fb7573b9816e533d6332d2046fb3fbce714a +size 53521 diff --git a/backend/static/und/hud_inv_mock_slot.png b/backend/static/und/hud_inv_mock_slot.png new file mode 100644 index 0000000000000000000000000000000000000000..6a42459f5db2e96bf02dd17e12f2acd89037e07d --- /dev/null +++ b/backend/static/und/hud_inv_mock_slot.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0c459be05833a5878f656f32d226bc8d73522b5f6bccc79479e28e0dd6f2795a +size 3657 diff --git a/chroma_db/34c32620-31ab-4a2f-bd92-3fcfd7be3432/data_level0.bin b/chroma_db/34c32620-31ab-4a2f-bd92-3fcfd7be3432/data_level0.bin new file mode 100644 index 0000000000000000000000000000000000000000..db4e4653a32f73f0e00c8593986747affc9b5c65 --- /dev/null +++ b/chroma_db/34c32620-31ab-4a2f-bd92-3fcfd7be3432/data_level0.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:81f0c6b96f2341facf3a93d68612adc9e9a439f400ecaef44b1d8cf6b7c04cee +size 49712000 diff --git a/chroma_db/34c32620-31ab-4a2f-bd92-3fcfd7be3432/header.bin b/chroma_db/34c32620-31ab-4a2f-bd92-3fcfd7be3432/header.bin new file mode 100644 index 0000000000000000000000000000000000000000..59336d337c201b1e6a89001caa14a5b0e1bfa469 --- /dev/null +++ b/chroma_db/34c32620-31ab-4a2f-bd92-3fcfd7be3432/header.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4249c0260691fa07e044e4485ac0f8dec9d74f201d7bc51ad1477b9d0a0f449b +size 100 diff --git a/chroma_db/34c32620-31ab-4a2f-bd92-3fcfd7be3432/index_metadata.pickle b/chroma_db/34c32620-31ab-4a2f-bd92-3fcfd7be3432/index_metadata.pickle new file mode 100644 index 0000000000000000000000000000000000000000..f4eefa148f75024d75a6da916bb55161af9a3d32 --- /dev/null +++ b/chroma_db/34c32620-31ab-4a2f-bd92-3fcfd7be3432/index_metadata.pickle @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bbcd348f1add61b67d5090224baea714f174ef4563cf7110e3df276b40c9ad0e +size 136900 diff --git a/chroma_db/34c32620-31ab-4a2f-bd92-3fcfd7be3432/length.bin b/chroma_db/34c32620-31ab-4a2f-bd92-3fcfd7be3432/length.bin new file mode 100644 index 0000000000000000000000000000000000000000..78616a1aee71066af666827fceb165c57f0581ce --- /dev/null +++ b/chroma_db/34c32620-31ab-4a2f-bd92-3fcfd7be3432/length.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b45949af9c51cb6f9dcea62eff86fb5ae816aa39ebf70d56b5511fce6fda8ee5 +size 16000 diff --git a/chroma_db/34c32620-31ab-4a2f-bd92-3fcfd7be3432/link_lists.bin b/chroma_db/34c32620-31ab-4a2f-bd92-3fcfd7be3432/link_lists.bin new file mode 100644 index 0000000000000000000000000000000000000000..60703ae8f0d408138a6d6ff266966b35cedf131c --- /dev/null +++ b/chroma_db/34c32620-31ab-4a2f-bd92-3fcfd7be3432/link_lists.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:300e2af9926d31d95836a63a7d797aa6760093a5eced3767750a0de466b14f3d +size 34156 diff --git a/chroma_db/chroma.sqlite3 b/chroma_db/chroma.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..bc05e41304c67e059f749d713ceb129c55e4a0b8 --- /dev/null +++ b/chroma_db/chroma.sqlite3 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:77b3a792237df14bd70fe0e04a556525c1cabe7a0141b29756b9fc988c6dd7ef +size 60760064 diff --git a/frontend/env.d.ts b/frontend/env.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..c24723fcfac404371dfd56a6d94f95cbed6b82d1 --- /dev/null +++ b/frontend/env.d.ts @@ -0,0 +1,9 @@ +/// + +declare module '*.vue' { + import type { DefineComponent } from 'vue' + const component: DefineComponent<{}, {}, any> + export default component +} + +declare const ASSETS_PATH: string; diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 0000000000000000000000000000000000000000..fee6c31ba3d6fdcaae784fb78aac048f5a43cf2e --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,16 @@ + + + + + + Learn Pathophysiology — WC3 Edition + + + + + + +
    + + + diff --git a/frontend/package-lock.json b/frontend/package-lock.json new file mode 100644 index 0000000000000000000000000000000000000000..c3dae05610938479a88518457405bed82c3c1b9b --- /dev/null +++ b/frontend/package-lock.json @@ -0,0 +1,1823 @@ +{ + "name": "learn-pathophysiology-wc3", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "learn-pathophysiology-wc3", + "version": "1.0.0", + "dependencies": { + "@vueuse/core": "^14.2.0", + "marked": "^15.0.0", + "sass": "^1.97.3", + "vue": "^3.5.0" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.2.0", + "typescript": "~5.7.0", + "vite": "^6.1.0", + "vue-tsc": "^2.2.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==" + }, + "node_modules/@parcel/watcher": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", + "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "detect-libc": "^2.0.3", + "is-glob": "^4.0.3", + "node-addon-api": "^7.0.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.6", + "@parcel/watcher-darwin-arm64": "2.5.6", + "@parcel/watcher-darwin-x64": "2.5.6", + "@parcel/watcher-freebsd-x64": "2.5.6", + "@parcel/watcher-linux-arm-glibc": "2.5.6", + "@parcel/watcher-linux-arm-musl": "2.5.6", + "@parcel/watcher-linux-arm64-glibc": "2.5.6", + "@parcel/watcher-linux-arm64-musl": "2.5.6", + "@parcel/watcher-linux-x64-glibc": "2.5.6", + "@parcel/watcher-linux-x64-musl": "2.5.6", + "@parcel/watcher-win32-arm64": "2.5.6", + "@parcel/watcher-win32-ia32": "2.5.6", + "@parcel/watcher-win32-x64": "2.5.6" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", + "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", + "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", + "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", + "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", + "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", + "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", + "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", + "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", + "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", + "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", + "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", + "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", + "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.1.tgz", + "integrity": "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.1.tgz", + "integrity": "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.1.tgz", + "integrity": "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.1.tgz", + "integrity": "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.1.tgz", + "integrity": "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.1.tgz", + "integrity": "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.1.tgz", + "integrity": "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.1.tgz", + "integrity": "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.1.tgz", + "integrity": "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.1.tgz", + "integrity": "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.1.tgz", + "integrity": "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.1.tgz", + "integrity": "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.1.tgz", + "integrity": "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.1.tgz", + "integrity": "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.1.tgz", + "integrity": "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.1.tgz", + "integrity": "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.1.tgz", + "integrity": "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.1.tgz", + "integrity": "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.1.tgz", + "integrity": "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.1.tgz", + "integrity": "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.1.tgz", + "integrity": "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.1.tgz", + "integrity": "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.1.tgz", + "integrity": "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.1.tgz", + "integrity": "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.1.tgz", + "integrity": "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", + "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", + "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", + "dev": true, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.15.tgz", + "integrity": "sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==", + "dev": true, + "dependencies": { + "@volar/source-map": "2.4.15" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.15.tgz", + "integrity": "sha512-CPbMWlUN6hVZJYGcU/GSoHu4EnCHiLaXI9n8c9la6RaI9W5JHX+NqG+GSQcB0JdC2FIBLdZJwGsfKyBB71VlTg==", + "dev": true + }, + "node_modules/@volar/typescript": { + "version": "2.4.15", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.15.tgz", + "integrity": "sha512-2aZ8i0cqPGjXb4BhkMsPYDkkuc2ZQ6yOpqwAuNwUoncELqoy5fRgOQtLR9gB0g902iS0NAkvpIzs27geVyVdPg==", + "dev": true, + "dependencies": { + "@volar/language-core": "2.4.15", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.28.tgz", + "integrity": "sha512-kviccYxTgoE8n6OCw96BNdYlBg2GOWfBuOW4Vqwrt7mSKWKwFVvI8egdTltqRgITGPsTFYtKYfxIG8ptX2PJHQ==", + "dependencies": { + "@babel/parser": "^7.29.0", + "@vue/shared": "3.5.28", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.28.tgz", + "integrity": "sha512-/1ZepxAb159jKR1btkefDP+J2xuWL5V3WtleRmxaT+K2Aqiek/Ab/+Ebrw2pPj0sdHO8ViAyyJWfhXXOP/+LQA==", + "dependencies": { + "@vue/compiler-core": "3.5.28", + "@vue/shared": "3.5.28" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.28.tgz", + "integrity": "sha512-6TnKMiNkd6u6VeVDhZn/07KhEZuBSn43Wd2No5zaP5s3xm8IqFTHBj84HJah4UepSUJTro5SoqqlOY22FKY96g==", + "dependencies": { + "@babel/parser": "^7.29.0", + "@vue/compiler-core": "3.5.28", + "@vue/compiler-dom": "3.5.28", + "@vue/compiler-ssr": "3.5.28", + "@vue/shared": "3.5.28", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.6", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.28.tgz", + "integrity": "sha512-JCq//9w1qmC6UGLWJX7RXzrGpKkroubey/ZFqTpvEIDJEKGgntuDMqkuWiZvzTzTA5h2qZvFBFHY7fAAa9475g==", + "dependencies": { + "@vue/compiler-dom": "3.5.28", + "@vue/shared": "3.5.28" + } + }, + "node_modules/@vue/compiler-vue2": { + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz", + "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==", + "dev": true, + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, + "node_modules/@vue/language-core": { + "version": "2.2.12", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.2.12.tgz", + "integrity": "sha512-IsGljWbKGU1MZpBPN+BvPAdr55YPkj2nB/TBNGNC32Vy2qLG25DYu/NBN2vNtZqdRbTRjaoYrahLrToim2NanA==", + "dev": true, + "dependencies": { + "@volar/language-core": "2.4.15", + "@vue/compiler-dom": "^3.5.0", + "@vue/compiler-vue2": "^2.7.16", + "@vue/shared": "^3.5.0", + "alien-signals": "^1.0.3", + "minimatch": "^9.0.3", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.28.tgz", + "integrity": "sha512-gr5hEsxvn+RNyu9/9o1WtdYdwDjg5FgjUSBEkZWqgTKlo/fvwZ2+8W6AfKsc9YN2k/+iHYdS9vZYAhpi10kNaw==", + "dependencies": { + "@vue/shared": "3.5.28" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.28.tgz", + "integrity": "sha512-POVHTdbgnrBBIpnbYU4y7pOMNlPn2QVxVzkvEA2pEgvzbelQq4ZOUxbp2oiyo+BOtiYlm8Q44wShHJoBvDPAjQ==", + "dependencies": { + "@vue/reactivity": "3.5.28", + "@vue/shared": "3.5.28" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.28.tgz", + "integrity": "sha512-4SXxSF8SXYMuhAIkT+eBRqOkWEfPu6nhccrzrkioA6l0boiq7sp18HCOov9qWJA5HML61kW8p/cB4MmBiG9dSA==", + "dependencies": { + "@vue/reactivity": "3.5.28", + "@vue/runtime-core": "3.5.28", + "@vue/shared": "3.5.28", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.28.tgz", + "integrity": "sha512-pf+5ECKGj8fX95bNincbzJ6yp6nyzuLDhYZCeFxUNp8EBrQpPpQaLX3nNCp49+UbgbPun3CeVE+5CXVV1Xydfg==", + "dependencies": { + "@vue/compiler-ssr": "3.5.28", + "@vue/shared": "3.5.28" + }, + "peerDependencies": { + "vue": "3.5.28" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.28.tgz", + "integrity": "sha512-cfWa1fCGBxrvaHRhvV3Is0MgmrbSCxYTXCSCau2I0a1Xw1N1pHAvkWCiXPRAqjvToILvguNyEwjevUqAuBQWvQ==" + }, + "node_modules/@vueuse/core": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-14.2.0.tgz", + "integrity": "sha512-tpjzVl7KCQNVd/qcaCE9XbejL38V6KJAEq/tVXj7mDPtl6JtzmUdnXelSS+ULRkkrDgzYVK7EerQJvd2jR794Q==", + "dependencies": { + "@types/web-bluetooth": "^0.0.21", + "@vueuse/metadata": "14.2.0", + "@vueuse/shared": "14.2.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/@vueuse/metadata": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-14.2.0.tgz", + "integrity": "sha512-i3axTGjU8b13FtyR4Keeama+43iD+BwX9C2TmzBVKqjSHArF03hjkp2SBZ1m72Jk2UtrX0aYCugBq2R1fhkuAQ==", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-14.2.0.tgz", + "integrity": "sha512-Z0bmluZTlAXgUcJ4uAFaML16JcD8V0QG00Db3quR642I99JXIDRa2MI2LGxiLVhcBjVnL1jOzIvT5TT2lqJlkA==", + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/alien-signals": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-1.0.13.tgz", + "integrity": "sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==", + "dev": true + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==" + }, + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/immutable": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.4.tgz", + "integrity": "sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "optional": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/marked": { + "version": "15.0.12", + "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.12.tgz", + "integrity": "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "optional": true + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "devOptional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/rollup": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", + "integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.57.1", + "@rollup/rollup-android-arm64": "4.57.1", + "@rollup/rollup-darwin-arm64": "4.57.1", + "@rollup/rollup-darwin-x64": "4.57.1", + "@rollup/rollup-freebsd-arm64": "4.57.1", + "@rollup/rollup-freebsd-x64": "4.57.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", + "@rollup/rollup-linux-arm-musleabihf": "4.57.1", + "@rollup/rollup-linux-arm64-gnu": "4.57.1", + "@rollup/rollup-linux-arm64-musl": "4.57.1", + "@rollup/rollup-linux-loong64-gnu": "4.57.1", + "@rollup/rollup-linux-loong64-musl": "4.57.1", + "@rollup/rollup-linux-ppc64-gnu": "4.57.1", + "@rollup/rollup-linux-ppc64-musl": "4.57.1", + "@rollup/rollup-linux-riscv64-gnu": "4.57.1", + "@rollup/rollup-linux-riscv64-musl": "4.57.1", + "@rollup/rollup-linux-s390x-gnu": "4.57.1", + "@rollup/rollup-linux-x64-gnu": "4.57.1", + "@rollup/rollup-linux-x64-musl": "4.57.1", + "@rollup/rollup-openbsd-x64": "4.57.1", + "@rollup/rollup-openharmony-arm64": "4.57.1", + "@rollup/rollup-win32-arm64-msvc": "4.57.1", + "@rollup/rollup-win32-ia32-msvc": "4.57.1", + "@rollup/rollup-win32-x64-gnu": "4.57.1", + "@rollup/rollup-win32-x64-msvc": "4.57.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/sass": { + "version": "1.97.3", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.97.3.tgz", + "integrity": "sha512-fDz1zJpd5GycprAbu4Q2PV/RprsRtKC/0z82z0JLgdytmcq0+ujJbJ/09bPGDxCLkKY3Np5cRAOcWiVkLXJURg==", + "dependencies": { + "chokidar": "^4.0.0", + "immutable": "^5.0.2", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/typescript": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "devOptional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/vite": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", + "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", + "dev": true, + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true + }, + "node_modules/vue": { + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.28.tgz", + "integrity": "sha512-BRdrNfeoccSoIZeIhyPBfvWSLFP4q8J3u8Ju8Ug5vu3LdD+yTM13Sg4sKtljxozbnuMu1NB1X5HBHRYUzFocKg==", + "dependencies": { + "@vue/compiler-dom": "3.5.28", + "@vue/compiler-sfc": "3.5.28", + "@vue/runtime-dom": "3.5.28", + "@vue/server-renderer": "3.5.28", + "@vue/shared": "3.5.28" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-tsc": { + "version": "2.2.12", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.2.12.tgz", + "integrity": "sha512-P7OP77b2h/Pmk+lZdJ0YWs+5tJ6J2+uOQPo7tlBnY44QqQSPYvS0qVT4wqDJgwrZaLe47etJLLQRFia71GYITw==", + "dev": true, + "dependencies": { + "@volar/typescript": "2.4.15", + "@vue/language-core": "2.2.12" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + } + } +} diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 0000000000000000000000000000000000000000..7a9ffce172f35a88181cc93cc47c96a1870e204a --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,23 @@ +{ + "name": "learn-pathophysiology-wc3", + "private": true, + "version": "1.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vue-tsc -b && vite build", + "preview": "vite preview" + }, + "dependencies": { + "@vueuse/core": "^14.2.0", + "marked": "^15.0.0", + "sass": "^1.97.3", + "vue": "^3.5.0" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.2.0", + "typescript": "~5.7.0", + "vite": "^6.1.0", + "vue-tsc": "^2.2.0" + } +} diff --git a/frontend/public/any/hud_time_indicator.png b/frontend/public/any/hud_time_indicator.png new file mode 100644 index 0000000000000000000000000000000000000000..80ea672ea033903fb79a4ca2b2bae75a4f0dfeb8 --- /dev/null +++ b/frontend/public/any/hud_time_indicator.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3278868b0512fc4c6feaeef519d0c337e6e77f215859ac4ab97993e1c189c864 +size 131312 diff --git a/frontend/public/any/resource_icons/gold.png b/frontend/public/any/resource_icons/gold.png new file mode 100644 index 0000000000000000000000000000000000000000..3331ff942581ea01af1dceb5a410d9e52e366643 --- /dev/null +++ b/frontend/public/any/resource_icons/gold.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc3ff9674247028ebe34ac1e8c84bd97ca821199e1bfa4f7c0c635cca3fe0cd4 +size 1837 diff --git a/frontend/public/any/resource_icons/lumber.png b/frontend/public/any/resource_icons/lumber.png new file mode 100644 index 0000000000000000000000000000000000000000..f544107eb78781a58f552dfcba1dab3566922c98 --- /dev/null +++ b/frontend/public/any/resource_icons/lumber.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:650c574ce17ab7766f9d8cbf2bd6c3b5b1281954925d7d35bba9219dc8c81896 +size 1588 diff --git a/frontend/public/any/resource_icons/supply.png b/frontend/public/any/resource_icons/supply.png new file mode 100644 index 0000000000000000000000000000000000000000..f2e2dffae19b88b7f658fba3583368d194f898cc --- /dev/null +++ b/frontend/public/any/resource_icons/supply.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:11202af9a7fc0b73be772be538b5ab1f142f915c49a81a762b12623e90074309 +size 1405 diff --git a/frontend/public/hum/btn_default.png b/frontend/public/hum/btn_default.png new file mode 100644 index 0000000000000000000000000000000000000000..f6aae268ec016594a8f28c4b685fa47bfc0ef3a2 --- /dev/null +++ b/frontend/public/hum/btn_default.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b416cf7964b1cdc7314d69371f104aaf6c29b848c9a0081bf10dbdd205c240f6 +size 3167 diff --git a/frontend/public/hum/btn_disabled.png b/frontend/public/hum/btn_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..8e3b59389550a457a3c2938e291b09a8b069dde7 --- /dev/null +++ b/frontend/public/hum/btn_disabled.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:39fc64b1fba442258573c9bc5d7cdeff62bdc12b87094102dbd6e4fc2ce3c090 +size 2374 diff --git a/frontend/public/hum/btn_hover_bg.png b/frontend/public/hum/btn_hover_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..74a8d04413768cbdeb1630f51d154309b5046d4a --- /dev/null +++ b/frontend/public/hum/btn_hover_bg.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e9aac267b934c1bfe003de12535ae96c6d7ecc0b59092b77cf4096f20754de31 +size 1305 diff --git a/frontend/public/hum/btn_pressed.png b/frontend/public/hum/btn_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..ff3f31e05d42681708a6581f81eaf6b3b3f93aad --- /dev/null +++ b/frontend/public/hum/btn_pressed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3238ac55d25929e5758809e494f8b66da0e21620d0fe4a2fa6d98c9b76573e67 +size 2658 diff --git a/frontend/public/hum/cursor.png b/frontend/public/hum/cursor.png new file mode 100644 index 0000000000000000000000000000000000000000..fceb684c1be69bb7bd0a0636f44d47bb7b620d9e --- /dev/null +++ b/frontend/public/hum/cursor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f172e678d25df73e367fbe6fc2a134014c71b4951c6a4404370b5a4211adf004 +size 18047 diff --git a/frontend/public/hum/hud_footer.png b/frontend/public/hum/hud_footer.png new file mode 100644 index 0000000000000000000000000000000000000000..8013cbcfc1f7b06036396d8823e7337edc1f2994 --- /dev/null +++ b/frontend/public/hum/hud_footer.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d7194e7ebd0766414715c48726143a91435e6f11b4cdcf0eff769a3c53c584de +size 213087 diff --git a/frontend/public/hum/hud_header.png b/frontend/public/hum/hud_header.png new file mode 100644 index 0000000000000000000000000000000000000000..c7691f78cb65841ab091648ccc7a8a6b351c307b --- /dev/null +++ b/frontend/public/hum/hud_header.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b2e75eda4fe37055da8f956a28947f98d9ff8892c6b69df3512c7ee768cc9b30 +size 31698 diff --git a/frontend/public/hum/hud_inv_mock.png b/frontend/public/hum/hud_inv_mock.png new file mode 100644 index 0000000000000000000000000000000000000000..2f869a630d6d1df4b5f91e9910e70e55025b58fc --- /dev/null +++ b/frontend/public/hum/hud_inv_mock.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5099d37633d83fa5feba9279ceb1f087e4e696efbc0bd462c62c0bc7b38e8732 +size 95509 diff --git a/frontend/public/hum/hud_inv_mock_slot.png b/frontend/public/hum/hud_inv_mock_slot.png new file mode 100644 index 0000000000000000000000000000000000000000..20c354aefac942a7416e434f4068e83813672e6c --- /dev/null +++ b/frontend/public/hum/hud_inv_mock_slot.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7504e8e821ee070fb6a1cd53521bbfdab6be788bfe184905959dfc95b8a03cc4 +size 4492 diff --git a/frontend/public/nel/btn_default.png b/frontend/public/nel/btn_default.png new file mode 100644 index 0000000000000000000000000000000000000000..a45be6417cd285cbc884cd6d1275ecc9d3597b97 --- /dev/null +++ b/frontend/public/nel/btn_default.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c7a3600ade27dfc4df2e7b14739efc9b53f3d8cd772f0f0b7836f4e75d6bfbb9 +size 3084 diff --git a/frontend/public/nel/btn_disabled.png b/frontend/public/nel/btn_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..2b27df635642b16d3846d378e5b04f7dedb4fd44 --- /dev/null +++ b/frontend/public/nel/btn_disabled.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8e86445a348b78733d086f210b51c0e723212f9c1ae7a8d5b7186330558e2db7 +size 1766 diff --git a/frontend/public/nel/btn_hover_bg.png b/frontend/public/nel/btn_hover_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..219e834e553345d5f6848a4ef1e0f5358760b336 --- /dev/null +++ b/frontend/public/nel/btn_hover_bg.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7f7e43d86e4bd6918ee37ab7eb1f6780e8f0424c4a452bf06da4511bc601becd +size 1332 diff --git a/frontend/public/nel/btn_pressed.png b/frontend/public/nel/btn_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..45319d3dfff500d8d96632784fa2eb9f87694f9f --- /dev/null +++ b/frontend/public/nel/btn_pressed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6e15a1ea2bd8a3ac4420feb03e97969330cae16b64e4332a815740d391566da9 +size 2692 diff --git a/frontend/public/nel/cursor.png b/frontend/public/nel/cursor.png new file mode 100644 index 0000000000000000000000000000000000000000..0f77afedf7008f7a8df57b79bb77d3fa129623b3 --- /dev/null +++ b/frontend/public/nel/cursor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ca3b098a8516e5a770280965e10b0708637e811514ae986a4888e59d5a52ca8 +size 15202 diff --git a/frontend/public/nel/hud_footer.png b/frontend/public/nel/hud_footer.png new file mode 100644 index 0000000000000000000000000000000000000000..55211f9df7dc1705fbc8f5a3d324e68411087fa9 --- /dev/null +++ b/frontend/public/nel/hud_footer.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd0d75f008dffad62ad2e961f70ab4bfc10e9a9f468d6e94d7173a41699e4752 +size 263968 diff --git a/frontend/public/nel/hud_header.png b/frontend/public/nel/hud_header.png new file mode 100644 index 0000000000000000000000000000000000000000..cedf82a343b3717d8d070d66f7130394af81ef9e --- /dev/null +++ b/frontend/public/nel/hud_header.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6f479ba78e5d64fb0a97f3edae8b8757d8bc8296ae5332763088666d9b9836df +size 92718 diff --git a/frontend/public/nel/hud_inv_mock.png b/frontend/public/nel/hud_inv_mock.png new file mode 100644 index 0000000000000000000000000000000000000000..677edb6e2e6ee0a5f940de2dde6bc68e0ef8d531 --- /dev/null +++ b/frontend/public/nel/hud_inv_mock.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d25e96c77ba51df9d16a636d675a3eb23278ce9daef42acbde170a62aa9f83b1 +size 49391 diff --git a/frontend/public/nel/hud_inv_mock_slot.png b/frontend/public/nel/hud_inv_mock_slot.png new file mode 100644 index 0000000000000000000000000000000000000000..949b9489b2a3144c1fad3017797161edbd93d32e --- /dev/null +++ b/frontend/public/nel/hud_inv_mock_slot.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6f4504fe032ec6e1931e04e8bd85f1dabb2426fa1b7cfd9e4485fb1c2546d5e4 +size 4637 diff --git a/frontend/public/orc/btn_default.png b/frontend/public/orc/btn_default.png new file mode 100644 index 0000000000000000000000000000000000000000..bb59fe3d74c3bcee954865c4764b082157410688 --- /dev/null +++ b/frontend/public/orc/btn_default.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ad8feca70abe0d0e6a7aa948c9dc9d66283e3720649b84e2970dfcad3590eb3 +size 2781 diff --git a/frontend/public/orc/btn_disabled.png b/frontend/public/orc/btn_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..be757aba6ac2b01ea857dc6402220cc97fd255b2 --- /dev/null +++ b/frontend/public/orc/btn_disabled.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:953bf14a95dcb6b6120175ce4ed4b0f850fd8a1fbf65cd5f12b3a23ce5b4dbe2 +size 2105 diff --git a/frontend/public/orc/btn_hover_bg.png b/frontend/public/orc/btn_hover_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..d6e5cdbb3d729976270c31e2c5a7b5342dbc73ae --- /dev/null +++ b/frontend/public/orc/btn_hover_bg.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa21591323e8830d6aeb5ff09e192c0023032cc133d088730e334d8e3f0059f1 +size 1434 diff --git a/frontend/public/orc/btn_pressed.png b/frontend/public/orc/btn_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..2c73b6d33e8f169afb443f8fd756fd017381defd --- /dev/null +++ b/frontend/public/orc/btn_pressed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c014794f3f81d2509b47fef837a8bcd733d858c3bda04ce91ca96c742e9eb3eb +size 2524 diff --git a/frontend/public/orc/cursor.png b/frontend/public/orc/cursor.png new file mode 100644 index 0000000000000000000000000000000000000000..2b0a7e202d2c50811028155192500c4e296fb54d --- /dev/null +++ b/frontend/public/orc/cursor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cbc2565a8a6cff22a1ea7bebcbc671d350b0bf96fd4bf5b7aeedf5a10696a5ce +size 15108 diff --git a/frontend/public/orc/hud_footer.png b/frontend/public/orc/hud_footer.png new file mode 100644 index 0000000000000000000000000000000000000000..30b7b6f4f2608d3b2eaca5a2a84467263dfb9d99 --- /dev/null +++ b/frontend/public/orc/hud_footer.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5625f71d24f621a80e4b653d57bae65251d7016a09004491731205743ab8a8e1 +size 280808 diff --git a/frontend/public/orc/hud_header.png b/frontend/public/orc/hud_header.png new file mode 100644 index 0000000000000000000000000000000000000000..8dba453d4fd3deb907044bddb09c8a2f59dcc8c3 --- /dev/null +++ b/frontend/public/orc/hud_header.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3db8b4b92958cd53c42aecc535e9729df0d7a778b4b063bdca8b621a41680b5b +size 39433 diff --git a/frontend/public/orc/hud_inv_mock.png b/frontend/public/orc/hud_inv_mock.png new file mode 100644 index 0000000000000000000000000000000000000000..e87fa5cb31b95686738c27af37def22729e83eca --- /dev/null +++ b/frontend/public/orc/hud_inv_mock.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:05bcdfd6f0bc91cec360252704579c866da8dbcd42bac7dcd5a6b29e04bb39f1 +size 52513 diff --git a/frontend/public/orc/hud_inv_mock_slot.png b/frontend/public/orc/hud_inv_mock_slot.png new file mode 100644 index 0000000000000000000000000000000000000000..5ab724b2430c6afb987a0c7f1c39ffe96407f11a --- /dev/null +++ b/frontend/public/orc/hud_inv_mock_slot.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c20e037e2cb9a5f1b6e7ccfada6ac58f4eb0fa9b95dfe991c802bc50dcce3b2e +size 4310 diff --git a/frontend/public/und/btn_default.png b/frontend/public/und/btn_default.png new file mode 100644 index 0000000000000000000000000000000000000000..926b3e719c04adec848d8cf8a27b0d21aca7995d --- /dev/null +++ b/frontend/public/und/btn_default.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fe550270021fc6e1604d7e0bb682576027715c4de76f1f69cab6830cbc8835f2 +size 2734 diff --git a/frontend/public/und/btn_disabled.png b/frontend/public/und/btn_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..6b2ecf73a4ca2a1713d1340bdbac799e8cf42148 --- /dev/null +++ b/frontend/public/und/btn_disabled.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fce814c28c0ed48785d5c3b007ac4e4d8f6c765934f5dcdceb385901fcfe579e +size 2046 diff --git a/frontend/public/und/btn_hover_bg.png b/frontend/public/und/btn_hover_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..71e3531770c314008b5c55a4e3f984dc103282c8 --- /dev/null +++ b/frontend/public/und/btn_hover_bg.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:31995399159e873676e69b7841d79a505c292830003ca8db5d142c0a4e9845e7 +size 1181 diff --git a/frontend/public/und/btn_pressed.png b/frontend/public/und/btn_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..9250bf7963fcaf45a81e3b8af68640f1d7a604bf --- /dev/null +++ b/frontend/public/und/btn_pressed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0869ec9b3b9a2bedc9a3c245b4e3c7d35ff31891bb7cc7d6680f42f5650d4dc1 +size 2427 diff --git a/frontend/public/und/cursor.png b/frontend/public/und/cursor.png new file mode 100644 index 0000000000000000000000000000000000000000..abbd589d6f92af59c008adcc3063cfa0668d37a4 --- /dev/null +++ b/frontend/public/und/cursor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:10b68c7b7c875df547097add45409b8391e07a6d21df789a4b4700d18896e621 +size 12682 diff --git a/frontend/public/und/hud_footer.png b/frontend/public/und/hud_footer.png new file mode 100644 index 0000000000000000000000000000000000000000..0ca5731280023f043da66805ecf7d917801f5089 --- /dev/null +++ b/frontend/public/und/hud_footer.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b07074fdec92b009badb60d64f39aab2f26b5ab96f1983d551562309094bb725 +size 292403 diff --git a/frontend/public/und/hud_header.png b/frontend/public/und/hud_header.png new file mode 100644 index 0000000000000000000000000000000000000000..7028cc7359c2adf58bee0ed99052aab9d43306e7 --- /dev/null +++ b/frontend/public/und/hud_header.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3129bf0f86a4d8e48f3d5fd817bd90d29545483f595c762da95ad2cc20f52d45 +size 29892 diff --git a/frontend/public/und/hud_inv_mock.png b/frontend/public/und/hud_inv_mock.png new file mode 100644 index 0000000000000000000000000000000000000000..6148f8da4512ff370487f94b6da73693a645ba7c --- /dev/null +++ b/frontend/public/und/hud_inv_mock.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad3ca01b9ef3306c65f55c7c4057fb7573b9816e533d6332d2046fb3fbce714a +size 53521 diff --git a/frontend/public/und/hud_inv_mock_slot.png b/frontend/public/und/hud_inv_mock_slot.png new file mode 100644 index 0000000000000000000000000000000000000000..6a42459f5db2e96bf02dd17e12f2acd89037e07d --- /dev/null +++ b/frontend/public/und/hud_inv_mock_slot.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0c459be05833a5878f656f32d226bc8d73522b5f6bccc79479e28e0dd6f2795a +size 3657 diff --git a/frontend/src/App.vue b/frontend/src/App.vue new file mode 100644 index 0000000000000000000000000000000000000000..ff4505be318fd59d3480810918bc192b6842449a --- /dev/null +++ b/frontend/src/App.vue @@ -0,0 +1,733 @@ + + + + + diff --git a/frontend/src/api.ts b/frontend/src/api.ts new file mode 100644 index 0000000000000000000000000000000000000000..66e0d780ce821343d0ffad102bdb6a7c36c2f94a --- /dev/null +++ b/frontend/src/api.ts @@ -0,0 +1,128 @@ +import type { + ChatMessage, + ChatResponse, + ImageResponse, + ModelsResponse, + StatsResponse, + HealthResponse, + AuthConfig, + AuthResponse, + AuthUser, +} from './types' + +const BASE_URL = '/api' + +// --------------------------------------------------------------------------- +// Token management +// --------------------------------------------------------------------------- + +const TOKEN_KEY = 'lp_auth_token' + +export function getToken(): string | null { + return localStorage.getItem(TOKEN_KEY) +} + +export function setToken(token: string) { + localStorage.setItem(TOKEN_KEY, token) +} + +export function clearToken() { + localStorage.removeItem(TOKEN_KEY) +} + +function authHeaders(): Record { + const token = getToken() + return token ? { Authorization: `Bearer ${token}` } : {} +} + +// --------------------------------------------------------------------------- +// Generic request helper +// --------------------------------------------------------------------------- + +async function request(path: string, options?: RequestInit): Promise { + const res = await fetch(`${BASE_URL}${path}`, { + headers: { 'Content-Type': 'application/json', ...authHeaders() }, + ...options, + }) + if (!res.ok) { + const err = await res.json().catch(() => ({ detail: res.statusText })) + throw new Error(err.detail || `HTTP ${res.status}`) + } + return res.json() +} + +// --------------------------------------------------------------------------- +// Auth +// --------------------------------------------------------------------------- + +export async function getAuthConfig(): Promise { + return request('/auth/config') +} + +export async function loginWithGoogle(credential: string): Promise { + return request('/auth/google', { + method: 'POST', + body: JSON.stringify({ credential }), + }) +} + +export async function getMe(): Promise { + return request('/auth/me') +} + +// --------------------------------------------------------------------------- +// Public API +// --------------------------------------------------------------------------- + +export async function getHealth(): Promise { + return request('/health') +} + +export async function getModels(): Promise { + return request('/models') +} + +export async function getStats(): Promise { + return request('/stats') +} + +// --------------------------------------------------------------------------- +// Protected API +// --------------------------------------------------------------------------- + +export async function sendChat( + message: string, + model: string, + history: ChatMessage[], +): Promise { + return request('/chat', { + method: 'POST', + body: JSON.stringify({ + message, + model, + history: history.map((m) => ({ role: m.role, content: m.content })), + }), + }) +} + +export async function analyzeImage( + imageFile: File, + question: string, + model: string, +): Promise { + const formData = new FormData() + formData.append('image', imageFile) + formData.append('question', question) + formData.append('model', model) + + const res = await fetch(`${BASE_URL}/analyze-image`, { + method: 'POST', + body: formData, + headers: authHeaders(), + }) + if (!res.ok) { + const err = await res.json().catch(() => ({ detail: res.statusText })) + throw new Error(err.detail || `HTTP ${res.status}`) + } + return res.json() +} diff --git a/frontend/src/components/ChatView.vue b/frontend/src/components/ChatView.vue new file mode 100644 index 0000000000000000000000000000000000000000..19c5935510cdc1d91cbcfe932ffbafa3639cfbb4 --- /dev/null +++ b/frontend/src/components/ChatView.vue @@ -0,0 +1,140 @@ + + + + + diff --git a/frontend/src/components/CitationPanel.vue b/frontend/src/components/CitationPanel.vue new file mode 100644 index 0000000000000000000000000000000000000000..6ba22a015273b619a7b23ac4c8a36e3c69fa85fe --- /dev/null +++ b/frontend/src/components/CitationPanel.vue @@ -0,0 +1,52 @@ + + + diff --git a/frontend/src/components/ImageView.vue b/frontend/src/components/ImageView.vue new file mode 100644 index 0000000000000000000000000000000000000000..aa087fb385aa5a71f71ba3cd9832919828c570f7 --- /dev/null +++ b/frontend/src/components/ImageView.vue @@ -0,0 +1,117 @@ + + + diff --git a/frontend/src/components/LoginPage.vue b/frontend/src/components/LoginPage.vue new file mode 100644 index 0000000000000000000000000000000000000000..173659bb777e11a21df17ee23fa5e3edf2ba3755 --- /dev/null +++ b/frontend/src/components/LoginPage.vue @@ -0,0 +1,181 @@ + + + + + diff --git a/frontend/src/components/SidePanel.vue b/frontend/src/components/SidePanel.vue new file mode 100644 index 0000000000000000000000000000000000000000..cc9f0717548e7f9f2033a76acec6b30eb2fac915 --- /dev/null +++ b/frontend/src/components/SidePanel.vue @@ -0,0 +1,93 @@ + + + diff --git a/frontend/src/main.ts b/frontend/src/main.ts new file mode 100644 index 0000000000000000000000000000000000000000..01433bca2ac76590c48fabfee8d69d7b223f48bb --- /dev/null +++ b/frontend/src/main.ts @@ -0,0 +1,4 @@ +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/frontend/src/types.ts b/frontend/src/types.ts new file mode 100644 index 0000000000000000000000000000000000000000..86c239e5e681307f33867f3db0e44a6471eccd49 --- /dev/null +++ b/frontend/src/types.ts @@ -0,0 +1,66 @@ +export interface Citation { + text: string + score: number + source: string + page_num: string | number + rank: number +} + +export interface ChatMessage { + role: 'user' | 'assistant' + content: string + citations?: Citation[] + model_used?: string +} + +export interface ModelInfo { + name: string + description: string + icon: string + wc3_name: string + tier: string +} + +export interface ModelsResponse { + models: Record + default: string +} + +export interface ChatResponse { + reply: string + citations: Citation[] + model_used: string +} + +export interface ImageResponse { + analysis: string + citations: Citation[] + model_used: string +} + +export interface StatsResponse { + documents: number + collection: string +} + +export interface HealthResponse { + status: string + chroma_docs: number + has_api_key: boolean +} + +export interface AuthConfig { + auth_enabled: boolean + google_client_id: string | null +} + +export interface AuthUser { + email: string + name: string + picture: string +} + +export interface AuthResponse { + token: string + user: AuthUser +} \ No newline at end of file diff --git a/frontend/src/wc3/ConfigProvider.ts b/frontend/src/wc3/ConfigProvider.ts new file mode 100644 index 0000000000000000000000000000000000000000..1e89f4e11b4f525f45bea321534d58d3914181b5 --- /dev/null +++ b/frontend/src/wc3/ConfigProvider.ts @@ -0,0 +1,44 @@ +import { + defineComponent, inject, PropType, provide, renderSlot, Component, + computed, type ComputedRef, +} from 'vue'; +import { RACE_KEY } from './consts'; + +const injectKey = 'wc3ui-config'; + +type InternalAPI = { + readonly theme: ComputedRef +} + +type IConfigAPI = { + theme: ComputedRef +} + +export type WidgetsList = Record; + +export default defineComponent({ + props: { + theme: { + type: String as PropType, + default: RACE_KEY.HUMAN, + }, + }, + setup(props, ctx) { + // Use computed so theme stays reactive when prop changes + const theme = computed(() => props.theme); + + const api: InternalAPI = { theme }; + provide(injectKey, api); + + return () => renderSlot(ctx.slots, 'default'); + }, +}); + +export function useConfig(): IConfigAPI { + const config = inject(injectKey) as InternalAPI | undefined; + + return { + // Return a computed ref so consumers can track reactivity with .value + theme: computed(() => config?.theme.value ?? RACE_KEY.HUMAN), + }; +} diff --git a/frontend/src/wc3/Hud.stories.ts b/frontend/src/wc3/Hud.stories.ts new file mode 100644 index 0000000000000000000000000000000000000000..e75bfff6f2eead5040b52131c0329fd373df02d8 --- /dev/null +++ b/frontend/src/wc3/Hud.stories.ts @@ -0,0 +1,34 @@ +import Hud from './Hud.vue'; +import ConfigProvider from './ConfigProvider'; +import { RACE_KEY } from '../consts'; + +export default { + title: 'Combined/Hud', + component: Hud, +}; + +const Template = (args: any) => ({ + components: { Hud, ConfigProvider }, + setup() { + return { args }; + }, + template: ` + +
    + +
    +
    + `, +}); + +export const Human = Template.bind({}); +Human.args = { raceTheme: RACE_KEY.HUMAN }; + +export const NightElf = Template.bind({}); +NightElf.args = { raceTheme: RACE_KEY.NIGHT_ELF }; + +export const Orc = Template.bind({}); +Orc.args = { raceTheme: RACE_KEY.ORC }; + +export const Undead = Template.bind({}); +Undead.args = { raceTheme: RACE_KEY.UNDEAD }; diff --git a/frontend/src/wc3/Hud.vue b/frontend/src/wc3/Hud.vue new file mode 100644 index 0000000000000000000000000000000000000000..bdebe334ff605d161d06343ad664ee74c2389f64 --- /dev/null +++ b/frontend/src/wc3/Hud.vue @@ -0,0 +1,31 @@ + + + + + diff --git a/frontend/src/wc3/HudFooter.stories.ts b/frontend/src/wc3/HudFooter.stories.ts new file mode 100644 index 0000000000000000000000000000000000000000..13b25e3a6a334cedc8cd19198e9508630bbdb984 --- /dev/null +++ b/frontend/src/wc3/HudFooter.stories.ts @@ -0,0 +1,40 @@ +import HudFooter from './HudFooter.vue'; +import { unflatten } from 'flat'; +import ConfigProvider from './ConfigProvider'; +import { RACE_KEY } from '../consts'; + +export default { + title: 'Combined/HudFooter', + component: HudFooter, + argTypes: { + 'inventory.slots': { + control: { type: 'range', min: 0, max: 6 }, + }, + } +}; + +const Template = (args: any) => ({ + components: { HudFooter, ConfigProvider }, + setup() { + return { + args: unflatten(args, '.') + }; + }, + template: ` + + + + `, +}); + +export const Human = Template.bind({}); +Human.args = { raceTheme: RACE_KEY.HUMAN }; + +export const NightElf = Template.bind({}); +NightElf.args = { raceTheme: RACE_KEY.NIGHT_ELF }; + +export const Orc = Template.bind({}); +Orc.args = { raceTheme: RACE_KEY.ORC }; + +export const Undead = Template.bind({}); +Undead.args = { raceTheme: RACE_KEY.UNDEAD }; diff --git a/frontend/src/wc3/HudFooter.vue b/frontend/src/wc3/HudFooter.vue new file mode 100644 index 0000000000000000000000000000000000000000..ea4ba565936732475cb714a500722e4b3a204351 --- /dev/null +++ b/frontend/src/wc3/HudFooter.vue @@ -0,0 +1,100 @@ + + + + + diff --git a/frontend/src/wc3/HudHeader.stories.ts b/frontend/src/wc3/HudHeader.stories.ts new file mode 100644 index 0000000000000000000000000000000000000000..e7249d1be75a8c32d20c904346f5ce14e181afde --- /dev/null +++ b/frontend/src/wc3/HudHeader.stories.ts @@ -0,0 +1,32 @@ +import HudHeader from './HudHeader.vue'; +import ConfigProvider from './ConfigProvider'; +import { RACE_KEY } from '../consts'; + +export default { + title: 'Combined/HudHeader', + component: HudHeader, +}; + +const Template = (args: any) => ({ + components: { HudHeader, ConfigProvider }, + setup() { + return { args }; + }, + template: ` + + + + `, +}); + +export const Human = Template.bind({}); +Human.args = { raceTheme: RACE_KEY.HUMAN }; + +export const NightElf = Template.bind({}); +NightElf.args = { raceTheme: RACE_KEY.NIGHT_ELF }; + +export const Orc = Template.bind({}); +Orc.args = { raceTheme: RACE_KEY.ORC }; + +export const Undead = Template.bind({}); +Undead.args = { raceTheme: RACE_KEY.UNDEAD }; diff --git a/frontend/src/wc3/HudHeader.vue b/frontend/src/wc3/HudHeader.vue new file mode 100644 index 0000000000000000000000000000000000000000..ee31db0282b7979bba786e4ebb3ec6ec3bcb6d26 --- /dev/null +++ b/frontend/src/wc3/HudHeader.vue @@ -0,0 +1,159 @@ + + + + + diff --git a/frontend/src/wc3/base/Button.stories.ts b/frontend/src/wc3/base/Button.stories.ts new file mode 100644 index 0000000000000000000000000000000000000000..1514e92b2d9a0388473fb43804d18fc1a928a090 --- /dev/null +++ b/frontend/src/wc3/base/Button.stories.ts @@ -0,0 +1,41 @@ +import { RACE_KEY } from '../../consts'; +import Button from './Button.vue'; +import ConfigProvider from '../ConfigProvider'; + +export default { + title: 'Basic/Button', + component: Button, + argTypes: { + size: { + control: { type: 'select' }, + options: ['s', 'm'], + }, + } +}; + +const Template = (args) => ({ + components: { Button, ConfigProvider }, + setup() { + return { args }; + }, + template: ` + +
    + + + +
    +
    `, +}); + +export const Human = Template.bind({}); +Human.args = { raceTheme: RACE_KEY.HUMAN }; + +export const NightElf = Template.bind({}); +NightElf.args = { raceTheme: RACE_KEY.NIGHT_ELF }; + +export const Orc = Template.bind({}); +Orc.args = { raceTheme: RACE_KEY.ORC }; + +export const Undead = Template.bind({}); +Undead.args = { raceTheme: RACE_KEY.UNDEAD }; diff --git a/frontend/src/wc3/base/Button.vue b/frontend/src/wc3/base/Button.vue new file mode 100644 index 0000000000000000000000000000000000000000..0efd25073c3c1b83c08f829d74258d6af124ef52 --- /dev/null +++ b/frontend/src/wc3/base/Button.vue @@ -0,0 +1,108 @@ + + + + + diff --git a/frontend/src/wc3/base/Cursor.stories.ts b/frontend/src/wc3/base/Cursor.stories.ts new file mode 100644 index 0000000000000000000000000000000000000000..e5bb43888e10787e7905f307b2fd99887a567307 --- /dev/null +++ b/frontend/src/wc3/base/Cursor.stories.ts @@ -0,0 +1,59 @@ +import { ref } from 'vue'; +import Cursor from './Cursor.vue'; +import ConfigProvider from '../ConfigProvider'; +import { RACE_KEY } from '../../consts'; + +export default { + title: 'Basic/Cursor', + component: Cursor, +}; + +const states = [ + 'default', + 'default-active', + 'pointer', + 'pointer-active', + 'pointer-denied', + 'hold', + 'arrow-top', + 'arrow-right', + 'arrow-bottom', + 'arrow-left', +]; + +const Template = (args: any) => ({ + components: { Cursor, ConfigProvider }, + setup() { + const state = ref('default'); + return { args, state }; + }, + template: ` + +
    + + ${states + .map((s) => ` +
    + ${s} +
    + `) + .join('')} +
    +
    + `, +}); + +export const Human = Template.bind({}); +Human.args = { raceTheme: RACE_KEY.HUMAN }; + +export const NightElf = Template.bind({}); +NightElf.args = { raceTheme: RACE_KEY.NIGHT_ELF }; + +export const Orc = Template.bind({}); +Orc.args = { raceTheme: RACE_KEY.ORC }; + +export const Undead = Template.bind({}); +Undead.args = { raceTheme: RACE_KEY.UNDEAD }; diff --git a/frontend/src/wc3/base/Cursor.vue b/frontend/src/wc3/base/Cursor.vue new file mode 100644 index 0000000000000000000000000000000000000000..802f27fc30697d02b31bdc0c7f2ed12c9090a244 --- /dev/null +++ b/frontend/src/wc3/base/Cursor.vue @@ -0,0 +1,135 @@ + + + + + diff --git a/frontend/src/wc3/composables/useTime.ts b/frontend/src/wc3/composables/useTime.ts new file mode 100644 index 0000000000000000000000000000000000000000..ba29b90e356576da1defc03be1de5f3f1e6c6c57 --- /dev/null +++ b/frontend/src/wc3/composables/useTime.ts @@ -0,0 +1,50 @@ +import { Ref, ref } from 'vue'; + +export interface IUseTime { + value: Ref + isDay: Ref + set(v: number): void + add(v?: number): void + /** Returns progress percent (from 0 up to 1). + * If `isOfHalfDay` is true, returns progress in 6-18 (day) or 18-6 (night) interval + * else, returns progress in 18-18 (start of night - end of day) interval + */ + getProgress(isOfHalfDay?: boolean): number + getTimeCaption(): string +} + +function clampTime(value: number): number { + return value % 24; +} + +// TODO: make basing on game minutes instead of hours, to get more flexible logic +export function useTime(startValue = 0): IUseTime { + const value = ref(startValue); + const isDay = ref(false); + + function update(newValRaw: number) { + const newVal = clampTime(newValRaw); + value.value = newVal; + isDay.value = newVal >= 6 && newVal <= 18; + } + + return { + value, + isDay, + set(val) { + update(val) + }, + add(val = 1) { + update(value.value + val) + }, + getProgress(isOfHalfDay = false) { + const limiter = isOfHalfDay ? 12 : 24; + return ((value.value + 6) % limiter) / limiter; + }, + getTimeCaption() { + const minutes = `${Math.trunc((value.value % 1) * 60)}`.padStart(2, '0'); + const hours = `${Math.trunc(value.value)}`.padStart(2, '0'); + return `${hours}:${minutes}`; + } + }; +} \ No newline at end of file diff --git a/frontend/src/wc3/consts.ts b/frontend/src/wc3/consts.ts new file mode 100644 index 0000000000000000000000000000000000000000..bb1c1509b650779e576a59241bccae5e518a10f1 --- /dev/null +++ b/frontend/src/wc3/consts.ts @@ -0,0 +1,6 @@ +export enum RACE_KEY { + HUMAN = 'hum', + NIGHT_ELF = 'nel', + ORC = 'orc', + UNDEAD = 'und', +} diff --git a/frontend/src/wc3/directives.ts b/frontend/src/wc3/directives.ts new file mode 100644 index 0000000000000000000000000000000000000000..ec469de11f545f8ce9fac992d5947d4ef9498c3d --- /dev/null +++ b/frontend/src/wc3/directives.ts @@ -0,0 +1,5 @@ +import { Directive } from 'vue'; + +export const vVisible: Directive = { + mounted: (el, binding) => el.style.visibility = !!binding.value ? 'visible' : 'hidden', +} diff --git a/frontend/src/wc3/utils.ts b/frontend/src/wc3/utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..91722047a852b42adfc69232b5c5f4254ef0acbf --- /dev/null +++ b/frontend/src/wc3/utils.ts @@ -0,0 +1,10 @@ +import { RACE_KEY } from './consts'; + +export function getAssetPath(path: string, theme: RACE_KEY | 'any' = 'any'): string { + return `${ASSETS_PATH}${theme}/${path}`; +} + +export function getAssetUrl(path: string, theme?: RACE_KEY | 'any'): string { + return `url(${getAssetPath(path, theme)})`; +} + diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..8482931b299f7895d3ddc9fadf94e4a74006b377 --- /dev/null +++ b/frontend/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "preserve", + "strict": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "noFallthroughCasesInSwitch": true, + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "env.d.ts"] +} diff --git a/frontend/tsconfig.tsbuildinfo b/frontend/tsconfig.tsbuildinfo new file mode 100644 index 0000000000000000000000000000000000000000..8315c5a5f40a41be3892ebb21dc63cf8a9ddaceb --- /dev/null +++ b/frontend/tsconfig.tsbuildinfo @@ -0,0 +1 @@ +{"root":["./src/api.ts","./src/main.ts","./src/types.ts","./src/wc3/configprovider.ts","./src/wc3/hud.stories.ts","./src/wc3/hudfooter.stories.ts","./src/wc3/hudheader.stories.ts","./src/wc3/consts.ts","./src/wc3/directives.ts","./src/wc3/utils.ts","./src/wc3/base/button.stories.ts","./src/wc3/base/cursor.stories.ts","./src/wc3/composables/usetime.ts","./src/app.vue","./src/components/chatview.vue","./src/components/citationpanel.vue","./src/components/imageview.vue","./src/components/sidepanel.vue","./src/wc3/hud.vue","./src/wc3/hudfooter.vue","./src/wc3/hudheader.vue","./src/wc3/base/button.vue","./src/wc3/base/cursor.vue","./env.d.ts"],"errors":true,"version":"5.7.3"} \ No newline at end of file diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts new file mode 100644 index 0000000000000000000000000000000000000000..d410b0fd1657267c829ad74f0e0dbb755e6795c5 --- /dev/null +++ b/frontend/vite.config.ts @@ -0,0 +1,22 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +export default defineConfig({ + plugins: [vue()], + define: { + ASSETS_PATH: `'/'`, // WC3 assets served from root of static dir + }, + server: { + port: 5173, + proxy: { + '/api': { + target: 'http://localhost:7860', + changeOrigin: true, + }, + }, + }, + build: { + outDir: 'dist', + emptyOutDir: true, + }, +})