Spaces:
Running
Running
Add Next frontend build and serving pipeline
Browse files- .gitignore +3 -0
- Dockerfile +12 -0
- app.py +9 -0
- ui/app/globals.css +837 -0
- ui/app/layout.tsx +20 -0
- ui/app/page.tsx +917 -0
- ui/next-env.d.ts +6 -0
- ui/next.config.mjs +9 -0
- ui/package-lock.json +1019 -0
- ui/package.json +23 -0
- ui/tsconfig.json +20 -0
.gitignore
CHANGED
|
@@ -67,6 +67,9 @@ datasets/
|
|
| 67 |
dist/
|
| 68 |
build/
|
| 69 |
out/
|
|
|
|
|
|
|
|
|
|
| 70 |
|
| 71 |
# =========================
|
| 72 |
# TEMP FILES
|
|
|
|
| 67 |
dist/
|
| 68 |
build/
|
| 69 |
out/
|
| 70 |
+
ui/node_modules/
|
| 71 |
+
ui/.next/
|
| 72 |
+
ui/out/
|
| 73 |
|
| 74 |
# =========================
|
| 75 |
# TEMP FILES
|
Dockerfile
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
FROM python:3.11-slim
|
| 2 |
|
| 3 |
WORKDIR /app
|
|
@@ -23,6 +34,7 @@ COPY pyproject.toml .
|
|
| 23 |
COPY server ./server
|
| 24 |
COPY static ./static
|
| 25 |
COPY outputs ./outputs
|
|
|
|
| 26 |
|
| 27 |
# Create outputs directory for baseline scores
|
| 28 |
RUN mkdir -p outputs
|
|
|
|
| 1 |
+
FROM node:20-alpine AS ui-builder
|
| 2 |
+
|
| 3 |
+
WORKDIR /ui
|
| 4 |
+
|
| 5 |
+
COPY ui/package.json ui/package-lock.json ./
|
| 6 |
+
RUN npm ci
|
| 7 |
+
|
| 8 |
+
COPY ui ./
|
| 9 |
+
RUN npm run build
|
| 10 |
+
|
| 11 |
+
|
| 12 |
FROM python:3.11-slim
|
| 13 |
|
| 14 |
WORKDIR /app
|
|
|
|
| 34 |
COPY server ./server
|
| 35 |
COPY static ./static
|
| 36 |
COPY outputs ./outputs
|
| 37 |
+
COPY --from=ui-builder /ui/out ./ui/out
|
| 38 |
|
| 39 |
# Create outputs directory for baseline scores
|
| 40 |
RUN mkdir -p outputs
|
app.py
CHANGED
|
@@ -5,6 +5,7 @@ from pathlib import Path
|
|
| 5 |
from typing import Any
|
| 6 |
|
| 7 |
from fastapi import FastAPI, HTTPException, Query
|
|
|
|
| 8 |
from fastapi.responses import FileResponse, JSONResponse
|
| 9 |
from pydantic import BaseModel
|
| 10 |
|
|
@@ -28,6 +29,11 @@ app = FastAPI(
|
|
| 28 |
_sessions: dict[str, SentinelEnv] = {}
|
| 29 |
_STATIC_DIR = Path(__file__).resolve().parent / "static"
|
| 30 |
_OUTPUTS_DIR = Path(__file__).resolve().parent / "outputs"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
|
| 32 |
def _get_env(session_id: str) -> SentinelEnv:
|
| 33 |
if session_id not in _sessions:
|
|
@@ -64,6 +70,9 @@ def health():
|
|
| 64 |
|
| 65 |
@app.get("/")
|
| 66 |
def root():
|
|
|
|
|
|
|
|
|
|
| 67 |
index_path = _STATIC_DIR / "index.html"
|
| 68 |
if index_path.exists():
|
| 69 |
return FileResponse(index_path)
|
|
|
|
| 5 |
from typing import Any
|
| 6 |
|
| 7 |
from fastapi import FastAPI, HTTPException, Query
|
| 8 |
+
from fastapi.staticfiles import StaticFiles
|
| 9 |
from fastapi.responses import FileResponse, JSONResponse
|
| 10 |
from pydantic import BaseModel
|
| 11 |
|
|
|
|
| 29 |
_sessions: dict[str, SentinelEnv] = {}
|
| 30 |
_STATIC_DIR = Path(__file__).resolve().parent / "static"
|
| 31 |
_OUTPUTS_DIR = Path(__file__).resolve().parent / "outputs"
|
| 32 |
+
_FRONTEND_OUT_DIR = Path(__file__).resolve().parent / "ui" / "out"
|
| 33 |
+
_FRONTEND_NEXT_DIR = _FRONTEND_OUT_DIR / "_next"
|
| 34 |
+
|
| 35 |
+
if _FRONTEND_NEXT_DIR.exists():
|
| 36 |
+
app.mount("/_next", StaticFiles(directory=_FRONTEND_NEXT_DIR), name="next-assets")
|
| 37 |
|
| 38 |
def _get_env(session_id: str) -> SentinelEnv:
|
| 39 |
if session_id not in _sessions:
|
|
|
|
| 70 |
|
| 71 |
@app.get("/")
|
| 72 |
def root():
|
| 73 |
+
frontend_index = _FRONTEND_OUT_DIR / "index.html"
|
| 74 |
+
if frontend_index.exists():
|
| 75 |
+
return FileResponse(frontend_index)
|
| 76 |
index_path = _STATIC_DIR / "index.html"
|
| 77 |
if index_path.exists():
|
| 78 |
return FileResponse(index_path)
|
ui/app/globals.css
ADDED
|
@@ -0,0 +1,837 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
:root {
|
| 2 |
+
--bg: #050711;
|
| 3 |
+
--bg-soft: #0b1020;
|
| 4 |
+
--panel: rgba(18, 24, 40, 0.68);
|
| 5 |
+
--panel-strong: rgba(24, 31, 51, 0.82);
|
| 6 |
+
--panel-soft: rgba(255, 255, 255, 0.04);
|
| 7 |
+
--line: rgba(255, 255, 255, 0.1);
|
| 8 |
+
--ink: #f5f7ff;
|
| 9 |
+
--muted: #9fa9c5;
|
| 10 |
+
--blue: #8ab5ff;
|
| 11 |
+
--mint: #7be1d7;
|
| 12 |
+
--warm: #ffc68d;
|
| 13 |
+
--rose: #ff8f9f;
|
| 14 |
+
--shadow: 0 24px 60px rgba(1, 6, 20, 0.36);
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
* {
|
| 18 |
+
box-sizing: border-box;
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
html {
|
| 22 |
+
background: var(--bg);
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
body {
|
| 26 |
+
margin: 0;
|
| 27 |
+
color: var(--ink);
|
| 28 |
+
background:
|
| 29 |
+
radial-gradient(circle at 12% 0%, rgba(138, 181, 255, 0.18), transparent 22%),
|
| 30 |
+
radial-gradient(circle at 88% 10%, rgba(255, 143, 159, 0.12), transparent 18%),
|
| 31 |
+
radial-gradient(circle at 50% 100%, rgba(123, 225, 215, 0.08), transparent 18%),
|
| 32 |
+
linear-gradient(180deg, #04060d 0%, #080c16 44%, #050711 100%);
|
| 33 |
+
font-family:
|
| 34 |
+
Inter,
|
| 35 |
+
ui-sans-serif,
|
| 36 |
+
system-ui,
|
| 37 |
+
-apple-system,
|
| 38 |
+
BlinkMacSystemFont,
|
| 39 |
+
"Segoe UI",
|
| 40 |
+
sans-serif;
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
button,
|
| 44 |
+
select,
|
| 45 |
+
input {
|
| 46 |
+
font: inherit;
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
.sentinel-shell {
|
| 50 |
+
min-height: 100vh;
|
| 51 |
+
position: relative;
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
.bg-grid {
|
| 55 |
+
position: fixed;
|
| 56 |
+
inset: 0;
|
| 57 |
+
pointer-events: none;
|
| 58 |
+
background:
|
| 59 |
+
linear-gradient(rgba(255, 255, 255, 0.022) 1px, transparent 1px),
|
| 60 |
+
linear-gradient(90deg, rgba(255, 255, 255, 0.018) 1px, transparent 1px);
|
| 61 |
+
background-size: 44px 44px;
|
| 62 |
+
mask-image: radial-gradient(circle at center, black 36%, transparent 84%);
|
| 63 |
+
opacity: 0.34;
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
.topbar,
|
| 67 |
+
.tabbar,
|
| 68 |
+
.section,
|
| 69 |
+
.glass-card,
|
| 70 |
+
.metric-card,
|
| 71 |
+
.control-pill,
|
| 72 |
+
.stat-box,
|
| 73 |
+
.story-lane,
|
| 74 |
+
.json-card,
|
| 75 |
+
.event-row,
|
| 76 |
+
.judge-card,
|
| 77 |
+
.specialist-node,
|
| 78 |
+
.subtask-card {
|
| 79 |
+
border: 1px solid var(--line);
|
| 80 |
+
background:
|
| 81 |
+
linear-gradient(180deg, rgba(255, 255, 255, 0.07), rgba(255, 255, 255, 0.015)),
|
| 82 |
+
var(--panel);
|
| 83 |
+
box-shadow:
|
| 84 |
+
inset 0 1px 0 rgba(255, 255, 255, 0.05),
|
| 85 |
+
var(--shadow);
|
| 86 |
+
backdrop-filter: blur(20px) saturate(1.35);
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
.topbar {
|
| 90 |
+
position: sticky;
|
| 91 |
+
top: 0;
|
| 92 |
+
z-index: 30;
|
| 93 |
+
margin: 18px auto 0;
|
| 94 |
+
width: min(1460px, calc(100% - 24px));
|
| 95 |
+
border-radius: 28px;
|
| 96 |
+
padding: 18px 20px;
|
| 97 |
+
display: grid;
|
| 98 |
+
grid-template-columns: minmax(340px, 1fr) auto;
|
| 99 |
+
gap: 18px;
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
.brand {
|
| 103 |
+
display: flex;
|
| 104 |
+
gap: 16px;
|
| 105 |
+
align-items: center;
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
.brand-mark {
|
| 109 |
+
width: 56px;
|
| 110 |
+
height: 56px;
|
| 111 |
+
border-radius: 18px;
|
| 112 |
+
display: grid;
|
| 113 |
+
place-items: center;
|
| 114 |
+
color: #eef4ff;
|
| 115 |
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
| 116 |
+
background:
|
| 117 |
+
radial-gradient(circle at 30% 24%, rgba(138, 181, 255, 0.44), transparent 56%),
|
| 118 |
+
linear-gradient(180deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.02)),
|
| 119 |
+
rgba(18, 23, 35, 0.9);
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
.eyebrow {
|
| 123 |
+
color: var(--muted);
|
| 124 |
+
font-size: 12px;
|
| 125 |
+
letter-spacing: 0.12em;
|
| 126 |
+
text-transform: uppercase;
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
.brand h1 {
|
| 130 |
+
margin: 4px 0 6px;
|
| 131 |
+
font-size: clamp(32px, 5vw, 52px);
|
| 132 |
+
line-height: 0.95;
|
| 133 |
+
}
|
| 134 |
+
|
| 135 |
+
.brand p,
|
| 136 |
+
.tab-copy,
|
| 137 |
+
.section-head span,
|
| 138 |
+
.story-step,
|
| 139 |
+
.proof-row span,
|
| 140 |
+
.proof-row strong,
|
| 141 |
+
.json-head,
|
| 142 |
+
.event-copy span,
|
| 143 |
+
.judge-card span,
|
| 144 |
+
.architecture-card span,
|
| 145 |
+
.subtask-card p,
|
| 146 |
+
.stat-box span {
|
| 147 |
+
color: var(--muted);
|
| 148 |
+
}
|
| 149 |
+
|
| 150 |
+
.controls {
|
| 151 |
+
display: flex;
|
| 152 |
+
gap: 12px;
|
| 153 |
+
align-items: center;
|
| 154 |
+
flex-wrap: wrap;
|
| 155 |
+
justify-content: flex-end;
|
| 156 |
+
}
|
| 157 |
+
|
| 158 |
+
.control-pill {
|
| 159 |
+
min-width: 122px;
|
| 160 |
+
border-radius: 18px;
|
| 161 |
+
padding: 10px 12px;
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
.control-pill label {
|
| 165 |
+
display: block;
|
| 166 |
+
font-size: 11px;
|
| 167 |
+
color: var(--muted);
|
| 168 |
+
margin-bottom: 6px;
|
| 169 |
+
text-transform: uppercase;
|
| 170 |
+
letter-spacing: 0.08em;
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
.control-pill select,
|
| 174 |
+
.control-pill input {
|
| 175 |
+
width: 100%;
|
| 176 |
+
border: 0;
|
| 177 |
+
outline: none;
|
| 178 |
+
background: transparent;
|
| 179 |
+
color: var(--ink);
|
| 180 |
+
}
|
| 181 |
+
|
| 182 |
+
.btn {
|
| 183 |
+
min-height: 48px;
|
| 184 |
+
border-radius: 18px;
|
| 185 |
+
border: 1px solid var(--line);
|
| 186 |
+
padding: 0 18px;
|
| 187 |
+
background:
|
| 188 |
+
linear-gradient(180deg, rgba(255, 255, 255, 0.06), rgba(255, 255, 255, 0.02)),
|
| 189 |
+
rgba(255, 255, 255, 0.03);
|
| 190 |
+
color: var(--ink);
|
| 191 |
+
cursor: pointer;
|
| 192 |
+
display: inline-flex;
|
| 193 |
+
align-items: center;
|
| 194 |
+
justify-content: center;
|
| 195 |
+
gap: 10px;
|
| 196 |
+
transition: transform 160ms ease, border-color 160ms ease, background 160ms ease;
|
| 197 |
+
}
|
| 198 |
+
|
| 199 |
+
.btn:hover {
|
| 200 |
+
transform: translateY(-1px);
|
| 201 |
+
border-color: rgba(255, 255, 255, 0.18);
|
| 202 |
+
}
|
| 203 |
+
|
| 204 |
+
.btn.primary {
|
| 205 |
+
border-color: rgba(138, 181, 255, 0.22);
|
| 206 |
+
background:
|
| 207 |
+
linear-gradient(180deg, rgba(138, 181, 255, 0.24), rgba(138, 181, 255, 0.08)),
|
| 208 |
+
rgba(255, 255, 255, 0.03);
|
| 209 |
+
}
|
| 210 |
+
|
| 211 |
+
.btn.wide {
|
| 212 |
+
width: 100%;
|
| 213 |
+
}
|
| 214 |
+
|
| 215 |
+
.btn.micro {
|
| 216 |
+
min-height: 42px;
|
| 217 |
+
border-radius: 14px;
|
| 218 |
+
}
|
| 219 |
+
|
| 220 |
+
.btn:disabled {
|
| 221 |
+
opacity: 0.58;
|
| 222 |
+
cursor: not-allowed;
|
| 223 |
+
transform: none;
|
| 224 |
+
}
|
| 225 |
+
|
| 226 |
+
.tabbar {
|
| 227 |
+
width: min(1460px, calc(100% - 24px));
|
| 228 |
+
margin: 14px auto 0;
|
| 229 |
+
border-radius: 24px;
|
| 230 |
+
padding: 14px 18px 18px;
|
| 231 |
+
}
|
| 232 |
+
|
| 233 |
+
.tab {
|
| 234 |
+
min-height: 44px;
|
| 235 |
+
border-radius: 999px;
|
| 236 |
+
border: 1px solid var(--line);
|
| 237 |
+
padding: 0 16px;
|
| 238 |
+
margin-right: 10px;
|
| 239 |
+
background: rgba(255, 255, 255, 0.03);
|
| 240 |
+
color: var(--ink);
|
| 241 |
+
cursor: pointer;
|
| 242 |
+
}
|
| 243 |
+
|
| 244 |
+
.tab.active {
|
| 245 |
+
background:
|
| 246 |
+
linear-gradient(180deg, rgba(138, 181, 255, 0.2), rgba(138, 181, 255, 0.08)),
|
| 247 |
+
rgba(255, 255, 255, 0.04);
|
| 248 |
+
border-color: rgba(138, 181, 255, 0.28);
|
| 249 |
+
}
|
| 250 |
+
|
| 251 |
+
.tab-copy {
|
| 252 |
+
margin: 14px 4px 0;
|
| 253 |
+
max-width: 900px;
|
| 254 |
+
line-height: 1.5;
|
| 255 |
+
}
|
| 256 |
+
|
| 257 |
+
.viewport {
|
| 258 |
+
width: min(1460px, calc(100% - 24px));
|
| 259 |
+
margin: 18px auto 60px;
|
| 260 |
+
display: grid;
|
| 261 |
+
gap: 18px;
|
| 262 |
+
}
|
| 263 |
+
|
| 264 |
+
.viewport-overview {
|
| 265 |
+
grid-template-columns: minmax(420px, 1.05fr) minmax(360px, 0.95fr);
|
| 266 |
+
grid-template-areas:
|
| 267 |
+
"hero hero"
|
| 268 |
+
"architecture architecture"
|
| 269 |
+
"story proof";
|
| 270 |
+
}
|
| 271 |
+
|
| 272 |
+
.viewport-playground {
|
| 273 |
+
grid-template-columns: minmax(520px, 1.14fr) minmax(360px, 0.86fr);
|
| 274 |
+
grid-template-areas:
|
| 275 |
+
"hero hero"
|
| 276 |
+
"mission controls"
|
| 277 |
+
"theater payloads"
|
| 278 |
+
"recorder payloads";
|
| 279 |
+
}
|
| 280 |
+
|
| 281 |
+
.viewport-judge {
|
| 282 |
+
grid-template-columns: minmax(460px, 1.02fr) minmax(360px, 0.98fr);
|
| 283 |
+
grid-template-areas:
|
| 284 |
+
"hero hero"
|
| 285 |
+
"story proof"
|
| 286 |
+
"theater judge"
|
| 287 |
+
"mission judge";
|
| 288 |
+
}
|
| 289 |
+
|
| 290 |
+
.section {
|
| 291 |
+
border-radius: 30px;
|
| 292 |
+
padding: 22px;
|
| 293 |
+
}
|
| 294 |
+
|
| 295 |
+
.hero-surface {
|
| 296 |
+
grid-area: hero;
|
| 297 |
+
display: grid;
|
| 298 |
+
grid-template-columns: minmax(340px, 1.08fr) minmax(320px, 0.92fr);
|
| 299 |
+
gap: 24px;
|
| 300 |
+
align-items: center;
|
| 301 |
+
}
|
| 302 |
+
|
| 303 |
+
.hero-copy h2 {
|
| 304 |
+
margin: 18px 0 12px;
|
| 305 |
+
font-size: clamp(28px, 4vw, 50px);
|
| 306 |
+
line-height: 1.02;
|
| 307 |
+
max-width: 760px;
|
| 308 |
+
}
|
| 309 |
+
|
| 310 |
+
.hero-copy p {
|
| 311 |
+
max-width: 760px;
|
| 312 |
+
color: #d9e2f8;
|
| 313 |
+
font-size: 16px;
|
| 314 |
+
line-height: 1.7;
|
| 315 |
+
}
|
| 316 |
+
|
| 317 |
+
.badge-row {
|
| 318 |
+
display: flex;
|
| 319 |
+
flex-wrap: wrap;
|
| 320 |
+
gap: 10px;
|
| 321 |
+
}
|
| 322 |
+
|
| 323 |
+
.badge {
|
| 324 |
+
min-height: 32px;
|
| 325 |
+
border-radius: 999px;
|
| 326 |
+
border: 1px solid var(--line);
|
| 327 |
+
padding: 0 12px;
|
| 328 |
+
display: inline-flex;
|
| 329 |
+
align-items: center;
|
| 330 |
+
justify-content: center;
|
| 331 |
+
font-size: 13px;
|
| 332 |
+
color: #d9e1f4;
|
| 333 |
+
}
|
| 334 |
+
|
| 335 |
+
.badge.ghost {
|
| 336 |
+
background: rgba(255, 255, 255, 0.04);
|
| 337 |
+
}
|
| 338 |
+
|
| 339 |
+
.badge.warm {
|
| 340 |
+
background: rgba(255, 198, 141, 0.1);
|
| 341 |
+
border-color: rgba(255, 198, 141, 0.22);
|
| 342 |
+
}
|
| 343 |
+
|
| 344 |
+
.metric-strip {
|
| 345 |
+
margin-top: 20px;
|
| 346 |
+
display: grid;
|
| 347 |
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
| 348 |
+
gap: 12px;
|
| 349 |
+
}
|
| 350 |
+
|
| 351 |
+
.metric-card {
|
| 352 |
+
border-radius: 22px;
|
| 353 |
+
padding: 14px 16px;
|
| 354 |
+
display: flex;
|
| 355 |
+
gap: 12px;
|
| 356 |
+
align-items: center;
|
| 357 |
+
}
|
| 358 |
+
|
| 359 |
+
.metric-card span {
|
| 360 |
+
display: block;
|
| 361 |
+
color: var(--muted);
|
| 362 |
+
font-size: 12px;
|
| 363 |
+
}
|
| 364 |
+
|
| 365 |
+
.metric-card strong {
|
| 366 |
+
display: block;
|
| 367 |
+
font-size: 22px;
|
| 368 |
+
margin-top: 4px;
|
| 369 |
+
}
|
| 370 |
+
|
| 371 |
+
.hero-constellation {
|
| 372 |
+
position: relative;
|
| 373 |
+
min-height: 400px;
|
| 374 |
+
border-radius: 28px;
|
| 375 |
+
overflow: hidden;
|
| 376 |
+
background:
|
| 377 |
+
radial-gradient(circle at center, rgba(138, 181, 255, 0.2), transparent 32%),
|
| 378 |
+
linear-gradient(180deg, rgba(255, 255, 255, 0.07), rgba(255, 255, 255, 0.02)),
|
| 379 |
+
rgba(14, 19, 31, 0.74);
|
| 380 |
+
border: 1px solid var(--line);
|
| 381 |
+
}
|
| 382 |
+
|
| 383 |
+
.orb-core {
|
| 384 |
+
position: absolute;
|
| 385 |
+
inset: 50% auto auto 50%;
|
| 386 |
+
width: 170px;
|
| 387 |
+
height: 170px;
|
| 388 |
+
border-radius: 50%;
|
| 389 |
+
transform: translate(-50%, -50%);
|
| 390 |
+
background:
|
| 391 |
+
radial-gradient(circle at 35% 30%, rgba(255, 255, 255, 0.85), transparent 16%),
|
| 392 |
+
radial-gradient(circle at center, rgba(138, 181, 255, 0.62), rgba(123, 225, 215, 0.18) 44%, transparent 72%);
|
| 393 |
+
filter: blur(1px);
|
| 394 |
+
}
|
| 395 |
+
|
| 396 |
+
.orb-ring {
|
| 397 |
+
position: absolute;
|
| 398 |
+
inset: 50% auto auto 50%;
|
| 399 |
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
| 400 |
+
border-radius: 50%;
|
| 401 |
+
transform: translate(-50%, -50%);
|
| 402 |
+
}
|
| 403 |
+
|
| 404 |
+
.ring-a {
|
| 405 |
+
width: 300px;
|
| 406 |
+
height: 300px;
|
| 407 |
+
}
|
| 408 |
+
|
| 409 |
+
.ring-b {
|
| 410 |
+
width: 420px;
|
| 411 |
+
height: 420px;
|
| 412 |
+
}
|
| 413 |
+
|
| 414 |
+
.hero-node {
|
| 415 |
+
position: absolute;
|
| 416 |
+
min-width: 110px;
|
| 417 |
+
border-radius: 18px;
|
| 418 |
+
padding: 12px 14px;
|
| 419 |
+
border: 1px solid var(--line);
|
| 420 |
+
background:
|
| 421 |
+
linear-gradient(180deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.02)),
|
| 422 |
+
rgba(15, 20, 32, 0.74);
|
| 423 |
+
display: inline-flex;
|
| 424 |
+
align-items: center;
|
| 425 |
+
gap: 8px;
|
| 426 |
+
justify-content: center;
|
| 427 |
+
}
|
| 428 |
+
|
| 429 |
+
.hero-node span {
|
| 430 |
+
color: #eef3ff;
|
| 431 |
+
}
|
| 432 |
+
|
| 433 |
+
.hero-node-main {
|
| 434 |
+
left: 50%;
|
| 435 |
+
top: 49%;
|
| 436 |
+
transform: translate(-50%, -50%);
|
| 437 |
+
min-width: 160px;
|
| 438 |
+
z-index: 2;
|
| 439 |
+
}
|
| 440 |
+
|
| 441 |
+
.hero-node-1 { top: 14%; left: 18%; }
|
| 442 |
+
.hero-node-2 { top: 20%; right: 12%; }
|
| 443 |
+
.hero-node-3 { bottom: 18%; left: 14%; }
|
| 444 |
+
.hero-node-4 { bottom: 16%; right: 16%; }
|
| 445 |
+
.hero-node-5 { top: 60%; right: 4%; }
|
| 446 |
+
|
| 447 |
+
.architecture { grid-area: architecture; }
|
| 448 |
+
.story { grid-area: story; }
|
| 449 |
+
.proof { grid-area: proof; }
|
| 450 |
+
.mission { grid-area: mission; }
|
| 451 |
+
.theater { grid-area: theater; }
|
| 452 |
+
.controls-panel { grid-area: controls; }
|
| 453 |
+
.payloads { grid-area: payloads; }
|
| 454 |
+
.recorder { grid-area: recorder; }
|
| 455 |
+
.judge { grid-area: judge; }
|
| 456 |
+
|
| 457 |
+
.section-head {
|
| 458 |
+
margin-bottom: 18px;
|
| 459 |
+
}
|
| 460 |
+
|
| 461 |
+
.section-head span {
|
| 462 |
+
display: block;
|
| 463 |
+
margin-bottom: 8px;
|
| 464 |
+
font-size: 12px;
|
| 465 |
+
text-transform: uppercase;
|
| 466 |
+
letter-spacing: 0.12em;
|
| 467 |
+
}
|
| 468 |
+
|
| 469 |
+
.section-head h3 {
|
| 470 |
+
margin: 0;
|
| 471 |
+
font-size: 28px;
|
| 472 |
+
}
|
| 473 |
+
|
| 474 |
+
.architecture-grid,
|
| 475 |
+
.story-grid,
|
| 476 |
+
.proof-grid,
|
| 477 |
+
.payload-grid,
|
| 478 |
+
.mission-grid,
|
| 479 |
+
.judge-sequence {
|
| 480 |
+
display: grid;
|
| 481 |
+
gap: 14px;
|
| 482 |
+
}
|
| 483 |
+
|
| 484 |
+
.architecture-grid {
|
| 485 |
+
grid-template-columns: repeat(4, minmax(0, 1fr));
|
| 486 |
+
}
|
| 487 |
+
|
| 488 |
+
.architecture-card {
|
| 489 |
+
border-radius: 22px;
|
| 490 |
+
padding: 18px;
|
| 491 |
+
}
|
| 492 |
+
|
| 493 |
+
.architecture-card strong {
|
| 494 |
+
display: block;
|
| 495 |
+
margin: 14px 0 8px;
|
| 496 |
+
font-size: 18px;
|
| 497 |
+
}
|
| 498 |
+
|
| 499 |
+
.story-grid {
|
| 500 |
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
| 501 |
+
}
|
| 502 |
+
|
| 503 |
+
.story-lane {
|
| 504 |
+
border-radius: 24px;
|
| 505 |
+
padding: 18px;
|
| 506 |
+
}
|
| 507 |
+
|
| 508 |
+
.story-lane.before {
|
| 509 |
+
background:
|
| 510 |
+
linear-gradient(180deg, rgba(255, 143, 159, 0.14), rgba(255, 143, 159, 0.05)),
|
| 511 |
+
rgba(18, 24, 40, 0.72);
|
| 512 |
+
}
|
| 513 |
+
|
| 514 |
+
.story-lane.after {
|
| 515 |
+
background:
|
| 516 |
+
linear-gradient(180deg, rgba(138, 181, 255, 0.14), rgba(123, 225, 215, 0.06)),
|
| 517 |
+
rgba(18, 24, 40, 0.72);
|
| 518 |
+
}
|
| 519 |
+
|
| 520 |
+
.story-header {
|
| 521 |
+
display: grid;
|
| 522 |
+
gap: 10px;
|
| 523 |
+
margin-bottom: 14px;
|
| 524 |
+
}
|
| 525 |
+
|
| 526 |
+
.story-label {
|
| 527 |
+
width: fit-content;
|
| 528 |
+
min-height: 30px;
|
| 529 |
+
border-radius: 999px;
|
| 530 |
+
padding: 0 12px;
|
| 531 |
+
display: inline-flex;
|
| 532 |
+
align-items: center;
|
| 533 |
+
border: 1px solid var(--line);
|
| 534 |
+
background: rgba(255, 255, 255, 0.04);
|
| 535 |
+
color: #eaf0ff;
|
| 536 |
+
}
|
| 537 |
+
|
| 538 |
+
.story-header strong {
|
| 539 |
+
font-size: 20px;
|
| 540 |
+
}
|
| 541 |
+
|
| 542 |
+
.story-steps {
|
| 543 |
+
display: grid;
|
| 544 |
+
gap: 10px;
|
| 545 |
+
}
|
| 546 |
+
|
| 547 |
+
.story-step {
|
| 548 |
+
border-radius: 18px;
|
| 549 |
+
padding: 14px;
|
| 550 |
+
background: rgba(8, 12, 20, 0.42);
|
| 551 |
+
}
|
| 552 |
+
|
| 553 |
+
.proof-grid {
|
| 554 |
+
grid-template-columns: minmax(280px, 0.95fr) minmax(300px, 1.05fr);
|
| 555 |
+
}
|
| 556 |
+
|
| 557 |
+
.proof-list {
|
| 558 |
+
display: grid;
|
| 559 |
+
gap: 12px;
|
| 560 |
+
}
|
| 561 |
+
|
| 562 |
+
.proof-row {
|
| 563 |
+
display: grid;
|
| 564 |
+
grid-template-columns: 92px 1fr 54px;
|
| 565 |
+
align-items: center;
|
| 566 |
+
gap: 12px;
|
| 567 |
+
}
|
| 568 |
+
|
| 569 |
+
.proof-meter {
|
| 570 |
+
height: 12px;
|
| 571 |
+
border-radius: 999px;
|
| 572 |
+
background: rgba(255, 255, 255, 0.08);
|
| 573 |
+
overflow: hidden;
|
| 574 |
+
}
|
| 575 |
+
|
| 576 |
+
.proof-meter span {
|
| 577 |
+
display: block;
|
| 578 |
+
height: 100%;
|
| 579 |
+
border-radius: inherit;
|
| 580 |
+
}
|
| 581 |
+
|
| 582 |
+
.tone-bad { background: linear-gradient(90deg, #ff8f9f, #ffb07c); }
|
| 583 |
+
.tone-neutral { background: linear-gradient(90deg, #8ab5ff, #b19dff); }
|
| 584 |
+
.tone-good { background: linear-gradient(90deg, #7be1d7, #8ab5ff); }
|
| 585 |
+
.tone-warm { background: linear-gradient(90deg, #ffc68d, #ff8f9f); }
|
| 586 |
+
|
| 587 |
+
.chart-card {
|
| 588 |
+
border-radius: 24px;
|
| 589 |
+
padding: 14px;
|
| 590 |
+
border: 1px solid rgba(255, 255, 255, 0.16);
|
| 591 |
+
background:
|
| 592 |
+
linear-gradient(180deg, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0.04)),
|
| 593 |
+
rgba(247, 249, 255, 0.94);
|
| 594 |
+
}
|
| 595 |
+
|
| 596 |
+
.chart-card img {
|
| 597 |
+
width: 100%;
|
| 598 |
+
display: block;
|
| 599 |
+
border-radius: 14px;
|
| 600 |
+
}
|
| 601 |
+
|
| 602 |
+
.mission-grid {
|
| 603 |
+
grid-template-columns: repeat(4, minmax(0, 1fr));
|
| 604 |
+
}
|
| 605 |
+
|
| 606 |
+
.stat-box {
|
| 607 |
+
border-radius: 18px;
|
| 608 |
+
padding: 16px;
|
| 609 |
+
}
|
| 610 |
+
|
| 611 |
+
.stat-box strong {
|
| 612 |
+
display: block;
|
| 613 |
+
margin-top: 8px;
|
| 614 |
+
font-size: 24px;
|
| 615 |
+
}
|
| 616 |
+
|
| 617 |
+
.subtask-card {
|
| 618 |
+
border-radius: 24px;
|
| 619 |
+
padding: 18px;
|
| 620 |
+
margin-top: 14px;
|
| 621 |
+
}
|
| 622 |
+
|
| 623 |
+
.subtask-head {
|
| 624 |
+
display: flex;
|
| 625 |
+
justify-content: space-between;
|
| 626 |
+
gap: 12px;
|
| 627 |
+
align-items: center;
|
| 628 |
+
}
|
| 629 |
+
|
| 630 |
+
.subtask-head strong {
|
| 631 |
+
font-size: 14px;
|
| 632 |
+
}
|
| 633 |
+
|
| 634 |
+
.subtask-card p {
|
| 635 |
+
margin: 14px 0 0;
|
| 636 |
+
line-height: 1.6;
|
| 637 |
+
}
|
| 638 |
+
|
| 639 |
+
.theater-stage {
|
| 640 |
+
display: grid;
|
| 641 |
+
grid-template-columns: repeat(5, minmax(0, 1fr));
|
| 642 |
+
gap: 12px;
|
| 643 |
+
}
|
| 644 |
+
|
| 645 |
+
.specialist-node {
|
| 646 |
+
border-radius: 22px;
|
| 647 |
+
padding: 16px;
|
| 648 |
+
}
|
| 649 |
+
|
| 650 |
+
.specialist-node.active {
|
| 651 |
+
border-color: rgba(138, 181, 255, 0.28);
|
| 652 |
+
}
|
| 653 |
+
|
| 654 |
+
.specialist-top,
|
| 655 |
+
.subtask-head {
|
| 656 |
+
color: #f7faff;
|
| 657 |
+
}
|
| 658 |
+
|
| 659 |
+
.specialist-top {
|
| 660 |
+
display: flex;
|
| 661 |
+
justify-content: space-between;
|
| 662 |
+
gap: 8px;
|
| 663 |
+
}
|
| 664 |
+
|
| 665 |
+
.meter {
|
| 666 |
+
height: 10px;
|
| 667 |
+
border-radius: 999px;
|
| 668 |
+
margin: 16px 0 12px;
|
| 669 |
+
background: rgba(255, 255, 255, 0.08);
|
| 670 |
+
overflow: hidden;
|
| 671 |
+
}
|
| 672 |
+
|
| 673 |
+
.meter span {
|
| 674 |
+
display: block;
|
| 675 |
+
height: 100%;
|
| 676 |
+
border-radius: inherit;
|
| 677 |
+
}
|
| 678 |
+
|
| 679 |
+
.specialist-foot {
|
| 680 |
+
color: var(--muted);
|
| 681 |
+
font-size: 13px;
|
| 682 |
+
}
|
| 683 |
+
|
| 684 |
+
.action-stack {
|
| 685 |
+
display: grid;
|
| 686 |
+
gap: 14px;
|
| 687 |
+
}
|
| 688 |
+
|
| 689 |
+
.micro-actions {
|
| 690 |
+
display: grid;
|
| 691 |
+
gap: 10px;
|
| 692 |
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
| 693 |
+
}
|
| 694 |
+
|
| 695 |
+
.payload-grid {
|
| 696 |
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
| 697 |
+
}
|
| 698 |
+
|
| 699 |
+
.json-card {
|
| 700 |
+
border-radius: 22px;
|
| 701 |
+
overflow: hidden;
|
| 702 |
+
}
|
| 703 |
+
|
| 704 |
+
.json-head {
|
| 705 |
+
padding: 14px 16px;
|
| 706 |
+
border-bottom: 1px solid var(--line);
|
| 707 |
+
}
|
| 708 |
+
|
| 709 |
+
.json-card pre {
|
| 710 |
+
margin: 0;
|
| 711 |
+
padding: 16px;
|
| 712 |
+
max-height: 340px;
|
| 713 |
+
overflow: auto;
|
| 714 |
+
color: #d8e4ff;
|
| 715 |
+
font-size: 12px;
|
| 716 |
+
line-height: 1.55;
|
| 717 |
+
font-family:
|
| 718 |
+
ui-monospace,
|
| 719 |
+
SFMono-Regular,
|
| 720 |
+
Menlo,
|
| 721 |
+
Monaco,
|
| 722 |
+
Consolas,
|
| 723 |
+
"Liberation Mono",
|
| 724 |
+
monospace;
|
| 725 |
+
}
|
| 726 |
+
|
| 727 |
+
.event-list {
|
| 728 |
+
display: grid;
|
| 729 |
+
gap: 10px;
|
| 730 |
+
}
|
| 731 |
+
|
| 732 |
+
.event-row {
|
| 733 |
+
border-radius: 18px;
|
| 734 |
+
padding: 14px;
|
| 735 |
+
display: grid;
|
| 736 |
+
grid-template-columns: 58px 1fr 54px;
|
| 737 |
+
gap: 12px;
|
| 738 |
+
align-items: start;
|
| 739 |
+
}
|
| 740 |
+
|
| 741 |
+
.event-step,
|
| 742 |
+
.event-reward {
|
| 743 |
+
color: #ecf2ff;
|
| 744 |
+
font-weight: 700;
|
| 745 |
+
}
|
| 746 |
+
|
| 747 |
+
.event-copy strong,
|
| 748 |
+
.judge-card strong {
|
| 749 |
+
display: block;
|
| 750 |
+
margin-bottom: 6px;
|
| 751 |
+
color: #f7fbff;
|
| 752 |
+
}
|
| 753 |
+
|
| 754 |
+
.judge-sequence {
|
| 755 |
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
| 756 |
+
}
|
| 757 |
+
|
| 758 |
+
.judge-card {
|
| 759 |
+
border-radius: 24px;
|
| 760 |
+
padding: 18px;
|
| 761 |
+
}
|
| 762 |
+
|
| 763 |
+
@media (max-width: 1100px) {
|
| 764 |
+
.topbar,
|
| 765 |
+
.hero-surface,
|
| 766 |
+
.proof-grid,
|
| 767 |
+
.story-grid,
|
| 768 |
+
.architecture-grid,
|
| 769 |
+
.payload-grid,
|
| 770 |
+
.mission-grid,
|
| 771 |
+
.judge-sequence {
|
| 772 |
+
grid-template-columns: 1fr;
|
| 773 |
+
}
|
| 774 |
+
|
| 775 |
+
.viewport-overview,
|
| 776 |
+
.viewport-playground,
|
| 777 |
+
.viewport-judge {
|
| 778 |
+
grid-template-columns: 1fr;
|
| 779 |
+
grid-template-areas:
|
| 780 |
+
"hero"
|
| 781 |
+
"architecture"
|
| 782 |
+
"story"
|
| 783 |
+
"proof"
|
| 784 |
+
"mission"
|
| 785 |
+
"controls"
|
| 786 |
+
"theater"
|
| 787 |
+
"payloads"
|
| 788 |
+
"recorder"
|
| 789 |
+
"judge";
|
| 790 |
+
}
|
| 791 |
+
|
| 792 |
+
.theater-stage {
|
| 793 |
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
| 794 |
+
}
|
| 795 |
+
}
|
| 796 |
+
|
| 797 |
+
@media (max-width: 720px) {
|
| 798 |
+
.topbar {
|
| 799 |
+
grid-template-columns: 1fr;
|
| 800 |
+
}
|
| 801 |
+
|
| 802 |
+
.controls,
|
| 803 |
+
.badge-row,
|
| 804 |
+
.micro-actions,
|
| 805 |
+
.theater-stage {
|
| 806 |
+
grid-template-columns: 1fr;
|
| 807 |
+
}
|
| 808 |
+
|
| 809 |
+
.controls {
|
| 810 |
+
justify-content: flex-start;
|
| 811 |
+
}
|
| 812 |
+
|
| 813 |
+
.metric-strip,
|
| 814 |
+
.payload-grid,
|
| 815 |
+
.mission-grid,
|
| 816 |
+
.judge-sequence {
|
| 817 |
+
grid-template-columns: 1fr;
|
| 818 |
+
}
|
| 819 |
+
|
| 820 |
+
.event-row,
|
| 821 |
+
.proof-row {
|
| 822 |
+
grid-template-columns: 1fr;
|
| 823 |
+
}
|
| 824 |
+
|
| 825 |
+
.hero-constellation {
|
| 826 |
+
min-height: 320px;
|
| 827 |
+
}
|
| 828 |
+
|
| 829 |
+
.hero-node-1,
|
| 830 |
+
.hero-node-2,
|
| 831 |
+
.hero-node-3,
|
| 832 |
+
.hero-node-4,
|
| 833 |
+
.hero-node-5 {
|
| 834 |
+
position: static;
|
| 835 |
+
margin: 10px;
|
| 836 |
+
}
|
| 837 |
+
}
|
ui/app/layout.tsx
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import "./globals.css";
|
| 2 |
+
import type { Metadata } from "next";
|
| 3 |
+
|
| 4 |
+
export const metadata: Metadata = {
|
| 5 |
+
title: "SENTINEL",
|
| 6 |
+
description:
|
| 7 |
+
"Trust-calibration environment for long-horizon multi-agent RL training."
|
| 8 |
+
};
|
| 9 |
+
|
| 10 |
+
export default function RootLayout({
|
| 11 |
+
children
|
| 12 |
+
}: Readonly<{
|
| 13 |
+
children: React.ReactNode;
|
| 14 |
+
}>) {
|
| 15 |
+
return (
|
| 16 |
+
<html lang="en">
|
| 17 |
+
<body>{children}</body>
|
| 18 |
+
</html>
|
| 19 |
+
);
|
| 20 |
+
}
|
ui/app/page.tsx
ADDED
|
@@ -0,0 +1,917 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use client";
|
| 2 |
+
|
| 3 |
+
import { useEffect, useMemo, useState } from "react";
|
| 4 |
+
import { AnimatePresence, motion } from "framer-motion";
|
| 5 |
+
import {
|
| 6 |
+
Activity,
|
| 7 |
+
ArrowRight,
|
| 8 |
+
Brain,
|
| 9 |
+
CircleGauge,
|
| 10 |
+
Cpu,
|
| 11 |
+
Eye,
|
| 12 |
+
Radar,
|
| 13 |
+
ShieldAlert,
|
| 14 |
+
Sparkles,
|
| 15 |
+
SplitSquareHorizontal,
|
| 16 |
+
Waves
|
| 17 |
+
} from "lucide-react";
|
| 18 |
+
|
| 19 |
+
type ViewMode = "overview" | "playground" | "judge";
|
| 20 |
+
type TaskType = "task1" | "task2" | "task3";
|
| 21 |
+
type ActionType = "delegate" | "verify" | "solve_independently" | "skip";
|
| 22 |
+
|
| 23 |
+
type Observation = {
|
| 24 |
+
session_id: string;
|
| 25 |
+
scenario_id: string;
|
| 26 |
+
task_type: TaskType;
|
| 27 |
+
difficulty: string;
|
| 28 |
+
task_description: string;
|
| 29 |
+
current_subtask: string;
|
| 30 |
+
subtask_index: number;
|
| 31 |
+
subtasks_total: number;
|
| 32 |
+
subtasks_remaining: number;
|
| 33 |
+
available_specialists: string[];
|
| 34 |
+
trust_snapshot: Record<string, number>;
|
| 35 |
+
stakes_level: number;
|
| 36 |
+
step_count: number;
|
| 37 |
+
max_steps: number;
|
| 38 |
+
last_action_summary: string | null;
|
| 39 |
+
last_reward: number;
|
| 40 |
+
episode_status: string;
|
| 41 |
+
};
|
| 42 |
+
|
| 43 |
+
type Reward = {
|
| 44 |
+
value: number;
|
| 45 |
+
reason: string;
|
| 46 |
+
signal_breakdown?: Record<string, number>;
|
| 47 |
+
};
|
| 48 |
+
|
| 49 |
+
type StepResult = {
|
| 50 |
+
observation: Observation;
|
| 51 |
+
reward: Reward;
|
| 52 |
+
done: boolean;
|
| 53 |
+
info: {
|
| 54 |
+
session_id: string;
|
| 55 |
+
step_count: number;
|
| 56 |
+
max_steps: number;
|
| 57 |
+
total_reward: number;
|
| 58 |
+
score: number;
|
| 59 |
+
adversarial_detections?: number;
|
| 60 |
+
adversarial_poisonings?: number;
|
| 61 |
+
};
|
| 62 |
+
};
|
| 63 |
+
|
| 64 |
+
type EvalSummary = {
|
| 65 |
+
avg_score: number;
|
| 66 |
+
avg_completion_rate: number;
|
| 67 |
+
avg_detection_rate: number;
|
| 68 |
+
avg_trust_calibration: number;
|
| 69 |
+
avg_steps: number;
|
| 70 |
+
};
|
| 71 |
+
|
| 72 |
+
type EvaluationData = {
|
| 73 |
+
summary: {
|
| 74 |
+
random: EvalSummary;
|
| 75 |
+
heuristic: EvalSummary;
|
| 76 |
+
oracle_lite: EvalSummary;
|
| 77 |
+
};
|
| 78 |
+
by_task: {
|
| 79 |
+
task1: Record<string, EvalSummary>;
|
| 80 |
+
task2: Record<string, EvalSummary>;
|
| 81 |
+
task3: Record<string, EvalSummary>;
|
| 82 |
+
};
|
| 83 |
+
};
|
| 84 |
+
|
| 85 |
+
type EventItem = {
|
| 86 |
+
step: number;
|
| 87 |
+
action: string;
|
| 88 |
+
summary: string;
|
| 89 |
+
reward: string;
|
| 90 |
+
};
|
| 91 |
+
|
| 92 |
+
const tabs: { id: ViewMode; label: string; copy: string }[] = [
|
| 93 |
+
{
|
| 94 |
+
id: "overview",
|
| 95 |
+
label: "Overview",
|
| 96 |
+
copy:
|
| 97 |
+
"A product-style explanation of why SENTINEL exists, what it teaches, and how reward proves learning."
|
| 98 |
+
},
|
| 99 |
+
{
|
| 100 |
+
id: "playground",
|
| 101 |
+
label: "Playground",
|
| 102 |
+
copy:
|
| 103 |
+
"A live browser-facing mission surface where every trust change, request, response, and step result stays visible."
|
| 104 |
+
},
|
| 105 |
+
{
|
| 106 |
+
id: "judge",
|
| 107 |
+
label: "Judge Demo",
|
| 108 |
+
copy:
|
| 109 |
+
"A tighter pitch mode: show the baseline failure, the calibrated recovery, then the profile swap that proves generalization."
|
| 110 |
+
}
|
| 111 |
+
];
|
| 112 |
+
|
| 113 |
+
const taskOptions: { value: TaskType; label: string }[] = [
|
| 114 |
+
{ value: "task1", label: "Task 1" },
|
| 115 |
+
{ value: "task2", label: "Task 2" },
|
| 116 |
+
{ value: "task3", label: "Task 3" }
|
| 117 |
+
];
|
| 118 |
+
|
| 119 |
+
const architectureCards = [
|
| 120 |
+
{
|
| 121 |
+
icon: Brain,
|
| 122 |
+
title: "Orchestrator",
|
| 123 |
+
copy:
|
| 124 |
+
"One public-facing decision maker learns trust, verification, and recovery from behavior alone."
|
| 125 |
+
},
|
| 126 |
+
{
|
| 127 |
+
icon: SplitSquareHorizontal,
|
| 128 |
+
title: "Shuffled Specialists",
|
| 129 |
+
copy:
|
| 130 |
+
"Public slots stay the same. Hidden specialist profiles reshuffle every reset, so identity memorization breaks."
|
| 131 |
+
},
|
| 132 |
+
{
|
| 133 |
+
icon: CircleGauge,
|
| 134 |
+
title: "Trust Ledger",
|
| 135 |
+
copy:
|
| 136 |
+
"Bayesian trust updates convert observed behavior into reusable routing signal across the episode."
|
| 137 |
+
},
|
| 138 |
+
{
|
| 139 |
+
icon: ShieldAlert,
|
| 140 |
+
title: "Reward Engine",
|
| 141 |
+
copy:
|
| 142 |
+
"Completion, adversarial detection, calibration, and efficiency form a reward the agent cannot cheaply hack."
|
| 143 |
+
}
|
| 144 |
+
];
|
| 145 |
+
|
| 146 |
+
function formatScore(value: number | undefined) {
|
| 147 |
+
return typeof value === "number" ? value.toFixed(3) : "0.000";
|
| 148 |
+
}
|
| 149 |
+
|
| 150 |
+
function trustColor(value: number) {
|
| 151 |
+
if (value >= 0.72) return "#7CE0D6";
|
| 152 |
+
if (value >= 0.5) return "#8DB5FF";
|
| 153 |
+
if (value >= 0.3) return "#FFC07E";
|
| 154 |
+
return "#FF8B94";
|
| 155 |
+
}
|
| 156 |
+
|
| 157 |
+
function bestSpecialist(obs: Observation | null) {
|
| 158 |
+
if (!obs) return "S0";
|
| 159 |
+
return [...obs.available_specialists].sort(
|
| 160 |
+
(a, b) => (obs.trust_snapshot[b] ?? 0.5) - (obs.trust_snapshot[a] ?? 0.5)
|
| 161 |
+
)[0];
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
function recommendedMove(obs: Observation | null): {
|
| 165 |
+
action: ActionType;
|
| 166 |
+
specialist: string;
|
| 167 |
+
trust: number;
|
| 168 |
+
} {
|
| 169 |
+
if (!obs) {
|
| 170 |
+
return { action: "delegate", specialist: "S0", trust: 0.5 };
|
| 171 |
+
}
|
| 172 |
+
const specialist = bestSpecialist(obs);
|
| 173 |
+
const trust = obs.trust_snapshot[specialist] ?? 0.5;
|
| 174 |
+
if (obs.stakes_level >= 0.7 && trust < 0.65) {
|
| 175 |
+
return { action: "verify", specialist, trust };
|
| 176 |
+
}
|
| 177 |
+
return { action: "delegate", specialist, trust };
|
| 178 |
+
}
|
| 179 |
+
|
| 180 |
+
function randomMove(obs: Observation | null): {
|
| 181 |
+
action: ActionType;
|
| 182 |
+
specialist: string;
|
| 183 |
+
trust: number;
|
| 184 |
+
} {
|
| 185 |
+
if (!obs) {
|
| 186 |
+
return { action: "delegate", specialist: "S0", trust: 0.5 };
|
| 187 |
+
}
|
| 188 |
+
const specialist =
|
| 189 |
+
obs.available_specialists[
|
| 190 |
+
Math.floor(Math.random() * obs.available_specialists.length)
|
| 191 |
+
] || "S0";
|
| 192 |
+
return {
|
| 193 |
+
action: "delegate",
|
| 194 |
+
specialist,
|
| 195 |
+
trust: obs.trust_snapshot[specialist] ?? 0.5
|
| 196 |
+
};
|
| 197 |
+
}
|
| 198 |
+
|
| 199 |
+
export default function Page() {
|
| 200 |
+
const [view, setView] = useState<ViewMode>("overview");
|
| 201 |
+
const [taskType, setTaskType] = useState<TaskType>("task3");
|
| 202 |
+
const [seed, setSeed] = useState(42);
|
| 203 |
+
const [sessionId, setSessionId] = useState<string | null>(null);
|
| 204 |
+
const [result, setResult] = useState<StepResult | null>(null);
|
| 205 |
+
const [running, setRunning] = useState(false);
|
| 206 |
+
const [events, setEvents] = useState<EventItem[]>([]);
|
| 207 |
+
const [lastRequest, setLastRequest] = useState<Record<string, unknown> | null>(
|
| 208 |
+
null
|
| 209 |
+
);
|
| 210 |
+
const [lastResponse, setLastResponse] = useState<Record<string, unknown> | null>(
|
| 211 |
+
null
|
| 212 |
+
);
|
| 213 |
+
const [evaluation, setEvaluation] = useState<EvaluationData | null>(null);
|
| 214 |
+
const [demoPolicy, setDemoPolicy] = useState<"heuristic" | "random">(
|
| 215 |
+
"heuristic"
|
| 216 |
+
);
|
| 217 |
+
|
| 218 |
+
useEffect(() => {
|
| 219 |
+
fetch("/assets/evaluation_results.json")
|
| 220 |
+
.then((res) => res.json())
|
| 221 |
+
.then(setEvaluation)
|
| 222 |
+
.catch(() => null);
|
| 223 |
+
}, []);
|
| 224 |
+
|
| 225 |
+
useEffect(() => {
|
| 226 |
+
void resetEpisode(taskType, seed);
|
| 227 |
+
}, []);
|
| 228 |
+
|
| 229 |
+
const observation = result?.observation ?? null;
|
| 230 |
+
const info = result?.info;
|
| 231 |
+
const reward = result?.reward;
|
| 232 |
+
const move = recommendedMove(observation);
|
| 233 |
+
|
| 234 |
+
const proof = useMemo(() => {
|
| 235 |
+
if (!evaluation) return null;
|
| 236 |
+
return {
|
| 237 |
+
random: evaluation.summary.random,
|
| 238 |
+
heuristic: evaluation.summary.heuristic,
|
| 239 |
+
oracle: evaluation.summary.oracle_lite,
|
| 240 |
+
task3Random: evaluation.by_task.task3.random,
|
| 241 |
+
task3Heuristic: evaluation.by_task.task3.heuristic
|
| 242 |
+
};
|
| 243 |
+
}, [evaluation]);
|
| 244 |
+
|
| 245 |
+
async function resetEpisode(
|
| 246 |
+
nextTask = taskType,
|
| 247 |
+
nextSeed = seed
|
| 248 |
+
): Promise<StepResult | null> {
|
| 249 |
+
setRunning(true);
|
| 250 |
+
const payload = { task_type: nextTask, seed: nextSeed };
|
| 251 |
+
setLastRequest({ method: "POST", path: "/reset", body: payload });
|
| 252 |
+
try {
|
| 253 |
+
const res = await fetch("/reset", {
|
| 254 |
+
method: "POST",
|
| 255 |
+
headers: { "Content-Type": "application/json" },
|
| 256 |
+
body: JSON.stringify(payload)
|
| 257 |
+
});
|
| 258 |
+
const data = (await res.json()) as StepResult;
|
| 259 |
+
setResult(data);
|
| 260 |
+
setLastResponse(data as unknown as Record<string, unknown>);
|
| 261 |
+
setSessionId(data.info.session_id);
|
| 262 |
+
setEvents([
|
| 263 |
+
{
|
| 264 |
+
step: 0,
|
| 265 |
+
action: "reset",
|
| 266 |
+
summary: "Episode initialized. Hidden profiles reshuffled.",
|
| 267 |
+
reward: "0.00"
|
| 268 |
+
}
|
| 269 |
+
]);
|
| 270 |
+
return data;
|
| 271 |
+
} finally {
|
| 272 |
+
setRunning(false);
|
| 273 |
+
}
|
| 274 |
+
}
|
| 275 |
+
|
| 276 |
+
async function stepEpisode(
|
| 277 |
+
action: ActionType,
|
| 278 |
+
specialistOverride?: string,
|
| 279 |
+
context?: StepResult | null
|
| 280 |
+
): Promise<StepResult | null> {
|
| 281 |
+
const activeResult = context ?? result;
|
| 282 |
+
const activeObservation = activeResult?.observation ?? observation;
|
| 283 |
+
const activeSessionId = activeResult?.info.session_id ?? sessionId;
|
| 284 |
+
|
| 285 |
+
if (!activeSessionId || !activeObservation || running || activeResult?.done) {
|
| 286 |
+
return null;
|
| 287 |
+
}
|
| 288 |
+
setRunning(true);
|
| 289 |
+
const specialist =
|
| 290 |
+
action === "delegate" || action === "verify"
|
| 291 |
+
? specialistOverride || bestSpecialist(activeObservation)
|
| 292 |
+
: null;
|
| 293 |
+
const payload = {
|
| 294 |
+
session_id: activeSessionId,
|
| 295 |
+
task_type: activeObservation.task_type,
|
| 296 |
+
action_type: action,
|
| 297 |
+
specialist_id: specialist,
|
| 298 |
+
subtask_response: action === "solve_independently" ? "SELF_SOLVED" : null,
|
| 299 |
+
reasoning: `next-ui-${action}${specialist ? `-${specialist}` : ""}`
|
| 300 |
+
};
|
| 301 |
+
setLastRequest({
|
| 302 |
+
method: "POST",
|
| 303 |
+
path: `/step?session_id=${activeSessionId}`,
|
| 304 |
+
body: payload
|
| 305 |
+
});
|
| 306 |
+
try {
|
| 307 |
+
const res = await fetch(
|
| 308 |
+
`/step?session_id=${encodeURIComponent(activeSessionId)}`,
|
| 309 |
+
{
|
| 310 |
+
method: "POST",
|
| 311 |
+
headers: { "Content-Type": "application/json" },
|
| 312 |
+
body: JSON.stringify(payload)
|
| 313 |
+
}
|
| 314 |
+
);
|
| 315 |
+
const data = (await res.json()) as StepResult;
|
| 316 |
+
setResult(data);
|
| 317 |
+
setLastResponse(data as unknown as Record<string, unknown>);
|
| 318 |
+
setEvents((prev) => [
|
| 319 |
+
...prev,
|
| 320 |
+
{
|
| 321 |
+
step: data.info.step_count,
|
| 322 |
+
action: specialist ? `${action}:${specialist}` : action,
|
| 323 |
+
summary: data.reward.reason,
|
| 324 |
+
reward: data.reward.value.toFixed(2)
|
| 325 |
+
}
|
| 326 |
+
]);
|
| 327 |
+
return data;
|
| 328 |
+
} finally {
|
| 329 |
+
setRunning(false);
|
| 330 |
+
}
|
| 331 |
+
}
|
| 332 |
+
|
| 333 |
+
async function autoRun(policy: "heuristic" | "random") {
|
| 334 |
+
setDemoPolicy(policy);
|
| 335 |
+
let localResult = result;
|
| 336 |
+
if (!localResult || localResult.done) {
|
| 337 |
+
localResult = await resetEpisode();
|
| 338 |
+
}
|
| 339 |
+
let guard = 0;
|
| 340 |
+
while (!localResult?.done && guard < 70) {
|
| 341 |
+
const obs = localResult?.observation ?? observation;
|
| 342 |
+
const selected =
|
| 343 |
+
policy === "random" ? randomMove(obs) : recommendedMove(obs);
|
| 344 |
+
const nextResult = await stepEpisode(
|
| 345 |
+
selected.action,
|
| 346 |
+
selected.specialist,
|
| 347 |
+
localResult
|
| 348 |
+
);
|
| 349 |
+
guard += 1;
|
| 350 |
+
await new Promise((resolve) => setTimeout(resolve, 130));
|
| 351 |
+
if (!nextResult) break;
|
| 352 |
+
localResult = nextResult;
|
| 353 |
+
}
|
| 354 |
+
}
|
| 355 |
+
|
| 356 |
+
async function swapProfilesAndReplay() {
|
| 357 |
+
const nextSeed = seed + 1;
|
| 358 |
+
setSeed(nextSeed);
|
| 359 |
+
await resetEpisode(taskType, nextSeed);
|
| 360 |
+
await autoRun(demoPolicy);
|
| 361 |
+
}
|
| 362 |
+
|
| 363 |
+
return (
|
| 364 |
+
<div className="sentinel-shell">
|
| 365 |
+
<div className="bg-grid" />
|
| 366 |
+
<header className="topbar">
|
| 367 |
+
<div className="brand">
|
| 368 |
+
<div className="brand-mark">
|
| 369 |
+
<Waves size={18} />
|
| 370 |
+
</div>
|
| 371 |
+
<div>
|
| 372 |
+
<div className="eyebrow">THE_BOYS • OpenEnv Finale Build</div>
|
| 373 |
+
<h1>SENTINEL</h1>
|
| 374 |
+
<p>
|
| 375 |
+
A Next-style mission surface for multi-agent trust calibration,
|
| 376 |
+
adversarial detection, and long-horizon orchestration.
|
| 377 |
+
</p>
|
| 378 |
+
</div>
|
| 379 |
+
</div>
|
| 380 |
+
|
| 381 |
+
<div className="controls">
|
| 382 |
+
<div className="control-pill">
|
| 383 |
+
<label>Task</label>
|
| 384 |
+
<select
|
| 385 |
+
value={taskType}
|
| 386 |
+
onChange={(e) => {
|
| 387 |
+
const next = e.target.value as TaskType;
|
| 388 |
+
setTaskType(next);
|
| 389 |
+
void resetEpisode(next, seed);
|
| 390 |
+
}}
|
| 391 |
+
>
|
| 392 |
+
{taskOptions.map((item) => (
|
| 393 |
+
<option key={item.value} value={item.value}>
|
| 394 |
+
{item.label}
|
| 395 |
+
</option>
|
| 396 |
+
))}
|
| 397 |
+
</select>
|
| 398 |
+
</div>
|
| 399 |
+
<div className="control-pill">
|
| 400 |
+
<label>Seed</label>
|
| 401 |
+
<input
|
| 402 |
+
type="number"
|
| 403 |
+
value={seed}
|
| 404 |
+
onChange={(e) => setSeed(Number(e.target.value || 0))}
|
| 405 |
+
/>
|
| 406 |
+
</div>
|
| 407 |
+
<button className="btn primary" onClick={() => void resetEpisode()}>
|
| 408 |
+
Reset
|
| 409 |
+
</button>
|
| 410 |
+
<button className="btn" onClick={() => void swapProfilesAndReplay()}>
|
| 411 |
+
Swap Profiles
|
| 412 |
+
</button>
|
| 413 |
+
</div>
|
| 414 |
+
</header>
|
| 415 |
+
|
| 416 |
+
<nav className="tabbar">
|
| 417 |
+
{tabs.map((tab) => (
|
| 418 |
+
<button
|
| 419 |
+
key={tab.id}
|
| 420 |
+
className={`tab ${view === tab.id ? "active" : ""}`}
|
| 421 |
+
onClick={() => setView(tab.id)}
|
| 422 |
+
>
|
| 423 |
+
{tab.label}
|
| 424 |
+
</button>
|
| 425 |
+
))}
|
| 426 |
+
<p className="tab-copy">{tabs.find((tab) => tab.id === view)?.copy}</p>
|
| 427 |
+
</nav>
|
| 428 |
+
|
| 429 |
+
<main className={`viewport viewport-${view}`}>
|
| 430 |
+
<section className="hero-panel section hero-surface">
|
| 431 |
+
<div className="hero-copy">
|
| 432 |
+
<div className="badge-row">
|
| 433 |
+
<span className="badge ghost">reset → step → state</span>
|
| 434 |
+
<span className="badge ghost">OpenEnv backend intact</span>
|
| 435 |
+
<span className="badge warm">skill, not identity</span>
|
| 436 |
+
</div>
|
| 437 |
+
<h2>LLMs don't fail only because they reason badly.</h2>
|
| 438 |
+
<p>
|
| 439 |
+
They fail because they trust the wrong agent too early, skip
|
| 440 |
+
verification when the stakes rise, and compound poisoned state
|
| 441 |
+
across long workflows. SENTINEL turns that into a trainable skill.
|
| 442 |
+
</p>
|
| 443 |
+
<div className="metric-strip">
|
| 444 |
+
<MetricCard
|
| 445 |
+
icon={Activity}
|
| 446 |
+
label="Random baseline"
|
| 447 |
+
value={formatScore(proof?.random.avg_score)}
|
| 448 |
+
/>
|
| 449 |
+
<MetricCard
|
| 450 |
+
icon={Radar}
|
| 451 |
+
label="Heuristic baseline"
|
| 452 |
+
value={formatScore(proof?.heuristic.avg_score)}
|
| 453 |
+
/>
|
| 454 |
+
<MetricCard
|
| 455 |
+
icon={ShieldAlert}
|
| 456 |
+
label="Task 3 detect"
|
| 457 |
+
value={formatScore(proof?.task3Heuristic.avg_detection_rate)}
|
| 458 |
+
/>
|
| 459 |
+
</div>
|
| 460 |
+
</div>
|
| 461 |
+
<HeroConstellation observation={observation} />
|
| 462 |
+
</section>
|
| 463 |
+
|
| 464 |
+
{(view === "overview" || view === "judge") && (
|
| 465 |
+
<>
|
| 466 |
+
<section className="section architecture">
|
| 467 |
+
<SectionHead
|
| 468 |
+
eyebrow="Architecture"
|
| 469 |
+
title="What the system is actually made of"
|
| 470 |
+
/>
|
| 471 |
+
<div className="architecture-grid">
|
| 472 |
+
{architectureCards.map((card, index) => (
|
| 473 |
+
<motion.div
|
| 474 |
+
key={card.title}
|
| 475 |
+
className="glass-card architecture-card"
|
| 476 |
+
initial={{ opacity: 0, y: 18 }}
|
| 477 |
+
animate={{ opacity: 1, y: 0 }}
|
| 478 |
+
transition={{ duration: 0.45, delay: index * 0.05 }}
|
| 479 |
+
>
|
| 480 |
+
<card.icon size={18} />
|
| 481 |
+
<strong>{card.title}</strong>
|
| 482 |
+
<span>{card.copy}</span>
|
| 483 |
+
</motion.div>
|
| 484 |
+
))}
|
| 485 |
+
</div>
|
| 486 |
+
</section>
|
| 487 |
+
|
| 488 |
+
<section className="section story">
|
| 489 |
+
<SectionHead
|
| 490 |
+
eyebrow="Before / After"
|
| 491 |
+
title="Why this environment matters to judges"
|
| 492 |
+
/>
|
| 493 |
+
<div className="story-grid">
|
| 494 |
+
<StoryLane
|
| 495 |
+
tone="before"
|
| 496 |
+
label={`Task 3 random ${formatScore(
|
| 497 |
+
proof?.task3Random.avg_score
|
| 498 |
+
)}`}
|
| 499 |
+
title="Without trust calibration"
|
| 500 |
+
steps={[
|
| 501 |
+
"Public slots start close together, so the orchestrator routes with weak evidence.",
|
| 502 |
+
"A high-confidence but wrong specialist can poison a high-stakes node.",
|
| 503 |
+
"That poisoned state propagates across later subtasks before anyone notices.",
|
| 504 |
+
"Detection remains weak and the agent cannot explain which slot became risky."
|
| 505 |
+
]}
|
| 506 |
+
/>
|
| 507 |
+
<StoryLane
|
| 508 |
+
tone="after"
|
| 509 |
+
label={`Task 3 heuristic ${formatScore(
|
| 510 |
+
proof?.task3Heuristic.avg_score
|
| 511 |
+
)}`}
|
| 512 |
+
title="With SENTINEL-style routing"
|
| 513 |
+
steps={[
|
| 514 |
+
"Behavior updates the trust ledger after every step, so public slots diverge fast.",
|
| 515 |
+
"When stakes rise and trust is shaky, the orchestrator switches from delegate to verify.",
|
| 516 |
+
"Adversarial attempts are detected before they cascade into the rest of the workflow.",
|
| 517 |
+
"Profile reshuffle forces evidence-based re-learning, proving skill instead of memorized identity."
|
| 518 |
+
]}
|
| 519 |
+
/>
|
| 520 |
+
</div>
|
| 521 |
+
</section>
|
| 522 |
+
|
| 523 |
+
<section className="section proof">
|
| 524 |
+
<SectionHead
|
| 525 |
+
eyebrow="Reward Proof"
|
| 526 |
+
title="Real baseline numbers from the evaluator"
|
| 527 |
+
/>
|
| 528 |
+
<div className="proof-grid">
|
| 529 |
+
<div className="proof-list">
|
| 530 |
+
<ProofBar
|
| 531 |
+
label="Random"
|
| 532 |
+
value={proof?.random.avg_score}
|
| 533 |
+
tone="bad"
|
| 534 |
+
/>
|
| 535 |
+
<ProofBar
|
| 536 |
+
label="Heuristic"
|
| 537 |
+
value={proof?.heuristic.avg_score}
|
| 538 |
+
tone="neutral"
|
| 539 |
+
/>
|
| 540 |
+
<ProofBar
|
| 541 |
+
label="Oracle-lite"
|
| 542 |
+
value={proof?.oracle.avg_score}
|
| 543 |
+
tone="good"
|
| 544 |
+
/>
|
| 545 |
+
<ProofBar
|
| 546 |
+
label="Task 3 detect"
|
| 547 |
+
value={proof?.task3Heuristic.avg_detection_rate}
|
| 548 |
+
tone="warm"
|
| 549 |
+
/>
|
| 550 |
+
</div>
|
| 551 |
+
<div className="chart-card">
|
| 552 |
+
<img
|
| 553 |
+
src="/assets/baseline_comparison.png"
|
| 554 |
+
alt="Baseline comparison"
|
| 555 |
+
/>
|
| 556 |
+
</div>
|
| 557 |
+
</div>
|
| 558 |
+
</section>
|
| 559 |
+
</>
|
| 560 |
+
)}
|
| 561 |
+
|
| 562 |
+
{(view === "playground" || view === "judge") && (
|
| 563 |
+
<>
|
| 564 |
+
<section className="section mission">
|
| 565 |
+
<SectionHead
|
| 566 |
+
eyebrow="Mission"
|
| 567 |
+
title="Live orchestrator state"
|
| 568 |
+
/>
|
| 569 |
+
<div className="mission-grid">
|
| 570 |
+
<StatBox label="Session" value={sessionId?.slice(0, 8) ?? "—"} />
|
| 571 |
+
<StatBox label="Score" value={formatScore(info?.score)} />
|
| 572 |
+
<StatBox
|
| 573 |
+
label="Budget"
|
| 574 |
+
value={
|
| 575 |
+
observation
|
| 576 |
+
? `${observation.step_count}/${observation.max_steps}`
|
| 577 |
+
: "0/0"
|
| 578 |
+
}
|
| 579 |
+
/>
|
| 580 |
+
<StatBox
|
| 581 |
+
label="Stakes"
|
| 582 |
+
value={
|
| 583 |
+
observation ? observation.stakes_level.toFixed(2) : "0.00"
|
| 584 |
+
}
|
| 585 |
+
/>
|
| 586 |
+
</div>
|
| 587 |
+
<div className="subtask-card">
|
| 588 |
+
<div className="subtask-head">
|
| 589 |
+
<span>Current subtask</span>
|
| 590 |
+
<strong>{move.action}:{move.specialist}</strong>
|
| 591 |
+
</div>
|
| 592 |
+
<p>
|
| 593 |
+
{observation?.current_subtask ??
|
| 594 |
+
"Reset the episode to begin the live flow."}
|
| 595 |
+
</p>
|
| 596 |
+
</div>
|
| 597 |
+
</section>
|
| 598 |
+
|
| 599 |
+
<section className="section theater">
|
| 600 |
+
<SectionHead
|
| 601 |
+
eyebrow="Trust Surface"
|
| 602 |
+
title="Public slots vs hidden risk"
|
| 603 |
+
/>
|
| 604 |
+
<div className="theater-stage">
|
| 605 |
+
{observation?.available_specialists.map((id, index) => {
|
| 606 |
+
const trust = observation.trust_snapshot[id] ?? 0.5;
|
| 607 |
+
return (
|
| 608 |
+
<motion.div
|
| 609 |
+
key={id}
|
| 610 |
+
className={`specialist-node ${
|
| 611 |
+
id === move.specialist ? "active" : ""
|
| 612 |
+
}`}
|
| 613 |
+
initial={{ opacity: 0, y: 14 }}
|
| 614 |
+
animate={{ opacity: 1, y: 0 }}
|
| 615 |
+
transition={{ duration: 0.35, delay: index * 0.05 }}
|
| 616 |
+
>
|
| 617 |
+
<div className="specialist-top">
|
| 618 |
+
<strong>{id}</strong>
|
| 619 |
+
<span>{trust.toFixed(2)}</span>
|
| 620 |
+
</div>
|
| 621 |
+
<div className="meter">
|
| 622 |
+
<span
|
| 623 |
+
style={{
|
| 624 |
+
width: `${trust * 100}%`,
|
| 625 |
+
background: trustColor(trust)
|
| 626 |
+
}}
|
| 627 |
+
/>
|
| 628 |
+
</div>
|
| 629 |
+
<div className="specialist-foot">
|
| 630 |
+
{id === move.specialist ? "Recommended" : "Public slot"}
|
| 631 |
+
</div>
|
| 632 |
+
</motion.div>
|
| 633 |
+
);
|
| 634 |
+
})}
|
| 635 |
+
</div>
|
| 636 |
+
</section>
|
| 637 |
+
|
| 638 |
+
<section className="section controls-panel">
|
| 639 |
+
<SectionHead
|
| 640 |
+
eyebrow="Command"
|
| 641 |
+
title="Run the orchestrator"
|
| 642 |
+
/>
|
| 643 |
+
<div className="action-stack">
|
| 644 |
+
<button
|
| 645 |
+
className="btn primary wide"
|
| 646 |
+
disabled={running}
|
| 647 |
+
onClick={() => void autoRun("heuristic")}
|
| 648 |
+
>
|
| 649 |
+
<Brain size={16} />
|
| 650 |
+
Run Heuristic
|
| 651 |
+
</button>
|
| 652 |
+
<button
|
| 653 |
+
className="btn wide"
|
| 654 |
+
disabled={running}
|
| 655 |
+
onClick={() => void autoRun("random")}
|
| 656 |
+
>
|
| 657 |
+
<Cpu size={16} />
|
| 658 |
+
Run Random
|
| 659 |
+
</button>
|
| 660 |
+
<div className="micro-actions">
|
| 661 |
+
<button
|
| 662 |
+
className="btn micro"
|
| 663 |
+
disabled={running}
|
| 664 |
+
onClick={() => void stepEpisode("delegate", move.specialist)}
|
| 665 |
+
>
|
| 666 |
+
Delegate
|
| 667 |
+
</button>
|
| 668 |
+
<button
|
| 669 |
+
className="btn micro"
|
| 670 |
+
disabled={running}
|
| 671 |
+
onClick={() => void stepEpisode("verify", move.specialist)}
|
| 672 |
+
>
|
| 673 |
+
Verify
|
| 674 |
+
</button>
|
| 675 |
+
<button
|
| 676 |
+
className="btn micro"
|
| 677 |
+
disabled={running}
|
| 678 |
+
onClick={() => void stepEpisode("solve_independently")}
|
| 679 |
+
>
|
| 680 |
+
Self solve
|
| 681 |
+
</button>
|
| 682 |
+
<button
|
| 683 |
+
className="btn micro"
|
| 684 |
+
disabled={running}
|
| 685 |
+
onClick={() => void stepEpisode("skip")}
|
| 686 |
+
>
|
| 687 |
+
Skip
|
| 688 |
+
</button>
|
| 689 |
+
</div>
|
| 690 |
+
</div>
|
| 691 |
+
</section>
|
| 692 |
+
|
| 693 |
+
<section className="section payloads">
|
| 694 |
+
<SectionHead
|
| 695 |
+
eyebrow="Backend Visible"
|
| 696 |
+
title="Request / response playground"
|
| 697 |
+
/>
|
| 698 |
+
<div className="payload-grid">
|
| 699 |
+
<JsonCard title="Last request" data={lastRequest} />
|
| 700 |
+
<JsonCard title="Last response" data={lastResponse} />
|
| 701 |
+
</div>
|
| 702 |
+
</section>
|
| 703 |
+
|
| 704 |
+
<section className="section recorder">
|
| 705 |
+
<SectionHead
|
| 706 |
+
eyebrow="Flight Recorder"
|
| 707 |
+
title="Event trail"
|
| 708 |
+
/>
|
| 709 |
+
<div className="event-list">
|
| 710 |
+
{events.slice(-8).reverse().map((event) => (
|
| 711 |
+
<div className="event-row" key={`${event.step}-${event.action}`}>
|
| 712 |
+
<div className="event-step">#{event.step}</div>
|
| 713 |
+
<div className="event-copy">
|
| 714 |
+
<strong>{event.action}</strong>
|
| 715 |
+
<span>{event.summary}</span>
|
| 716 |
+
</div>
|
| 717 |
+
<div className="event-reward">{event.reward}</div>
|
| 718 |
+
</div>
|
| 719 |
+
))}
|
| 720 |
+
</div>
|
| 721 |
+
</section>
|
| 722 |
+
</>
|
| 723 |
+
)}
|
| 724 |
+
|
| 725 |
+
{view === "judge" && (
|
| 726 |
+
<section className="section judge">
|
| 727 |
+
<SectionHead
|
| 728 |
+
eyebrow="Judge Flow"
|
| 729 |
+
title="A crisp 3-minute demo rail"
|
| 730 |
+
/>
|
| 731 |
+
<div className="judge-sequence">
|
| 732 |
+
<JudgeStep
|
| 733 |
+
icon={ShieldAlert}
|
| 734 |
+
title="1. Show the failure"
|
| 735 |
+
copy="Run Random to show that long-horizon multi-agent routing collapses when trust is static."
|
| 736 |
+
/>
|
| 737 |
+
<JudgeStep
|
| 738 |
+
icon={Eye}
|
| 739 |
+
title="2. Show the recovery"
|
| 740 |
+
copy="Run Heuristic to show trust divergence, verification at risky gates, and stronger detection."
|
| 741 |
+
/>
|
| 742 |
+
<JudgeStep
|
| 743 |
+
icon={Sparkles}
|
| 744 |
+
title="3. Show generalization"
|
| 745 |
+
copy="Swap hidden profiles and replay to prove the orchestrator learned a transferable skill rather than a memorized slot."
|
| 746 |
+
/>
|
| 747 |
+
</div>
|
| 748 |
+
</section>
|
| 749 |
+
)}
|
| 750 |
+
</main>
|
| 751 |
+
</div>
|
| 752 |
+
);
|
| 753 |
+
}
|
| 754 |
+
|
| 755 |
+
function SectionHead({
|
| 756 |
+
eyebrow,
|
| 757 |
+
title
|
| 758 |
+
}: {
|
| 759 |
+
eyebrow: string;
|
| 760 |
+
title: string;
|
| 761 |
+
}) {
|
| 762 |
+
return (
|
| 763 |
+
<div className="section-head">
|
| 764 |
+
<span>{eyebrow}</span>
|
| 765 |
+
<h3>{title}</h3>
|
| 766 |
+
</div>
|
| 767 |
+
);
|
| 768 |
+
}
|
| 769 |
+
|
| 770 |
+
function MetricCard({
|
| 771 |
+
icon: Icon,
|
| 772 |
+
label,
|
| 773 |
+
value
|
| 774 |
+
}: {
|
| 775 |
+
icon: typeof Activity;
|
| 776 |
+
label: string;
|
| 777 |
+
value: string;
|
| 778 |
+
}) {
|
| 779 |
+
return (
|
| 780 |
+
<div className="metric-card">
|
| 781 |
+
<Icon size={16} />
|
| 782 |
+
<div>
|
| 783 |
+
<span>{label}</span>
|
| 784 |
+
<strong>{value}</strong>
|
| 785 |
+
</div>
|
| 786 |
+
</div>
|
| 787 |
+
);
|
| 788 |
+
}
|
| 789 |
+
|
| 790 |
+
function StoryLane({
|
| 791 |
+
tone,
|
| 792 |
+
label,
|
| 793 |
+
title,
|
| 794 |
+
steps
|
| 795 |
+
}: {
|
| 796 |
+
tone: "before" | "after";
|
| 797 |
+
label: string;
|
| 798 |
+
title: string;
|
| 799 |
+
steps: string[];
|
| 800 |
+
}) {
|
| 801 |
+
return (
|
| 802 |
+
<div className={`story-lane ${tone}`}>
|
| 803 |
+
<div className="story-header">
|
| 804 |
+
<span className="story-label">{label}</span>
|
| 805 |
+
<strong>{title}</strong>
|
| 806 |
+
</div>
|
| 807 |
+
<div className="story-steps">
|
| 808 |
+
{steps.map((step) => (
|
| 809 |
+
<div key={step} className="story-step">
|
| 810 |
+
{step}
|
| 811 |
+
</div>
|
| 812 |
+
))}
|
| 813 |
+
</div>
|
| 814 |
+
</div>
|
| 815 |
+
);
|
| 816 |
+
}
|
| 817 |
+
|
| 818 |
+
function ProofBar({
|
| 819 |
+
label,
|
| 820 |
+
value,
|
| 821 |
+
tone
|
| 822 |
+
}: {
|
| 823 |
+
label: string;
|
| 824 |
+
value: number | undefined;
|
| 825 |
+
tone: "bad" | "neutral" | "good" | "warm";
|
| 826 |
+
}) {
|
| 827 |
+
const widths = typeof value === "number" ? `${Math.max(0, value * 100)}%` : "0%";
|
| 828 |
+
return (
|
| 829 |
+
<div className="proof-row">
|
| 830 |
+
<span>{label}</span>
|
| 831 |
+
<div className="proof-meter">
|
| 832 |
+
<span className={`tone-${tone}`} style={{ width: widths }} />
|
| 833 |
+
</div>
|
| 834 |
+
<strong>{formatScore(value)}</strong>
|
| 835 |
+
</div>
|
| 836 |
+
);
|
| 837 |
+
}
|
| 838 |
+
|
| 839 |
+
function StatBox({ label, value }: { label: string; value: string }) {
|
| 840 |
+
return (
|
| 841 |
+
<div className="stat-box">
|
| 842 |
+
<span>{label}</span>
|
| 843 |
+
<strong>{value}</strong>
|
| 844 |
+
</div>
|
| 845 |
+
);
|
| 846 |
+
}
|
| 847 |
+
|
| 848 |
+
function JsonCard({
|
| 849 |
+
title,
|
| 850 |
+
data
|
| 851 |
+
}: {
|
| 852 |
+
title: string;
|
| 853 |
+
data: Record<string, unknown> | null;
|
| 854 |
+
}) {
|
| 855 |
+
return (
|
| 856 |
+
<div className="json-card">
|
| 857 |
+
<div className="json-head">{title}</div>
|
| 858 |
+
<pre>{JSON.stringify(data ?? { waiting: true }, null, 2)}</pre>
|
| 859 |
+
</div>
|
| 860 |
+
);
|
| 861 |
+
}
|
| 862 |
+
|
| 863 |
+
function JudgeStep({
|
| 864 |
+
icon: Icon,
|
| 865 |
+
title,
|
| 866 |
+
copy
|
| 867 |
+
}: {
|
| 868 |
+
icon: typeof ArrowRight;
|
| 869 |
+
title: string;
|
| 870 |
+
copy: string;
|
| 871 |
+
}) {
|
| 872 |
+
return (
|
| 873 |
+
<motion.div
|
| 874 |
+
className="judge-card"
|
| 875 |
+
whileHover={{ y: -3 }}
|
| 876 |
+
transition={{ duration: 0.18 }}
|
| 877 |
+
>
|
| 878 |
+
<Icon size={18} />
|
| 879 |
+
<strong>{title}</strong>
|
| 880 |
+
<span>{copy}</span>
|
| 881 |
+
</motion.div>
|
| 882 |
+
);
|
| 883 |
+
}
|
| 884 |
+
|
| 885 |
+
function HeroConstellation({ observation }: { observation: Observation | null }) {
|
| 886 |
+
const ids = observation?.available_specialists ?? ["S0", "S1", "S2", "S3", "S4"];
|
| 887 |
+
return (
|
| 888 |
+
<div className="hero-constellation">
|
| 889 |
+
<motion.div
|
| 890 |
+
className="orb-core"
|
| 891 |
+
animate={{ scale: [1, 1.06, 1], rotate: [0, 3, 0] }}
|
| 892 |
+
transition={{ duration: 6, repeat: Infinity, ease: "easeInOut" }}
|
| 893 |
+
/>
|
| 894 |
+
<div className="orb-ring ring-a" />
|
| 895 |
+
<div className="orb-ring ring-b" />
|
| 896 |
+
<div className="hero-node hero-node-main">
|
| 897 |
+
<Brain size={18} />
|
| 898 |
+
<span>Orchestrator</span>
|
| 899 |
+
</div>
|
| 900 |
+
{ids.map((id, index) => (
|
| 901 |
+
<motion.div
|
| 902 |
+
key={id}
|
| 903 |
+
className={`hero-node hero-node-${index + 1}`}
|
| 904 |
+
animate={{ y: [0, -6, 0] }}
|
| 905 |
+
transition={{
|
| 906 |
+
duration: 3 + index * 0.4,
|
| 907 |
+
repeat: Infinity,
|
| 908 |
+
ease: "easeInOut",
|
| 909 |
+
delay: index * 0.2
|
| 910 |
+
}}
|
| 911 |
+
>
|
| 912 |
+
<span>{id}</span>
|
| 913 |
+
</motion.div>
|
| 914 |
+
))}
|
| 915 |
+
</div>
|
| 916 |
+
);
|
| 917 |
+
}
|
ui/next-env.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/// <reference types="next" />
|
| 2 |
+
/// <reference types="next/image-types/global" />
|
| 3 |
+
/// <reference path="./.next/types/routes.d.ts" />
|
| 4 |
+
|
| 5 |
+
// NOTE: This file should not be edited
|
| 6 |
+
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
ui/next.config.mjs
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/** @type {import('next').NextConfig} */
|
| 2 |
+
const nextConfig = {
|
| 3 |
+
output: "export",
|
| 4 |
+
images: {
|
| 5 |
+
unoptimized: true
|
| 6 |
+
}
|
| 7 |
+
};
|
| 8 |
+
|
| 9 |
+
export default nextConfig;
|
ui/package-lock.json
ADDED
|
@@ -0,0 +1,1019 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "sentinel-ui",
|
| 3 |
+
"version": "0.1.0",
|
| 4 |
+
"lockfileVersion": 3,
|
| 5 |
+
"requires": true,
|
| 6 |
+
"packages": {
|
| 7 |
+
"": {
|
| 8 |
+
"name": "sentinel-ui",
|
| 9 |
+
"version": "0.1.0",
|
| 10 |
+
"dependencies": {
|
| 11 |
+
"framer-motion": "^12.23.24",
|
| 12 |
+
"lucide-react": "^0.539.0",
|
| 13 |
+
"next": "^15.3.3",
|
| 14 |
+
"react": "^19.1.1",
|
| 15 |
+
"react-dom": "^19.1.1"
|
| 16 |
+
},
|
| 17 |
+
"devDependencies": {
|
| 18 |
+
"@types/node": "^24.3.0",
|
| 19 |
+
"@types/react": "^19.1.11",
|
| 20 |
+
"@types/react-dom": "^19.1.7",
|
| 21 |
+
"typescript": "^5.9.2"
|
| 22 |
+
}
|
| 23 |
+
},
|
| 24 |
+
"node_modules/@emnapi/runtime": {
|
| 25 |
+
"version": "1.10.0",
|
| 26 |
+
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz",
|
| 27 |
+
"integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==",
|
| 28 |
+
"license": "MIT",
|
| 29 |
+
"optional": true,
|
| 30 |
+
"dependencies": {
|
| 31 |
+
"tslib": "^2.4.0"
|
| 32 |
+
}
|
| 33 |
+
},
|
| 34 |
+
"node_modules/@img/colour": {
|
| 35 |
+
"version": "1.1.0",
|
| 36 |
+
"resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz",
|
| 37 |
+
"integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==",
|
| 38 |
+
"license": "MIT",
|
| 39 |
+
"optional": true,
|
| 40 |
+
"engines": {
|
| 41 |
+
"node": ">=18"
|
| 42 |
+
}
|
| 43 |
+
},
|
| 44 |
+
"node_modules/@img/sharp-darwin-arm64": {
|
| 45 |
+
"version": "0.34.5",
|
| 46 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz",
|
| 47 |
+
"integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==",
|
| 48 |
+
"cpu": [
|
| 49 |
+
"arm64"
|
| 50 |
+
],
|
| 51 |
+
"license": "Apache-2.0",
|
| 52 |
+
"optional": true,
|
| 53 |
+
"os": [
|
| 54 |
+
"darwin"
|
| 55 |
+
],
|
| 56 |
+
"engines": {
|
| 57 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 58 |
+
},
|
| 59 |
+
"funding": {
|
| 60 |
+
"url": "https://opencollective.com/libvips"
|
| 61 |
+
},
|
| 62 |
+
"optionalDependencies": {
|
| 63 |
+
"@img/sharp-libvips-darwin-arm64": "1.2.4"
|
| 64 |
+
}
|
| 65 |
+
},
|
| 66 |
+
"node_modules/@img/sharp-darwin-x64": {
|
| 67 |
+
"version": "0.34.5",
|
| 68 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz",
|
| 69 |
+
"integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==",
|
| 70 |
+
"cpu": [
|
| 71 |
+
"x64"
|
| 72 |
+
],
|
| 73 |
+
"license": "Apache-2.0",
|
| 74 |
+
"optional": true,
|
| 75 |
+
"os": [
|
| 76 |
+
"darwin"
|
| 77 |
+
],
|
| 78 |
+
"engines": {
|
| 79 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 80 |
+
},
|
| 81 |
+
"funding": {
|
| 82 |
+
"url": "https://opencollective.com/libvips"
|
| 83 |
+
},
|
| 84 |
+
"optionalDependencies": {
|
| 85 |
+
"@img/sharp-libvips-darwin-x64": "1.2.4"
|
| 86 |
+
}
|
| 87 |
+
},
|
| 88 |
+
"node_modules/@img/sharp-libvips-darwin-arm64": {
|
| 89 |
+
"version": "1.2.4",
|
| 90 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz",
|
| 91 |
+
"integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==",
|
| 92 |
+
"cpu": [
|
| 93 |
+
"arm64"
|
| 94 |
+
],
|
| 95 |
+
"license": "LGPL-3.0-or-later",
|
| 96 |
+
"optional": true,
|
| 97 |
+
"os": [
|
| 98 |
+
"darwin"
|
| 99 |
+
],
|
| 100 |
+
"funding": {
|
| 101 |
+
"url": "https://opencollective.com/libvips"
|
| 102 |
+
}
|
| 103 |
+
},
|
| 104 |
+
"node_modules/@img/sharp-libvips-darwin-x64": {
|
| 105 |
+
"version": "1.2.4",
|
| 106 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz",
|
| 107 |
+
"integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==",
|
| 108 |
+
"cpu": [
|
| 109 |
+
"x64"
|
| 110 |
+
],
|
| 111 |
+
"license": "LGPL-3.0-or-later",
|
| 112 |
+
"optional": true,
|
| 113 |
+
"os": [
|
| 114 |
+
"darwin"
|
| 115 |
+
],
|
| 116 |
+
"funding": {
|
| 117 |
+
"url": "https://opencollective.com/libvips"
|
| 118 |
+
}
|
| 119 |
+
},
|
| 120 |
+
"node_modules/@img/sharp-libvips-linux-arm": {
|
| 121 |
+
"version": "1.2.4",
|
| 122 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz",
|
| 123 |
+
"integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==",
|
| 124 |
+
"cpu": [
|
| 125 |
+
"arm"
|
| 126 |
+
],
|
| 127 |
+
"license": "LGPL-3.0-or-later",
|
| 128 |
+
"optional": true,
|
| 129 |
+
"os": [
|
| 130 |
+
"linux"
|
| 131 |
+
],
|
| 132 |
+
"funding": {
|
| 133 |
+
"url": "https://opencollective.com/libvips"
|
| 134 |
+
}
|
| 135 |
+
},
|
| 136 |
+
"node_modules/@img/sharp-libvips-linux-arm64": {
|
| 137 |
+
"version": "1.2.4",
|
| 138 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz",
|
| 139 |
+
"integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==",
|
| 140 |
+
"cpu": [
|
| 141 |
+
"arm64"
|
| 142 |
+
],
|
| 143 |
+
"license": "LGPL-3.0-or-later",
|
| 144 |
+
"optional": true,
|
| 145 |
+
"os": [
|
| 146 |
+
"linux"
|
| 147 |
+
],
|
| 148 |
+
"funding": {
|
| 149 |
+
"url": "https://opencollective.com/libvips"
|
| 150 |
+
}
|
| 151 |
+
},
|
| 152 |
+
"node_modules/@img/sharp-libvips-linux-ppc64": {
|
| 153 |
+
"version": "1.2.4",
|
| 154 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz",
|
| 155 |
+
"integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==",
|
| 156 |
+
"cpu": [
|
| 157 |
+
"ppc64"
|
| 158 |
+
],
|
| 159 |
+
"license": "LGPL-3.0-or-later",
|
| 160 |
+
"optional": true,
|
| 161 |
+
"os": [
|
| 162 |
+
"linux"
|
| 163 |
+
],
|
| 164 |
+
"funding": {
|
| 165 |
+
"url": "https://opencollective.com/libvips"
|
| 166 |
+
}
|
| 167 |
+
},
|
| 168 |
+
"node_modules/@img/sharp-libvips-linux-riscv64": {
|
| 169 |
+
"version": "1.2.4",
|
| 170 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz",
|
| 171 |
+
"integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==",
|
| 172 |
+
"cpu": [
|
| 173 |
+
"riscv64"
|
| 174 |
+
],
|
| 175 |
+
"license": "LGPL-3.0-or-later",
|
| 176 |
+
"optional": true,
|
| 177 |
+
"os": [
|
| 178 |
+
"linux"
|
| 179 |
+
],
|
| 180 |
+
"funding": {
|
| 181 |
+
"url": "https://opencollective.com/libvips"
|
| 182 |
+
}
|
| 183 |
+
},
|
| 184 |
+
"node_modules/@img/sharp-libvips-linux-s390x": {
|
| 185 |
+
"version": "1.2.4",
|
| 186 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz",
|
| 187 |
+
"integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==",
|
| 188 |
+
"cpu": [
|
| 189 |
+
"s390x"
|
| 190 |
+
],
|
| 191 |
+
"license": "LGPL-3.0-or-later",
|
| 192 |
+
"optional": true,
|
| 193 |
+
"os": [
|
| 194 |
+
"linux"
|
| 195 |
+
],
|
| 196 |
+
"funding": {
|
| 197 |
+
"url": "https://opencollective.com/libvips"
|
| 198 |
+
}
|
| 199 |
+
},
|
| 200 |
+
"node_modules/@img/sharp-libvips-linux-x64": {
|
| 201 |
+
"version": "1.2.4",
|
| 202 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz",
|
| 203 |
+
"integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==",
|
| 204 |
+
"cpu": [
|
| 205 |
+
"x64"
|
| 206 |
+
],
|
| 207 |
+
"license": "LGPL-3.0-or-later",
|
| 208 |
+
"optional": true,
|
| 209 |
+
"os": [
|
| 210 |
+
"linux"
|
| 211 |
+
],
|
| 212 |
+
"funding": {
|
| 213 |
+
"url": "https://opencollective.com/libvips"
|
| 214 |
+
}
|
| 215 |
+
},
|
| 216 |
+
"node_modules/@img/sharp-libvips-linuxmusl-arm64": {
|
| 217 |
+
"version": "1.2.4",
|
| 218 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz",
|
| 219 |
+
"integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==",
|
| 220 |
+
"cpu": [
|
| 221 |
+
"arm64"
|
| 222 |
+
],
|
| 223 |
+
"license": "LGPL-3.0-or-later",
|
| 224 |
+
"optional": true,
|
| 225 |
+
"os": [
|
| 226 |
+
"linux"
|
| 227 |
+
],
|
| 228 |
+
"funding": {
|
| 229 |
+
"url": "https://opencollective.com/libvips"
|
| 230 |
+
}
|
| 231 |
+
},
|
| 232 |
+
"node_modules/@img/sharp-libvips-linuxmusl-x64": {
|
| 233 |
+
"version": "1.2.4",
|
| 234 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz",
|
| 235 |
+
"integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==",
|
| 236 |
+
"cpu": [
|
| 237 |
+
"x64"
|
| 238 |
+
],
|
| 239 |
+
"license": "LGPL-3.0-or-later",
|
| 240 |
+
"optional": true,
|
| 241 |
+
"os": [
|
| 242 |
+
"linux"
|
| 243 |
+
],
|
| 244 |
+
"funding": {
|
| 245 |
+
"url": "https://opencollective.com/libvips"
|
| 246 |
+
}
|
| 247 |
+
},
|
| 248 |
+
"node_modules/@img/sharp-linux-arm": {
|
| 249 |
+
"version": "0.34.5",
|
| 250 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz",
|
| 251 |
+
"integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==",
|
| 252 |
+
"cpu": [
|
| 253 |
+
"arm"
|
| 254 |
+
],
|
| 255 |
+
"license": "Apache-2.0",
|
| 256 |
+
"optional": true,
|
| 257 |
+
"os": [
|
| 258 |
+
"linux"
|
| 259 |
+
],
|
| 260 |
+
"engines": {
|
| 261 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 262 |
+
},
|
| 263 |
+
"funding": {
|
| 264 |
+
"url": "https://opencollective.com/libvips"
|
| 265 |
+
},
|
| 266 |
+
"optionalDependencies": {
|
| 267 |
+
"@img/sharp-libvips-linux-arm": "1.2.4"
|
| 268 |
+
}
|
| 269 |
+
},
|
| 270 |
+
"node_modules/@img/sharp-linux-arm64": {
|
| 271 |
+
"version": "0.34.5",
|
| 272 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz",
|
| 273 |
+
"integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==",
|
| 274 |
+
"cpu": [
|
| 275 |
+
"arm64"
|
| 276 |
+
],
|
| 277 |
+
"license": "Apache-2.0",
|
| 278 |
+
"optional": true,
|
| 279 |
+
"os": [
|
| 280 |
+
"linux"
|
| 281 |
+
],
|
| 282 |
+
"engines": {
|
| 283 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 284 |
+
},
|
| 285 |
+
"funding": {
|
| 286 |
+
"url": "https://opencollective.com/libvips"
|
| 287 |
+
},
|
| 288 |
+
"optionalDependencies": {
|
| 289 |
+
"@img/sharp-libvips-linux-arm64": "1.2.4"
|
| 290 |
+
}
|
| 291 |
+
},
|
| 292 |
+
"node_modules/@img/sharp-linux-ppc64": {
|
| 293 |
+
"version": "0.34.5",
|
| 294 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz",
|
| 295 |
+
"integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==",
|
| 296 |
+
"cpu": [
|
| 297 |
+
"ppc64"
|
| 298 |
+
],
|
| 299 |
+
"license": "Apache-2.0",
|
| 300 |
+
"optional": true,
|
| 301 |
+
"os": [
|
| 302 |
+
"linux"
|
| 303 |
+
],
|
| 304 |
+
"engines": {
|
| 305 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 306 |
+
},
|
| 307 |
+
"funding": {
|
| 308 |
+
"url": "https://opencollective.com/libvips"
|
| 309 |
+
},
|
| 310 |
+
"optionalDependencies": {
|
| 311 |
+
"@img/sharp-libvips-linux-ppc64": "1.2.4"
|
| 312 |
+
}
|
| 313 |
+
},
|
| 314 |
+
"node_modules/@img/sharp-linux-riscv64": {
|
| 315 |
+
"version": "0.34.5",
|
| 316 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz",
|
| 317 |
+
"integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==",
|
| 318 |
+
"cpu": [
|
| 319 |
+
"riscv64"
|
| 320 |
+
],
|
| 321 |
+
"license": "Apache-2.0",
|
| 322 |
+
"optional": true,
|
| 323 |
+
"os": [
|
| 324 |
+
"linux"
|
| 325 |
+
],
|
| 326 |
+
"engines": {
|
| 327 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 328 |
+
},
|
| 329 |
+
"funding": {
|
| 330 |
+
"url": "https://opencollective.com/libvips"
|
| 331 |
+
},
|
| 332 |
+
"optionalDependencies": {
|
| 333 |
+
"@img/sharp-libvips-linux-riscv64": "1.2.4"
|
| 334 |
+
}
|
| 335 |
+
},
|
| 336 |
+
"node_modules/@img/sharp-linux-s390x": {
|
| 337 |
+
"version": "0.34.5",
|
| 338 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz",
|
| 339 |
+
"integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==",
|
| 340 |
+
"cpu": [
|
| 341 |
+
"s390x"
|
| 342 |
+
],
|
| 343 |
+
"license": "Apache-2.0",
|
| 344 |
+
"optional": true,
|
| 345 |
+
"os": [
|
| 346 |
+
"linux"
|
| 347 |
+
],
|
| 348 |
+
"engines": {
|
| 349 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 350 |
+
},
|
| 351 |
+
"funding": {
|
| 352 |
+
"url": "https://opencollective.com/libvips"
|
| 353 |
+
},
|
| 354 |
+
"optionalDependencies": {
|
| 355 |
+
"@img/sharp-libvips-linux-s390x": "1.2.4"
|
| 356 |
+
}
|
| 357 |
+
},
|
| 358 |
+
"node_modules/@img/sharp-linux-x64": {
|
| 359 |
+
"version": "0.34.5",
|
| 360 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz",
|
| 361 |
+
"integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==",
|
| 362 |
+
"cpu": [
|
| 363 |
+
"x64"
|
| 364 |
+
],
|
| 365 |
+
"license": "Apache-2.0",
|
| 366 |
+
"optional": true,
|
| 367 |
+
"os": [
|
| 368 |
+
"linux"
|
| 369 |
+
],
|
| 370 |
+
"engines": {
|
| 371 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 372 |
+
},
|
| 373 |
+
"funding": {
|
| 374 |
+
"url": "https://opencollective.com/libvips"
|
| 375 |
+
},
|
| 376 |
+
"optionalDependencies": {
|
| 377 |
+
"@img/sharp-libvips-linux-x64": "1.2.4"
|
| 378 |
+
}
|
| 379 |
+
},
|
| 380 |
+
"node_modules/@img/sharp-linuxmusl-arm64": {
|
| 381 |
+
"version": "0.34.5",
|
| 382 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz",
|
| 383 |
+
"integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==",
|
| 384 |
+
"cpu": [
|
| 385 |
+
"arm64"
|
| 386 |
+
],
|
| 387 |
+
"license": "Apache-2.0",
|
| 388 |
+
"optional": true,
|
| 389 |
+
"os": [
|
| 390 |
+
"linux"
|
| 391 |
+
],
|
| 392 |
+
"engines": {
|
| 393 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 394 |
+
},
|
| 395 |
+
"funding": {
|
| 396 |
+
"url": "https://opencollective.com/libvips"
|
| 397 |
+
},
|
| 398 |
+
"optionalDependencies": {
|
| 399 |
+
"@img/sharp-libvips-linuxmusl-arm64": "1.2.4"
|
| 400 |
+
}
|
| 401 |
+
},
|
| 402 |
+
"node_modules/@img/sharp-linuxmusl-x64": {
|
| 403 |
+
"version": "0.34.5",
|
| 404 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz",
|
| 405 |
+
"integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==",
|
| 406 |
+
"cpu": [
|
| 407 |
+
"x64"
|
| 408 |
+
],
|
| 409 |
+
"license": "Apache-2.0",
|
| 410 |
+
"optional": true,
|
| 411 |
+
"os": [
|
| 412 |
+
"linux"
|
| 413 |
+
],
|
| 414 |
+
"engines": {
|
| 415 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 416 |
+
},
|
| 417 |
+
"funding": {
|
| 418 |
+
"url": "https://opencollective.com/libvips"
|
| 419 |
+
},
|
| 420 |
+
"optionalDependencies": {
|
| 421 |
+
"@img/sharp-libvips-linuxmusl-x64": "1.2.4"
|
| 422 |
+
}
|
| 423 |
+
},
|
| 424 |
+
"node_modules/@img/sharp-wasm32": {
|
| 425 |
+
"version": "0.34.5",
|
| 426 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz",
|
| 427 |
+
"integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==",
|
| 428 |
+
"cpu": [
|
| 429 |
+
"wasm32"
|
| 430 |
+
],
|
| 431 |
+
"license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
|
| 432 |
+
"optional": true,
|
| 433 |
+
"dependencies": {
|
| 434 |
+
"@emnapi/runtime": "^1.7.0"
|
| 435 |
+
},
|
| 436 |
+
"engines": {
|
| 437 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 438 |
+
},
|
| 439 |
+
"funding": {
|
| 440 |
+
"url": "https://opencollective.com/libvips"
|
| 441 |
+
}
|
| 442 |
+
},
|
| 443 |
+
"node_modules/@img/sharp-win32-arm64": {
|
| 444 |
+
"version": "0.34.5",
|
| 445 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz",
|
| 446 |
+
"integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==",
|
| 447 |
+
"cpu": [
|
| 448 |
+
"arm64"
|
| 449 |
+
],
|
| 450 |
+
"license": "Apache-2.0 AND LGPL-3.0-or-later",
|
| 451 |
+
"optional": true,
|
| 452 |
+
"os": [
|
| 453 |
+
"win32"
|
| 454 |
+
],
|
| 455 |
+
"engines": {
|
| 456 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 457 |
+
},
|
| 458 |
+
"funding": {
|
| 459 |
+
"url": "https://opencollective.com/libvips"
|
| 460 |
+
}
|
| 461 |
+
},
|
| 462 |
+
"node_modules/@img/sharp-win32-ia32": {
|
| 463 |
+
"version": "0.34.5",
|
| 464 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz",
|
| 465 |
+
"integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==",
|
| 466 |
+
"cpu": [
|
| 467 |
+
"ia32"
|
| 468 |
+
],
|
| 469 |
+
"license": "Apache-2.0 AND LGPL-3.0-or-later",
|
| 470 |
+
"optional": true,
|
| 471 |
+
"os": [
|
| 472 |
+
"win32"
|
| 473 |
+
],
|
| 474 |
+
"engines": {
|
| 475 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 476 |
+
},
|
| 477 |
+
"funding": {
|
| 478 |
+
"url": "https://opencollective.com/libvips"
|
| 479 |
+
}
|
| 480 |
+
},
|
| 481 |
+
"node_modules/@img/sharp-win32-x64": {
|
| 482 |
+
"version": "0.34.5",
|
| 483 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz",
|
| 484 |
+
"integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==",
|
| 485 |
+
"cpu": [
|
| 486 |
+
"x64"
|
| 487 |
+
],
|
| 488 |
+
"license": "Apache-2.0 AND LGPL-3.0-or-later",
|
| 489 |
+
"optional": true,
|
| 490 |
+
"os": [
|
| 491 |
+
"win32"
|
| 492 |
+
],
|
| 493 |
+
"engines": {
|
| 494 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 495 |
+
},
|
| 496 |
+
"funding": {
|
| 497 |
+
"url": "https://opencollective.com/libvips"
|
| 498 |
+
}
|
| 499 |
+
},
|
| 500 |
+
"node_modules/@next/env": {
|
| 501 |
+
"version": "15.5.15",
|
| 502 |
+
"resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.15.tgz",
|
| 503 |
+
"integrity": "sha512-vcmyu5/MyFzN7CdqRHO3uHO44p/QPCZkuTUXroeUmhNP8bL5PHFEhik22JUazt+CDDoD6EpBYRCaS2pISL+/hg==",
|
| 504 |
+
"license": "MIT"
|
| 505 |
+
},
|
| 506 |
+
"node_modules/@next/swc-darwin-arm64": {
|
| 507 |
+
"version": "15.5.15",
|
| 508 |
+
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.15.tgz",
|
| 509 |
+
"integrity": "sha512-6PvFO2Tzt10GFK2Ro9tAVEtacMqRmTarYMFKAnV2vYMdwWc73xzmDQyAV7SwEdMhzmiRoo7+m88DuiXlJlGeaw==",
|
| 510 |
+
"cpu": [
|
| 511 |
+
"arm64"
|
| 512 |
+
],
|
| 513 |
+
"license": "MIT",
|
| 514 |
+
"optional": true,
|
| 515 |
+
"os": [
|
| 516 |
+
"darwin"
|
| 517 |
+
],
|
| 518 |
+
"engines": {
|
| 519 |
+
"node": ">= 10"
|
| 520 |
+
}
|
| 521 |
+
},
|
| 522 |
+
"node_modules/@next/swc-darwin-x64": {
|
| 523 |
+
"version": "15.5.15",
|
| 524 |
+
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.15.tgz",
|
| 525 |
+
"integrity": "sha512-G+YNV+z6FDZTp/+IdGyIMFqalBTaQSnvAA+X/hrt+eaTRFSznRMz9K7rTmzvM6tDmKegNtyzgufZW0HwVzEqaQ==",
|
| 526 |
+
"cpu": [
|
| 527 |
+
"x64"
|
| 528 |
+
],
|
| 529 |
+
"license": "MIT",
|
| 530 |
+
"optional": true,
|
| 531 |
+
"os": [
|
| 532 |
+
"darwin"
|
| 533 |
+
],
|
| 534 |
+
"engines": {
|
| 535 |
+
"node": ">= 10"
|
| 536 |
+
}
|
| 537 |
+
},
|
| 538 |
+
"node_modules/@next/swc-linux-arm64-gnu": {
|
| 539 |
+
"version": "15.5.15",
|
| 540 |
+
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.15.tgz",
|
| 541 |
+
"integrity": "sha512-eVkrMcVIBqGfXB+QUC7jjZ94Z6uX/dNStbQFabewAnk13Uy18Igd1YZ/GtPRzdhtm7QwC0e6o7zOQecul4iC1w==",
|
| 542 |
+
"cpu": [
|
| 543 |
+
"arm64"
|
| 544 |
+
],
|
| 545 |
+
"license": "MIT",
|
| 546 |
+
"optional": true,
|
| 547 |
+
"os": [
|
| 548 |
+
"linux"
|
| 549 |
+
],
|
| 550 |
+
"engines": {
|
| 551 |
+
"node": ">= 10"
|
| 552 |
+
}
|
| 553 |
+
},
|
| 554 |
+
"node_modules/@next/swc-linux-arm64-musl": {
|
| 555 |
+
"version": "15.5.15",
|
| 556 |
+
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.15.tgz",
|
| 557 |
+
"integrity": "sha512-RwSHKMQ7InLy5GfkY2/n5PcFycKA08qI1VST78n09nN36nUPqCvGSMiLXlfUmzmpQpF6XeBYP2KRWHi0UW3uNg==",
|
| 558 |
+
"cpu": [
|
| 559 |
+
"arm64"
|
| 560 |
+
],
|
| 561 |
+
"license": "MIT",
|
| 562 |
+
"optional": true,
|
| 563 |
+
"os": [
|
| 564 |
+
"linux"
|
| 565 |
+
],
|
| 566 |
+
"engines": {
|
| 567 |
+
"node": ">= 10"
|
| 568 |
+
}
|
| 569 |
+
},
|
| 570 |
+
"node_modules/@next/swc-linux-x64-gnu": {
|
| 571 |
+
"version": "15.5.15",
|
| 572 |
+
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.15.tgz",
|
| 573 |
+
"integrity": "sha512-nplqvY86LakS+eeiuWsNWvfmK8pFcOEW7ZtVRt4QH70lL+0x6LG/m1OpJ/tvrbwjmR8HH9/fH2jzW1GlL03TIg==",
|
| 574 |
+
"cpu": [
|
| 575 |
+
"x64"
|
| 576 |
+
],
|
| 577 |
+
"license": "MIT",
|
| 578 |
+
"optional": true,
|
| 579 |
+
"os": [
|
| 580 |
+
"linux"
|
| 581 |
+
],
|
| 582 |
+
"engines": {
|
| 583 |
+
"node": ">= 10"
|
| 584 |
+
}
|
| 585 |
+
},
|
| 586 |
+
"node_modules/@next/swc-linux-x64-musl": {
|
| 587 |
+
"version": "15.5.15",
|
| 588 |
+
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.15.tgz",
|
| 589 |
+
"integrity": "sha512-eAgl9NKQ84/sww0v81DQINl/vL2IBxD7sMybd0cWRw6wqgouVI53brVRBrggqBRP/NWeIAE1dm5cbKYoiMlqDQ==",
|
| 590 |
+
"cpu": [
|
| 591 |
+
"x64"
|
| 592 |
+
],
|
| 593 |
+
"license": "MIT",
|
| 594 |
+
"optional": true,
|
| 595 |
+
"os": [
|
| 596 |
+
"linux"
|
| 597 |
+
],
|
| 598 |
+
"engines": {
|
| 599 |
+
"node": ">= 10"
|
| 600 |
+
}
|
| 601 |
+
},
|
| 602 |
+
"node_modules/@next/swc-win32-arm64-msvc": {
|
| 603 |
+
"version": "15.5.15",
|
| 604 |
+
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.15.tgz",
|
| 605 |
+
"integrity": "sha512-GJVZC86lzSquh0MtvZT+L7G8+jMnJcldloOjA8Kf3wXvBrvb6OGe2MzPuALxFshSm/IpwUtD2mIoof39ymf52A==",
|
| 606 |
+
"cpu": [
|
| 607 |
+
"arm64"
|
| 608 |
+
],
|
| 609 |
+
"license": "MIT",
|
| 610 |
+
"optional": true,
|
| 611 |
+
"os": [
|
| 612 |
+
"win32"
|
| 613 |
+
],
|
| 614 |
+
"engines": {
|
| 615 |
+
"node": ">= 10"
|
| 616 |
+
}
|
| 617 |
+
},
|
| 618 |
+
"node_modules/@next/swc-win32-x64-msvc": {
|
| 619 |
+
"version": "15.5.15",
|
| 620 |
+
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.15.tgz",
|
| 621 |
+
"integrity": "sha512-nFucjVdwlFqxh/JG3hWSJ4p8+YJV7Ii8aPDuBQULB6DzUF4UNZETXLfEUk+oI2zEznWWULPt7MeuTE6xtK1HSA==",
|
| 622 |
+
"cpu": [
|
| 623 |
+
"x64"
|
| 624 |
+
],
|
| 625 |
+
"license": "MIT",
|
| 626 |
+
"optional": true,
|
| 627 |
+
"os": [
|
| 628 |
+
"win32"
|
| 629 |
+
],
|
| 630 |
+
"engines": {
|
| 631 |
+
"node": ">= 10"
|
| 632 |
+
}
|
| 633 |
+
},
|
| 634 |
+
"node_modules/@swc/helpers": {
|
| 635 |
+
"version": "0.5.15",
|
| 636 |
+
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
|
| 637 |
+
"integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
|
| 638 |
+
"license": "Apache-2.0",
|
| 639 |
+
"dependencies": {
|
| 640 |
+
"tslib": "^2.8.0"
|
| 641 |
+
}
|
| 642 |
+
},
|
| 643 |
+
"node_modules/@types/node": {
|
| 644 |
+
"version": "24.12.2",
|
| 645 |
+
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.2.tgz",
|
| 646 |
+
"integrity": "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==",
|
| 647 |
+
"dev": true,
|
| 648 |
+
"license": "MIT",
|
| 649 |
+
"dependencies": {
|
| 650 |
+
"undici-types": "~7.16.0"
|
| 651 |
+
}
|
| 652 |
+
},
|
| 653 |
+
"node_modules/@types/react": {
|
| 654 |
+
"version": "19.2.14",
|
| 655 |
+
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
|
| 656 |
+
"integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
|
| 657 |
+
"dev": true,
|
| 658 |
+
"license": "MIT",
|
| 659 |
+
"peer": true,
|
| 660 |
+
"dependencies": {
|
| 661 |
+
"csstype": "^3.2.2"
|
| 662 |
+
}
|
| 663 |
+
},
|
| 664 |
+
"node_modules/@types/react-dom": {
|
| 665 |
+
"version": "19.2.3",
|
| 666 |
+
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
|
| 667 |
+
"integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
|
| 668 |
+
"dev": true,
|
| 669 |
+
"license": "MIT",
|
| 670 |
+
"peerDependencies": {
|
| 671 |
+
"@types/react": "^19.2.0"
|
| 672 |
+
}
|
| 673 |
+
},
|
| 674 |
+
"node_modules/caniuse-lite": {
|
| 675 |
+
"version": "1.0.30001790",
|
| 676 |
+
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001790.tgz",
|
| 677 |
+
"integrity": "sha512-bOoxfJPyYo+ds6W0YfptaCWbFnJYjh2Y1Eow5lRv+vI2u8ganPZqNm1JwNh0t2ELQCqIWg4B3dWEusgAmsoyOw==",
|
| 678 |
+
"funding": [
|
| 679 |
+
{
|
| 680 |
+
"type": "opencollective",
|
| 681 |
+
"url": "https://opencollective.com/browserslist"
|
| 682 |
+
},
|
| 683 |
+
{
|
| 684 |
+
"type": "tidelift",
|
| 685 |
+
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
|
| 686 |
+
},
|
| 687 |
+
{
|
| 688 |
+
"type": "github",
|
| 689 |
+
"url": "https://github.com/sponsors/ai"
|
| 690 |
+
}
|
| 691 |
+
],
|
| 692 |
+
"license": "CC-BY-4.0"
|
| 693 |
+
},
|
| 694 |
+
"node_modules/client-only": {
|
| 695 |
+
"version": "0.0.1",
|
| 696 |
+
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
| 697 |
+
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
|
| 698 |
+
"license": "MIT"
|
| 699 |
+
},
|
| 700 |
+
"node_modules/csstype": {
|
| 701 |
+
"version": "3.2.3",
|
| 702 |
+
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
|
| 703 |
+
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
|
| 704 |
+
"dev": true,
|
| 705 |
+
"license": "MIT"
|
| 706 |
+
},
|
| 707 |
+
"node_modules/detect-libc": {
|
| 708 |
+
"version": "2.1.2",
|
| 709 |
+
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
| 710 |
+
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
|
| 711 |
+
"license": "Apache-2.0",
|
| 712 |
+
"optional": true,
|
| 713 |
+
"engines": {
|
| 714 |
+
"node": ">=8"
|
| 715 |
+
}
|
| 716 |
+
},
|
| 717 |
+
"node_modules/framer-motion": {
|
| 718 |
+
"version": "12.38.0",
|
| 719 |
+
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.38.0.tgz",
|
| 720 |
+
"integrity": "sha512-rFYkY/pigbcswl1XQSb7q424kSTQ8q6eAC+YUsSKooHQYuLdzdHjrt6uxUC+PRAO++q5IS7+TamgIw1AphxR+g==",
|
| 721 |
+
"license": "MIT",
|
| 722 |
+
"dependencies": {
|
| 723 |
+
"motion-dom": "^12.38.0",
|
| 724 |
+
"motion-utils": "^12.36.0",
|
| 725 |
+
"tslib": "^2.4.0"
|
| 726 |
+
},
|
| 727 |
+
"peerDependencies": {
|
| 728 |
+
"@emotion/is-prop-valid": "*",
|
| 729 |
+
"react": "^18.0.0 || ^19.0.0",
|
| 730 |
+
"react-dom": "^18.0.0 || ^19.0.0"
|
| 731 |
+
},
|
| 732 |
+
"peerDependenciesMeta": {
|
| 733 |
+
"@emotion/is-prop-valid": {
|
| 734 |
+
"optional": true
|
| 735 |
+
},
|
| 736 |
+
"react": {
|
| 737 |
+
"optional": true
|
| 738 |
+
},
|
| 739 |
+
"react-dom": {
|
| 740 |
+
"optional": true
|
| 741 |
+
}
|
| 742 |
+
}
|
| 743 |
+
},
|
| 744 |
+
"node_modules/lucide-react": {
|
| 745 |
+
"version": "0.539.0",
|
| 746 |
+
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.539.0.tgz",
|
| 747 |
+
"integrity": "sha512-VVISr+VF2krO91FeuCrm1rSOLACQUYVy7NQkzrOty52Y8TlTPcXcMdQFj9bYzBgXbWCiywlwSZ3Z8u6a+6bMlg==",
|
| 748 |
+
"license": "ISC",
|
| 749 |
+
"peerDependencies": {
|
| 750 |
+
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
| 751 |
+
}
|
| 752 |
+
},
|
| 753 |
+
"node_modules/motion-dom": {
|
| 754 |
+
"version": "12.38.0",
|
| 755 |
+
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.38.0.tgz",
|
| 756 |
+
"integrity": "sha512-pdkHLD8QYRp8VfiNLb8xIBJis1byQ9gPT3Jnh2jqfFtAsWUA3dEepDlsWe/xMpO8McV+VdpKVcp+E+TGJEtOoA==",
|
| 757 |
+
"license": "MIT",
|
| 758 |
+
"dependencies": {
|
| 759 |
+
"motion-utils": "^12.36.0"
|
| 760 |
+
}
|
| 761 |
+
},
|
| 762 |
+
"node_modules/motion-utils": {
|
| 763 |
+
"version": "12.36.0",
|
| 764 |
+
"resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.36.0.tgz",
|
| 765 |
+
"integrity": "sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg==",
|
| 766 |
+
"license": "MIT"
|
| 767 |
+
},
|
| 768 |
+
"node_modules/nanoid": {
|
| 769 |
+
"version": "3.3.11",
|
| 770 |
+
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
| 771 |
+
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
|
| 772 |
+
"funding": [
|
| 773 |
+
{
|
| 774 |
+
"type": "github",
|
| 775 |
+
"url": "https://github.com/sponsors/ai"
|
| 776 |
+
}
|
| 777 |
+
],
|
| 778 |
+
"license": "MIT",
|
| 779 |
+
"bin": {
|
| 780 |
+
"nanoid": "bin/nanoid.cjs"
|
| 781 |
+
},
|
| 782 |
+
"engines": {
|
| 783 |
+
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
| 784 |
+
}
|
| 785 |
+
},
|
| 786 |
+
"node_modules/next": {
|
| 787 |
+
"version": "15.5.15",
|
| 788 |
+
"resolved": "https://registry.npmjs.org/next/-/next-15.5.15.tgz",
|
| 789 |
+
"integrity": "sha512-VSqCrJwtLVGwAVE0Sb/yikrQfkwkZW9p+lL/J4+xe+G3ZA+QnWPqgcfH1tDUEuk9y+pthzzVFp4L/U8JerMfMQ==",
|
| 790 |
+
"license": "MIT",
|
| 791 |
+
"dependencies": {
|
| 792 |
+
"@next/env": "15.5.15",
|
| 793 |
+
"@swc/helpers": "0.5.15",
|
| 794 |
+
"caniuse-lite": "^1.0.30001579",
|
| 795 |
+
"postcss": "8.4.31",
|
| 796 |
+
"styled-jsx": "5.1.6"
|
| 797 |
+
},
|
| 798 |
+
"bin": {
|
| 799 |
+
"next": "dist/bin/next"
|
| 800 |
+
},
|
| 801 |
+
"engines": {
|
| 802 |
+
"node": "^18.18.0 || ^19.8.0 || >= 20.0.0"
|
| 803 |
+
},
|
| 804 |
+
"optionalDependencies": {
|
| 805 |
+
"@next/swc-darwin-arm64": "15.5.15",
|
| 806 |
+
"@next/swc-darwin-x64": "15.5.15",
|
| 807 |
+
"@next/swc-linux-arm64-gnu": "15.5.15",
|
| 808 |
+
"@next/swc-linux-arm64-musl": "15.5.15",
|
| 809 |
+
"@next/swc-linux-x64-gnu": "15.5.15",
|
| 810 |
+
"@next/swc-linux-x64-musl": "15.5.15",
|
| 811 |
+
"@next/swc-win32-arm64-msvc": "15.5.15",
|
| 812 |
+
"@next/swc-win32-x64-msvc": "15.5.15",
|
| 813 |
+
"sharp": "^0.34.3"
|
| 814 |
+
},
|
| 815 |
+
"peerDependencies": {
|
| 816 |
+
"@opentelemetry/api": "^1.1.0",
|
| 817 |
+
"@playwright/test": "^1.51.1",
|
| 818 |
+
"babel-plugin-react-compiler": "*",
|
| 819 |
+
"react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0",
|
| 820 |
+
"react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0",
|
| 821 |
+
"sass": "^1.3.0"
|
| 822 |
+
},
|
| 823 |
+
"peerDependenciesMeta": {
|
| 824 |
+
"@opentelemetry/api": {
|
| 825 |
+
"optional": true
|
| 826 |
+
},
|
| 827 |
+
"@playwright/test": {
|
| 828 |
+
"optional": true
|
| 829 |
+
},
|
| 830 |
+
"babel-plugin-react-compiler": {
|
| 831 |
+
"optional": true
|
| 832 |
+
},
|
| 833 |
+
"sass": {
|
| 834 |
+
"optional": true
|
| 835 |
+
}
|
| 836 |
+
}
|
| 837 |
+
},
|
| 838 |
+
"node_modules/picocolors": {
|
| 839 |
+
"version": "1.1.1",
|
| 840 |
+
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
| 841 |
+
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
|
| 842 |
+
"license": "ISC"
|
| 843 |
+
},
|
| 844 |
+
"node_modules/postcss": {
|
| 845 |
+
"version": "8.4.31",
|
| 846 |
+
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
|
| 847 |
+
"integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
|
| 848 |
+
"funding": [
|
| 849 |
+
{
|
| 850 |
+
"type": "opencollective",
|
| 851 |
+
"url": "https://opencollective.com/postcss/"
|
| 852 |
+
},
|
| 853 |
+
{
|
| 854 |
+
"type": "tidelift",
|
| 855 |
+
"url": "https://tidelift.com/funding/github/npm/postcss"
|
| 856 |
+
},
|
| 857 |
+
{
|
| 858 |
+
"type": "github",
|
| 859 |
+
"url": "https://github.com/sponsors/ai"
|
| 860 |
+
}
|
| 861 |
+
],
|
| 862 |
+
"license": "MIT",
|
| 863 |
+
"dependencies": {
|
| 864 |
+
"nanoid": "^3.3.6",
|
| 865 |
+
"picocolors": "^1.0.0",
|
| 866 |
+
"source-map-js": "^1.0.2"
|
| 867 |
+
},
|
| 868 |
+
"engines": {
|
| 869 |
+
"node": "^10 || ^12 || >=14"
|
| 870 |
+
}
|
| 871 |
+
},
|
| 872 |
+
"node_modules/react": {
|
| 873 |
+
"version": "19.2.5",
|
| 874 |
+
"resolved": "https://registry.npmjs.org/react/-/react-19.2.5.tgz",
|
| 875 |
+
"integrity": "sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==",
|
| 876 |
+
"license": "MIT",
|
| 877 |
+
"peer": true,
|
| 878 |
+
"engines": {
|
| 879 |
+
"node": ">=0.10.0"
|
| 880 |
+
}
|
| 881 |
+
},
|
| 882 |
+
"node_modules/react-dom": {
|
| 883 |
+
"version": "19.2.5",
|
| 884 |
+
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.5.tgz",
|
| 885 |
+
"integrity": "sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==",
|
| 886 |
+
"license": "MIT",
|
| 887 |
+
"peer": true,
|
| 888 |
+
"dependencies": {
|
| 889 |
+
"scheduler": "^0.27.0"
|
| 890 |
+
},
|
| 891 |
+
"peerDependencies": {
|
| 892 |
+
"react": "^19.2.5"
|
| 893 |
+
}
|
| 894 |
+
},
|
| 895 |
+
"node_modules/scheduler": {
|
| 896 |
+
"version": "0.27.0",
|
| 897 |
+
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
|
| 898 |
+
"integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
|
| 899 |
+
"license": "MIT"
|
| 900 |
+
},
|
| 901 |
+
"node_modules/semver": {
|
| 902 |
+
"version": "7.7.4",
|
| 903 |
+
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
|
| 904 |
+
"integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
|
| 905 |
+
"license": "ISC",
|
| 906 |
+
"optional": true,
|
| 907 |
+
"bin": {
|
| 908 |
+
"semver": "bin/semver.js"
|
| 909 |
+
},
|
| 910 |
+
"engines": {
|
| 911 |
+
"node": ">=10"
|
| 912 |
+
}
|
| 913 |
+
},
|
| 914 |
+
"node_modules/sharp": {
|
| 915 |
+
"version": "0.34.5",
|
| 916 |
+
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz",
|
| 917 |
+
"integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==",
|
| 918 |
+
"hasInstallScript": true,
|
| 919 |
+
"license": "Apache-2.0",
|
| 920 |
+
"optional": true,
|
| 921 |
+
"dependencies": {
|
| 922 |
+
"@img/colour": "^1.0.0",
|
| 923 |
+
"detect-libc": "^2.1.2",
|
| 924 |
+
"semver": "^7.7.3"
|
| 925 |
+
},
|
| 926 |
+
"engines": {
|
| 927 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 928 |
+
},
|
| 929 |
+
"funding": {
|
| 930 |
+
"url": "https://opencollective.com/libvips"
|
| 931 |
+
},
|
| 932 |
+
"optionalDependencies": {
|
| 933 |
+
"@img/sharp-darwin-arm64": "0.34.5",
|
| 934 |
+
"@img/sharp-darwin-x64": "0.34.5",
|
| 935 |
+
"@img/sharp-libvips-darwin-arm64": "1.2.4",
|
| 936 |
+
"@img/sharp-libvips-darwin-x64": "1.2.4",
|
| 937 |
+
"@img/sharp-libvips-linux-arm": "1.2.4",
|
| 938 |
+
"@img/sharp-libvips-linux-arm64": "1.2.4",
|
| 939 |
+
"@img/sharp-libvips-linux-ppc64": "1.2.4",
|
| 940 |
+
"@img/sharp-libvips-linux-riscv64": "1.2.4",
|
| 941 |
+
"@img/sharp-libvips-linux-s390x": "1.2.4",
|
| 942 |
+
"@img/sharp-libvips-linux-x64": "1.2.4",
|
| 943 |
+
"@img/sharp-libvips-linuxmusl-arm64": "1.2.4",
|
| 944 |
+
"@img/sharp-libvips-linuxmusl-x64": "1.2.4",
|
| 945 |
+
"@img/sharp-linux-arm": "0.34.5",
|
| 946 |
+
"@img/sharp-linux-arm64": "0.34.5",
|
| 947 |
+
"@img/sharp-linux-ppc64": "0.34.5",
|
| 948 |
+
"@img/sharp-linux-riscv64": "0.34.5",
|
| 949 |
+
"@img/sharp-linux-s390x": "0.34.5",
|
| 950 |
+
"@img/sharp-linux-x64": "0.34.5",
|
| 951 |
+
"@img/sharp-linuxmusl-arm64": "0.34.5",
|
| 952 |
+
"@img/sharp-linuxmusl-x64": "0.34.5",
|
| 953 |
+
"@img/sharp-wasm32": "0.34.5",
|
| 954 |
+
"@img/sharp-win32-arm64": "0.34.5",
|
| 955 |
+
"@img/sharp-win32-ia32": "0.34.5",
|
| 956 |
+
"@img/sharp-win32-x64": "0.34.5"
|
| 957 |
+
}
|
| 958 |
+
},
|
| 959 |
+
"node_modules/source-map-js": {
|
| 960 |
+
"version": "1.2.1",
|
| 961 |
+
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
| 962 |
+
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
| 963 |
+
"license": "BSD-3-Clause",
|
| 964 |
+
"engines": {
|
| 965 |
+
"node": ">=0.10.0"
|
| 966 |
+
}
|
| 967 |
+
},
|
| 968 |
+
"node_modules/styled-jsx": {
|
| 969 |
+
"version": "5.1.6",
|
| 970 |
+
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz",
|
| 971 |
+
"integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==",
|
| 972 |
+
"license": "MIT",
|
| 973 |
+
"dependencies": {
|
| 974 |
+
"client-only": "0.0.1"
|
| 975 |
+
},
|
| 976 |
+
"engines": {
|
| 977 |
+
"node": ">= 12.0.0"
|
| 978 |
+
},
|
| 979 |
+
"peerDependencies": {
|
| 980 |
+
"react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0"
|
| 981 |
+
},
|
| 982 |
+
"peerDependenciesMeta": {
|
| 983 |
+
"@babel/core": {
|
| 984 |
+
"optional": true
|
| 985 |
+
},
|
| 986 |
+
"babel-plugin-macros": {
|
| 987 |
+
"optional": true
|
| 988 |
+
}
|
| 989 |
+
}
|
| 990 |
+
},
|
| 991 |
+
"node_modules/tslib": {
|
| 992 |
+
"version": "2.8.1",
|
| 993 |
+
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
| 994 |
+
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
| 995 |
+
"license": "0BSD"
|
| 996 |
+
},
|
| 997 |
+
"node_modules/typescript": {
|
| 998 |
+
"version": "5.9.3",
|
| 999 |
+
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
| 1000 |
+
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
| 1001 |
+
"dev": true,
|
| 1002 |
+
"license": "Apache-2.0",
|
| 1003 |
+
"bin": {
|
| 1004 |
+
"tsc": "bin/tsc",
|
| 1005 |
+
"tsserver": "bin/tsserver"
|
| 1006 |
+
},
|
| 1007 |
+
"engines": {
|
| 1008 |
+
"node": ">=14.17"
|
| 1009 |
+
}
|
| 1010 |
+
},
|
| 1011 |
+
"node_modules/undici-types": {
|
| 1012 |
+
"version": "7.16.0",
|
| 1013 |
+
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
|
| 1014 |
+
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
|
| 1015 |
+
"dev": true,
|
| 1016 |
+
"license": "MIT"
|
| 1017 |
+
}
|
| 1018 |
+
}
|
| 1019 |
+
}
|
ui/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "sentinel-ui",
|
| 3 |
+
"private": true,
|
| 4 |
+
"version": "0.1.0",
|
| 5 |
+
"scripts": {
|
| 6 |
+
"dev": "next dev",
|
| 7 |
+
"build": "next build",
|
| 8 |
+
"start": "next start"
|
| 9 |
+
},
|
| 10 |
+
"dependencies": {
|
| 11 |
+
"framer-motion": "^12.23.24",
|
| 12 |
+
"lucide-react": "^0.539.0",
|
| 13 |
+
"next": "^15.3.3",
|
| 14 |
+
"react": "^19.1.1",
|
| 15 |
+
"react-dom": "^19.1.1"
|
| 16 |
+
},
|
| 17 |
+
"devDependencies": {
|
| 18 |
+
"@types/node": "^24.3.0",
|
| 19 |
+
"@types/react": "^19.1.11",
|
| 20 |
+
"@types/react-dom": "^19.1.7",
|
| 21 |
+
"typescript": "^5.9.2"
|
| 22 |
+
}
|
| 23 |
+
}
|
ui/tsconfig.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"compilerOptions": {
|
| 3 |
+
"target": "ES2017",
|
| 4 |
+
"lib": ["dom", "dom.iterable", "esnext"],
|
| 5 |
+
"allowJs": false,
|
| 6 |
+
"skipLibCheck": true,
|
| 7 |
+
"strict": true,
|
| 8 |
+
"noEmit": true,
|
| 9 |
+
"esModuleInterop": true,
|
| 10 |
+
"module": "esnext",
|
| 11 |
+
"moduleResolution": "bundler",
|
| 12 |
+
"resolveJsonModule": true,
|
| 13 |
+
"isolatedModules": true,
|
| 14 |
+
"jsx": "preserve",
|
| 15 |
+
"incremental": true,
|
| 16 |
+
"plugins": [{ "name": "next" }]
|
| 17 |
+
},
|
| 18 |
+
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
| 19 |
+
"exclude": ["node_modules"]
|
| 20 |
+
}
|